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