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