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