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