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