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