1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa 5 * Copyright (c) 2014-2025 Yandex LLC 6 * Copyright (c) 2014 Alexander V. Chernikov 7 * 8 * Supported by: Valeria Paoli 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 /* 34 * Control socket and rule management routines for ipfw. 35 * Control is currently implemented via IP_FW3 setsockopt() code. 36 */ 37 38 #include "opt_ipfw.h" 39 #include "opt_inet.h" 40 #ifndef INET 41 #error IPFIREWALL requires INET. 42 #endif /* INET */ 43 #include "opt_inet6.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/malloc.h> 48 #include <sys/mbuf.h> /* struct m_tag used by nested headers */ 49 #include <sys/kernel.h> 50 #include <sys/lock.h> 51 #include <sys/priv.h> 52 #include <sys/proc.h> 53 #include <sys/rwlock.h> 54 #include <sys/rmlock.h> 55 #include <sys/socket.h> 56 #include <sys/socketvar.h> 57 #include <sys/sysctl.h> 58 #include <sys/syslog.h> 59 #include <sys/fnv_hash.h> 60 #include <net/if.h> 61 #include <net/route.h> 62 #include <net/vnet.h> 63 #include <vm/vm.h> 64 #include <vm/vm_extern.h> 65 66 #include <netinet/in.h> 67 #include <netinet/ip_var.h> /* hooks */ 68 #include <netinet/ip_fw.h> 69 70 #include <netpfil/ipfw/ip_fw_private.h> 71 #include <netpfil/ipfw/ip_fw_table.h> 72 73 #ifdef MAC 74 #include <security/mac/mac_framework.h> 75 #endif 76 77 static enum ipfw_opcheck_result 78 check_opcode_compat_nop(ipfw_insn **pcmd, int *plen, 79 struct rule_check_info *ci) 80 { 81 /* Compatibility code is not registered */ 82 return (FAILED); 83 } 84 85 static ipfw_check_opcode_t check_opcode_f = check_opcode_compat_nop; 86 87 static int check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, 88 struct rule_check_info *ci); 89 static int rewrite_rule_uidx(struct ip_fw_chain *chain, 90 struct rule_check_info *ci); 91 92 struct namedobj_instance { 93 struct namedobjects_head *names; 94 struct namedobjects_head *values; 95 uint32_t nn_size; /* names hash size */ 96 uint32_t nv_size; /* number hash size */ 97 u_long *idx_mask; /* used items bitmask */ 98 uint32_t max_blocks; /* number of "long" blocks in bitmask */ 99 uint32_t count; /* number of items */ 100 uint16_t free_off[IPFW_MAX_SETS]; /* first possible free offset */ 101 objhash_hash_f *hash_f; 102 objhash_cmp_f *cmp_f; 103 }; 104 #define BLOCK_ITEMS (8 * sizeof(u_long)) /* Number of items for ffsl() */ 105 106 static uint32_t objhash_hash_name(struct namedobj_instance *ni, 107 const void *key, uint32_t kopt); 108 static uint32_t objhash_hash_idx(struct namedobj_instance *ni, uint32_t val); 109 static int objhash_cmp_name(struct named_object *no, const void *name, 110 uint32_t set); 111 112 MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's"); 113 114 /* ctl3 handler data */ 115 static struct mtx ctl3_lock; 116 #define CTL3_LOCK_INIT() mtx_init(&ctl3_lock, "ctl3_lock", NULL, MTX_DEF) 117 #define CTL3_LOCK_DESTROY() mtx_destroy(&ctl3_lock) 118 #define CTL3_LOCK() mtx_lock(&ctl3_lock) 119 #define CTL3_UNLOCK() mtx_unlock(&ctl3_lock) 120 121 static struct ipfw_sopt_handler *ctl3_handlers; 122 static size_t ctl3_hsize; 123 static uint64_t ctl3_refct, ctl3_gencnt; 124 #define CTL3_SMALLBUF 4096 /* small page-size write buffer */ 125 #define CTL3_LARGEBUF (16 * 1024 * 1024) /* handle large rulesets */ 126 127 static int ipfw_flush_sopt_data(struct sockopt_data *sd); 128 129 static sopt_handler_f dump_config, add_rules, del_rules, clear_rules, 130 move_rules, manage_sets, dump_soptcodes, dump_srvobjects, 131 manage_skiptocache; 132 133 static struct ipfw_sopt_handler scodes[] = { 134 { IP_FW_XGET, IP_FW3_OPVER, HDIR_GET, dump_config }, 135 { IP_FW_XADD, IP_FW3_OPVER, HDIR_BOTH, add_rules }, 136 { IP_FW_XDEL, IP_FW3_OPVER, HDIR_BOTH, del_rules }, 137 { IP_FW_XZERO, IP_FW3_OPVER, HDIR_SET, clear_rules }, 138 { IP_FW_XRESETLOG, IP_FW3_OPVER, HDIR_SET, clear_rules }, 139 { IP_FW_XMOVE, IP_FW3_OPVER, HDIR_SET, move_rules }, 140 { IP_FW_SET_SWAP, IP_FW3_OPVER, HDIR_SET, manage_sets }, 141 { IP_FW_SET_MOVE, IP_FW3_OPVER, HDIR_SET, manage_sets }, 142 { IP_FW_SET_ENABLE, IP_FW3_OPVER, HDIR_SET, manage_sets }, 143 { IP_FW_DUMP_SOPTCODES, IP_FW3_OPVER, HDIR_GET, dump_soptcodes }, 144 { IP_FW_DUMP_SRVOBJECTS, IP_FW3_OPVER, HDIR_GET, dump_srvobjects }, 145 { IP_FW_SKIPTO_CACHE, IP_FW3_OPVER, HDIR_BOTH, manage_skiptocache }, 146 }; 147 148 static struct opcode_obj_rewrite *find_op_rw(ipfw_insn *cmd, 149 uint32_t *puidx, uint8_t *ptype); 150 static int ref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule, 151 struct rule_check_info *ci, struct obj_idx *oib, struct tid_info *ti); 152 static int ref_opcode_object(struct ip_fw_chain *ch, ipfw_insn *cmd, 153 struct tid_info *ti, struct obj_idx *pidx, int *unresolved); 154 static void unref_rule_objects(struct ip_fw_chain *chain, struct ip_fw *rule); 155 static void unref_oib_objects(struct ip_fw_chain *ch, ipfw_insn *cmd, 156 struct obj_idx *oib, struct obj_idx *end); 157 static int export_objhash_ntlv(struct namedobj_instance *ni, uint32_t kidx, 158 struct sockopt_data *sd); 159 160 /* 161 * Opcode object rewriter variables 162 */ 163 struct opcode_obj_rewrite *ctl3_rewriters; 164 static size_t ctl3_rsize; 165 166 /* 167 * static variables followed by global ones 168 */ 169 170 VNET_DEFINE_STATIC(uma_zone_t, ipfw_cntr_zone); 171 #define V_ipfw_cntr_zone VNET(ipfw_cntr_zone) 172 173 void 174 ipfw_init_counters(void) 175 { 176 177 V_ipfw_cntr_zone = uma_zcreate("IPFW counters", 178 IPFW_RULE_CNTR_SIZE, NULL, NULL, NULL, NULL, 179 UMA_ALIGN_PTR, UMA_ZONE_PCPU); 180 } 181 182 void 183 ipfw_destroy_counters(void) 184 { 185 186 uma_zdestroy(V_ipfw_cntr_zone); 187 } 188 189 struct ip_fw * 190 ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize) 191 { 192 struct ip_fw *rule; 193 194 rule = malloc(rulesize, M_IPFW, M_WAITOK | M_ZERO); 195 rule->cntr = uma_zalloc_pcpu(V_ipfw_cntr_zone, M_WAITOK | M_ZERO); 196 rule->refcnt = 1; 197 198 return (rule); 199 } 200 201 void 202 ipfw_free_rule(struct ip_fw *rule) 203 { 204 205 /* 206 * We don't release refcnt here, since this function 207 * can be called without any locks held. The caller 208 * must release reference under IPFW_UH_WLOCK, and then 209 * call this function if refcount becomes 1. 210 */ 211 if (rule->refcnt > 1) 212 return; 213 uma_zfree_pcpu(V_ipfw_cntr_zone, rule->cntr); 214 free(rule, M_IPFW); 215 } 216 217 /* 218 * Find the smallest rule >= key, id. 219 * We could use bsearch but it is so simple that we code it directly 220 */ 221 int 222 ipfw_find_rule(struct ip_fw_chain *chain, uint32_t key, uint32_t id) 223 { 224 int i, lo, hi; 225 struct ip_fw *r; 226 227 for (lo = 0, hi = chain->n_rules - 1; lo < hi;) { 228 i = (lo + hi) / 2; 229 r = chain->map[i]; 230 if (r->rulenum < key) 231 lo = i + 1; /* continue from the next one */ 232 else if (r->rulenum > key) 233 hi = i; /* this might be good */ 234 else if (r->id < id) 235 lo = i + 1; /* continue from the next one */ 236 else /* r->id >= id */ 237 hi = i; /* this might be good */ 238 } 239 return hi; 240 } 241 242 /* 243 * Builds skipto cache on rule set @map. 244 */ 245 static void 246 update_skipto_cache(struct ip_fw_chain *chain, struct ip_fw **map) 247 { 248 uint32_t *smap, rulenum; 249 int i, mi; 250 251 IPFW_UH_WLOCK_ASSERT(chain); 252 253 mi = 0; 254 rulenum = map[mi]->rulenum; 255 smap = chain->idxmap_back; 256 257 if (smap == NULL) 258 return; 259 260 for (i = 0; i <= IPFW_DEFAULT_RULE; i++) { 261 smap[i] = mi; 262 /* Use the same rule index until i < rulenum */ 263 if (i != rulenum || i == IPFW_DEFAULT_RULE) 264 continue; 265 /* Find next rule with num > i */ 266 rulenum = map[++mi]->rulenum; 267 while (rulenum == i) 268 rulenum = map[++mi]->rulenum; 269 } 270 } 271 272 /* 273 * Swaps prepared (backup) index with current one. 274 */ 275 static void 276 swap_skipto_cache(struct ip_fw_chain *chain) 277 { 278 uint32_t *map; 279 280 IPFW_UH_WLOCK_ASSERT(chain); 281 IPFW_WLOCK_ASSERT(chain); 282 283 map = chain->idxmap; 284 chain->idxmap = chain->idxmap_back; 285 chain->idxmap_back = map; 286 } 287 288 /* 289 * Allocate and initialize skipto cache. 290 */ 291 void 292 ipfw_init_skipto_cache(struct ip_fw_chain *chain) 293 { 294 uint32_t *idxmap, *idxmap_back; 295 296 idxmap = malloc((IPFW_DEFAULT_RULE + 1) * sizeof(uint32_t), 297 M_IPFW, M_WAITOK | M_ZERO); 298 idxmap_back = malloc((IPFW_DEFAULT_RULE + 1) * sizeof(uint32_t), 299 M_IPFW, M_WAITOK | M_ZERO); 300 301 /* 302 * Note we may be called at any time after initialization, 303 * for example, on first skipto rule, so we need to 304 * provide valid chain->idxmap on return 305 */ 306 307 IPFW_UH_WLOCK(chain); 308 if (chain->idxmap != NULL) { 309 IPFW_UH_WUNLOCK(chain); 310 free(idxmap, M_IPFW); 311 free(idxmap_back, M_IPFW); 312 return; 313 } 314 315 /* Set backup pointer first to permit building cache */ 316 chain->idxmap_back = idxmap_back; 317 if (V_skipto_cache != 0) 318 update_skipto_cache(chain, chain->map); 319 IPFW_WLOCK(chain); 320 /* It is now safe to set chain->idxmap ptr */ 321 chain->idxmap = idxmap; 322 swap_skipto_cache(chain); 323 IPFW_WUNLOCK(chain); 324 IPFW_UH_WUNLOCK(chain); 325 } 326 327 /* 328 * Destroys skipto cache. 329 */ 330 void 331 ipfw_destroy_skipto_cache(struct ip_fw_chain *chain) 332 { 333 free(chain->idxmap, M_IPFW); 334 free(chain->idxmap_back, M_IPFW); 335 } 336 337 /* 338 * allocate a new map, returns the chain locked. extra is the number 339 * of entries to add or delete. 340 */ 341 static struct ip_fw ** 342 get_map(struct ip_fw_chain *chain, int extra, int locked) 343 { 344 345 for (;;) { 346 struct ip_fw **map; 347 u_int i, mflags; 348 349 mflags = M_ZERO | ((locked != 0) ? M_NOWAIT : M_WAITOK); 350 351 i = chain->n_rules + extra; 352 map = malloc(i * sizeof(struct ip_fw *), M_IPFW, mflags); 353 if (map == NULL) { 354 printf("%s: cannot allocate map\n", __FUNCTION__); 355 return NULL; 356 } 357 if (!locked) 358 IPFW_UH_WLOCK(chain); 359 if (i >= chain->n_rules + extra) /* good */ 360 return map; 361 /* otherwise we lost the race, free and retry */ 362 if (!locked) 363 IPFW_UH_WUNLOCK(chain); 364 free(map, M_IPFW); 365 } 366 } 367 368 /* 369 * swap the maps. It is supposed to be called with IPFW_UH_WLOCK 370 */ 371 static struct ip_fw ** 372 swap_map(struct ip_fw_chain *chain, struct ip_fw **new_map, int new_len) 373 { 374 struct ip_fw **old_map; 375 376 IPFW_WLOCK(chain); 377 chain->id++; 378 chain->n_rules = new_len; 379 old_map = chain->map; 380 chain->map = new_map; 381 swap_skipto_cache(chain); 382 IPFW_WUNLOCK(chain); 383 return old_map; 384 } 385 386 static void 387 export_cntr1_base(struct ip_fw *krule, struct ip_fw_bcounter *cntr) 388 { 389 struct timeval boottime; 390 391 cntr->size = sizeof(*cntr); 392 393 if (krule->cntr != NULL) { 394 cntr->pcnt = counter_u64_fetch(krule->cntr); 395 cntr->bcnt = counter_u64_fetch(krule->cntr + 1); 396 cntr->timestamp = krule->timestamp; 397 } 398 if (cntr->timestamp > 0) { 399 getboottime(&boottime); 400 cntr->timestamp += boottime.tv_sec; 401 } 402 } 403 404 /* 405 * Export rule into v1 format (Current). 406 * Layout: 407 * [ ipfw_obj_tlv(IPFW_TLV_RULE_ENT) 408 * [ ip_fw_rule ] OR 409 * [ ip_fw_bcounter ip_fw_rule] (depends on rcntrs). 410 * ] 411 * Assume @data is zeroed. 412 */ 413 static void 414 export_rule1(struct ip_fw *krule, caddr_t data, int len, int rcntrs) 415 { 416 struct ip_fw_bcounter *cntr; 417 struct ip_fw_rule *urule; 418 ipfw_obj_tlv *tlv; 419 420 /* Fill in TLV header */ 421 tlv = (ipfw_obj_tlv *)data; 422 tlv->type = IPFW_TLV_RULE_ENT; 423 tlv->length = len; 424 425 if (rcntrs != 0) { 426 /* Copy counters */ 427 cntr = (struct ip_fw_bcounter *)(tlv + 1); 428 urule = (struct ip_fw_rule *)(cntr + 1); 429 export_cntr1_base(krule, cntr); 430 } else 431 urule = (struct ip_fw_rule *)(tlv + 1); 432 433 /* copy header */ 434 urule->act_ofs = krule->act_ofs; 435 urule->cmd_len = krule->cmd_len; 436 urule->rulenum = krule->rulenum; 437 urule->set = krule->set; 438 urule->flags = krule->flags; 439 urule->id = krule->id; 440 441 /* Copy opcodes */ 442 memcpy(urule->cmd, krule->cmd, krule->cmd_len * sizeof(uint32_t)); 443 } 444 445 /* 446 * Add new rule(s) to the list possibly creating rule number for each. 447 * Update the rule_number in the input struct so the caller knows it as well. 448 * Must be called without IPFW_UH held 449 */ 450 int 451 ipfw_commit_rules(struct ip_fw_chain *chain, struct rule_check_info *rci, 452 int count) 453 { 454 int error, i, insert_before, tcount, rule_idx, last_rule_idx; 455 uint32_t rulenum; 456 struct rule_check_info *ci; 457 struct ip_fw *krule; 458 struct ip_fw **map; /* the new array of pointers */ 459 460 /* Check if we need to do table/obj index remap */ 461 tcount = 0; 462 for (ci = rci, i = 0; i < count; ci++, i++) { 463 if (ci->object_opcodes == 0) 464 continue; 465 466 /* 467 * Rule has some object opcodes. 468 * We need to find (and create non-existing) 469 * kernel objects, and reference existing ones. 470 */ 471 error = rewrite_rule_uidx(chain, ci); 472 if (error != 0) { 473 474 /* 475 * rewrite failed, state for current rule 476 * has been reverted. Check if we need to 477 * revert more. 478 */ 479 if (tcount > 0) { 480 481 /* 482 * We have some more table rules 483 * we need to rollback. 484 */ 485 486 IPFW_UH_WLOCK(chain); 487 while (ci != rci) { 488 ci--; 489 if (ci->object_opcodes == 0) 490 continue; 491 unref_rule_objects(chain,ci->krule); 492 493 } 494 IPFW_UH_WUNLOCK(chain); 495 496 } 497 498 return (error); 499 } 500 501 tcount++; 502 } 503 504 /* get_map returns with IPFW_UH_WLOCK if successful */ 505 map = get_map(chain, count, 0 /* not locked */); 506 if (map == NULL) { 507 if (tcount > 0) { 508 /* Unbind tables */ 509 IPFW_UH_WLOCK(chain); 510 for (ci = rci, i = 0; i < count; ci++, i++) { 511 if (ci->object_opcodes == 0) 512 continue; 513 514 unref_rule_objects(chain, ci->krule); 515 } 516 IPFW_UH_WUNLOCK(chain); 517 } 518 519 return (ENOSPC); 520 } 521 522 if (V_autoinc_step < 1) 523 V_autoinc_step = 1; 524 else if (V_autoinc_step > 1000) 525 V_autoinc_step = 1000; 526 527 last_rule_idx = 0; 528 for (ci = rci, i = 0; i < count; ci++, i++) { 529 krule = ci->krule; 530 rulenum = krule->rulenum; 531 532 krule->id = chain->id + 1; 533 534 /* find the insertion point, we will insert before */ 535 insert_before = rulenum ? rulenum + 1 : IPFW_DEFAULT_RULE; 536 rule_idx = ipfw_find_rule(chain, insert_before, 0); 537 /* duplicate the previous part */ 538 if (last_rule_idx < rule_idx) 539 bcopy(chain->map + last_rule_idx, map + last_rule_idx + i, 540 (rule_idx - last_rule_idx) * sizeof(struct ip_fw *)); 541 last_rule_idx = rule_idx; 542 map[rule_idx + i] = krule; 543 if (rulenum == 0) { 544 /* Compute rule number and write it back */ 545 rulenum = rule_idx + i > 0 ? map[rule_idx + i - 1]->rulenum : 0; 546 if (rulenum < IPFW_DEFAULT_RULE - V_autoinc_step) 547 rulenum += V_autoinc_step; 548 krule->rulenum = rulenum; 549 /* Save number to userland rule */ 550 memcpy((char *)ci->urule + ci->urule_numoff, &rulenum, 551 sizeof(rulenum)); 552 } 553 } 554 555 /* duplicate the remaining part, we always have the default rule */ 556 bcopy(chain->map + last_rule_idx, map + last_rule_idx + count, 557 (chain->n_rules - last_rule_idx) * sizeof(struct ip_fw *)); 558 559 if (V_skipto_cache != 0) 560 update_skipto_cache(chain, map); 561 map = swap_map(chain, map, chain->n_rules + count); 562 IPFW_UH_WUNLOCK(chain); 563 if (map) 564 free(map, M_IPFW); 565 return (0); 566 } 567 568 int 569 ipfw_add_protected_rule(struct ip_fw_chain *chain, struct ip_fw *rule, 570 int locked) 571 { 572 struct ip_fw **map; 573 574 map = get_map(chain, 1, locked); 575 if (map == NULL) 576 return (ENOMEM); 577 if (chain->n_rules > 0) 578 bcopy(chain->map, map, 579 chain->n_rules * sizeof(struct ip_fw *)); 580 map[chain->n_rules] = rule; 581 rule->rulenum = IPFW_DEFAULT_RULE; 582 rule->set = RESVD_SET; 583 rule->id = chain->id + 1; 584 /* We add rule in the end of chain, no need to update skipto cache */ 585 map = swap_map(chain, map, chain->n_rules + 1); 586 IPFW_UH_WUNLOCK(chain); 587 free(map, M_IPFW); 588 return (0); 589 } 590 591 /* 592 * Adds @rule to the list of rules to reap 593 */ 594 void 595 ipfw_reap_add(struct ip_fw_chain *chain, struct ip_fw **head, 596 struct ip_fw *rule) 597 { 598 599 IPFW_UH_WLOCK_ASSERT(chain); 600 601 /* Unlink rule from everywhere */ 602 unref_rule_objects(chain, rule); 603 604 rule->next = *head; 605 *head = rule; 606 } 607 608 /* 609 * Reclaim storage associated with a list of rules. This is 610 * typically the list created using remove_rule. 611 * A NULL pointer on input is handled correctly. 612 */ 613 void 614 ipfw_reap_rules(struct ip_fw *head) 615 { 616 struct ip_fw *rule; 617 618 while ((rule = head) != NULL) { 619 head = head->next; 620 ipfw_free_rule(rule); 621 } 622 } 623 624 /* 625 * Rules to keep are 626 * (default || reserved || !match_set || !match_number) 627 * where 628 * default ::= (rule->rulenum == IPFW_DEFAULT_RULE) 629 * // the default rule is always protected 630 * 631 * reserved ::= (cmd == 0 && n == 0 && rule->set == RESVD_SET) 632 * // RESVD_SET is protected only if cmd == 0 and n == 0 ("ipfw flush") 633 * 634 * match_set ::= (cmd == 0 || rule->set == set) 635 * // set number is ignored for cmd == 0 636 * 637 * match_number ::= (cmd == 1 || n == 0 || n == rule->rulenum) 638 * // number is ignored for cmd == 1 or n == 0 639 * 640 */ 641 int 642 ipfw_match_range(struct ip_fw *rule, ipfw_range_tlv *rt) 643 { 644 645 /* Don't match default rule for modification queries */ 646 if (rule->rulenum == IPFW_DEFAULT_RULE && 647 (rt->flags & IPFW_RCFLAG_DEFAULT) == 0) 648 return (0); 649 650 /* Don't match rules in reserved set for flush requests */ 651 if ((rt->flags & IPFW_RCFLAG_ALL) != 0 && rule->set == RESVD_SET) 652 return (0); 653 654 /* If we're filtering by set, don't match other sets */ 655 if ((rt->flags & IPFW_RCFLAG_SET) != 0 && rule->set != rt->set) 656 return (0); 657 658 if ((rt->flags & IPFW_RCFLAG_RANGE) != 0 && 659 (rule->rulenum < rt->start_rule || rule->rulenum > rt->end_rule)) 660 return (0); 661 662 return (1); 663 } 664 665 struct manage_sets_args { 666 uint32_t set; 667 uint8_t new_set; 668 }; 669 670 static int 671 swap_sets_cb(struct namedobj_instance *ni, struct named_object *no, 672 void *arg) 673 { 674 struct manage_sets_args *args; 675 676 args = (struct manage_sets_args *)arg; 677 if (no->set == (uint8_t)args->set) 678 no->set = args->new_set; 679 else if (no->set == args->new_set) 680 no->set = (uint8_t)args->set; 681 return (0); 682 } 683 684 static int 685 move_sets_cb(struct namedobj_instance *ni, struct named_object *no, 686 void *arg) 687 { 688 struct manage_sets_args *args; 689 690 args = (struct manage_sets_args *)arg; 691 if (no->set == (uint8_t)args->set) 692 no->set = args->new_set; 693 return (0); 694 } 695 696 static int 697 test_sets_cb(struct namedobj_instance *ni, struct named_object *no, 698 void *arg) 699 { 700 struct manage_sets_args *args; 701 702 args = (struct manage_sets_args *)arg; 703 if (no->set != (uint8_t)args->set) 704 return (0); 705 if (ipfw_objhash_lookup_name_type(ni, args->new_set, 706 no->etlv, no->name) != NULL) 707 return (EEXIST); 708 return (0); 709 } 710 711 /* 712 * Generic function to handler moving and swapping sets. 713 */ 714 int 715 ipfw_obj_manage_sets(struct namedobj_instance *ni, uint16_t type, 716 uint32_t set, uint8_t new_set, enum ipfw_sets_cmd cmd) 717 { 718 struct manage_sets_args args; 719 struct named_object *no; 720 721 args.set = set; 722 args.new_set = new_set; 723 switch (cmd) { 724 case SWAP_ALL: 725 return (ipfw_objhash_foreach_type(ni, swap_sets_cb, 726 &args, type)); 727 case TEST_ALL: 728 return (ipfw_objhash_foreach_type(ni, test_sets_cb, 729 &args, type)); 730 case MOVE_ALL: 731 return (ipfw_objhash_foreach_type(ni, move_sets_cb, 732 &args, type)); 733 case COUNT_ONE: 734 /* 735 * @set used to pass kidx. 736 * When @new_set is zero - reset object counter, 737 * otherwise increment it. 738 */ 739 no = ipfw_objhash_lookup_kidx(ni, set); 740 if (new_set != 0) 741 no->ocnt++; 742 else 743 no->ocnt = 0; 744 return (0); 745 case TEST_ONE: 746 /* @set used to pass kidx */ 747 no = ipfw_objhash_lookup_kidx(ni, set); 748 /* 749 * First check number of references: 750 * when it differs, this mean other rules are holding 751 * reference to given object, so it is not possible to 752 * change its set. Note that refcnt may account references 753 * to some going-to-be-added rules. Since we don't know 754 * their numbers (and even if they will be added) it is 755 * perfectly OK to return error here. 756 */ 757 if (no->ocnt != no->refcnt) 758 return (EBUSY); 759 if (ipfw_objhash_lookup_name_type(ni, new_set, type, 760 no->name) != NULL) 761 return (EEXIST); 762 return (0); 763 case MOVE_ONE: 764 /* @set used to pass kidx */ 765 no = ipfw_objhash_lookup_kidx(ni, set); 766 no->set = new_set; 767 return (0); 768 } 769 return (EINVAL); 770 } 771 772 /* 773 * Delete rules matching range @rt. 774 * Saves number of deleted rules in @ndel. 775 * 776 * Returns 0 on success. 777 */ 778 int 779 delete_range(struct ip_fw_chain *chain, ipfw_range_tlv *rt, int *ndel) 780 { 781 struct ip_fw *reap, *rule, **map; 782 uint32_t end, start; 783 int i, n, ndyn, ofs; 784 785 reap = NULL; 786 IPFW_UH_WLOCK(chain); /* arbitrate writers */ 787 788 /* 789 * Stage 1: Determine range to inspect. 790 * Range is half-inclusive, e.g [start, end). 791 */ 792 start = 0; 793 end = chain->n_rules - 1; 794 795 if ((rt->flags & IPFW_RCFLAG_RANGE) != 0) { 796 start = ipfw_find_rule(chain, rt->start_rule, 0); 797 798 if (rt->end_rule >= IPFW_DEFAULT_RULE) 799 rt->end_rule = IPFW_DEFAULT_RULE - 1; 800 end = ipfw_find_rule(chain, rt->end_rule, UINT32_MAX); 801 } 802 803 if (rt->flags & IPFW_RCFLAG_DYNAMIC) { 804 /* 805 * Requested deleting only for dynamic states. 806 */ 807 *ndel = 0; 808 ipfw_expire_dyn_states(chain, rt); 809 IPFW_UH_WUNLOCK(chain); 810 return (0); 811 } 812 813 /* Allocate new map of the same size */ 814 map = get_map(chain, 0, 1 /* locked */); 815 if (map == NULL) { 816 IPFW_UH_WUNLOCK(chain); 817 return (ENOMEM); 818 } 819 820 n = 0; 821 ndyn = 0; 822 ofs = start; 823 /* 1. bcopy the initial part of the map */ 824 if (start > 0) 825 bcopy(chain->map, map, start * sizeof(struct ip_fw *)); 826 /* 2. copy active rules between start and end */ 827 for (i = start; i < end; i++) { 828 rule = chain->map[i]; 829 if (ipfw_match_range(rule, rt) == 0) { 830 map[ofs++] = rule; 831 continue; 832 } 833 834 n++; 835 if (ipfw_is_dyn_rule(rule) != 0) 836 ndyn++; 837 } 838 /* 3. copy the final part of the map */ 839 bcopy(chain->map + end, map + ofs, 840 (chain->n_rules - end) * sizeof(struct ip_fw *)); 841 /* 4. recalculate skipto cache */ 842 update_skipto_cache(chain, map); 843 /* 5. swap the maps (under UH_WLOCK + WHLOCK) */ 844 map = swap_map(chain, map, chain->n_rules - n); 845 /* 6. Remove all dynamic states originated by deleted rules */ 846 if (ndyn > 0) 847 ipfw_expire_dyn_states(chain, rt); 848 /* 7. now remove the rules deleted from the old map */ 849 for (i = start; i < end; i++) { 850 rule = map[i]; 851 if (ipfw_match_range(rule, rt) == 0) 852 continue; 853 ipfw_reap_add(chain, &reap, rule); 854 } 855 IPFW_UH_WUNLOCK(chain); 856 857 ipfw_reap_rules(reap); 858 if (map != NULL) 859 free(map, M_IPFW); 860 *ndel = n; 861 return (0); 862 } 863 864 static int 865 move_objects(struct ip_fw_chain *ch, ipfw_range_tlv *rt) 866 { 867 struct opcode_obj_rewrite *rw; 868 struct ip_fw *rule; 869 ipfw_insn *cmd; 870 uint32_t kidx; 871 int cmdlen, i, l, c; 872 873 IPFW_UH_WLOCK_ASSERT(ch); 874 875 /* Stage 1: count number of references by given rules */ 876 for (c = 0, i = 0; i < ch->n_rules - 1; i++) { 877 rule = ch->map[i]; 878 if (ipfw_match_range(rule, rt) == 0) 879 continue; 880 if (rule->set == rt->new_set) /* nothing to do */ 881 continue; 882 /* Search opcodes with named objects */ 883 for (l = rule->cmd_len, cmdlen = 0, cmd = rule->cmd; 884 l > 0; l -= cmdlen, cmd += cmdlen) { 885 cmdlen = F_LEN(cmd); 886 rw = find_op_rw(cmd, &kidx, NULL); 887 if (rw == NULL || rw->manage_sets == NULL) 888 continue; 889 /* 890 * When manage_sets() returns non-zero value to 891 * COUNT_ONE command, consider this as an object 892 * doesn't support sets (e.g. disabled with sysctl). 893 * So, skip checks for this object. 894 */ 895 if (rw->manage_sets(ch, kidx, 1, COUNT_ONE) != 0) 896 continue; 897 c++; 898 } 899 } 900 if (c == 0) /* No objects found */ 901 return (0); 902 /* Stage 2: verify "ownership" */ 903 for (c = 0, i = 0; (i < ch->n_rules - 1) && c == 0; i++) { 904 rule = ch->map[i]; 905 if (ipfw_match_range(rule, rt) == 0) 906 continue; 907 if (rule->set == rt->new_set) /* nothing to do */ 908 continue; 909 /* Search opcodes with named objects */ 910 for (l = rule->cmd_len, cmdlen = 0, cmd = rule->cmd; 911 l > 0 && c == 0; l -= cmdlen, cmd += cmdlen) { 912 cmdlen = F_LEN(cmd); 913 rw = find_op_rw(cmd, &kidx, NULL); 914 if (rw == NULL || rw->manage_sets == NULL) 915 continue; 916 /* Test for ownership and conflicting names */ 917 c = rw->manage_sets(ch, kidx, 918 (uint8_t)rt->new_set, TEST_ONE); 919 } 920 } 921 /* Stage 3: change set and cleanup */ 922 for (i = 0; i < ch->n_rules - 1; i++) { 923 rule = ch->map[i]; 924 if (ipfw_match_range(rule, rt) == 0) 925 continue; 926 if (rule->set == rt->new_set) /* nothing to do */ 927 continue; 928 /* Search opcodes with named objects */ 929 for (l = rule->cmd_len, cmdlen = 0, cmd = rule->cmd; 930 l > 0; l -= cmdlen, cmd += cmdlen) { 931 cmdlen = F_LEN(cmd); 932 rw = find_op_rw(cmd, &kidx, NULL); 933 if (rw == NULL || rw->manage_sets == NULL) 934 continue; 935 /* cleanup object counter */ 936 rw->manage_sets(ch, kidx, 937 0 /* reset counter */, COUNT_ONE); 938 if (c != 0) 939 continue; 940 /* change set */ 941 rw->manage_sets(ch, kidx, 942 (uint8_t)rt->new_set, MOVE_ONE); 943 } 944 } 945 return (c); 946 } 947 948 /* 949 * Changes set of given rule rannge @rt 950 * with each other. 951 * 952 * Returns 0 on success. 953 */ 954 static int 955 move_range(struct ip_fw_chain *chain, ipfw_range_tlv *rt) 956 { 957 struct ip_fw *rule; 958 int i; 959 960 IPFW_UH_WLOCK(chain); 961 962 /* 963 * Move rules with matching paramenerts to a new set. 964 * This one is much more complex. We have to ensure 965 * that all referenced tables (if any) are referenced 966 * by given rule subset only. Otherwise, we can't move 967 * them to new set and have to return error. 968 */ 969 if ((i = move_objects(chain, rt)) != 0) { 970 IPFW_UH_WUNLOCK(chain); 971 return (i); 972 } 973 974 /* XXX: We have to do swap holding WLOCK */ 975 for (i = 0; i < chain->n_rules; i++) { 976 rule = chain->map[i]; 977 if (ipfw_match_range(rule, rt) == 0) 978 continue; 979 rule->set = rt->new_set; 980 } 981 982 IPFW_UH_WUNLOCK(chain); 983 984 return (0); 985 } 986 987 /* 988 * Returns pointer to action instruction, skips all possible rule 989 * modifiers like O_LOG, O_TAG, O_ALTQ. 990 */ 991 ipfw_insn * 992 ipfw_get_action(struct ip_fw *rule) 993 { 994 ipfw_insn *cmd; 995 int l, cmdlen; 996 997 cmd = ACTION_PTR(rule); 998 l = rule->cmd_len - rule->act_ofs; 999 while (l > 0) { 1000 switch (cmd->opcode) { 1001 case O_ALTQ: 1002 case O_LOG: 1003 case O_TAG: 1004 break; 1005 default: 1006 return (cmd); 1007 } 1008 cmdlen = F_LEN(cmd); 1009 l -= cmdlen; 1010 cmd += cmdlen; 1011 } 1012 panic("%s: rule (%p) has not action opcode", __func__, rule); 1013 return (NULL); 1014 } 1015 1016 /* 1017 * Clear counters for a specific rule. 1018 * Normally run under IPFW_UH_RLOCK, but these are idempotent ops 1019 * so we only care that rules do not disappear. 1020 */ 1021 static void 1022 clear_counters(struct ip_fw *rule, int log_only) 1023 { 1024 ipfw_insn_log *l = (ipfw_insn_log *)ACTION_PTR(rule); 1025 1026 if (log_only == 0) 1027 IPFW_ZERO_RULE_COUNTER(rule); 1028 if (l->o.opcode == O_LOG) 1029 l->log_left = l->max_log; 1030 } 1031 1032 /* 1033 * Flushes rules counters and/or log values on matching range. 1034 * 1035 * Returns number of items cleared. 1036 */ 1037 static int 1038 clear_range(struct ip_fw_chain *chain, ipfw_range_tlv *rt, int log_only) 1039 { 1040 struct ip_fw *rule; 1041 int num; 1042 int i; 1043 1044 num = 0; 1045 rt->flags |= IPFW_RCFLAG_DEFAULT; 1046 1047 IPFW_UH_WLOCK(chain); /* arbitrate writers */ 1048 for (i = 0; i < chain->n_rules; i++) { 1049 rule = chain->map[i]; 1050 if (ipfw_match_range(rule, rt) == 0) 1051 continue; 1052 clear_counters(rule, log_only); 1053 num++; 1054 } 1055 IPFW_UH_WUNLOCK(chain); 1056 1057 return (num); 1058 } 1059 1060 static int 1061 check_range_tlv(ipfw_range_tlv *rt) 1062 { 1063 1064 if (rt->head.length != sizeof(*rt)) 1065 return (1); 1066 if (rt->start_rule > rt->end_rule) 1067 return (1); 1068 if (rt->set >= IPFW_MAX_SETS || rt->new_set >= IPFW_MAX_SETS) 1069 return (1); 1070 1071 if ((rt->flags & IPFW_RCFLAG_USER) != rt->flags) 1072 return (1); 1073 1074 return (0); 1075 } 1076 1077 /* 1078 * Delete rules matching specified parameters 1079 * Data layout (v0)(current): 1080 * Request: [ ipfw_obj_header ipfw_range_tlv ] 1081 * Reply: [ ipfw_obj_header ipfw_range_tlv ] 1082 * 1083 * Saves number of deleted rules in ipfw_range_tlv->new_set. 1084 * 1085 * Returns 0 on success. 1086 */ 1087 static int 1088 del_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 1089 struct sockopt_data *sd) 1090 { 1091 ipfw_range_header *rh; 1092 int error, ndel; 1093 1094 if (sd->valsize != sizeof(*rh)) 1095 return (EINVAL); 1096 1097 rh = (ipfw_range_header *)ipfw_get_sopt_space(sd, sd->valsize); 1098 1099 if (check_range_tlv(&rh->range) != 0) 1100 return (EINVAL); 1101 1102 ndel = 0; 1103 if ((error = delete_range(chain, &rh->range, &ndel)) != 0) 1104 return (error); 1105 1106 /* Save number of rules deleted */ 1107 rh->range.new_set = ndel; 1108 return (0); 1109 } 1110 1111 /* 1112 * Move rules/sets matching specified parameters 1113 * Data layout (v0)(current): 1114 * Request: [ ipfw_obj_header ipfw_range_tlv ] 1115 * 1116 * Returns 0 on success. 1117 */ 1118 static int 1119 move_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 1120 struct sockopt_data *sd) 1121 { 1122 ipfw_range_header *rh; 1123 1124 if (sd->valsize != sizeof(*rh)) 1125 return (EINVAL); 1126 1127 rh = (ipfw_range_header *)ipfw_get_sopt_space(sd, sd->valsize); 1128 1129 if (check_range_tlv(&rh->range) != 0) 1130 return (EINVAL); 1131 1132 return (move_range(chain, &rh->range)); 1133 } 1134 1135 /* 1136 * Clear rule accounting data matching specified parameters 1137 * Data layout (v0)(current): 1138 * Request: [ ipfw_obj_header ipfw_range_tlv ] 1139 * Reply: [ ipfw_obj_header ipfw_range_tlv ] 1140 * 1141 * Saves number of cleared rules in ipfw_range_tlv->new_set. 1142 * 1143 * Returns 0 on success. 1144 */ 1145 static int 1146 clear_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 1147 struct sockopt_data *sd) 1148 { 1149 ipfw_range_header *rh; 1150 int log_only, num; 1151 char *msg; 1152 1153 if (sd->valsize != sizeof(*rh)) 1154 return (EINVAL); 1155 1156 rh = (ipfw_range_header *)ipfw_get_sopt_space(sd, sd->valsize); 1157 1158 if (check_range_tlv(&rh->range) != 0) 1159 return (EINVAL); 1160 1161 log_only = (op3->opcode == IP_FW_XRESETLOG); 1162 1163 num = clear_range(chain, &rh->range, log_only); 1164 1165 if (rh->range.flags & IPFW_RCFLAG_ALL) 1166 msg = log_only ? "All logging counts reset" : 1167 "Accounting cleared"; 1168 else 1169 msg = log_only ? "logging count reset" : "cleared"; 1170 1171 if (V_fw_verbose) { 1172 int lev = LOG_SECURITY | LOG_NOTICE; 1173 log(lev, "ipfw: %s.\n", msg); 1174 } 1175 1176 /* Save number of rules cleared */ 1177 rh->range.new_set = num; 1178 return (0); 1179 } 1180 1181 static void 1182 enable_sets(struct ip_fw_chain *chain, ipfw_range_tlv *rt) 1183 { 1184 uint32_t v_set; 1185 1186 IPFW_UH_WLOCK_ASSERT(chain); 1187 1188 /* Change enabled/disabled sets mask */ 1189 v_set = (V_set_disable | rt->set) & ~rt->new_set; 1190 v_set &= ~(1 << RESVD_SET); /* set RESVD_SET always enabled */ 1191 IPFW_WLOCK(chain); 1192 V_set_disable = v_set; 1193 IPFW_WUNLOCK(chain); 1194 } 1195 1196 static int 1197 swap_sets(struct ip_fw_chain *chain, ipfw_range_tlv *rt, int mv) 1198 { 1199 struct opcode_obj_rewrite *rw; 1200 struct ip_fw *rule; 1201 int i; 1202 1203 IPFW_UH_WLOCK_ASSERT(chain); 1204 1205 if (rt->set == rt->new_set) /* nothing to do */ 1206 return (0); 1207 1208 if (mv != 0) { 1209 /* 1210 * Berfore moving the rules we need to check that 1211 * there aren't any conflicting named objects. 1212 */ 1213 for (rw = ctl3_rewriters; 1214 rw < ctl3_rewriters + ctl3_rsize; rw++) { 1215 if (rw->manage_sets == NULL) 1216 continue; 1217 i = rw->manage_sets(chain, (uint8_t)rt->set, 1218 (uint8_t)rt->new_set, TEST_ALL); 1219 if (i != 0) 1220 return (EEXIST); 1221 } 1222 } 1223 /* Swap or move two sets */ 1224 for (i = 0; i < chain->n_rules - 1; i++) { 1225 rule = chain->map[i]; 1226 if (rule->set == (uint8_t)rt->set) 1227 rule->set = (uint8_t)rt->new_set; 1228 else if (rule->set == (uint8_t)rt->new_set && mv == 0) 1229 rule->set = (uint8_t)rt->set; 1230 } 1231 for (rw = ctl3_rewriters; rw < ctl3_rewriters + ctl3_rsize; rw++) { 1232 if (rw->manage_sets == NULL) 1233 continue; 1234 rw->manage_sets(chain, (uint8_t)rt->set, 1235 (uint8_t)rt->new_set, mv != 0 ? MOVE_ALL: SWAP_ALL); 1236 } 1237 return (0); 1238 } 1239 1240 /* 1241 * Swaps or moves set 1242 * Data layout (v0)(current): 1243 * Request: [ ipfw_obj_header ipfw_range_tlv ] 1244 * 1245 * Returns 0 on success. 1246 */ 1247 static int 1248 manage_sets(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 1249 struct sockopt_data *sd) 1250 { 1251 ipfw_range_header *rh; 1252 int ret; 1253 1254 if (sd->valsize != sizeof(*rh)) 1255 return (EINVAL); 1256 1257 rh = (ipfw_range_header *)ipfw_get_sopt_space(sd, sd->valsize); 1258 1259 if (rh->range.head.length != sizeof(ipfw_range_tlv)) 1260 return (1); 1261 /* enable_sets() expects bitmasks. */ 1262 if (op3->opcode != IP_FW_SET_ENABLE && 1263 (rh->range.set >= IPFW_MAX_SETS || 1264 rh->range.new_set >= IPFW_MAX_SETS)) 1265 return (EINVAL); 1266 1267 ret = 0; 1268 IPFW_UH_WLOCK(chain); 1269 switch (op3->opcode) { 1270 case IP_FW_SET_SWAP: 1271 case IP_FW_SET_MOVE: 1272 ret = swap_sets(chain, &rh->range, 1273 op3->opcode == IP_FW_SET_MOVE); 1274 break; 1275 case IP_FW_SET_ENABLE: 1276 enable_sets(chain, &rh->range); 1277 break; 1278 } 1279 IPFW_UH_WUNLOCK(chain); 1280 1281 return (ret); 1282 } 1283 1284 /* Check rule format */ 1285 int 1286 ipfw_check_rule(struct ip_fw_rule *rule, size_t size, 1287 struct rule_check_info *ci) 1288 { 1289 int l; 1290 1291 if (size < sizeof(*rule)) { 1292 printf("ipfw: rule too short\n"); 1293 return (EINVAL); 1294 } 1295 1296 /* Check for valid cmd_len */ 1297 l = roundup2(RULESIZE(rule), sizeof(uint64_t)); 1298 if (l != size) { 1299 printf("ipfw: size mismatch (have %zu want %d)\n", size, l); 1300 return (EINVAL); 1301 } 1302 if (rule->act_ofs >= rule->cmd_len) { 1303 printf("ipfw: bogus action offset (%u > %u)\n", 1304 rule->act_ofs, rule->cmd_len - 1); 1305 return (EINVAL); 1306 } 1307 1308 if (rule->rulenum > IPFW_DEFAULT_RULE - 1) 1309 return (EINVAL); 1310 1311 return (check_ipfw_rule_body(rule->cmd, rule->cmd_len, ci)); 1312 } 1313 1314 #define CHECK_TARG(a, c) \ 1315 ((a) == IP_FW_TARG && ((c)->flags & IPFW_RCIFLAG_HAS_STATE)) 1316 1317 enum ipfw_opcheck_result 1318 ipfw_check_opcode(ipfw_insn **pcmd, int *plen, struct rule_check_info *ci) 1319 { 1320 ipfw_insn *cmd; 1321 size_t cmdlen; 1322 1323 cmd = *pcmd; 1324 cmdlen = F_LEN(cmd); 1325 1326 switch (cmd->opcode) { 1327 case O_PROBE_STATE: 1328 case O_KEEP_STATE: 1329 if (cmdlen != F_INSN_SIZE(ipfw_insn_kidx)) 1330 return (BAD_SIZE); 1331 ci->object_opcodes++; 1332 ci->flags |= IPFW_RCIFLAG_HAS_STATE; 1333 break; 1334 case O_PROTO: 1335 case O_IP_SRC_ME: 1336 case O_IP_DST_ME: 1337 case O_LAYER2: 1338 case O_IN: 1339 case O_FRAG: 1340 case O_DIVERTED: 1341 case O_IPOPT: 1342 case O_IPTOS: 1343 case O_IPPRECEDENCE: 1344 case O_IPVER: 1345 case O_SOCKARG: 1346 case O_TCPFLAGS: 1347 case O_TCPOPTS: 1348 case O_ESTAB: 1349 case O_VERREVPATH: 1350 case O_VERSRCREACH: 1351 case O_ANTISPOOF: 1352 case O_IPSEC: 1353 #ifdef INET6 1354 case O_IP6_SRC_ME: 1355 case O_IP6_DST_ME: 1356 case O_EXT_HDR: 1357 case O_IP6: 1358 #endif 1359 case O_IP4: 1360 case O_TAG: 1361 case O_SKIP_ACTION: 1362 if (cmdlen != F_INSN_SIZE(ipfw_insn)) 1363 return (BAD_SIZE); 1364 break; 1365 1366 case O_EXTERNAL_ACTION: 1367 if (cmdlen != F_INSN_SIZE(ipfw_insn_kidx)) 1368 return (BAD_SIZE); 1369 1370 if (insntod(cmd, kidx)->kidx == 0) 1371 return (FAILED); 1372 ci->object_opcodes++; 1373 /* 1374 * Do we have O_EXTERNAL_INSTANCE or O_EXTERNAL_DATA 1375 * opcode? 1376 */ 1377 if (*plen != cmdlen) { 1378 *plen -= cmdlen; 1379 cmd += cmdlen; 1380 *pcmd = cmd; 1381 cmdlen = F_LEN(cmd); 1382 if (cmd->opcode == O_EXTERNAL_DATA) 1383 return (CHECK_ACTION); 1384 if (cmd->opcode != O_EXTERNAL_INSTANCE) { 1385 printf("ipfw: invalid opcode " 1386 "next to external action %u\n", 1387 cmd->opcode); 1388 return (FAILED); 1389 } 1390 if (cmdlen != F_INSN_SIZE(ipfw_insn_kidx)) 1391 return (BAD_SIZE); 1392 if (insntod(cmd, kidx)->kidx == 0) 1393 return (FAILED); 1394 ci->object_opcodes++; 1395 } 1396 return (CHECK_ACTION); 1397 1398 case O_FIB: 1399 if (cmdlen != F_INSN_SIZE(ipfw_insn)) 1400 return (BAD_SIZE); 1401 if (cmd->arg1 >= rt_numfibs) { 1402 printf("ipfw: invalid fib number %d\n", 1403 cmd->arg1); 1404 return (FAILED); 1405 } 1406 break; 1407 1408 case O_SETFIB: 1409 if (cmdlen != F_INSN_SIZE(ipfw_insn)) 1410 return (BAD_SIZE); 1411 if ((cmd->arg1 != IP_FW_TARG) && 1412 ((cmd->arg1 & 0x7FFF) >= rt_numfibs)) { 1413 printf("ipfw: invalid fib number %d\n", 1414 cmd->arg1 & 0x7FFF); 1415 return (FAILED); 1416 } 1417 if (CHECK_TARG(cmd->arg1, ci)) 1418 goto bad_targ; 1419 return (CHECK_ACTION); 1420 1421 case O_UID: 1422 case O_GID: 1423 case O_JAIL: 1424 case O_IP_SRC: 1425 case O_IP_DST: 1426 case O_TCPSEQ: 1427 case O_TCPACK: 1428 case O_PROB: 1429 case O_ICMPTYPE: 1430 if (cmdlen != F_INSN_SIZE(ipfw_insn_u32)) 1431 return (BAD_SIZE); 1432 break; 1433 1434 case O_LIMIT: 1435 if (cmdlen != F_INSN_SIZE(ipfw_insn_limit)) 1436 return (BAD_SIZE); 1437 ci->object_opcodes++; 1438 break; 1439 1440 case O_LOG: 1441 if (cmdlen != F_INSN_SIZE(ipfw_insn_log)) 1442 return (BAD_SIZE); 1443 insntod(cmd, log)->log_left = insntod(cmd, log)->max_log; 1444 break; 1445 1446 case O_IP_SRC_MASK: 1447 case O_IP_DST_MASK: 1448 /* only odd command lengths */ 1449 if ((cmdlen & 1) == 0) 1450 return (BAD_SIZE); 1451 break; 1452 1453 case O_IP_SRC_SET: 1454 case O_IP_DST_SET: 1455 if (cmd->arg1 == 0 || cmd->arg1 > 256) { 1456 printf("ipfw: invalid set size %d\n", 1457 cmd->arg1); 1458 return (FAILED); 1459 } 1460 if (cmdlen != F_INSN_SIZE(ipfw_insn_u32) + 1461 (cmd->arg1+31)/32 ) 1462 return (BAD_SIZE); 1463 break; 1464 1465 case O_IP_SRC_LOOKUP: 1466 case O_IP_DST_LOOKUP: 1467 case O_IP_FLOW_LOOKUP: 1468 case O_MAC_SRC_LOOKUP: 1469 case O_MAC_DST_LOOKUP: 1470 if (cmdlen != F_INSN_SIZE(ipfw_insn_kidx) && 1471 cmdlen != F_INSN_SIZE(ipfw_insn_table)) 1472 return (BAD_SIZE); 1473 if (insntod(cmd, kidx)->kidx >= V_fw_tables_max) { 1474 printf("ipfw: invalid table index %u\n", 1475 insntod(cmd, kidx)->kidx); 1476 return (FAILED); 1477 } 1478 ci->object_opcodes++; 1479 break; 1480 case O_MACADDR2: 1481 if (cmdlen != F_INSN_SIZE(ipfw_insn_mac)) 1482 return (BAD_SIZE); 1483 break; 1484 1485 case O_NOP: 1486 case O_IPID: 1487 case O_IPTTL: 1488 case O_IPLEN: 1489 case O_TCPDATALEN: 1490 case O_TCPMSS: 1491 case O_TCPWIN: 1492 case O_TAGGED: 1493 if (cmdlen < 1 || cmdlen > 31) 1494 return (BAD_SIZE); 1495 break; 1496 1497 case O_DSCP: 1498 case O_MARK: 1499 if (cmdlen != F_INSN_SIZE(ipfw_insn_u32) + 1) 1500 return (BAD_SIZE); 1501 break; 1502 1503 case O_MAC_TYPE: 1504 case O_IP_SRCPORT: 1505 case O_IP_DSTPORT: /* XXX artificial limit, 30 port pairs */ 1506 if (cmdlen < 2 || cmdlen > 31) 1507 return (BAD_SIZE); 1508 break; 1509 1510 case O_RECV: 1511 case O_XMIT: 1512 case O_VIA: 1513 if (cmdlen != F_INSN_SIZE(ipfw_insn_if)) 1514 return (BAD_SIZE); 1515 ci->object_opcodes++; 1516 break; 1517 1518 case O_ALTQ: 1519 if (cmdlen != F_INSN_SIZE(ipfw_insn_altq)) 1520 return (BAD_SIZE); 1521 break; 1522 1523 case O_PIPE: 1524 case O_QUEUE: 1525 if (cmdlen != F_INSN_SIZE(ipfw_insn)) 1526 return (BAD_SIZE); 1527 if (CHECK_TARG(cmd->arg1, ci)) 1528 goto bad_targ; 1529 return (CHECK_ACTION); 1530 1531 case O_FORWARD_IP: 1532 if (cmdlen != F_INSN_SIZE(ipfw_insn_sa)) 1533 return (BAD_SIZE); 1534 if (insntoc(cmd, sa)->sa.sin_addr.s_addr == INADDR_ANY && 1535 (ci->flags & IPFW_RCIFLAG_HAS_STATE)) 1536 goto bad_targ; 1537 return (CHECK_ACTION); 1538 #ifdef INET6 1539 case O_FORWARD_IP6: 1540 if (cmdlen != F_INSN_SIZE(ipfw_insn_sa6)) 1541 return (BAD_SIZE); 1542 return (CHECK_ACTION); 1543 #endif /* INET6 */ 1544 1545 case O_DIVERT: 1546 case O_TEE: 1547 if (ip_divert_ptr == NULL) 1548 return (FAILED); 1549 if (cmdlen != F_INSN_SIZE(ipfw_insn)) 1550 return (BAD_SIZE); 1551 if (CHECK_TARG(cmd->arg1, ci)) 1552 goto bad_targ; 1553 return (CHECK_ACTION); 1554 case O_NETGRAPH: 1555 case O_NGTEE: 1556 if (ng_ipfw_input_p == NULL) 1557 return (FAILED); 1558 if (cmdlen != F_INSN_SIZE(ipfw_insn)) 1559 return (BAD_SIZE); 1560 if (CHECK_TARG(cmd->arg1, ci)) 1561 goto bad_targ; 1562 return (CHECK_ACTION); 1563 case O_NAT: 1564 if (!IPFW_NAT_LOADED) 1565 return (FAILED); 1566 if (cmdlen != F_INSN_SIZE(ipfw_insn_nat)) 1567 return (BAD_SIZE); 1568 if (CHECK_TARG(cmd->arg1, ci)) 1569 goto bad_targ; 1570 return (CHECK_ACTION); 1571 1572 case O_SKIPTO: 1573 case O_CALLRETURN: 1574 case O_SETMARK: 1575 if (cmdlen != F_INSN_SIZE(ipfw_insn_u32)) 1576 return (BAD_SIZE); 1577 /* O_CALLRETURN + F_NOT means 'return' opcode. */ 1578 if (cmd->opcode != O_CALLRETURN || (cmd->len & F_NOT) == 0) { 1579 if (CHECK_TARG(insntoc(cmd, u32)->d[0], ci)) 1580 goto bad_targ; 1581 } 1582 return (CHECK_ACTION); 1583 1584 case O_CHECK_STATE: 1585 if (cmdlen != F_INSN_SIZE(ipfw_insn_kidx)) 1586 return (BAD_SIZE); 1587 ci->object_opcodes++; 1588 return (CHECK_ACTION); 1589 1590 case O_FORWARD_MAC: /* XXX not implemented yet */ 1591 case O_COUNT: 1592 case O_ACCEPT: 1593 case O_DENY: 1594 case O_REJECT: 1595 case O_SETDSCP: 1596 #ifdef INET6 1597 case O_UNREACH6: 1598 #endif 1599 case O_REASS: 1600 if (cmdlen != F_INSN_SIZE(ipfw_insn)) 1601 return (BAD_SIZE); 1602 if (cmd->opcode == O_SETDSCP && CHECK_TARG(cmd->arg1, ci)) 1603 goto bad_targ; 1604 return (CHECK_ACTION); 1605 #ifdef INET6 1606 case O_IP6_SRC: 1607 case O_IP6_DST: 1608 if (cmdlen != F_INSN_SIZE(struct in6_addr) + 1609 F_INSN_SIZE(ipfw_insn)) 1610 return (BAD_SIZE); 1611 break; 1612 1613 case O_FLOW6ID: 1614 if (cmdlen != F_INSN_SIZE(ipfw_insn_u32) + 1615 ((ipfw_insn_u32 *)cmd)->o.arg1) 1616 return (BAD_SIZE); 1617 break; 1618 1619 case O_IP6_SRC_MASK: 1620 case O_IP6_DST_MASK: 1621 if ( !(cmdlen & 1) || cmdlen > 127) 1622 return (BAD_SIZE); 1623 break; 1624 case O_ICMP6TYPE: 1625 if( cmdlen != F_INSN_SIZE( ipfw_insn_icmp6 ) ) 1626 return (BAD_SIZE); 1627 break; 1628 #endif 1629 1630 default: 1631 switch (cmd->opcode) { 1632 #ifndef INET6 1633 case O_IP6_SRC_ME: 1634 case O_IP6_DST_ME: 1635 case O_EXT_HDR: 1636 case O_IP6: 1637 case O_UNREACH6: 1638 case O_IP6_SRC: 1639 case O_IP6_DST: 1640 case O_FLOW6ID: 1641 case O_IP6_SRC_MASK: 1642 case O_IP6_DST_MASK: 1643 case O_ICMP6TYPE: 1644 printf("ipfw: no IPv6 support in kernel\n"); 1645 return (FAILED); 1646 #endif 1647 default: 1648 printf("ipfw: opcode %d: unknown opcode\n", 1649 cmd->opcode); 1650 return (FAILED); 1651 } 1652 } 1653 return (SUCCESS); 1654 bad_targ: 1655 /* 1656 * For dynamic states we can not correctly initialize tablearg value, 1657 * because we don't go through rule's opcodes except rule action. 1658 */ 1659 printf("ipfw: tablearg is not allowed with dynamic states\n"); 1660 return (FAILED); 1661 } 1662 1663 static __noinline int 1664 check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci) 1665 { 1666 int cmdlen, l; 1667 int have_action, ret; 1668 1669 /* 1670 * Now go for the individual checks. Very simple ones, basically only 1671 * instruction sizes. 1672 */ 1673 have_action = 0; 1674 for (l = cmd_len; l > 0 ; l -= cmdlen, cmd += cmdlen) { 1675 cmdlen = F_LEN(cmd); 1676 if (cmdlen > l) { 1677 printf("ipfw: opcode %d: size truncated\n", 1678 cmd->opcode); 1679 return (EINVAL); 1680 } 1681 if (ci->version != IP_FW3_OPVER) 1682 ret = (*check_opcode_f)(&cmd, &l, ci); 1683 else 1684 ret = ipfw_check_opcode(&cmd, &l, ci); 1685 1686 if (ret == CHECK_ACTION) { 1687 if (have_action != 0) { 1688 printf("ipfw: opcode %d: multiple actions" 1689 " not allowed\n", cmd->opcode); 1690 ret = FAILED; 1691 } else 1692 have_action = 1; 1693 1694 if (l != F_LEN(cmd)) { 1695 printf("ipfw: opcode %d: action must be" 1696 " last opcode\n", cmd->opcode); 1697 ret = FAILED; 1698 } 1699 } 1700 switch (ret) { 1701 case SUCCESS: 1702 continue; 1703 case BAD_SIZE: 1704 printf("ipfw: opcode %d: wrong size %d\n", 1705 cmd->opcode, cmdlen); 1706 /* FALLTHROUGH */ 1707 case FAILED: 1708 return (EINVAL); 1709 } 1710 } 1711 if (have_action == 0) { 1712 printf("ipfw: missing action\n"); 1713 return (EINVAL); 1714 } 1715 return (0); 1716 } 1717 1718 struct dump_args { 1719 uint32_t b; /* start rule */ 1720 uint32_t e; /* end rule */ 1721 uint32_t rcount; /* number of rules */ 1722 uint32_t rsize; /* rules size */ 1723 uint32_t tcount; /* number of tables */ 1724 int rcounters; /* counters */ 1725 uint32_t *bmask; /* index bitmask of used named objects */ 1726 }; 1727 1728 void 1729 ipfw_export_obj_ntlv(struct named_object *no, ipfw_obj_ntlv *ntlv) 1730 { 1731 1732 ntlv->head.type = no->etlv; 1733 ntlv->head.length = sizeof(*ntlv); 1734 ntlv->idx = no->kidx; 1735 strlcpy(ntlv->name, no->name, sizeof(ntlv->name)); 1736 } 1737 1738 /* 1739 * Export named object info in instance @ni, identified by @kidx 1740 * to ipfw_obj_ntlv. TLV is allocated from @sd space. 1741 * 1742 * Returns 0 on success. 1743 */ 1744 static int 1745 export_objhash_ntlv(struct namedobj_instance *ni, uint32_t kidx, 1746 struct sockopt_data *sd) 1747 { 1748 struct named_object *no; 1749 ipfw_obj_ntlv *ntlv; 1750 1751 no = ipfw_objhash_lookup_kidx(ni, kidx); 1752 KASSERT(no != NULL, ("invalid object kernel index passed")); 1753 1754 ntlv = (ipfw_obj_ntlv *)ipfw_get_sopt_space(sd, sizeof(*ntlv)); 1755 if (ntlv == NULL) 1756 return (ENOMEM); 1757 1758 ipfw_export_obj_ntlv(no, ntlv); 1759 return (0); 1760 } 1761 1762 static int 1763 export_named_objects(struct namedobj_instance *ni, struct dump_args *da, 1764 struct sockopt_data *sd) 1765 { 1766 uint32_t i; 1767 int error; 1768 1769 for (i = 0; i < IPFW_TABLES_MAX && da->tcount > 0; i++) { 1770 if ((da->bmask[i / 32] & (1 << (i % 32))) == 0) 1771 continue; 1772 if ((error = export_objhash_ntlv(ni, i, sd)) != 0) 1773 return (error); 1774 da->tcount--; 1775 } 1776 return (0); 1777 } 1778 1779 static int 1780 dump_named_objects(struct ip_fw_chain *ch, struct dump_args *da, 1781 struct sockopt_data *sd) 1782 { 1783 ipfw_obj_ctlv *ctlv; 1784 int error; 1785 1786 MPASS(da->tcount > 0); 1787 /* Header first */ 1788 ctlv = (ipfw_obj_ctlv *)ipfw_get_sopt_space(sd, sizeof(*ctlv)); 1789 if (ctlv == NULL) 1790 return (ENOMEM); 1791 ctlv->head.type = IPFW_TLV_TBLNAME_LIST; 1792 ctlv->head.length = da->tcount * sizeof(ipfw_obj_ntlv) + 1793 sizeof(*ctlv); 1794 ctlv->count = da->tcount; 1795 ctlv->objsize = sizeof(ipfw_obj_ntlv); 1796 1797 /* Dump table names first (if any) */ 1798 error = export_named_objects(ipfw_get_table_objhash(ch), da, sd); 1799 if (error != 0) 1800 return (error); 1801 /* Then dump another named objects */ 1802 da->bmask += IPFW_TABLES_MAX / 32; 1803 return (export_named_objects(CHAIN_TO_SRV(ch), da, sd)); 1804 } 1805 1806 /* 1807 * Dumps static rules with table TLVs in buffer @sd. 1808 * 1809 * Returns 0 on success. 1810 */ 1811 static int 1812 dump_static_rules(struct ip_fw_chain *chain, struct dump_args *da, 1813 struct sockopt_data *sd) 1814 { 1815 ipfw_obj_ctlv *ctlv; 1816 struct ip_fw *krule; 1817 caddr_t dst; 1818 int i, l; 1819 1820 /* Dump rules */ 1821 ctlv = (ipfw_obj_ctlv *)ipfw_get_sopt_space(sd, sizeof(*ctlv)); 1822 if (ctlv == NULL) 1823 return (ENOMEM); 1824 ctlv->head.type = IPFW_TLV_RULE_LIST; 1825 ctlv->head.length = da->rsize + sizeof(*ctlv); 1826 ctlv->count = da->rcount; 1827 1828 for (i = da->b; i < da->e; i++) { 1829 krule = chain->map[i]; 1830 1831 l = RULEUSIZE1(krule) + sizeof(ipfw_obj_tlv); 1832 if (da->rcounters != 0) 1833 l += sizeof(struct ip_fw_bcounter); 1834 dst = (caddr_t)ipfw_get_sopt_space(sd, l); 1835 if (dst == NULL) 1836 return (ENOMEM); 1837 1838 export_rule1(krule, dst, l, da->rcounters); 1839 } 1840 1841 return (0); 1842 } 1843 1844 int 1845 ipfw_mark_object_kidx(uint32_t *bmask, uint16_t etlv, uint32_t kidx) 1846 { 1847 uint32_t bidx; 1848 1849 /* 1850 * Maintain separate bitmasks for table and non-table objects. 1851 */ 1852 bidx = (etlv == IPFW_TLV_TBL_NAME) ? 0: IPFW_TABLES_MAX / 32; 1853 bidx += kidx / 32; 1854 if ((bmask[bidx] & (1 << (kidx % 32))) != 0) 1855 return (0); 1856 1857 bmask[bidx] |= 1 << (kidx % 32); 1858 return (1); 1859 } 1860 1861 /* 1862 * Marks every object index used in @rule with bit in @bmask. 1863 * Used to generate bitmask of referenced tables/objects for given ruleset 1864 * or its part. 1865 */ 1866 static void 1867 mark_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule, 1868 struct dump_args *da) 1869 { 1870 struct opcode_obj_rewrite *rw; 1871 ipfw_insn *cmd; 1872 uint32_t kidx; 1873 int cmdlen, l; 1874 uint8_t subtype; 1875 1876 l = rule->cmd_len; 1877 cmd = rule->cmd; 1878 cmdlen = 0; 1879 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { 1880 cmdlen = F_LEN(cmd); 1881 1882 rw = find_op_rw(cmd, &kidx, &subtype); 1883 if (rw == NULL) 1884 continue; 1885 1886 if (ipfw_mark_object_kidx(da->bmask, rw->etlv, kidx)) 1887 da->tcount++; 1888 } 1889 } 1890 1891 /* 1892 * Dumps requested objects data 1893 * Data layout (version 0)(current): 1894 * Request: [ ipfw_cfg_lheader ] + IPFW_CFG_GET_* flags 1895 * size = ipfw_cfg_lheader.size 1896 * Reply: [ ipfw_cfg_lheader 1897 * [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional) 1898 * [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) 1899 * ipfw_obj_tlv(IPFW_TLV_RULE_ENT) [ ip_fw_bcounter (optional) ip_fw_rule ] 1900 * ] (optional) 1901 * [ ipfw_obj_ctlv(IPFW_TLV_STATE_LIST) ipfw_obj_dyntlv x N ] (optional) 1902 * ] 1903 * * NOTE IPFW_TLV_STATE_LIST has the single valid field: objsize. 1904 * The rest (size, count) are set to zero and needs to be ignored. 1905 * 1906 * Returns 0 on success. 1907 */ 1908 static int 1909 dump_config(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 1910 struct sockopt_data *sd) 1911 { 1912 struct dump_args da; 1913 ipfw_cfg_lheader *hdr; 1914 struct ip_fw *rule; 1915 size_t sz, rnum; 1916 uint32_t hdr_flags, *bmask; 1917 int error, i; 1918 1919 hdr = (ipfw_cfg_lheader *)ipfw_get_sopt_header(sd, sizeof(*hdr)); 1920 if (hdr == NULL) 1921 return (EINVAL); 1922 1923 error = 0; 1924 bmask = NULL; 1925 memset(&da, 0, sizeof(da)); 1926 /* 1927 * Allocate needed state. 1928 * Note we allocate 2xspace mask, for table & srv 1929 */ 1930 if (hdr->flags & (IPFW_CFG_GET_STATIC | IPFW_CFG_GET_STATES)) 1931 da.bmask = bmask = malloc( 1932 sizeof(uint32_t) * IPFW_TABLES_MAX * 2 / 32, M_TEMP, 1933 M_WAITOK | M_ZERO); 1934 IPFW_UH_RLOCK(chain); 1935 1936 /* 1937 * STAGE 1: Determine size/count for objects in range. 1938 * Prepare used tables bitmask. 1939 */ 1940 sz = sizeof(ipfw_cfg_lheader); 1941 da.e = chain->n_rules; 1942 1943 if (hdr->end_rule != 0) { 1944 /* Handle custom range */ 1945 if ((rnum = hdr->start_rule) > IPFW_DEFAULT_RULE) 1946 rnum = IPFW_DEFAULT_RULE; 1947 da.b = ipfw_find_rule(chain, rnum, 0); 1948 rnum = (hdr->end_rule < IPFW_DEFAULT_RULE) ? 1949 hdr->end_rule + 1: IPFW_DEFAULT_RULE; 1950 da.e = ipfw_find_rule(chain, rnum, UINT32_MAX) + 1; 1951 } 1952 1953 if (hdr->flags & IPFW_CFG_GET_STATIC) { 1954 for (i = da.b; i < da.e; i++) { 1955 rule = chain->map[i]; 1956 da.rsize += RULEUSIZE1(rule) + sizeof(ipfw_obj_tlv); 1957 da.rcount++; 1958 /* Update bitmask of used objects for given range */ 1959 mark_rule_objects(chain, rule, &da); 1960 } 1961 /* Add counters if requested */ 1962 if (hdr->flags & IPFW_CFG_GET_COUNTERS) { 1963 da.rsize += sizeof(struct ip_fw_bcounter) * da.rcount; 1964 da.rcounters = 1; 1965 } 1966 sz += da.rsize + sizeof(ipfw_obj_ctlv); 1967 } 1968 1969 if (hdr->flags & IPFW_CFG_GET_STATES) { 1970 sz += sizeof(ipfw_obj_ctlv) + 1971 ipfw_dyn_get_count(bmask, &i) * sizeof(ipfw_obj_dyntlv); 1972 da.tcount += i; 1973 } 1974 1975 if (da.tcount > 0) 1976 sz += da.tcount * sizeof(ipfw_obj_ntlv) + 1977 sizeof(ipfw_obj_ctlv); 1978 1979 /* 1980 * Fill header anyway. 1981 * Note we have to save header fields to stable storage 1982 * buffer inside @sd can be flushed after dumping rules 1983 */ 1984 hdr->size = sz; 1985 hdr->set_mask = ~V_set_disable; 1986 hdr_flags = hdr->flags; 1987 hdr = NULL; 1988 1989 if (sd->valsize < sz) { 1990 error = ENOMEM; 1991 goto cleanup; 1992 } 1993 1994 /* STAGE2: Store actual data */ 1995 if (da.tcount > 0) { 1996 error = dump_named_objects(chain, &da, sd); 1997 if (error != 0) 1998 goto cleanup; 1999 } 2000 2001 if (hdr_flags & IPFW_CFG_GET_STATIC) { 2002 error = dump_static_rules(chain, &da, sd); 2003 if (error != 0) 2004 goto cleanup; 2005 } 2006 2007 if (hdr_flags & IPFW_CFG_GET_STATES) 2008 error = ipfw_dump_states(chain, sd); 2009 2010 cleanup: 2011 IPFW_UH_RUNLOCK(chain); 2012 2013 if (bmask != NULL) 2014 free(bmask, M_TEMP); 2015 2016 return (error); 2017 } 2018 2019 int 2020 ipfw_check_object_name_generic(const char *name) 2021 { 2022 int nsize; 2023 2024 nsize = sizeof(((ipfw_obj_ntlv *)0)->name); 2025 if (strnlen(name, nsize) == nsize) 2026 return (EINVAL); 2027 if (name[0] == '\0') 2028 return (EINVAL); 2029 return (0); 2030 } 2031 2032 /* 2033 * Creates non-existent objects referenced by rule. 2034 * 2035 * Return 0 on success. 2036 */ 2037 int 2038 create_objects_compat(struct ip_fw_chain *ch, ipfw_insn *cmd, 2039 struct obj_idx *oib, struct obj_idx *pidx, struct tid_info *ti) 2040 { 2041 struct opcode_obj_rewrite *rw; 2042 struct obj_idx *p; 2043 uint32_t kidx; 2044 int error; 2045 2046 /* 2047 * Compatibility stuff: do actual creation for non-existing, 2048 * but referenced objects. 2049 */ 2050 for (p = oib; p < pidx; p++) { 2051 if (p->kidx != 0) 2052 continue; 2053 2054 ti->uidx = p->uidx; 2055 ti->type = p->type; 2056 ti->atype = 0; 2057 2058 rw = find_op_rw(cmd + p->off, NULL, NULL); 2059 KASSERT(rw != NULL, ("Unable to find handler for op %d", 2060 (cmd + p->off)->opcode)); 2061 2062 if (rw->create_object == NULL) 2063 error = EOPNOTSUPP; 2064 else 2065 error = rw->create_object(ch, ti, &kidx); 2066 if (error == 0) { 2067 p->kidx = kidx; 2068 continue; 2069 } 2070 2071 /* 2072 * Error happened. We have to rollback everything. 2073 * Drop all already acquired references. 2074 */ 2075 IPFW_UH_WLOCK(ch); 2076 unref_oib_objects(ch, cmd, oib, pidx); 2077 IPFW_UH_WUNLOCK(ch); 2078 2079 return (error); 2080 } 2081 2082 return (0); 2083 } 2084 2085 /* 2086 * Unreferences all already-referenced objects in given @cmd rule, 2087 * using information in @oib. 2088 * 2089 * Used to rollback partially converted rule on error. 2090 */ 2091 static void 2092 unref_oib_objects(struct ip_fw_chain *ch, ipfw_insn *cmd, struct obj_idx *oib, 2093 struct obj_idx *end) 2094 { 2095 struct opcode_obj_rewrite *rw; 2096 struct named_object *no; 2097 struct obj_idx *p; 2098 2099 IPFW_UH_WLOCK_ASSERT(ch); 2100 2101 for (p = oib; p < end; p++) { 2102 if (p->kidx == 0) 2103 continue; 2104 2105 rw = find_op_rw(cmd + p->off, NULL, NULL); 2106 KASSERT(rw != NULL, ("Unable to find handler for op %d", 2107 (cmd + p->off)->opcode)); 2108 2109 /* Find & unref by existing idx */ 2110 no = rw->find_bykidx(ch, p->kidx); 2111 KASSERT(no != NULL, ("Ref'd object %d disappeared", p->kidx)); 2112 no->refcnt--; 2113 } 2114 } 2115 2116 /* 2117 * Remove references from every object used in @rule. 2118 * Used at rule removal code. 2119 */ 2120 static void 2121 unref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule) 2122 { 2123 struct opcode_obj_rewrite *rw; 2124 struct named_object *no; 2125 ipfw_insn *cmd; 2126 uint32_t kidx; 2127 int cmdlen, l; 2128 uint8_t subtype; 2129 2130 IPFW_UH_WLOCK_ASSERT(ch); 2131 2132 l = rule->cmd_len; 2133 cmd = rule->cmd; 2134 cmdlen = 0; 2135 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { 2136 cmdlen = F_LEN(cmd); 2137 2138 rw = find_op_rw(cmd, &kidx, &subtype); 2139 if (rw == NULL) 2140 continue; 2141 no = rw->find_bykidx(ch, kidx); 2142 2143 KASSERT(no != NULL, ("object id %d not found", kidx)); 2144 KASSERT(no->subtype == subtype, 2145 ("wrong type %d (%d) for object id %d", 2146 no->subtype, subtype, kidx)); 2147 KASSERT(no->refcnt > 0, ("refcount for object %d is %d", 2148 kidx, no->refcnt)); 2149 2150 if (no->refcnt == 1 && rw->destroy_object != NULL) 2151 rw->destroy_object(ch, no); 2152 else 2153 no->refcnt--; 2154 } 2155 } 2156 2157 /* 2158 * Find and reference object (if any) stored in instruction @cmd. 2159 * 2160 * Saves object info in @pidx, sets 2161 * - @unresolved to 1 if object should exists but not found 2162 * 2163 * Returns non-zero value in case of error. 2164 */ 2165 static int 2166 ref_opcode_object(struct ip_fw_chain *ch, ipfw_insn *cmd, struct tid_info *ti, 2167 struct obj_idx *pidx, int *unresolved) 2168 { 2169 struct named_object *no; 2170 struct opcode_obj_rewrite *rw; 2171 int error; 2172 2173 /* Check if this opcode is candidate for rewrite */ 2174 rw = find_op_rw(cmd, &ti->uidx, &ti->type); 2175 if (rw == NULL) 2176 return (0); 2177 2178 /* Need to rewrite. Save necessary fields */ 2179 pidx->uidx = ti->uidx; 2180 pidx->type = ti->type; 2181 2182 /* Try to find referenced kernel object */ 2183 error = rw->find_byname(ch, ti, &no); 2184 if (error != 0) 2185 return (error); 2186 if (no == NULL) { 2187 /* 2188 * Report about unresolved object for automaic 2189 * creation. 2190 */ 2191 *unresolved = 1; 2192 return (0); 2193 } 2194 2195 /* 2196 * Object is already exist. 2197 * Its subtype should match with expected value. 2198 */ 2199 if (ti->type != no->subtype) 2200 return (EINVAL); 2201 2202 /* Bump refcount and update kidx. */ 2203 no->refcnt++; 2204 rw->update(cmd, no->kidx); 2205 return (0); 2206 } 2207 2208 /* 2209 * Finds and bumps refcount for objects referenced by given @rule. 2210 * Auto-creates non-existing tables. 2211 * Fills in @oib array with userland/kernel indexes. 2212 * 2213 * Returns 0 on success. 2214 */ 2215 static int 2216 ref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule, 2217 struct rule_check_info *ci, struct obj_idx *oib, struct tid_info *ti) 2218 { 2219 struct obj_idx *pidx; 2220 ipfw_insn *cmd; 2221 int cmdlen, error, l, unresolved; 2222 2223 pidx = oib; 2224 l = rule->cmd_len; 2225 cmd = rule->cmd; 2226 cmdlen = 0; 2227 error = 0; 2228 2229 IPFW_UH_WLOCK(ch); 2230 2231 /* Increase refcount on each existing referenced table. */ 2232 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { 2233 cmdlen = F_LEN(cmd); 2234 unresolved = 0; 2235 2236 error = ref_opcode_object(ch, cmd, ti, pidx, &unresolved); 2237 if (error != 0) 2238 break; 2239 /* 2240 * Compatibility stuff for old clients: 2241 * prepare to automaitcally create non-existing objects. 2242 */ 2243 if (unresolved != 0) { 2244 pidx->off = rule->cmd_len - l; 2245 pidx++; 2246 } 2247 } 2248 2249 if (error != 0) { 2250 /* Unref everything we have already done */ 2251 unref_oib_objects(ch, rule->cmd, oib, pidx); 2252 IPFW_UH_WUNLOCK(ch); 2253 return (error); 2254 } 2255 IPFW_UH_WUNLOCK(ch); 2256 2257 /* Perform auto-creation for non-existing objects */ 2258 if (pidx != oib) 2259 error = create_objects_compat(ch, rule->cmd, oib, pidx, ti); 2260 2261 /* Calculate real number of dynamic objects */ 2262 ci->object_opcodes = (uint16_t)(pidx - oib); 2263 2264 return (error); 2265 } 2266 2267 /* 2268 * Checks is opcode is referencing table of appropriate type. 2269 * Adds reference count for found table if true. 2270 * Rewrites user-supplied opcode values with kernel ones. 2271 * 2272 * Returns 0 on success and appropriate error code otherwise. 2273 */ 2274 static int 2275 rewrite_rule_uidx(struct ip_fw_chain *chain, struct rule_check_info *ci) 2276 { 2277 int error; 2278 ipfw_insn *cmd; 2279 struct obj_idx *p, *pidx_first, *pidx_last; 2280 struct tid_info ti; 2281 2282 /* 2283 * Prepare an array for storing opcode indices. 2284 * Use stack allocation by default. 2285 */ 2286 if (ci->object_opcodes <= (sizeof(ci->obuf)/sizeof(ci->obuf[0]))) { 2287 /* Stack */ 2288 pidx_first = ci->obuf; 2289 } else 2290 pidx_first = malloc( 2291 ci->object_opcodes * sizeof(struct obj_idx), 2292 M_IPFW, M_WAITOK | M_ZERO); 2293 2294 error = 0; 2295 memset(&ti, 0, sizeof(ti)); 2296 2297 /* Use set rule is assigned to. */ 2298 ti.set = ci->krule->set; 2299 if (ci->ctlv != NULL) { 2300 ti.tlvs = (void *)(ci->ctlv + 1); 2301 ti.tlen = ci->ctlv->head.length - sizeof(ipfw_obj_ctlv); 2302 } 2303 2304 /* Reference all used tables and other objects */ 2305 error = ref_rule_objects(chain, ci->krule, ci, pidx_first, &ti); 2306 if (error != 0) 2307 goto free; 2308 /* 2309 * Note that ref_rule_objects() might have updated ci->object_opcodes 2310 * to reflect actual number of object opcodes. 2311 */ 2312 2313 /* Perform rewrite of remaining opcodes */ 2314 p = pidx_first; 2315 pidx_last = pidx_first + ci->object_opcodes; 2316 for (p = pidx_first; p < pidx_last; p++) { 2317 cmd = ci->krule->cmd + p->off; 2318 update_opcode_kidx(cmd, p->kidx); 2319 } 2320 2321 free: 2322 if (pidx_first != ci->obuf) 2323 free(pidx_first, M_IPFW); 2324 2325 return (error); 2326 } 2327 2328 /* 2329 * Parses one or more rules from userland. 2330 * Data layout (version 1)(current): 2331 * Request: 2332 * [ 2333 * ip_fw3_opheader 2334 * [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional *1) 2335 * [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) ip_fw x N ] (*2) (*3) 2336 * ] 2337 * Reply: 2338 * [ 2339 * ip_fw3_opheader 2340 * [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional) 2341 * [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) ip_fw x N ] 2342 * ] 2343 * 2344 * Rules in reply are modified to store their actual ruleset number. 2345 * 2346 * (*1) TLVs inside IPFW_TLV_TBL_LIST needs to be sorted ascending 2347 * according to their idx field and there has to be no duplicates. 2348 * (*2) Numbered rules inside IPFW_TLV_RULE_LIST needs to be sorted ascending. 2349 * (*3) Each ip_fw structure needs to be aligned to u64 boundary. 2350 * 2351 * Returns 0 on success. 2352 */ 2353 static __noinline int 2354 parse_rules_v1(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 2355 struct sockopt_data *sd, ipfw_obj_ctlv **prtlv, 2356 struct rule_check_info **pci) 2357 { 2358 ipfw_obj_ctlv *ctlv, *rtlv, *tstate; 2359 ipfw_obj_ntlv *ntlv; 2360 struct rule_check_info *ci, *cbuf; 2361 struct ip_fw_rule *r; 2362 size_t count, clen, read, rsize; 2363 uint32_t idx, rulenum; 2364 int error; 2365 2366 op3 = (ip_fw3_opheader *)ipfw_get_sopt_space(sd, sd->valsize); 2367 ctlv = (ipfw_obj_ctlv *)(op3 + 1); 2368 read = sizeof(ip_fw3_opheader); 2369 if (read + sizeof(*ctlv) > sd->valsize) 2370 return (EINVAL); 2371 2372 rtlv = NULL; 2373 tstate = NULL; 2374 cbuf = NULL; 2375 /* Table names or other named objects. */ 2376 if (ctlv->head.type == IPFW_TLV_TBLNAME_LIST) { 2377 /* Check size and alignment. */ 2378 clen = ctlv->head.length; 2379 if (read + clen > sd->valsize || clen < sizeof(*ctlv) || 2380 (clen % sizeof(uint64_t)) != 0) 2381 return (EINVAL); 2382 /* Check for validness. */ 2383 count = (ctlv->head.length - sizeof(*ctlv)) / sizeof(*ntlv); 2384 if (ctlv->count != count || ctlv->objsize != sizeof(*ntlv)) 2385 return (EINVAL); 2386 /* 2387 * Check each TLV. 2388 * Ensure TLVs are sorted ascending and 2389 * there are no duplicates. 2390 */ 2391 idx = 0; 2392 ntlv = (ipfw_obj_ntlv *)(ctlv + 1); 2393 while (count > 0) { 2394 if (ntlv->head.length != sizeof(ipfw_obj_ntlv)) 2395 return (EINVAL); 2396 2397 error = ipfw_check_object_name_generic(ntlv->name); 2398 if (error != 0) 2399 return (error); 2400 2401 if (ntlv->idx <= idx) 2402 return (EINVAL); 2403 2404 idx = ntlv->idx; 2405 count--; 2406 ntlv++; 2407 } 2408 2409 tstate = ctlv; 2410 read += ctlv->head.length; 2411 ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv + ctlv->head.length); 2412 2413 if (read + sizeof(*ctlv) > sd->valsize) 2414 return (EINVAL); 2415 } 2416 2417 /* List of rules. */ 2418 if (ctlv->head.type == IPFW_TLV_RULE_LIST) { 2419 clen = ctlv->head.length; 2420 if (read + clen > sd->valsize || clen < sizeof(*ctlv) || 2421 (clen % sizeof(uint64_t)) != 0) 2422 return (EINVAL); 2423 2424 clen -= sizeof(*ctlv); 2425 if (ctlv->count == 0 || 2426 ctlv->count > clen / sizeof(struct ip_fw_rule)) 2427 return (EINVAL); 2428 2429 /* Allocate state for each rule */ 2430 cbuf = malloc(ctlv->count * sizeof(struct rule_check_info), 2431 M_TEMP, M_WAITOK | M_ZERO); 2432 2433 /* 2434 * Check each rule for validness. 2435 * Ensure numbered rules are sorted ascending 2436 * and properly aligned 2437 */ 2438 rulenum = 0; 2439 count = 0; 2440 error = 0; 2441 ci = cbuf; 2442 r = (struct ip_fw_rule *)(ctlv + 1); 2443 while (clen > 0) { 2444 rsize = RULEUSIZE1(r); 2445 if (rsize > clen || count > ctlv->count) { 2446 error = EINVAL; 2447 break; 2448 } 2449 ci->ctlv = tstate; 2450 ci->version = IP_FW3_OPVER; 2451 error = ipfw_check_rule(r, rsize, ci); 2452 if (error != 0) 2453 break; 2454 2455 /* Check sorting */ 2456 if (count != 0 && ((rulenum == 0) != (r->rulenum == 0) || 2457 r->rulenum < rulenum)) { 2458 printf("ipfw: wrong order: rulenum %u" 2459 " vs %u\n", r->rulenum, rulenum); 2460 error = EINVAL; 2461 break; 2462 } 2463 rulenum = r->rulenum; 2464 ci->urule = (caddr_t)r; 2465 clen -= rsize; 2466 r = (struct ip_fw_rule *)((caddr_t)r + rsize); 2467 count++; 2468 ci++; 2469 } 2470 2471 if (ctlv->count != count || error != 0) { 2472 free(cbuf, M_TEMP); 2473 return (EINVAL); 2474 } 2475 2476 rtlv = ctlv; 2477 read += ctlv->head.length; 2478 ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv + ctlv->head.length); 2479 } 2480 2481 if (read != sd->valsize || rtlv == NULL) { 2482 free(cbuf, M_TEMP); 2483 return (EINVAL); 2484 } 2485 2486 *prtlv = rtlv; 2487 *pci = cbuf; 2488 return (0); 2489 } 2490 2491 /* 2492 * Copy rule @urule from v1 userland format (current) to kernel @krule. 2493 */ 2494 static void 2495 import_rule_v1(struct ip_fw_chain *chain, struct rule_check_info *ci) 2496 { 2497 struct ip_fw_rule *urule; 2498 struct ip_fw *krule; 2499 2500 urule = (struct ip_fw_rule *)ci->urule; 2501 krule = ci->krule = ipfw_alloc_rule(chain, RULEKSIZE1(urule)); 2502 2503 krule->act_ofs = urule->act_ofs; 2504 krule->cmd_len = urule->cmd_len; 2505 krule->rulenum = urule->rulenum; 2506 krule->set = urule->set; 2507 krule->flags = urule->flags; 2508 2509 /* Save rulenum offset */ 2510 ci->urule_numoff = offsetof(struct ip_fw_rule, rulenum); 2511 2512 /* Copy opcodes */ 2513 memcpy(krule->cmd, urule->cmd, krule->cmd_len * sizeof(uint32_t)); 2514 } 2515 2516 /* 2517 * Adds one or more rules to ipfw @chain. 2518 */ 2519 static int 2520 add_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 2521 struct sockopt_data *sd) 2522 { 2523 ipfw_obj_ctlv *rtlv; 2524 struct rule_check_info *ci, *nci; 2525 int i, ret; 2526 2527 /* 2528 * Check rules buffer for validness. 2529 */ 2530 ret = parse_rules_v1(chain, op3, sd, &rtlv, &nci); 2531 if (ret != 0) 2532 return (ret); 2533 /* 2534 * Allocate storage for the kernel representation of rules. 2535 */ 2536 for (i = 0, ci = nci; i < rtlv->count; i++, ci++) 2537 import_rule_v1(chain, ci); 2538 /* 2539 * Try to add new rules to the chain. 2540 */ 2541 if ((ret = ipfw_commit_rules(chain, nci, rtlv->count)) != 0) { 2542 for (i = 0, ci = nci; i < rtlv->count; i++, ci++) 2543 ipfw_free_rule(ci->krule); 2544 } 2545 /* Cleanup after parse_rules() */ 2546 free(nci, M_TEMP); 2547 return (ret); 2548 } 2549 2550 /* 2551 * Lists all sopts currently registered. 2552 * Data layout (v1)(current): 2553 * Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size 2554 * Reply: [ ipfw_obj_lheader ipfw_sopt_info x N ] 2555 * 2556 * Returns 0 on success 2557 */ 2558 static int 2559 dump_soptcodes(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 2560 struct sockopt_data *sd) 2561 { 2562 struct _ipfw_obj_lheader *olh; 2563 ipfw_sopt_info *i; 2564 struct ipfw_sopt_handler *sh; 2565 uint32_t count, n, size; 2566 2567 olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd, 2568 sizeof(*olh)); 2569 if (olh == NULL) 2570 return (EINVAL); 2571 if (sd->valsize < olh->size) 2572 return (EINVAL); 2573 2574 CTL3_LOCK(); 2575 count = ctl3_hsize; 2576 size = count * sizeof(ipfw_sopt_info) + sizeof(ipfw_obj_lheader); 2577 2578 /* Fill in header regadless of buffer size */ 2579 olh->count = count; 2580 olh->objsize = sizeof(ipfw_sopt_info); 2581 2582 if (size > olh->size) { 2583 olh->size = size; 2584 CTL3_UNLOCK(); 2585 return (ENOMEM); 2586 } 2587 olh->size = size; 2588 2589 for (n = 0; n < count; n++) { 2590 i = (ipfw_sopt_info *)ipfw_get_sopt_space(sd, sizeof(*i)); 2591 KASSERT(i != NULL, ("previously checked buffer is not enough")); 2592 sh = &ctl3_handlers[n]; 2593 i->opcode = sh->opcode; 2594 i->version = sh->version; 2595 i->refcnt = sh->refcnt; 2596 } 2597 CTL3_UNLOCK(); 2598 2599 return (0); 2600 } 2601 2602 /* 2603 * Compares two opcodes. 2604 * Used both in qsort() and bsearch(). 2605 * 2606 * Returns 0 if match is found. 2607 */ 2608 static int 2609 compare_opcodes(const void *_a, const void *_b) 2610 { 2611 const struct opcode_obj_rewrite *a, *b; 2612 2613 a = (const struct opcode_obj_rewrite *)_a; 2614 b = (const struct opcode_obj_rewrite *)_b; 2615 2616 if (a->opcode < b->opcode) 2617 return (-1); 2618 else if (a->opcode > b->opcode) 2619 return (1); 2620 2621 return (0); 2622 } 2623 2624 /* 2625 * XXX: Rewrite bsearch() 2626 */ 2627 static int 2628 find_op_rw_range(uint16_t op, struct opcode_obj_rewrite **plo, 2629 struct opcode_obj_rewrite **phi) 2630 { 2631 struct opcode_obj_rewrite *ctl3_max, *lo, *hi, h, *rw; 2632 2633 memset(&h, 0, sizeof(h)); 2634 h.opcode = op; 2635 2636 rw = (struct opcode_obj_rewrite *)bsearch(&h, ctl3_rewriters, 2637 ctl3_rsize, sizeof(h), compare_opcodes); 2638 if (rw == NULL) 2639 return (1); 2640 2641 /* Find the first element matching the same opcode */ 2642 lo = rw; 2643 for ( ; lo > ctl3_rewriters && (lo - 1)->opcode == op; lo--) 2644 ; 2645 2646 /* Find the last element matching the same opcode */ 2647 hi = rw; 2648 ctl3_max = ctl3_rewriters + ctl3_rsize; 2649 for ( ; (hi + 1) < ctl3_max && (hi + 1)->opcode == op; hi++) 2650 ; 2651 2652 *plo = lo; 2653 *phi = hi; 2654 2655 return (0); 2656 } 2657 2658 /* 2659 * Finds opcode object rewriter based on @code. 2660 * 2661 * Returns pointer to handler or NULL. 2662 */ 2663 static struct opcode_obj_rewrite * 2664 find_op_rw(ipfw_insn *cmd, uint32_t *puidx, uint8_t *ptype) 2665 { 2666 struct opcode_obj_rewrite *rw, *lo, *hi; 2667 uint32_t uidx; 2668 uint8_t subtype; 2669 2670 if (find_op_rw_range(cmd->opcode, &lo, &hi) != 0) 2671 return (NULL); 2672 2673 for (rw = lo; rw <= hi; rw++) { 2674 if (rw->classifier(cmd, &uidx, &subtype) == 0) { 2675 if (puidx != NULL) 2676 *puidx = uidx; 2677 if (ptype != NULL) 2678 *ptype = subtype; 2679 return (rw); 2680 } 2681 } 2682 2683 return (NULL); 2684 } 2685 int 2686 classify_opcode_kidx(ipfw_insn *cmd, uint32_t *puidx) 2687 { 2688 2689 if (find_op_rw(cmd, puidx, NULL) == NULL) 2690 return (1); 2691 return (0); 2692 } 2693 2694 void 2695 update_opcode_kidx(ipfw_insn *cmd, uint32_t idx) 2696 { 2697 struct opcode_obj_rewrite *rw; 2698 2699 rw = find_op_rw(cmd, NULL, NULL); 2700 KASSERT(rw != NULL, ("No handler to update opcode %d", cmd->opcode)); 2701 rw->update(cmd, idx); 2702 } 2703 2704 void 2705 ipfw_init_obj_rewriter(void) 2706 { 2707 ctl3_rewriters = NULL; 2708 ctl3_rsize = 0; 2709 } 2710 2711 void 2712 ipfw_destroy_obj_rewriter(void) 2713 { 2714 if (ctl3_rewriters != NULL) 2715 free(ctl3_rewriters, M_IPFW); 2716 ctl3_rewriters = NULL; 2717 ctl3_rsize = 0; 2718 } 2719 2720 /* 2721 * Adds one or more opcode object rewrite handlers to the global array. 2722 * Function may sleep. 2723 */ 2724 void 2725 ipfw_add_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count) 2726 { 2727 size_t sz; 2728 struct opcode_obj_rewrite *tmp; 2729 2730 CTL3_LOCK(); 2731 2732 for (;;) { 2733 sz = ctl3_rsize + count; 2734 CTL3_UNLOCK(); 2735 tmp = malloc(sizeof(*rw) * sz, M_IPFW, M_WAITOK | M_ZERO); 2736 CTL3_LOCK(); 2737 if (ctl3_rsize + count <= sz) 2738 break; 2739 2740 /* Retry */ 2741 free(tmp, M_IPFW); 2742 } 2743 2744 /* Merge old & new arrays */ 2745 sz = ctl3_rsize + count; 2746 memcpy(tmp, ctl3_rewriters, ctl3_rsize * sizeof(*rw)); 2747 memcpy(&tmp[ctl3_rsize], rw, count * sizeof(*rw)); 2748 qsort(tmp, sz, sizeof(*rw), compare_opcodes); 2749 /* Switch new and free old */ 2750 if (ctl3_rewriters != NULL) 2751 free(ctl3_rewriters, M_IPFW); 2752 ctl3_rewriters = tmp; 2753 ctl3_rsize = sz; 2754 2755 CTL3_UNLOCK(); 2756 } 2757 2758 /* 2759 * Removes one or more object rewrite handlers from the global array. 2760 */ 2761 int 2762 ipfw_del_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count) 2763 { 2764 size_t sz; 2765 struct opcode_obj_rewrite *ctl3_max, *ktmp, *lo, *hi; 2766 int i; 2767 2768 CTL3_LOCK(); 2769 2770 for (i = 0; i < count; i++) { 2771 if (find_op_rw_range(rw[i].opcode, &lo, &hi) != 0) 2772 continue; 2773 2774 for (ktmp = lo; ktmp <= hi; ktmp++) { 2775 if (ktmp->classifier != rw[i].classifier) 2776 continue; 2777 2778 ctl3_max = ctl3_rewriters + ctl3_rsize; 2779 sz = (ctl3_max - (ktmp + 1)) * sizeof(*ktmp); 2780 memmove(ktmp, ktmp + 1, sz); 2781 ctl3_rsize--; 2782 break; 2783 } 2784 } 2785 2786 if (ctl3_rsize == 0) { 2787 if (ctl3_rewriters != NULL) 2788 free(ctl3_rewriters, M_IPFW); 2789 ctl3_rewriters = NULL; 2790 } 2791 2792 CTL3_UNLOCK(); 2793 2794 return (0); 2795 } 2796 2797 static int 2798 export_objhash_ntlv_internal(struct namedobj_instance *ni, 2799 struct named_object *no, void *arg) 2800 { 2801 struct sockopt_data *sd; 2802 ipfw_obj_ntlv *ntlv; 2803 2804 sd = (struct sockopt_data *)arg; 2805 ntlv = (ipfw_obj_ntlv *)ipfw_get_sopt_space(sd, sizeof(*ntlv)); 2806 if (ntlv == NULL) 2807 return (ENOMEM); 2808 ipfw_export_obj_ntlv(no, ntlv); 2809 return (0); 2810 } 2811 2812 /* 2813 * Lists all service objects. 2814 * Data layout (v0)(current): 2815 * Request: [ ipfw_obj_lheader ] size = ipfw_obj_lheader.size 2816 * Reply: [ ipfw_obj_lheader [ ipfw_obj_ntlv x N ] (optional) ] 2817 * Returns 0 on success 2818 */ 2819 static int 2820 dump_srvobjects(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 2821 struct sockopt_data *sd) 2822 { 2823 ipfw_obj_lheader *hdr; 2824 int count; 2825 2826 hdr = (ipfw_obj_lheader *)ipfw_get_sopt_header(sd, sizeof(*hdr)); 2827 if (hdr == NULL) 2828 return (EINVAL); 2829 2830 IPFW_UH_RLOCK(chain); 2831 count = ipfw_objhash_count(CHAIN_TO_SRV(chain)); 2832 hdr->size = sizeof(ipfw_obj_lheader) + count * sizeof(ipfw_obj_ntlv); 2833 if (sd->valsize < hdr->size) { 2834 IPFW_UH_RUNLOCK(chain); 2835 return (ENOMEM); 2836 } 2837 hdr->count = count; 2838 hdr->objsize = sizeof(ipfw_obj_ntlv); 2839 if (count > 0) 2840 ipfw_objhash_foreach(CHAIN_TO_SRV(chain), 2841 export_objhash_ntlv_internal, sd); 2842 IPFW_UH_RUNLOCK(chain); 2843 return (0); 2844 } 2845 2846 void 2847 ipfw_enable_skipto_cache(struct ip_fw_chain *chain) 2848 { 2849 2850 IPFW_UH_WLOCK_ASSERT(chain); 2851 update_skipto_cache(chain, chain->map); 2852 2853 IPFW_WLOCK(chain); 2854 swap_skipto_cache(chain); 2855 V_skipto_cache = 1; 2856 IPFW_WUNLOCK(chain); 2857 } 2858 2859 /* 2860 * Enables or disable skipto cache. 2861 * Request: [ ipfw_cmd_header ] size = ipfw_cmd_header.size 2862 * Reply: [ ipfw_cmd_header ] 2863 * Returns 0 on success 2864 */ 2865 static int 2866 manage_skiptocache(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 2867 struct sockopt_data *sd) 2868 { 2869 ipfw_cmd_header *hdr; 2870 2871 if (sd->valsize != sizeof(*hdr)) 2872 return (EINVAL); 2873 2874 hdr = (ipfw_cmd_header *)ipfw_get_sopt_space(sd, sd->valsize); 2875 if (hdr->cmd != SKIPTO_CACHE_DISABLE && 2876 hdr->cmd != SKIPTO_CACHE_ENABLE) 2877 return (EOPNOTSUPP); 2878 2879 IPFW_UH_WLOCK(chain); 2880 if (hdr->cmd != V_skipto_cache) { 2881 if (hdr->cmd == SKIPTO_CACHE_ENABLE) 2882 ipfw_enable_skipto_cache(chain); 2883 V_skipto_cache = hdr->cmd; 2884 } 2885 IPFW_UH_WUNLOCK(chain); 2886 return (0); 2887 } 2888 2889 /* 2890 * Compares two sopt handlers (code, version and handler ptr). 2891 * Used both as qsort() and bsearch(). 2892 * Does not compare handler for latter case. 2893 * 2894 * Returns 0 if match is found. 2895 */ 2896 static int 2897 compare_sh(const void *_a, const void *_b) 2898 { 2899 const struct ipfw_sopt_handler *a, *b; 2900 2901 a = (const struct ipfw_sopt_handler *)_a; 2902 b = (const struct ipfw_sopt_handler *)_b; 2903 2904 if (a->opcode < b->opcode) 2905 return (-1); 2906 else if (a->opcode > b->opcode) 2907 return (1); 2908 2909 if (a->version < b->version) 2910 return (-1); 2911 else if (a->version > b->version) 2912 return (1); 2913 2914 /* bsearch helper */ 2915 if (a->handler == NULL) 2916 return (0); 2917 2918 if ((uintptr_t)a->handler < (uintptr_t)b->handler) 2919 return (-1); 2920 else if ((uintptr_t)a->handler > (uintptr_t)b->handler) 2921 return (1); 2922 2923 return (0); 2924 } 2925 2926 /* 2927 * Finds sopt handler based on @code and @version. 2928 * 2929 * Returns pointer to handler or NULL. 2930 */ 2931 static struct ipfw_sopt_handler * 2932 find_sh(uint16_t code, uint8_t version, sopt_handler_f *handler) 2933 { 2934 struct ipfw_sopt_handler *sh, h; 2935 2936 memset(&h, 0, sizeof(h)); 2937 h.opcode = code; 2938 h.version = version; 2939 h.handler = handler; 2940 2941 sh = (struct ipfw_sopt_handler *)bsearch(&h, ctl3_handlers, 2942 ctl3_hsize, sizeof(h), compare_sh); 2943 2944 return (sh); 2945 } 2946 2947 static int 2948 find_ref_sh(uint16_t opcode, uint8_t version, struct ipfw_sopt_handler *psh) 2949 { 2950 struct ipfw_sopt_handler *sh; 2951 2952 CTL3_LOCK(); 2953 if ((sh = find_sh(opcode, version, NULL)) == NULL) { 2954 CTL3_UNLOCK(); 2955 printf("ipfw: ipfw_ctl3 invalid option %d""v""%d\n", 2956 opcode, version); 2957 return (EINVAL); 2958 } 2959 sh->refcnt++; 2960 ctl3_refct++; 2961 /* Copy handler data to requested buffer */ 2962 *psh = *sh; 2963 CTL3_UNLOCK(); 2964 2965 return (0); 2966 } 2967 2968 static void 2969 find_unref_sh(struct ipfw_sopt_handler *psh) 2970 { 2971 struct ipfw_sopt_handler *sh; 2972 2973 CTL3_LOCK(); 2974 sh = find_sh(psh->opcode, psh->version, NULL); 2975 KASSERT(sh != NULL, ("ctl3 handler disappeared")); 2976 sh->refcnt--; 2977 ctl3_refct--; 2978 CTL3_UNLOCK(); 2979 } 2980 2981 void 2982 ipfw_init_sopt_handler(void) 2983 { 2984 CTL3_LOCK_INIT(); 2985 IPFW_ADD_SOPT_HANDLER(1, scodes); 2986 } 2987 2988 void 2989 ipfw_destroy_sopt_handler(void) 2990 { 2991 IPFW_DEL_SOPT_HANDLER(1, scodes); 2992 CTL3_LOCK_DESTROY(); 2993 } 2994 2995 void 2996 ipfw_register_compat(ipfw_check_opcode_t f) 2997 { 2998 check_opcode_f = f; 2999 } 3000 3001 void 3002 ipfw_unregister_compat(void) 3003 { 3004 check_opcode_f = check_opcode_compat_nop; 3005 } 3006 3007 /* 3008 * Adds one or more sockopt handlers to the global array. 3009 * Function may sleep. 3010 */ 3011 void 3012 ipfw_add_sopt_handler(struct ipfw_sopt_handler *sh, size_t count) 3013 { 3014 size_t sz; 3015 struct ipfw_sopt_handler *tmp; 3016 3017 CTL3_LOCK(); 3018 3019 for (;;) { 3020 sz = ctl3_hsize + count; 3021 CTL3_UNLOCK(); 3022 tmp = malloc(sizeof(*sh) * sz, M_IPFW, M_WAITOK | M_ZERO); 3023 CTL3_LOCK(); 3024 if (ctl3_hsize + count <= sz) 3025 break; 3026 3027 /* Retry */ 3028 free(tmp, M_IPFW); 3029 } 3030 3031 /* Merge old & new arrays */ 3032 sz = ctl3_hsize + count; 3033 memcpy(tmp, ctl3_handlers, ctl3_hsize * sizeof(*sh)); 3034 memcpy(&tmp[ctl3_hsize], sh, count * sizeof(*sh)); 3035 qsort(tmp, sz, sizeof(*sh), compare_sh); 3036 /* Switch new and free old */ 3037 if (ctl3_handlers != NULL) 3038 free(ctl3_handlers, M_IPFW); 3039 ctl3_handlers = tmp; 3040 ctl3_hsize = sz; 3041 ctl3_gencnt++; 3042 3043 CTL3_UNLOCK(); 3044 } 3045 3046 /* 3047 * Removes one or more sockopt handlers from the global array. 3048 */ 3049 int 3050 ipfw_del_sopt_handler(struct ipfw_sopt_handler *sh, size_t count) 3051 { 3052 size_t sz; 3053 struct ipfw_sopt_handler *tmp, *h; 3054 int i; 3055 3056 CTL3_LOCK(); 3057 3058 for (i = 0; i < count; i++) { 3059 tmp = &sh[i]; 3060 h = find_sh(tmp->opcode, tmp->version, tmp->handler); 3061 if (h == NULL) 3062 continue; 3063 3064 sz = (ctl3_handlers + ctl3_hsize - (h + 1)) * sizeof(*h); 3065 memmove(h, h + 1, sz); 3066 ctl3_hsize--; 3067 } 3068 3069 if (ctl3_hsize == 0) { 3070 if (ctl3_handlers != NULL) 3071 free(ctl3_handlers, M_IPFW); 3072 ctl3_handlers = NULL; 3073 } 3074 3075 ctl3_gencnt++; 3076 3077 CTL3_UNLOCK(); 3078 3079 return (0); 3080 } 3081 3082 /* 3083 * Writes data accumulated in @sd to sockopt buffer. 3084 * Zeroes internal @sd buffer. 3085 */ 3086 static int 3087 ipfw_flush_sopt_data(struct sockopt_data *sd) 3088 { 3089 struct sockopt *sopt; 3090 int error; 3091 size_t sz; 3092 3093 sz = sd->koff; 3094 if (sz == 0) 3095 return (0); 3096 3097 sopt = sd->sopt; 3098 3099 if (sopt->sopt_dir == SOPT_GET) { 3100 error = copyout(sd->kbuf, sopt->sopt_val, sz); 3101 if (error != 0) 3102 return (error); 3103 } 3104 3105 memset(sd->kbuf, 0, sd->ksize); 3106 sd->ktotal += sz; 3107 sd->koff = 0; 3108 if (sd->ktotal + sd->ksize < sd->valsize) 3109 sd->kavail = sd->ksize; 3110 else 3111 sd->kavail = sd->valsize - sd->ktotal; 3112 3113 /* Update sopt buffer data */ 3114 sopt->sopt_valsize = sd->ktotal; 3115 sopt->sopt_val = sd->sopt_val + sd->ktotal; 3116 3117 return (0); 3118 } 3119 3120 /* 3121 * Ensures that @sd buffer has contiguous @neeeded number of 3122 * bytes. 3123 * 3124 * Returns pointer to requested space or NULL. 3125 */ 3126 caddr_t 3127 ipfw_get_sopt_space(struct sockopt_data *sd, size_t needed) 3128 { 3129 int error; 3130 caddr_t addr; 3131 3132 if (sd->kavail < needed) { 3133 /* 3134 * Flush data and try another time. 3135 */ 3136 error = ipfw_flush_sopt_data(sd); 3137 3138 if (sd->kavail < needed || error != 0) 3139 return (NULL); 3140 } 3141 3142 addr = sd->kbuf + sd->koff; 3143 sd->koff += needed; 3144 sd->kavail -= needed; 3145 return (addr); 3146 } 3147 3148 /* 3149 * Requests @needed contiguous bytes from @sd buffer. 3150 * Function is used to notify subsystem that we are 3151 * interesed in first @needed bytes (request header) 3152 * and the rest buffer can be safely zeroed. 3153 * 3154 * Returns pointer to requested space or NULL. 3155 */ 3156 caddr_t 3157 ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed) 3158 { 3159 caddr_t addr; 3160 3161 if ((addr = ipfw_get_sopt_space(sd, needed)) == NULL) 3162 return (NULL); 3163 3164 if (sd->kavail > 0) 3165 memset(sd->kbuf + sd->koff, 0, sd->kavail); 3166 3167 return (addr); 3168 } 3169 3170 /* 3171 * New sockopt handler. 3172 */ 3173 int 3174 ipfw_ctl3(struct sockopt *sopt) 3175 { 3176 int error, locked; 3177 size_t size, valsize; 3178 struct ip_fw_chain *chain; 3179 char xbuf[256]; 3180 struct sockopt_data sdata; 3181 struct ipfw_sopt_handler h; 3182 ip_fw3_opheader *op3 = NULL; 3183 3184 error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW); 3185 if (error != 0) 3186 return (error); 3187 3188 if (sopt->sopt_name != IP_FW3) 3189 return (EOPNOTSUPP); 3190 3191 chain = &V_layer3_chain; 3192 error = 0; 3193 3194 /* Save original valsize before it is altered via sooptcopyin() */ 3195 valsize = sopt->sopt_valsize; 3196 memset(&sdata, 0, sizeof(sdata)); 3197 /* Read op3 header first to determine actual operation */ 3198 op3 = (ip_fw3_opheader *)xbuf; 3199 error = sooptcopyin(sopt, op3, sizeof(*op3), sizeof(*op3)); 3200 if (error != 0) 3201 return (error); 3202 sopt->sopt_valsize = valsize; 3203 3204 /* 3205 * Find and reference command. 3206 */ 3207 error = find_ref_sh(op3->opcode, op3->version, &h); 3208 if (error != 0) 3209 return (error); 3210 3211 /* 3212 * Disallow modifications in really-really secure mode, but still allow 3213 * the logging counters to be reset. 3214 */ 3215 if ((h.dir & HDIR_SET) != 0 && h.opcode != IP_FW_XRESETLOG) { 3216 error = securelevel_ge(sopt->sopt_td->td_ucred, 3); 3217 if (error != 0) { 3218 find_unref_sh(&h); 3219 return (error); 3220 } 3221 } 3222 3223 /* 3224 * Fill in sockopt_data structure that may be useful for 3225 * IP_FW3 get requests. 3226 */ 3227 locked = 0; 3228 if (valsize <= sizeof(xbuf)) { 3229 /* use on-stack buffer */ 3230 sdata.kbuf = xbuf; 3231 sdata.ksize = sizeof(xbuf); 3232 sdata.kavail = valsize; 3233 } else { 3234 /* 3235 * Determine opcode type/buffer size: 3236 * allocate sliding-window buf for data export or 3237 * contiguous buffer for special ops. 3238 */ 3239 if ((h.dir & HDIR_SET) != 0) { 3240 /* Set request. Allocate contigous buffer. */ 3241 if (valsize > CTL3_LARGEBUF) { 3242 find_unref_sh(&h); 3243 return (EFBIG); 3244 } 3245 3246 size = valsize; 3247 } else { 3248 /* Get request. Allocate sliding window buffer */ 3249 size = (valsize<CTL3_SMALLBUF) ? valsize:CTL3_SMALLBUF; 3250 3251 if (size < valsize) { 3252 /* We have to wire user buffer */ 3253 error = vslock(sopt->sopt_val, valsize); 3254 if (error != 0) 3255 return (error); 3256 locked = 1; 3257 } 3258 } 3259 3260 sdata.kbuf = malloc(size, M_TEMP, M_WAITOK | M_ZERO); 3261 sdata.ksize = size; 3262 sdata.kavail = size; 3263 } 3264 3265 sdata.sopt = sopt; 3266 sdata.sopt_val = sopt->sopt_val; 3267 sdata.valsize = valsize; 3268 3269 /* 3270 * Copy either all request (if valsize < bsize_max) 3271 * or first bsize_max bytes to guarantee most consumers 3272 * that all necessary data has been copied). 3273 * Anyway, copy not less than sizeof(ip_fw3_opheader). 3274 */ 3275 if ((error = sooptcopyin(sopt, sdata.kbuf, sdata.ksize, 3276 sizeof(ip_fw3_opheader))) != 0) 3277 return (error); 3278 op3 = (ip_fw3_opheader *)sdata.kbuf; 3279 3280 /* Finally, run handler */ 3281 error = h.handler(chain, op3, &sdata); 3282 find_unref_sh(&h); 3283 3284 /* Flush state and free buffers */ 3285 if (error == 0) 3286 error = ipfw_flush_sopt_data(&sdata); 3287 else 3288 ipfw_flush_sopt_data(&sdata); 3289 3290 if (locked != 0) 3291 vsunlock(sdata.sopt_val, valsize); 3292 3293 /* Restore original pointer and set number of bytes written */ 3294 sopt->sopt_val = sdata.sopt_val; 3295 sopt->sopt_valsize = sdata.ktotal; 3296 if (sdata.kbuf != xbuf) 3297 free(sdata.kbuf, M_TEMP); 3298 3299 return (error); 3300 } 3301 3302 /* 3303 * Named object api 3304 * 3305 */ 3306 3307 void 3308 ipfw_init_srv(struct ip_fw_chain *ch) 3309 { 3310 ch->srvmap = ipfw_objhash_create(IPFW_OBJECTS_DEFAULT, 3311 DEFAULT_OBJHASH_SIZE); 3312 ch->srvstate = malloc(sizeof(void *) * IPFW_OBJECTS_DEFAULT, 3313 M_IPFW, M_WAITOK | M_ZERO); 3314 } 3315 3316 void 3317 ipfw_destroy_srv(struct ip_fw_chain *ch) 3318 { 3319 free(ch->srvstate, M_IPFW); 3320 ipfw_objhash_destroy(ch->srvmap); 3321 } 3322 3323 /* 3324 * Allocate new bitmask which can be used to enlarge/shrink 3325 * named instance index. 3326 */ 3327 void 3328 ipfw_objhash_bitmap_alloc(uint32_t items, void **idx, int *pblocks) 3329 { 3330 size_t size; 3331 int max_blocks; 3332 u_long *idx_mask; 3333 3334 KASSERT((items % BLOCK_ITEMS) == 0, 3335 ("bitmask size needs to power of 2 and greater or equal to %zu", 3336 BLOCK_ITEMS)); 3337 3338 max_blocks = items / BLOCK_ITEMS; 3339 size = items / 8; 3340 idx_mask = malloc(size * IPFW_MAX_SETS, M_IPFW, M_WAITOK); 3341 /* Mark all as free */ 3342 memset(idx_mask, 0xFF, size * IPFW_MAX_SETS); 3343 *idx_mask &= ~(u_long)1; /* Skip index 0 */ 3344 3345 *idx = idx_mask; 3346 *pblocks = max_blocks; 3347 } 3348 3349 /* 3350 * Copy current bitmask index to new one. 3351 */ 3352 void 3353 ipfw_objhash_bitmap_merge(struct namedobj_instance *ni, void **idx, int *blocks) 3354 { 3355 int old_blocks, new_blocks; 3356 u_long *old_idx, *new_idx; 3357 int i; 3358 3359 old_idx = ni->idx_mask; 3360 old_blocks = ni->max_blocks; 3361 new_idx = *idx; 3362 new_blocks = *blocks; 3363 3364 for (i = 0; i < IPFW_MAX_SETS; i++) { 3365 memcpy(&new_idx[new_blocks * i], &old_idx[old_blocks * i], 3366 old_blocks * sizeof(u_long)); 3367 } 3368 } 3369 3370 /* 3371 * Swaps current @ni index with new one. 3372 */ 3373 void 3374 ipfw_objhash_bitmap_swap(struct namedobj_instance *ni, void **idx, int *blocks) 3375 { 3376 int old_blocks; 3377 u_long *old_idx; 3378 3379 old_idx = ni->idx_mask; 3380 old_blocks = ni->max_blocks; 3381 3382 ni->idx_mask = *idx; 3383 ni->max_blocks = *blocks; 3384 3385 /* Save old values */ 3386 *idx = old_idx; 3387 *blocks = old_blocks; 3388 } 3389 3390 void 3391 ipfw_objhash_bitmap_free(void *idx, int blocks) 3392 { 3393 free(idx, M_IPFW); 3394 } 3395 3396 /* 3397 * Creates named hash instance. 3398 * Must be called without holding any locks. 3399 * Return pointer to new instance. 3400 */ 3401 struct namedobj_instance * 3402 ipfw_objhash_create(uint32_t items, size_t hash_size) 3403 { 3404 struct namedobj_instance *ni; 3405 int i; 3406 size_t size; 3407 3408 size = sizeof(struct namedobj_instance) + 3409 sizeof(struct namedobjects_head) * hash_size + 3410 sizeof(struct namedobjects_head) * hash_size; 3411 3412 ni = malloc(size, M_IPFW, M_WAITOK | M_ZERO); 3413 ni->nn_size = hash_size; 3414 ni->nv_size = hash_size; 3415 3416 ni->names = (struct namedobjects_head *)(ni +1); 3417 ni->values = &ni->names[ni->nn_size]; 3418 3419 for (i = 0; i < ni->nn_size; i++) 3420 TAILQ_INIT(&ni->names[i]); 3421 3422 for (i = 0; i < ni->nv_size; i++) 3423 TAILQ_INIT(&ni->values[i]); 3424 3425 /* Set default hashing/comparison functions */ 3426 ni->hash_f = objhash_hash_name; 3427 ni->cmp_f = objhash_cmp_name; 3428 3429 /* Allocate bitmask separately due to possible resize */ 3430 ipfw_objhash_bitmap_alloc(items, (void*)&ni->idx_mask, &ni->max_blocks); 3431 3432 return (ni); 3433 } 3434 3435 void 3436 ipfw_objhash_destroy(struct namedobj_instance *ni) 3437 { 3438 free(ni->idx_mask, M_IPFW); 3439 free(ni, M_IPFW); 3440 } 3441 3442 void 3443 ipfw_objhash_set_funcs(struct namedobj_instance *ni, objhash_hash_f *hash_f, 3444 objhash_cmp_f *cmp_f) 3445 { 3446 3447 ni->hash_f = hash_f; 3448 ni->cmp_f = cmp_f; 3449 } 3450 3451 static uint32_t 3452 objhash_hash_name(struct namedobj_instance *ni, const void *name, uint32_t set) 3453 { 3454 3455 return (fnv_32_str((const char *)name, FNV1_32_INIT)); 3456 } 3457 3458 static int 3459 objhash_cmp_name(struct named_object *no, const void *name, uint32_t set) 3460 { 3461 3462 if ((strcmp(no->name, (const char *)name) == 0) && (no->set == set)) 3463 return (0); 3464 3465 return (1); 3466 } 3467 3468 static uint32_t 3469 objhash_hash_idx(struct namedobj_instance *ni, uint32_t val) 3470 { 3471 uint32_t v; 3472 3473 v = val % (ni->nv_size - 1); 3474 3475 return (v); 3476 } 3477 3478 struct named_object * 3479 ipfw_objhash_lookup_name(struct namedobj_instance *ni, uint32_t set, 3480 const char *name) 3481 { 3482 struct named_object *no; 3483 uint32_t hash; 3484 3485 hash = ni->hash_f(ni, name, set) % ni->nn_size; 3486 3487 TAILQ_FOREACH(no, &ni->names[hash], nn_next) { 3488 if (ni->cmp_f(no, name, set) == 0) 3489 return (no); 3490 } 3491 3492 return (NULL); 3493 } 3494 3495 /* 3496 * Find named object by @uid. 3497 * Check @tlvs for valid data inside. 3498 * 3499 * Returns pointer to found TLV or NULL. 3500 */ 3501 ipfw_obj_ntlv * 3502 ipfw_find_name_tlv_type(void *tlvs, int len, uint32_t uidx, uint32_t etlv) 3503 { 3504 ipfw_obj_ntlv *ntlv; 3505 uintptr_t pa, pe; 3506 int l; 3507 3508 pa = (uintptr_t)tlvs; 3509 pe = pa + len; 3510 l = 0; 3511 for (; pa < pe; pa += l) { 3512 ntlv = (ipfw_obj_ntlv *)pa; 3513 l = ntlv->head.length; 3514 3515 if (l != sizeof(*ntlv)) 3516 return (NULL); 3517 3518 if (ntlv->idx != uidx) 3519 continue; 3520 /* 3521 * When userland has specified zero TLV type, do 3522 * not compare it with eltv. In some cases userland 3523 * doesn't know what type should it have. Use only 3524 * uidx and name for search named_object. 3525 */ 3526 if (ntlv->head.type != 0 && 3527 ntlv->head.type != (uint16_t)etlv) 3528 continue; 3529 3530 if (ipfw_check_object_name_generic(ntlv->name) != 0) 3531 return (NULL); 3532 3533 return (ntlv); 3534 } 3535 3536 return (NULL); 3537 } 3538 3539 /* 3540 * Finds object config based on either legacy index 3541 * or name in ntlv. 3542 * Note @ti structure contains unchecked data from userland. 3543 * 3544 * Returns 0 in success and fills in @pno with found config 3545 */ 3546 int 3547 ipfw_objhash_find_type(struct namedobj_instance *ni, struct tid_info *ti, 3548 uint32_t etlv, struct named_object **pno) 3549 { 3550 char *name; 3551 ipfw_obj_ntlv *ntlv; 3552 uint32_t set; 3553 3554 if (ti->tlvs == NULL) 3555 return (EINVAL); 3556 3557 ntlv = ipfw_find_name_tlv_type(ti->tlvs, ti->tlen, ti->uidx, etlv); 3558 if (ntlv == NULL) 3559 return (EINVAL); 3560 name = ntlv->name; 3561 3562 /* 3563 * Use set provided by @ti instead of @ntlv one. 3564 * This is needed due to different sets behavior 3565 * controlled by V_fw_tables_sets. 3566 */ 3567 set = ti->set; 3568 *pno = ipfw_objhash_lookup_name(ni, set, name); 3569 if (*pno == NULL) 3570 return (ESRCH); 3571 return (0); 3572 } 3573 3574 /* 3575 * Find named object by name, considering also its TLV type. 3576 */ 3577 struct named_object * 3578 ipfw_objhash_lookup_name_type(struct namedobj_instance *ni, uint32_t set, 3579 uint32_t type, const char *name) 3580 { 3581 struct named_object *no; 3582 uint32_t hash; 3583 3584 hash = ni->hash_f(ni, name, set) % ni->nn_size; 3585 3586 TAILQ_FOREACH(no, &ni->names[hash], nn_next) { 3587 if (ni->cmp_f(no, name, set) == 0 && 3588 no->etlv == (uint16_t)type) 3589 return (no); 3590 } 3591 3592 return (NULL); 3593 } 3594 3595 struct named_object * 3596 ipfw_objhash_lookup_kidx(struct namedobj_instance *ni, uint32_t kidx) 3597 { 3598 struct named_object *no; 3599 uint32_t hash; 3600 3601 hash = objhash_hash_idx(ni, kidx); 3602 3603 TAILQ_FOREACH(no, &ni->values[hash], nv_next) { 3604 if (no->kidx == kidx) 3605 return (no); 3606 } 3607 3608 return (NULL); 3609 } 3610 3611 int 3612 ipfw_objhash_same_name(struct namedobj_instance *ni, struct named_object *a, 3613 struct named_object *b) 3614 { 3615 3616 if ((strcmp(a->name, b->name) == 0) && a->set == b->set) 3617 return (1); 3618 3619 return (0); 3620 } 3621 3622 void 3623 ipfw_objhash_add(struct namedobj_instance *ni, struct named_object *no) 3624 { 3625 uint32_t hash; 3626 3627 hash = ni->hash_f(ni, no->name, no->set) % ni->nn_size; 3628 TAILQ_INSERT_HEAD(&ni->names[hash], no, nn_next); 3629 3630 hash = objhash_hash_idx(ni, no->kidx); 3631 TAILQ_INSERT_HEAD(&ni->values[hash], no, nv_next); 3632 3633 ni->count++; 3634 } 3635 3636 void 3637 ipfw_objhash_del(struct namedobj_instance *ni, struct named_object *no) 3638 { 3639 uint32_t hash; 3640 3641 hash = ni->hash_f(ni, no->name, no->set) % ni->nn_size; 3642 TAILQ_REMOVE(&ni->names[hash], no, nn_next); 3643 3644 hash = objhash_hash_idx(ni, no->kidx); 3645 TAILQ_REMOVE(&ni->values[hash], no, nv_next); 3646 3647 ni->count--; 3648 } 3649 3650 uint32_t 3651 ipfw_objhash_count(struct namedobj_instance *ni) 3652 { 3653 3654 return (ni->count); 3655 } 3656 3657 uint32_t 3658 ipfw_objhash_count_type(struct namedobj_instance *ni, uint16_t type) 3659 { 3660 struct named_object *no; 3661 uint32_t count; 3662 int i; 3663 3664 count = 0; 3665 for (i = 0; i < ni->nn_size; i++) { 3666 TAILQ_FOREACH(no, &ni->names[i], nn_next) { 3667 if (no->etlv == type) 3668 count++; 3669 } 3670 } 3671 return (count); 3672 } 3673 3674 /* 3675 * Runs @func for each found named object. 3676 * It is safe to delete objects from callback 3677 */ 3678 int 3679 ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f, void *arg) 3680 { 3681 struct named_object *no, *no_tmp; 3682 int i, ret; 3683 3684 for (i = 0; i < ni->nn_size; i++) { 3685 TAILQ_FOREACH_SAFE(no, &ni->names[i], nn_next, no_tmp) { 3686 ret = f(ni, no, arg); 3687 if (ret != 0) 3688 return (ret); 3689 } 3690 } 3691 return (0); 3692 } 3693 3694 /* 3695 * Runs @f for each found named object with type @type. 3696 * It is safe to delete objects from callback 3697 */ 3698 int 3699 ipfw_objhash_foreach_type(struct namedobj_instance *ni, objhash_cb_t *f, 3700 void *arg, uint16_t type) 3701 { 3702 struct named_object *no, *no_tmp; 3703 int i, ret; 3704 3705 for (i = 0; i < ni->nn_size; i++) { 3706 TAILQ_FOREACH_SAFE(no, &ni->names[i], nn_next, no_tmp) { 3707 if (no->etlv != type) 3708 continue; 3709 ret = f(ni, no, arg); 3710 if (ret != 0) 3711 return (ret); 3712 } 3713 } 3714 return (0); 3715 } 3716 3717 /* 3718 * Removes index from given set. 3719 * Returns 0 on success. 3720 */ 3721 int 3722 ipfw_objhash_free_idx(struct namedobj_instance *ni, uint32_t idx) 3723 { 3724 u_long *mask; 3725 int i, v; 3726 3727 i = idx / BLOCK_ITEMS; 3728 v = idx % BLOCK_ITEMS; 3729 3730 if (i >= ni->max_blocks) 3731 return (1); 3732 3733 mask = &ni->idx_mask[i]; 3734 3735 if ((*mask & ((u_long)1 << v)) != 0) 3736 return (1); 3737 3738 /* Mark as free */ 3739 *mask |= (u_long)1 << v; 3740 3741 /* Update free offset */ 3742 if (ni->free_off[0] > i) 3743 ni->free_off[0] = i; 3744 3745 return (0); 3746 } 3747 3748 /* 3749 * Allocate new index in given instance and stores in in @pidx. 3750 * Returns 0 on success. 3751 */ 3752 int 3753 ipfw_objhash_alloc_idx(void *n, uint32_t *pidx) 3754 { 3755 struct namedobj_instance *ni; 3756 u_long *mask; 3757 int i, off, v; 3758 3759 ni = (struct namedobj_instance *)n; 3760 3761 off = ni->free_off[0]; 3762 mask = &ni->idx_mask[off]; 3763 3764 for (i = off; i < ni->max_blocks; i++, mask++) { 3765 if ((v = ffsl(*mask)) == 0) 3766 continue; 3767 3768 /* Mark as busy */ 3769 *mask &= ~ ((u_long)1 << (v - 1)); 3770 3771 ni->free_off[0] = i; 3772 3773 v = BLOCK_ITEMS * i + v - 1; 3774 3775 *pidx = v; 3776 return (0); 3777 } 3778 3779 return (1); 3780 } 3781 3782 /* end of file */ 3783