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 if (cmdlen != F_INSN_SIZE(ipfw_insn)) 1754 goto bad_size; 1755 break; 1756 1757 case O_EXTERNAL_ACTION: 1758 if (cmd->arg1 == 0 || 1759 cmdlen != F_INSN_SIZE(ipfw_insn)) { 1760 printf("ipfw: invalid external " 1761 "action opcode\n"); 1762 return (EINVAL); 1763 } 1764 ci->object_opcodes++; 1765 /* 1766 * Do we have O_EXTERNAL_INSTANCE or O_EXTERNAL_DATA 1767 * opcode? 1768 */ 1769 if (l != cmdlen) { 1770 l -= cmdlen; 1771 cmd += cmdlen; 1772 cmdlen = F_LEN(cmd); 1773 if (cmd->opcode == O_EXTERNAL_DATA) 1774 goto check_action; 1775 if (cmd->opcode != O_EXTERNAL_INSTANCE) { 1776 printf("ipfw: invalid opcode " 1777 "next to external action %u\n", 1778 cmd->opcode); 1779 return (EINVAL); 1780 } 1781 if (cmd->arg1 == 0 || 1782 cmdlen != F_INSN_SIZE(ipfw_insn)) { 1783 printf("ipfw: invalid external " 1784 "action instance opcode\n"); 1785 return (EINVAL); 1786 } 1787 ci->object_opcodes++; 1788 } 1789 goto check_action; 1790 1791 case O_FIB: 1792 if (cmdlen != F_INSN_SIZE(ipfw_insn)) 1793 goto bad_size; 1794 if (cmd->arg1 >= rt_numfibs) { 1795 printf("ipfw: invalid fib number %d\n", 1796 cmd->arg1); 1797 return EINVAL; 1798 } 1799 break; 1800 1801 case O_SETFIB: 1802 if (cmdlen != F_INSN_SIZE(ipfw_insn)) 1803 goto bad_size; 1804 if ((cmd->arg1 != IP_FW_TARG) && 1805 ((cmd->arg1 & 0x7FFF) >= rt_numfibs)) { 1806 printf("ipfw: invalid fib number %d\n", 1807 cmd->arg1 & 0x7FFF); 1808 return EINVAL; 1809 } 1810 goto check_action; 1811 1812 case O_UID: 1813 case O_GID: 1814 case O_JAIL: 1815 case O_IP_SRC: 1816 case O_IP_DST: 1817 case O_TCPSEQ: 1818 case O_TCPACK: 1819 case O_PROB: 1820 case O_ICMPTYPE: 1821 if (cmdlen != F_INSN_SIZE(ipfw_insn_u32)) 1822 goto bad_size; 1823 break; 1824 1825 case O_LIMIT: 1826 if (cmdlen != F_INSN_SIZE(ipfw_insn_limit)) 1827 goto bad_size; 1828 ci->object_opcodes++; 1829 break; 1830 1831 case O_LOG: 1832 if (cmdlen != F_INSN_SIZE(ipfw_insn_log)) 1833 goto bad_size; 1834 1835 ((ipfw_insn_log *)cmd)->log_left = 1836 ((ipfw_insn_log *)cmd)->max_log; 1837 1838 break; 1839 1840 case O_IP_SRC_MASK: 1841 case O_IP_DST_MASK: 1842 /* only odd command lengths */ 1843 if ((cmdlen & 1) == 0) 1844 goto bad_size; 1845 break; 1846 1847 case O_IP_SRC_SET: 1848 case O_IP_DST_SET: 1849 if (cmd->arg1 == 0 || cmd->arg1 > 256) { 1850 printf("ipfw: invalid set size %d\n", 1851 cmd->arg1); 1852 return EINVAL; 1853 } 1854 if (cmdlen != F_INSN_SIZE(ipfw_insn_u32) + 1855 (cmd->arg1+31)/32 ) 1856 goto bad_size; 1857 break; 1858 1859 case O_IP_SRC_LOOKUP: 1860 if (cmdlen > F_INSN_SIZE(ipfw_insn_u32)) 1861 goto bad_size; 1862 case O_IP_DST_LOOKUP: 1863 if (cmd->arg1 >= V_fw_tables_max) { 1864 printf("ipfw: invalid table number %d\n", 1865 cmd->arg1); 1866 return (EINVAL); 1867 } 1868 if (cmdlen != F_INSN_SIZE(ipfw_insn) && 1869 cmdlen != F_INSN_SIZE(ipfw_insn_u32) + 1 && 1870 cmdlen != F_INSN_SIZE(ipfw_insn_u32)) 1871 goto bad_size; 1872 ci->object_opcodes++; 1873 break; 1874 case O_IP_FLOW_LOOKUP: 1875 if (cmd->arg1 >= V_fw_tables_max) { 1876 printf("ipfw: invalid table number %d\n", 1877 cmd->arg1); 1878 return (EINVAL); 1879 } 1880 if (cmdlen != F_INSN_SIZE(ipfw_insn) && 1881 cmdlen != F_INSN_SIZE(ipfw_insn_u32)) 1882 goto bad_size; 1883 ci->object_opcodes++; 1884 break; 1885 case O_MACADDR2: 1886 if (cmdlen != F_INSN_SIZE(ipfw_insn_mac)) 1887 goto bad_size; 1888 break; 1889 1890 case O_NOP: 1891 case O_IPID: 1892 case O_IPTTL: 1893 case O_IPLEN: 1894 case O_TCPDATALEN: 1895 case O_TCPWIN: 1896 case O_TAGGED: 1897 if (cmdlen < 1 || cmdlen > 31) 1898 goto bad_size; 1899 break; 1900 1901 case O_DSCP: 1902 if (cmdlen != F_INSN_SIZE(ipfw_insn_u32) + 1) 1903 goto bad_size; 1904 break; 1905 1906 case O_MAC_TYPE: 1907 case O_IP_SRCPORT: 1908 case O_IP_DSTPORT: /* XXX artificial limit, 30 port pairs */ 1909 if (cmdlen < 2 || cmdlen > 31) 1910 goto bad_size; 1911 break; 1912 1913 case O_RECV: 1914 case O_XMIT: 1915 case O_VIA: 1916 if (cmdlen != F_INSN_SIZE(ipfw_insn_if)) 1917 goto bad_size; 1918 ci->object_opcodes++; 1919 break; 1920 1921 case O_ALTQ: 1922 if (cmdlen != F_INSN_SIZE(ipfw_insn_altq)) 1923 goto bad_size; 1924 break; 1925 1926 case O_PIPE: 1927 case O_QUEUE: 1928 if (cmdlen != F_INSN_SIZE(ipfw_insn)) 1929 goto bad_size; 1930 goto check_action; 1931 1932 case O_FORWARD_IP: 1933 if (cmdlen != F_INSN_SIZE(ipfw_insn_sa)) 1934 goto bad_size; 1935 goto check_action; 1936 #ifdef INET6 1937 case O_FORWARD_IP6: 1938 if (cmdlen != F_INSN_SIZE(ipfw_insn_sa6)) 1939 goto bad_size; 1940 goto check_action; 1941 #endif /* INET6 */ 1942 1943 case O_DIVERT: 1944 case O_TEE: 1945 if (ip_divert_ptr == NULL) 1946 return EINVAL; 1947 else 1948 goto check_size; 1949 case O_NETGRAPH: 1950 case O_NGTEE: 1951 if (ng_ipfw_input_p == NULL) 1952 return EINVAL; 1953 else 1954 goto check_size; 1955 case O_NAT: 1956 if (!IPFW_NAT_LOADED) 1957 return EINVAL; 1958 if (cmdlen != F_INSN_SIZE(ipfw_insn_nat)) 1959 goto bad_size; 1960 goto check_action; 1961 case O_CHECK_STATE: 1962 ci->object_opcodes++; 1963 /* FALLTHROUGH */ 1964 case O_FORWARD_MAC: /* XXX not implemented yet */ 1965 case O_COUNT: 1966 case O_ACCEPT: 1967 case O_DENY: 1968 case O_REJECT: 1969 case O_SETDSCP: 1970 #ifdef INET6 1971 case O_UNREACH6: 1972 #endif 1973 case O_SKIPTO: 1974 case O_REASS: 1975 case O_CALLRETURN: 1976 check_size: 1977 if (cmdlen != F_INSN_SIZE(ipfw_insn)) 1978 goto bad_size; 1979 check_action: 1980 if (have_action) { 1981 printf("ipfw: opcode %d, multiple actions" 1982 " not allowed\n", 1983 cmd->opcode); 1984 return (EINVAL); 1985 } 1986 have_action = 1; 1987 if (l != cmdlen) { 1988 printf("ipfw: opcode %d, action must be" 1989 " last opcode\n", 1990 cmd->opcode); 1991 return (EINVAL); 1992 } 1993 break; 1994 #ifdef INET6 1995 case O_IP6_SRC: 1996 case O_IP6_DST: 1997 if (cmdlen != F_INSN_SIZE(struct in6_addr) + 1998 F_INSN_SIZE(ipfw_insn)) 1999 goto bad_size; 2000 break; 2001 2002 case O_FLOW6ID: 2003 if (cmdlen != F_INSN_SIZE(ipfw_insn_u32) + 2004 ((ipfw_insn_u32 *)cmd)->o.arg1) 2005 goto bad_size; 2006 break; 2007 2008 case O_IP6_SRC_MASK: 2009 case O_IP6_DST_MASK: 2010 if ( !(cmdlen & 1) || cmdlen > 127) 2011 goto bad_size; 2012 break; 2013 case O_ICMP6TYPE: 2014 if( cmdlen != F_INSN_SIZE( ipfw_insn_icmp6 ) ) 2015 goto bad_size; 2016 break; 2017 #endif 2018 2019 default: 2020 switch (cmd->opcode) { 2021 #ifndef INET6 2022 case O_IP6_SRC_ME: 2023 case O_IP6_DST_ME: 2024 case O_EXT_HDR: 2025 case O_IP6: 2026 case O_UNREACH6: 2027 case O_IP6_SRC: 2028 case O_IP6_DST: 2029 case O_FLOW6ID: 2030 case O_IP6_SRC_MASK: 2031 case O_IP6_DST_MASK: 2032 case O_ICMP6TYPE: 2033 printf("ipfw: no IPv6 support in kernel\n"); 2034 return (EPROTONOSUPPORT); 2035 #endif 2036 default: 2037 printf("ipfw: opcode %d, unknown opcode\n", 2038 cmd->opcode); 2039 return (EINVAL); 2040 } 2041 } 2042 } 2043 if (have_action == 0) { 2044 printf("ipfw: missing action\n"); 2045 return (EINVAL); 2046 } 2047 return 0; 2048 2049 bad_size: 2050 printf("ipfw: opcode %d size %d wrong\n", 2051 cmd->opcode, cmdlen); 2052 return (EINVAL); 2053 } 2054 2055 2056 /* 2057 * Translation of requests for compatibility with FreeBSD 7.2/8. 2058 * a static variable tells us if we have an old client from userland, 2059 * and if necessary we translate requests and responses between the 2060 * two formats. 2061 */ 2062 static int is7 = 0; 2063 2064 struct ip_fw7 { 2065 struct ip_fw7 *next; /* linked list of rules */ 2066 struct ip_fw7 *next_rule; /* ptr to next [skipto] rule */ 2067 /* 'next_rule' is used to pass up 'set_disable' status */ 2068 2069 uint16_t act_ofs; /* offset of action in 32-bit units */ 2070 uint16_t cmd_len; /* # of 32-bit words in cmd */ 2071 uint16_t rulenum; /* rule number */ 2072 uint8_t set; /* rule set (0..31) */ 2073 // #define RESVD_SET 31 /* set for default and persistent rules */ 2074 uint8_t _pad; /* padding */ 2075 // uint32_t id; /* rule id, only in v.8 */ 2076 /* These fields are present in all rules. */ 2077 uint64_t pcnt; /* Packet counter */ 2078 uint64_t bcnt; /* Byte counter */ 2079 uint32_t timestamp; /* tv_sec of last match */ 2080 2081 ipfw_insn cmd[1]; /* storage for commands */ 2082 }; 2083 2084 static int convert_rule_to_7(struct ip_fw_rule0 *rule); 2085 static int convert_rule_to_8(struct ip_fw_rule0 *rule); 2086 2087 #ifndef RULESIZE7 2088 #define RULESIZE7(rule) (sizeof(struct ip_fw7) + \ 2089 ((struct ip_fw7 *)(rule))->cmd_len * 4 - 4) 2090 #endif 2091 2092 2093 /* 2094 * Copy the static and dynamic rules to the supplied buffer 2095 * and return the amount of space actually used. 2096 * Must be run under IPFW_UH_RLOCK 2097 */ 2098 static size_t 2099 ipfw_getrules(struct ip_fw_chain *chain, void *buf, size_t space) 2100 { 2101 char *bp = buf; 2102 char *ep = bp + space; 2103 struct ip_fw *rule; 2104 struct ip_fw_rule0 *dst; 2105 struct timeval boottime; 2106 int error, i, l, warnflag; 2107 time_t boot_seconds; 2108 2109 warnflag = 0; 2110 2111 getboottime(&boottime); 2112 boot_seconds = boottime.tv_sec; 2113 for (i = 0; i < chain->n_rules; i++) { 2114 rule = chain->map[i]; 2115 2116 if (is7) { 2117 /* Convert rule to FreeBSd 7.2 format */ 2118 l = RULESIZE7(rule); 2119 if (bp + l + sizeof(uint32_t) <= ep) { 2120 bcopy(rule, bp, l + sizeof(uint32_t)); 2121 error = set_legacy_obj_kidx(chain, 2122 (struct ip_fw_rule0 *)bp); 2123 if (error != 0) 2124 return (0); 2125 error = convert_rule_to_7((struct ip_fw_rule0 *) bp); 2126 if (error) 2127 return 0; /*XXX correct? */ 2128 /* 2129 * XXX HACK. Store the disable mask in the "next" 2130 * pointer in a wild attempt to keep the ABI the same. 2131 * Why do we do this on EVERY rule? 2132 */ 2133 bcopy(&V_set_disable, 2134 &(((struct ip_fw7 *)bp)->next_rule), 2135 sizeof(V_set_disable)); 2136 if (((struct ip_fw7 *)bp)->timestamp) 2137 ((struct ip_fw7 *)bp)->timestamp += boot_seconds; 2138 bp += l; 2139 } 2140 continue; /* go to next rule */ 2141 } 2142 2143 l = RULEUSIZE0(rule); 2144 if (bp + l > ep) { /* should not happen */ 2145 printf("overflow dumping static rules\n"); 2146 break; 2147 } 2148 dst = (struct ip_fw_rule0 *)bp; 2149 export_rule0(rule, dst, l); 2150 error = set_legacy_obj_kidx(chain, dst); 2151 2152 /* 2153 * XXX HACK. Store the disable mask in the "next" 2154 * pointer in a wild attempt to keep the ABI the same. 2155 * Why do we do this on EVERY rule? 2156 * 2157 * XXX: "ipfw set show" (ab)uses IP_FW_GET to read disabled mask 2158 * so we need to fail _after_ saving at least one mask. 2159 */ 2160 bcopy(&V_set_disable, &dst->next_rule, sizeof(V_set_disable)); 2161 if (dst->timestamp) 2162 dst->timestamp += boot_seconds; 2163 bp += l; 2164 2165 if (error != 0) { 2166 if (error == 2) { 2167 /* Non-fatal table rewrite error. */ 2168 warnflag = 1; 2169 continue; 2170 } 2171 printf("Stop on rule %d. Fail to convert table\n", 2172 rule->rulenum); 2173 break; 2174 } 2175 } 2176 if (warnflag != 0) 2177 printf("ipfw: process %s is using legacy interfaces," 2178 " consider rebuilding\n", ""); 2179 ipfw_get_dynamic(chain, &bp, ep); /* protected by the dynamic lock */ 2180 return (bp - (char *)buf); 2181 } 2182 2183 2184 struct dump_args { 2185 uint32_t b; /* start rule */ 2186 uint32_t e; /* end rule */ 2187 uint32_t rcount; /* number of rules */ 2188 uint32_t rsize; /* rules size */ 2189 uint32_t tcount; /* number of tables */ 2190 int rcounters; /* counters */ 2191 }; 2192 2193 void 2194 ipfw_export_obj_ntlv(struct named_object *no, ipfw_obj_ntlv *ntlv) 2195 { 2196 2197 ntlv->head.type = no->etlv; 2198 ntlv->head.length = sizeof(*ntlv); 2199 ntlv->idx = no->kidx; 2200 strlcpy(ntlv->name, no->name, sizeof(ntlv->name)); 2201 } 2202 2203 /* 2204 * Export named object info in instance @ni, identified by @kidx 2205 * to ipfw_obj_ntlv. TLV is allocated from @sd space. 2206 * 2207 * Returns 0 on success. 2208 */ 2209 static int 2210 export_objhash_ntlv(struct namedobj_instance *ni, uint16_t kidx, 2211 struct sockopt_data *sd) 2212 { 2213 struct named_object *no; 2214 ipfw_obj_ntlv *ntlv; 2215 2216 no = ipfw_objhash_lookup_kidx(ni, kidx); 2217 KASSERT(no != NULL, ("invalid object kernel index passed")); 2218 2219 ntlv = (ipfw_obj_ntlv *)ipfw_get_sopt_space(sd, sizeof(*ntlv)); 2220 if (ntlv == NULL) 2221 return (ENOMEM); 2222 2223 ipfw_export_obj_ntlv(no, ntlv); 2224 return (0); 2225 } 2226 2227 /* 2228 * Dumps static rules with table TLVs in buffer @sd. 2229 * 2230 * Returns 0 on success. 2231 */ 2232 static int 2233 dump_static_rules(struct ip_fw_chain *chain, struct dump_args *da, 2234 uint32_t *bmask, struct sockopt_data *sd) 2235 { 2236 int error; 2237 int i, l; 2238 uint32_t tcount; 2239 ipfw_obj_ctlv *ctlv; 2240 struct ip_fw *krule; 2241 struct namedobj_instance *ni; 2242 caddr_t dst; 2243 2244 /* Dump table names first (if any) */ 2245 if (da->tcount > 0) { 2246 /* Header first */ 2247 ctlv = (ipfw_obj_ctlv *)ipfw_get_sopt_space(sd, sizeof(*ctlv)); 2248 if (ctlv == NULL) 2249 return (ENOMEM); 2250 ctlv->head.type = IPFW_TLV_TBLNAME_LIST; 2251 ctlv->head.length = da->tcount * sizeof(ipfw_obj_ntlv) + 2252 sizeof(*ctlv); 2253 ctlv->count = da->tcount; 2254 ctlv->objsize = sizeof(ipfw_obj_ntlv); 2255 } 2256 2257 i = 0; 2258 tcount = da->tcount; 2259 ni = ipfw_get_table_objhash(chain); 2260 while (tcount > 0) { 2261 if ((bmask[i / 32] & (1 << (i % 32))) == 0) { 2262 i++; 2263 continue; 2264 } 2265 2266 /* Jump to shared named object bitmask */ 2267 if (i >= IPFW_TABLES_MAX) { 2268 ni = CHAIN_TO_SRV(chain); 2269 i -= IPFW_TABLES_MAX; 2270 bmask += IPFW_TABLES_MAX / 32; 2271 } 2272 2273 if ((error = export_objhash_ntlv(ni, i, sd)) != 0) 2274 return (error); 2275 2276 i++; 2277 tcount--; 2278 } 2279 2280 /* Dump rules */ 2281 ctlv = (ipfw_obj_ctlv *)ipfw_get_sopt_space(sd, sizeof(*ctlv)); 2282 if (ctlv == NULL) 2283 return (ENOMEM); 2284 ctlv->head.type = IPFW_TLV_RULE_LIST; 2285 ctlv->head.length = da->rsize + sizeof(*ctlv); 2286 ctlv->count = da->rcount; 2287 2288 for (i = da->b; i < da->e; i++) { 2289 krule = chain->map[i]; 2290 2291 l = RULEUSIZE1(krule) + sizeof(ipfw_obj_tlv); 2292 if (da->rcounters != 0) 2293 l += sizeof(struct ip_fw_bcounter); 2294 dst = (caddr_t)ipfw_get_sopt_space(sd, l); 2295 if (dst == NULL) 2296 return (ENOMEM); 2297 2298 export_rule1(krule, dst, l, da->rcounters); 2299 } 2300 2301 return (0); 2302 } 2303 2304 /* 2305 * Marks every object index used in @rule with bit in @bmask. 2306 * Used to generate bitmask of referenced tables/objects for given ruleset 2307 * or its part. 2308 * 2309 * Returns number of newly-referenced objects. 2310 */ 2311 static int 2312 mark_object_kidx(struct ip_fw_chain *ch, struct ip_fw *rule, 2313 uint32_t *bmask) 2314 { 2315 struct opcode_obj_rewrite *rw; 2316 ipfw_insn *cmd; 2317 int bidx, cmdlen, l, count; 2318 uint16_t kidx; 2319 uint8_t subtype; 2320 2321 l = rule->cmd_len; 2322 cmd = rule->cmd; 2323 cmdlen = 0; 2324 count = 0; 2325 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { 2326 cmdlen = F_LEN(cmd); 2327 2328 rw = find_op_rw(cmd, &kidx, &subtype); 2329 if (rw == NULL) 2330 continue; 2331 2332 bidx = kidx / 32; 2333 /* 2334 * Maintain separate bitmasks for table and 2335 * non-table objects. 2336 */ 2337 if (rw->etlv != IPFW_TLV_TBL_NAME) 2338 bidx += IPFW_TABLES_MAX / 32; 2339 2340 if ((bmask[bidx] & (1 << (kidx % 32))) == 0) 2341 count++; 2342 2343 bmask[bidx] |= 1 << (kidx % 32); 2344 } 2345 2346 return (count); 2347 } 2348 2349 /* 2350 * Dumps requested objects data 2351 * Data layout (version 0)(current): 2352 * Request: [ ipfw_cfg_lheader ] + IPFW_CFG_GET_* flags 2353 * size = ipfw_cfg_lheader.size 2354 * Reply: [ ipfw_cfg_lheader 2355 * [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional) 2356 * [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) 2357 * ipfw_obj_tlv(IPFW_TLV_RULE_ENT) [ ip_fw_bcounter (optional) ip_fw_rule ] 2358 * ] (optional) 2359 * [ ipfw_obj_ctlv(IPFW_TLV_STATE_LIST) ipfw_obj_dyntlv x N ] (optional) 2360 * ] 2361 * * NOTE IPFW_TLV_STATE_LIST has the single valid field: objsize. 2362 * The rest (size, count) are set to zero and needs to be ignored. 2363 * 2364 * Returns 0 on success. 2365 */ 2366 static int 2367 dump_config(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 2368 struct sockopt_data *sd) 2369 { 2370 ipfw_cfg_lheader *hdr; 2371 struct ip_fw *rule; 2372 size_t sz, rnum; 2373 uint32_t hdr_flags; 2374 int error, i; 2375 struct dump_args da; 2376 uint32_t *bmask; 2377 2378 hdr = (ipfw_cfg_lheader *)ipfw_get_sopt_header(sd, sizeof(*hdr)); 2379 if (hdr == NULL) 2380 return (EINVAL); 2381 2382 error = 0; 2383 bmask = NULL; 2384 /* Allocate needed state. Note we allocate 2xspace mask, for table&srv */ 2385 if (hdr->flags & IPFW_CFG_GET_STATIC) 2386 bmask = malloc(IPFW_TABLES_MAX / 4, M_TEMP, M_WAITOK | M_ZERO); 2387 2388 IPFW_UH_RLOCK(chain); 2389 2390 /* 2391 * STAGE 1: Determine size/count for objects in range. 2392 * Prepare used tables bitmask. 2393 */ 2394 sz = sizeof(ipfw_cfg_lheader); 2395 memset(&da, 0, sizeof(da)); 2396 2397 da.b = 0; 2398 da.e = chain->n_rules; 2399 2400 if (hdr->end_rule != 0) { 2401 /* Handle custom range */ 2402 if ((rnum = hdr->start_rule) > IPFW_DEFAULT_RULE) 2403 rnum = IPFW_DEFAULT_RULE; 2404 da.b = ipfw_find_rule(chain, rnum, 0); 2405 rnum = (hdr->end_rule < IPFW_DEFAULT_RULE) ? 2406 hdr->end_rule + 1: IPFW_DEFAULT_RULE; 2407 da.e = ipfw_find_rule(chain, rnum, UINT32_MAX) + 1; 2408 } 2409 2410 if (hdr->flags & IPFW_CFG_GET_STATIC) { 2411 for (i = da.b; i < da.e; i++) { 2412 rule = chain->map[i]; 2413 da.rsize += RULEUSIZE1(rule) + sizeof(ipfw_obj_tlv); 2414 da.rcount++; 2415 /* Update bitmask of used objects for given range */ 2416 da.tcount += mark_object_kidx(chain, rule, bmask); 2417 } 2418 /* Add counters if requested */ 2419 if (hdr->flags & IPFW_CFG_GET_COUNTERS) { 2420 da.rsize += sizeof(struct ip_fw_bcounter) * da.rcount; 2421 da.rcounters = 1; 2422 } 2423 2424 if (da.tcount > 0) 2425 sz += da.tcount * sizeof(ipfw_obj_ntlv) + 2426 sizeof(ipfw_obj_ctlv); 2427 sz += da.rsize + sizeof(ipfw_obj_ctlv); 2428 } 2429 2430 if (hdr->flags & IPFW_CFG_GET_STATES) 2431 sz += ipfw_dyn_get_count() * sizeof(ipfw_obj_dyntlv) + 2432 sizeof(ipfw_obj_ctlv); 2433 2434 2435 /* 2436 * Fill header anyway. 2437 * Note we have to save header fields to stable storage 2438 * buffer inside @sd can be flushed after dumping rules 2439 */ 2440 hdr->size = sz; 2441 hdr->set_mask = ~V_set_disable; 2442 hdr_flags = hdr->flags; 2443 hdr = NULL; 2444 2445 if (sd->valsize < sz) { 2446 error = ENOMEM; 2447 goto cleanup; 2448 } 2449 2450 /* STAGE2: Store actual data */ 2451 if (hdr_flags & IPFW_CFG_GET_STATIC) { 2452 error = dump_static_rules(chain, &da, bmask, sd); 2453 if (error != 0) 2454 goto cleanup; 2455 } 2456 2457 if (hdr_flags & IPFW_CFG_GET_STATES) 2458 error = ipfw_dump_states(chain, sd); 2459 2460 cleanup: 2461 IPFW_UH_RUNLOCK(chain); 2462 2463 if (bmask != NULL) 2464 free(bmask, M_TEMP); 2465 2466 return (error); 2467 } 2468 2469 int 2470 ipfw_check_object_name_generic(const char *name) 2471 { 2472 int nsize; 2473 2474 nsize = sizeof(((ipfw_obj_ntlv *)0)->name); 2475 if (strnlen(name, nsize) == nsize) 2476 return (EINVAL); 2477 if (name[0] == '\0') 2478 return (EINVAL); 2479 return (0); 2480 } 2481 2482 /* 2483 * Creates non-existent objects referenced by rule. 2484 * 2485 * Return 0 on success. 2486 */ 2487 int 2488 create_objects_compat(struct ip_fw_chain *ch, ipfw_insn *cmd, 2489 struct obj_idx *oib, struct obj_idx *pidx, struct tid_info *ti) 2490 { 2491 struct opcode_obj_rewrite *rw; 2492 struct obj_idx *p; 2493 uint16_t kidx; 2494 int error; 2495 2496 /* 2497 * Compatibility stuff: do actual creation for non-existing, 2498 * but referenced objects. 2499 */ 2500 for (p = oib; p < pidx; p++) { 2501 if (p->kidx != 0) 2502 continue; 2503 2504 ti->uidx = p->uidx; 2505 ti->type = p->type; 2506 ti->atype = 0; 2507 2508 rw = find_op_rw(cmd + p->off, NULL, NULL); 2509 KASSERT(rw != NULL, ("Unable to find handler for op %d", 2510 (cmd + p->off)->opcode)); 2511 2512 if (rw->create_object == NULL) 2513 error = EOPNOTSUPP; 2514 else 2515 error = rw->create_object(ch, ti, &kidx); 2516 if (error == 0) { 2517 p->kidx = kidx; 2518 continue; 2519 } 2520 2521 /* 2522 * Error happened. We have to rollback everything. 2523 * Drop all already acquired references. 2524 */ 2525 IPFW_UH_WLOCK(ch); 2526 unref_oib_objects(ch, cmd, oib, pidx); 2527 IPFW_UH_WUNLOCK(ch); 2528 2529 return (error); 2530 } 2531 2532 return (0); 2533 } 2534 2535 /* 2536 * Compatibility function for old ipfw(8) binaries. 2537 * Rewrites table/nat kernel indices with userland ones. 2538 * Convert tables matching '/^\d+$/' to their atoi() value. 2539 * Use number 65535 for other tables. 2540 * 2541 * Returns 0 on success. 2542 */ 2543 static int 2544 set_legacy_obj_kidx(struct ip_fw_chain *ch, struct ip_fw_rule0 *rule) 2545 { 2546 struct opcode_obj_rewrite *rw; 2547 struct named_object *no; 2548 ipfw_insn *cmd; 2549 char *end; 2550 long val; 2551 int cmdlen, error, l; 2552 uint16_t kidx, uidx; 2553 uint8_t subtype; 2554 2555 error = 0; 2556 2557 l = rule->cmd_len; 2558 cmd = rule->cmd; 2559 cmdlen = 0; 2560 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { 2561 cmdlen = F_LEN(cmd); 2562 2563 /* Check if is index in given opcode */ 2564 rw = find_op_rw(cmd, &kidx, &subtype); 2565 if (rw == NULL) 2566 continue; 2567 2568 /* Try to find referenced kernel object */ 2569 no = rw->find_bykidx(ch, kidx); 2570 if (no == NULL) 2571 continue; 2572 2573 val = strtol(no->name, &end, 10); 2574 if (*end == '\0' && val < 65535) { 2575 uidx = val; 2576 } else { 2577 2578 /* 2579 * We are called via legacy opcode. 2580 * Save error and show table as fake number 2581 * not to make ipfw(8) hang. 2582 */ 2583 uidx = 65535; 2584 error = 2; 2585 } 2586 2587 rw->update(cmd, uidx); 2588 } 2589 2590 return (error); 2591 } 2592 2593 2594 /* 2595 * Unreferences all already-referenced objects in given @cmd rule, 2596 * using information in @oib. 2597 * 2598 * Used to rollback partially converted rule on error. 2599 */ 2600 static void 2601 unref_oib_objects(struct ip_fw_chain *ch, ipfw_insn *cmd, struct obj_idx *oib, 2602 struct obj_idx *end) 2603 { 2604 struct opcode_obj_rewrite *rw; 2605 struct named_object *no; 2606 struct obj_idx *p; 2607 2608 IPFW_UH_WLOCK_ASSERT(ch); 2609 2610 for (p = oib; p < end; p++) { 2611 if (p->kidx == 0) 2612 continue; 2613 2614 rw = find_op_rw(cmd + p->off, NULL, NULL); 2615 KASSERT(rw != NULL, ("Unable to find handler for op %d", 2616 (cmd + p->off)->opcode)); 2617 2618 /* Find & unref by existing idx */ 2619 no = rw->find_bykidx(ch, p->kidx); 2620 KASSERT(no != NULL, ("Ref'd object %d disappeared", p->kidx)); 2621 no->refcnt--; 2622 } 2623 } 2624 2625 /* 2626 * Remove references from every object used in @rule. 2627 * Used at rule removal code. 2628 */ 2629 static void 2630 unref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule) 2631 { 2632 struct opcode_obj_rewrite *rw; 2633 struct named_object *no; 2634 ipfw_insn *cmd; 2635 int cmdlen, l; 2636 uint16_t kidx; 2637 uint8_t subtype; 2638 2639 IPFW_UH_WLOCK_ASSERT(ch); 2640 2641 l = rule->cmd_len; 2642 cmd = rule->cmd; 2643 cmdlen = 0; 2644 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { 2645 cmdlen = F_LEN(cmd); 2646 2647 rw = find_op_rw(cmd, &kidx, &subtype); 2648 if (rw == NULL) 2649 continue; 2650 no = rw->find_bykidx(ch, kidx); 2651 2652 KASSERT(no != NULL, ("object id %d not found", kidx)); 2653 KASSERT(no->subtype == subtype, 2654 ("wrong type %d (%d) for object id %d", 2655 no->subtype, subtype, kidx)); 2656 KASSERT(no->refcnt > 0, ("refcount for object %d is %d", 2657 kidx, no->refcnt)); 2658 2659 if (no->refcnt == 1 && rw->destroy_object != NULL) 2660 rw->destroy_object(ch, no); 2661 else 2662 no->refcnt--; 2663 } 2664 } 2665 2666 2667 /* 2668 * Find and reference object (if any) stored in instruction @cmd. 2669 * 2670 * Saves object info in @pidx, sets 2671 * - @unresolved to 1 if object should exists but not found 2672 * 2673 * Returns non-zero value in case of error. 2674 */ 2675 static int 2676 ref_opcode_object(struct ip_fw_chain *ch, ipfw_insn *cmd, struct tid_info *ti, 2677 struct obj_idx *pidx, int *unresolved) 2678 { 2679 struct named_object *no; 2680 struct opcode_obj_rewrite *rw; 2681 int error; 2682 2683 /* Check if this opcode is candidate for rewrite */ 2684 rw = find_op_rw(cmd, &ti->uidx, &ti->type); 2685 if (rw == NULL) 2686 return (0); 2687 2688 /* Need to rewrite. Save necessary fields */ 2689 pidx->uidx = ti->uidx; 2690 pidx->type = ti->type; 2691 2692 /* Try to find referenced kernel object */ 2693 error = rw->find_byname(ch, ti, &no); 2694 if (error != 0) 2695 return (error); 2696 if (no == NULL) { 2697 /* 2698 * Report about unresolved object for automaic 2699 * creation. 2700 */ 2701 *unresolved = 1; 2702 return (0); 2703 } 2704 2705 /* 2706 * Object is already exist. 2707 * Its subtype should match with expected value. 2708 */ 2709 if (ti->type != no->subtype) 2710 return (EINVAL); 2711 2712 /* Bump refcount and update kidx. */ 2713 no->refcnt++; 2714 rw->update(cmd, no->kidx); 2715 return (0); 2716 } 2717 2718 /* 2719 * Finds and bumps refcount for objects referenced by given @rule. 2720 * Auto-creates non-existing tables. 2721 * Fills in @oib array with userland/kernel indexes. 2722 * 2723 * Returns 0 on success. 2724 */ 2725 static int 2726 ref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule, 2727 struct rule_check_info *ci, struct obj_idx *oib, struct tid_info *ti) 2728 { 2729 struct obj_idx *pidx; 2730 ipfw_insn *cmd; 2731 int cmdlen, error, l, unresolved; 2732 2733 pidx = oib; 2734 l = rule->cmd_len; 2735 cmd = rule->cmd; 2736 cmdlen = 0; 2737 error = 0; 2738 2739 IPFW_UH_WLOCK(ch); 2740 2741 /* Increase refcount on each existing referenced table. */ 2742 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { 2743 cmdlen = F_LEN(cmd); 2744 unresolved = 0; 2745 2746 error = ref_opcode_object(ch, cmd, ti, pidx, &unresolved); 2747 if (error != 0) 2748 break; 2749 /* 2750 * Compatibility stuff for old clients: 2751 * prepare to automaitcally create non-existing objects. 2752 */ 2753 if (unresolved != 0) { 2754 pidx->off = rule->cmd_len - l; 2755 pidx++; 2756 } 2757 } 2758 2759 if (error != 0) { 2760 /* Unref everything we have already done */ 2761 unref_oib_objects(ch, rule->cmd, oib, pidx); 2762 IPFW_UH_WUNLOCK(ch); 2763 return (error); 2764 } 2765 IPFW_UH_WUNLOCK(ch); 2766 2767 /* Perform auto-creation for non-existing objects */ 2768 if (pidx != oib) 2769 error = create_objects_compat(ch, rule->cmd, oib, pidx, ti); 2770 2771 /* Calculate real number of dynamic objects */ 2772 ci->object_opcodes = (uint16_t)(pidx - oib); 2773 2774 return (error); 2775 } 2776 2777 /* 2778 * Checks is opcode is referencing table of appropriate type. 2779 * Adds reference count for found table if true. 2780 * Rewrites user-supplied opcode values with kernel ones. 2781 * 2782 * Returns 0 on success and appropriate error code otherwise. 2783 */ 2784 static int 2785 rewrite_rule_uidx(struct ip_fw_chain *chain, struct rule_check_info *ci) 2786 { 2787 int error; 2788 ipfw_insn *cmd; 2789 uint8_t type; 2790 struct obj_idx *p, *pidx_first, *pidx_last; 2791 struct tid_info ti; 2792 2793 /* 2794 * Prepare an array for storing opcode indices. 2795 * Use stack allocation by default. 2796 */ 2797 if (ci->object_opcodes <= (sizeof(ci->obuf)/sizeof(ci->obuf[0]))) { 2798 /* Stack */ 2799 pidx_first = ci->obuf; 2800 } else 2801 pidx_first = malloc( 2802 ci->object_opcodes * sizeof(struct obj_idx), 2803 M_IPFW, M_WAITOK | M_ZERO); 2804 2805 error = 0; 2806 type = 0; 2807 memset(&ti, 0, sizeof(ti)); 2808 2809 /* Use set rule is assigned to. */ 2810 ti.set = ci->krule->set; 2811 if (ci->ctlv != NULL) { 2812 ti.tlvs = (void *)(ci->ctlv + 1); 2813 ti.tlen = ci->ctlv->head.length - sizeof(ipfw_obj_ctlv); 2814 } 2815 2816 /* Reference all used tables and other objects */ 2817 error = ref_rule_objects(chain, ci->krule, ci, pidx_first, &ti); 2818 if (error != 0) 2819 goto free; 2820 /* 2821 * Note that ref_rule_objects() might have updated ci->object_opcodes 2822 * to reflect actual number of object opcodes. 2823 */ 2824 2825 /* Perform rewrite of remaining opcodes */ 2826 p = pidx_first; 2827 pidx_last = pidx_first + ci->object_opcodes; 2828 for (p = pidx_first; p < pidx_last; p++) { 2829 cmd = ci->krule->cmd + p->off; 2830 update_opcode_kidx(cmd, p->kidx); 2831 } 2832 2833 free: 2834 if (pidx_first != ci->obuf) 2835 free(pidx_first, M_IPFW); 2836 2837 return (error); 2838 } 2839 2840 /* 2841 * Adds one or more rules to ipfw @chain. 2842 * Data layout (version 0)(current): 2843 * Request: 2844 * [ 2845 * ip_fw3_opheader 2846 * [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional *1) 2847 * [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) ip_fw x N ] (*2) (*3) 2848 * ] 2849 * Reply: 2850 * [ 2851 * ip_fw3_opheader 2852 * [ ipfw_obj_ctlv(IPFW_TLV_TBL_LIST) ipfw_obj_ntlv x N ] (optional) 2853 * [ ipfw_obj_ctlv(IPFW_TLV_RULE_LIST) ip_fw x N ] 2854 * ] 2855 * 2856 * Rules in reply are modified to store their actual ruleset number. 2857 * 2858 * (*1) TLVs inside IPFW_TLV_TBL_LIST needs to be sorted ascending 2859 * according to their idx field and there has to be no duplicates. 2860 * (*2) Numbered rules inside IPFW_TLV_RULE_LIST needs to be sorted ascending. 2861 * (*3) Each ip_fw structure needs to be aligned to u64 boundary. 2862 * 2863 * Returns 0 on success. 2864 */ 2865 static int 2866 add_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 2867 struct sockopt_data *sd) 2868 { 2869 ipfw_obj_ctlv *ctlv, *rtlv, *tstate; 2870 ipfw_obj_ntlv *ntlv; 2871 int clen, error, idx; 2872 uint32_t count, read; 2873 struct ip_fw_rule *r; 2874 struct rule_check_info rci, *ci, *cbuf; 2875 int i, rsize; 2876 2877 op3 = (ip_fw3_opheader *)ipfw_get_sopt_space(sd, sd->valsize); 2878 ctlv = (ipfw_obj_ctlv *)(op3 + 1); 2879 2880 read = sizeof(ip_fw3_opheader); 2881 rtlv = NULL; 2882 tstate = NULL; 2883 cbuf = NULL; 2884 memset(&rci, 0, sizeof(struct rule_check_info)); 2885 2886 if (read + sizeof(*ctlv) > sd->valsize) 2887 return (EINVAL); 2888 2889 if (ctlv->head.type == IPFW_TLV_TBLNAME_LIST) { 2890 clen = ctlv->head.length; 2891 /* Check size and alignment */ 2892 if (clen > sd->valsize || clen < sizeof(*ctlv)) 2893 return (EINVAL); 2894 if ((clen % sizeof(uint64_t)) != 0) 2895 return (EINVAL); 2896 2897 /* 2898 * Some table names or other named objects. 2899 * Check for validness. 2900 */ 2901 count = (ctlv->head.length - sizeof(*ctlv)) / sizeof(*ntlv); 2902 if (ctlv->count != count || ctlv->objsize != sizeof(*ntlv)) 2903 return (EINVAL); 2904 2905 /* 2906 * Check each TLV. 2907 * Ensure TLVs are sorted ascending and 2908 * there are no duplicates. 2909 */ 2910 idx = -1; 2911 ntlv = (ipfw_obj_ntlv *)(ctlv + 1); 2912 while (count > 0) { 2913 if (ntlv->head.length != sizeof(ipfw_obj_ntlv)) 2914 return (EINVAL); 2915 2916 error = ipfw_check_object_name_generic(ntlv->name); 2917 if (error != 0) 2918 return (error); 2919 2920 if (ntlv->idx <= idx) 2921 return (EINVAL); 2922 2923 idx = ntlv->idx; 2924 count--; 2925 ntlv++; 2926 } 2927 2928 tstate = ctlv; 2929 read += ctlv->head.length; 2930 ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv + ctlv->head.length); 2931 } 2932 2933 if (read + sizeof(*ctlv) > sd->valsize) 2934 return (EINVAL); 2935 2936 if (ctlv->head.type == IPFW_TLV_RULE_LIST) { 2937 clen = ctlv->head.length; 2938 if (clen + read > sd->valsize || clen < sizeof(*ctlv)) 2939 return (EINVAL); 2940 if ((clen % sizeof(uint64_t)) != 0) 2941 return (EINVAL); 2942 2943 /* 2944 * TODO: Permit adding multiple rules at once 2945 */ 2946 if (ctlv->count != 1) 2947 return (ENOTSUP); 2948 2949 clen -= sizeof(*ctlv); 2950 2951 if (ctlv->count > clen / sizeof(struct ip_fw_rule)) 2952 return (EINVAL); 2953 2954 /* Allocate state for each rule or use stack */ 2955 if (ctlv->count == 1) { 2956 memset(&rci, 0, sizeof(struct rule_check_info)); 2957 cbuf = &rci; 2958 } else 2959 cbuf = malloc(ctlv->count * sizeof(*ci), M_TEMP, 2960 M_WAITOK | M_ZERO); 2961 ci = cbuf; 2962 2963 /* 2964 * Check each rule for validness. 2965 * Ensure numbered rules are sorted ascending 2966 * and properly aligned 2967 */ 2968 idx = 0; 2969 r = (struct ip_fw_rule *)(ctlv + 1); 2970 count = 0; 2971 error = 0; 2972 while (clen > 0) { 2973 rsize = roundup2(RULESIZE(r), sizeof(uint64_t)); 2974 if (rsize > clen || ctlv->count <= count) { 2975 error = EINVAL; 2976 break; 2977 } 2978 2979 ci->ctlv = tstate; 2980 error = check_ipfw_rule1(r, rsize, ci); 2981 if (error != 0) 2982 break; 2983 2984 /* Check sorting */ 2985 if (r->rulenum != 0 && r->rulenum < idx) { 2986 printf("rulenum %d idx %d\n", r->rulenum, idx); 2987 error = EINVAL; 2988 break; 2989 } 2990 idx = r->rulenum; 2991 2992 ci->urule = (caddr_t)r; 2993 2994 rsize = roundup2(rsize, sizeof(uint64_t)); 2995 clen -= rsize; 2996 r = (struct ip_fw_rule *)((caddr_t)r + rsize); 2997 count++; 2998 ci++; 2999 } 3000 3001 if (ctlv->count != count || error != 0) { 3002 if (cbuf != &rci) 3003 free(cbuf, M_TEMP); 3004 return (EINVAL); 3005 } 3006 3007 rtlv = ctlv; 3008 read += ctlv->head.length; 3009 ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv + ctlv->head.length); 3010 } 3011 3012 if (read != sd->valsize || rtlv == NULL || rtlv->count == 0) { 3013 if (cbuf != NULL && cbuf != &rci) 3014 free(cbuf, M_TEMP); 3015 return (EINVAL); 3016 } 3017 3018 /* 3019 * Passed rules seems to be valid. 3020 * Allocate storage and try to add them to chain. 3021 */ 3022 for (i = 0, ci = cbuf; i < rtlv->count; i++, ci++) { 3023 clen = RULEKSIZE1((struct ip_fw_rule *)ci->urule); 3024 ci->krule = ipfw_alloc_rule(chain, clen); 3025 import_rule1(ci); 3026 } 3027 3028 if ((error = commit_rules(chain, cbuf, rtlv->count)) != 0) { 3029 /* Free allocate krules */ 3030 for (i = 0, ci = cbuf; i < rtlv->count; i++, ci++) 3031 free_rule(ci->krule); 3032 } 3033 3034 if (cbuf != NULL && cbuf != &rci) 3035 free(cbuf, M_TEMP); 3036 3037 return (error); 3038 } 3039 3040 /* 3041 * Lists all sopts currently registered. 3042 * Data layout (v0)(current): 3043 * Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size 3044 * Reply: [ ipfw_obj_lheader ipfw_sopt_info x N ] 3045 * 3046 * Returns 0 on success 3047 */ 3048 static int 3049 dump_soptcodes(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 3050 struct sockopt_data *sd) 3051 { 3052 struct _ipfw_obj_lheader *olh; 3053 ipfw_sopt_info *i; 3054 struct ipfw_sopt_handler *sh; 3055 uint32_t count, n, size; 3056 3057 olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd,sizeof(*olh)); 3058 if (olh == NULL) 3059 return (EINVAL); 3060 if (sd->valsize < olh->size) 3061 return (EINVAL); 3062 3063 CTL3_LOCK(); 3064 count = ctl3_hsize; 3065 size = count * sizeof(ipfw_sopt_info) + sizeof(ipfw_obj_lheader); 3066 3067 /* Fill in header regadless of buffer size */ 3068 olh->count = count; 3069 olh->objsize = sizeof(ipfw_sopt_info); 3070 3071 if (size > olh->size) { 3072 olh->size = size; 3073 CTL3_UNLOCK(); 3074 return (ENOMEM); 3075 } 3076 olh->size = size; 3077 3078 for (n = 1; n <= count; n++) { 3079 i = (ipfw_sopt_info *)ipfw_get_sopt_space(sd, sizeof(*i)); 3080 KASSERT(i != NULL, ("previously checked buffer is not enough")); 3081 sh = &ctl3_handlers[n]; 3082 i->opcode = sh->opcode; 3083 i->version = sh->version; 3084 i->refcnt = sh->refcnt; 3085 } 3086 CTL3_UNLOCK(); 3087 3088 return (0); 3089 } 3090 3091 /* 3092 * Compares two opcodes. 3093 * Used both in qsort() and bsearch(). 3094 * 3095 * Returns 0 if match is found. 3096 */ 3097 static int 3098 compare_opcodes(const void *_a, const void *_b) 3099 { 3100 const struct opcode_obj_rewrite *a, *b; 3101 3102 a = (const struct opcode_obj_rewrite *)_a; 3103 b = (const struct opcode_obj_rewrite *)_b; 3104 3105 if (a->opcode < b->opcode) 3106 return (-1); 3107 else if (a->opcode > b->opcode) 3108 return (1); 3109 3110 return (0); 3111 } 3112 3113 /* 3114 * XXX: Rewrite bsearch() 3115 */ 3116 static int 3117 find_op_rw_range(uint16_t op, struct opcode_obj_rewrite **plo, 3118 struct opcode_obj_rewrite **phi) 3119 { 3120 struct opcode_obj_rewrite *ctl3_max, *lo, *hi, h, *rw; 3121 3122 memset(&h, 0, sizeof(h)); 3123 h.opcode = op; 3124 3125 rw = (struct opcode_obj_rewrite *)bsearch(&h, ctl3_rewriters, 3126 ctl3_rsize, sizeof(h), compare_opcodes); 3127 if (rw == NULL) 3128 return (1); 3129 3130 /* Find the first element matching the same opcode */ 3131 lo = rw; 3132 for ( ; lo > ctl3_rewriters && (lo - 1)->opcode == op; lo--) 3133 ; 3134 3135 /* Find the last element matching the same opcode */ 3136 hi = rw; 3137 ctl3_max = ctl3_rewriters + ctl3_rsize; 3138 for ( ; (hi + 1) < ctl3_max && (hi + 1)->opcode == op; hi++) 3139 ; 3140 3141 *plo = lo; 3142 *phi = hi; 3143 3144 return (0); 3145 } 3146 3147 /* 3148 * Finds opcode object rewriter based on @code. 3149 * 3150 * Returns pointer to handler or NULL. 3151 */ 3152 static struct opcode_obj_rewrite * 3153 find_op_rw(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype) 3154 { 3155 struct opcode_obj_rewrite *rw, *lo, *hi; 3156 uint16_t uidx; 3157 uint8_t subtype; 3158 3159 if (find_op_rw_range(cmd->opcode, &lo, &hi) != 0) 3160 return (NULL); 3161 3162 for (rw = lo; rw <= hi; rw++) { 3163 if (rw->classifier(cmd, &uidx, &subtype) == 0) { 3164 if (puidx != NULL) 3165 *puidx = uidx; 3166 if (ptype != NULL) 3167 *ptype = subtype; 3168 return (rw); 3169 } 3170 } 3171 3172 return (NULL); 3173 } 3174 int 3175 classify_opcode_kidx(ipfw_insn *cmd, uint16_t *puidx) 3176 { 3177 3178 if (find_op_rw(cmd, puidx, NULL) == NULL) 3179 return (1); 3180 return (0); 3181 } 3182 3183 void 3184 update_opcode_kidx(ipfw_insn *cmd, uint16_t idx) 3185 { 3186 struct opcode_obj_rewrite *rw; 3187 3188 rw = find_op_rw(cmd, NULL, NULL); 3189 KASSERT(rw != NULL, ("No handler to update opcode %d", cmd->opcode)); 3190 rw->update(cmd, idx); 3191 } 3192 3193 void 3194 ipfw_init_obj_rewriter() 3195 { 3196 3197 ctl3_rewriters = NULL; 3198 ctl3_rsize = 0; 3199 } 3200 3201 void 3202 ipfw_destroy_obj_rewriter() 3203 { 3204 3205 if (ctl3_rewriters != NULL) 3206 free(ctl3_rewriters, M_IPFW); 3207 ctl3_rewriters = NULL; 3208 ctl3_rsize = 0; 3209 } 3210 3211 /* 3212 * Adds one or more opcode object rewrite handlers to the global array. 3213 * Function may sleep. 3214 */ 3215 void 3216 ipfw_add_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count) 3217 { 3218 size_t sz; 3219 struct opcode_obj_rewrite *tmp; 3220 3221 CTL3_LOCK(); 3222 3223 for (;;) { 3224 sz = ctl3_rsize + count; 3225 CTL3_UNLOCK(); 3226 tmp = malloc(sizeof(*rw) * sz, M_IPFW, M_WAITOK | M_ZERO); 3227 CTL3_LOCK(); 3228 if (ctl3_rsize + count <= sz) 3229 break; 3230 3231 /* Retry */ 3232 free(tmp, M_IPFW); 3233 } 3234 3235 /* Merge old & new arrays */ 3236 sz = ctl3_rsize + count; 3237 memcpy(tmp, ctl3_rewriters, ctl3_rsize * sizeof(*rw)); 3238 memcpy(&tmp[ctl3_rsize], rw, count * sizeof(*rw)); 3239 qsort(tmp, sz, sizeof(*rw), compare_opcodes); 3240 /* Switch new and free old */ 3241 if (ctl3_rewriters != NULL) 3242 free(ctl3_rewriters, M_IPFW); 3243 ctl3_rewriters = tmp; 3244 ctl3_rsize = sz; 3245 3246 CTL3_UNLOCK(); 3247 } 3248 3249 /* 3250 * Removes one or more object rewrite handlers from the global array. 3251 */ 3252 int 3253 ipfw_del_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count) 3254 { 3255 size_t sz; 3256 struct opcode_obj_rewrite *ctl3_max, *ktmp, *lo, *hi; 3257 int i; 3258 3259 CTL3_LOCK(); 3260 3261 for (i = 0; i < count; i++) { 3262 if (find_op_rw_range(rw[i].opcode, &lo, &hi) != 0) 3263 continue; 3264 3265 for (ktmp = lo; ktmp <= hi; ktmp++) { 3266 if (ktmp->classifier != rw[i].classifier) 3267 continue; 3268 3269 ctl3_max = ctl3_rewriters + ctl3_rsize; 3270 sz = (ctl3_max - (ktmp + 1)) * sizeof(*ktmp); 3271 memmove(ktmp, ktmp + 1, sz); 3272 ctl3_rsize--; 3273 break; 3274 } 3275 3276 } 3277 3278 if (ctl3_rsize == 0) { 3279 if (ctl3_rewriters != NULL) 3280 free(ctl3_rewriters, M_IPFW); 3281 ctl3_rewriters = NULL; 3282 } 3283 3284 CTL3_UNLOCK(); 3285 3286 return (0); 3287 } 3288 3289 static int 3290 export_objhash_ntlv_internal(struct namedobj_instance *ni, 3291 struct named_object *no, void *arg) 3292 { 3293 struct sockopt_data *sd; 3294 ipfw_obj_ntlv *ntlv; 3295 3296 sd = (struct sockopt_data *)arg; 3297 ntlv = (ipfw_obj_ntlv *)ipfw_get_sopt_space(sd, sizeof(*ntlv)); 3298 if (ntlv == NULL) 3299 return (ENOMEM); 3300 ipfw_export_obj_ntlv(no, ntlv); 3301 return (0); 3302 } 3303 3304 /* 3305 * Lists all service objects. 3306 * Data layout (v0)(current): 3307 * Request: [ ipfw_obj_lheader ] size = ipfw_obj_lheader.size 3308 * Reply: [ ipfw_obj_lheader [ ipfw_obj_ntlv x N ] (optional) ] 3309 * Returns 0 on success 3310 */ 3311 static int 3312 dump_srvobjects(struct ip_fw_chain *chain, ip_fw3_opheader *op3, 3313 struct sockopt_data *sd) 3314 { 3315 ipfw_obj_lheader *hdr; 3316 int count; 3317 3318 hdr = (ipfw_obj_lheader *)ipfw_get_sopt_header(sd, sizeof(*hdr)); 3319 if (hdr == NULL) 3320 return (EINVAL); 3321 3322 IPFW_UH_RLOCK(chain); 3323 count = ipfw_objhash_count(CHAIN_TO_SRV(chain)); 3324 hdr->size = sizeof(ipfw_obj_lheader) + count * sizeof(ipfw_obj_ntlv); 3325 if (sd->valsize < hdr->size) { 3326 IPFW_UH_RUNLOCK(chain); 3327 return (ENOMEM); 3328 } 3329 hdr->count = count; 3330 hdr->objsize = sizeof(ipfw_obj_ntlv); 3331 if (count > 0) 3332 ipfw_objhash_foreach(CHAIN_TO_SRV(chain), 3333 export_objhash_ntlv_internal, sd); 3334 IPFW_UH_RUNLOCK(chain); 3335 return (0); 3336 } 3337 3338 /* 3339 * Compares two sopt handlers (code, version and handler ptr). 3340 * Used both as qsort() and bsearch(). 3341 * Does not compare handler for latter case. 3342 * 3343 * Returns 0 if match is found. 3344 */ 3345 static int 3346 compare_sh(const void *_a, const void *_b) 3347 { 3348 const struct ipfw_sopt_handler *a, *b; 3349 3350 a = (const struct ipfw_sopt_handler *)_a; 3351 b = (const struct ipfw_sopt_handler *)_b; 3352 3353 if (a->opcode < b->opcode) 3354 return (-1); 3355 else if (a->opcode > b->opcode) 3356 return (1); 3357 3358 if (a->version < b->version) 3359 return (-1); 3360 else if (a->version > b->version) 3361 return (1); 3362 3363 /* bsearch helper */ 3364 if (a->handler == NULL) 3365 return (0); 3366 3367 if ((uintptr_t)a->handler < (uintptr_t)b->handler) 3368 return (-1); 3369 else if ((uintptr_t)a->handler > (uintptr_t)b->handler) 3370 return (1); 3371 3372 return (0); 3373 } 3374 3375 /* 3376 * Finds sopt handler based on @code and @version. 3377 * 3378 * Returns pointer to handler or NULL. 3379 */ 3380 static struct ipfw_sopt_handler * 3381 find_sh(uint16_t code, uint8_t version, sopt_handler_f *handler) 3382 { 3383 struct ipfw_sopt_handler *sh, h; 3384 3385 memset(&h, 0, sizeof(h)); 3386 h.opcode = code; 3387 h.version = version; 3388 h.handler = handler; 3389 3390 sh = (struct ipfw_sopt_handler *)bsearch(&h, ctl3_handlers, 3391 ctl3_hsize, sizeof(h), compare_sh); 3392 3393 return (sh); 3394 } 3395 3396 static int 3397 find_ref_sh(uint16_t opcode, uint8_t version, struct ipfw_sopt_handler *psh) 3398 { 3399 struct ipfw_sopt_handler *sh; 3400 3401 CTL3_LOCK(); 3402 if ((sh = find_sh(opcode, version, NULL)) == NULL) { 3403 CTL3_UNLOCK(); 3404 printf("ipfw: ipfw_ctl3 invalid option %d""v""%d\n", 3405 opcode, version); 3406 return (EINVAL); 3407 } 3408 sh->refcnt++; 3409 ctl3_refct++; 3410 /* Copy handler data to requested buffer */ 3411 *psh = *sh; 3412 CTL3_UNLOCK(); 3413 3414 return (0); 3415 } 3416 3417 static void 3418 find_unref_sh(struct ipfw_sopt_handler *psh) 3419 { 3420 struct ipfw_sopt_handler *sh; 3421 3422 CTL3_LOCK(); 3423 sh = find_sh(psh->opcode, psh->version, NULL); 3424 KASSERT(sh != NULL, ("ctl3 handler disappeared")); 3425 sh->refcnt--; 3426 ctl3_refct--; 3427 CTL3_UNLOCK(); 3428 } 3429 3430 void 3431 ipfw_init_sopt_handler() 3432 { 3433 3434 CTL3_LOCK_INIT(); 3435 IPFW_ADD_SOPT_HANDLER(1, scodes); 3436 } 3437 3438 void 3439 ipfw_destroy_sopt_handler() 3440 { 3441 3442 IPFW_DEL_SOPT_HANDLER(1, scodes); 3443 CTL3_LOCK_DESTROY(); 3444 } 3445 3446 /* 3447 * Adds one or more sockopt handlers to the global array. 3448 * Function may sleep. 3449 */ 3450 void 3451 ipfw_add_sopt_handler(struct ipfw_sopt_handler *sh, size_t count) 3452 { 3453 size_t sz; 3454 struct ipfw_sopt_handler *tmp; 3455 3456 CTL3_LOCK(); 3457 3458 for (;;) { 3459 sz = ctl3_hsize + count; 3460 CTL3_UNLOCK(); 3461 tmp = malloc(sizeof(*sh) * sz, M_IPFW, M_WAITOK | M_ZERO); 3462 CTL3_LOCK(); 3463 if (ctl3_hsize + count <= sz) 3464 break; 3465 3466 /* Retry */ 3467 free(tmp, M_IPFW); 3468 } 3469 3470 /* Merge old & new arrays */ 3471 sz = ctl3_hsize + count; 3472 memcpy(tmp, ctl3_handlers, ctl3_hsize * sizeof(*sh)); 3473 memcpy(&tmp[ctl3_hsize], sh, count * sizeof(*sh)); 3474 qsort(tmp, sz, sizeof(*sh), compare_sh); 3475 /* Switch new and free old */ 3476 if (ctl3_handlers != NULL) 3477 free(ctl3_handlers, M_IPFW); 3478 ctl3_handlers = tmp; 3479 ctl3_hsize = sz; 3480 ctl3_gencnt++; 3481 3482 CTL3_UNLOCK(); 3483 } 3484 3485 /* 3486 * Removes one or more sockopt handlers from the global array. 3487 */ 3488 int 3489 ipfw_del_sopt_handler(struct ipfw_sopt_handler *sh, size_t count) 3490 { 3491 size_t sz; 3492 struct ipfw_sopt_handler *tmp, *h; 3493 int i; 3494 3495 CTL3_LOCK(); 3496 3497 for (i = 0; i < count; i++) { 3498 tmp = &sh[i]; 3499 h = find_sh(tmp->opcode, tmp->version, tmp->handler); 3500 if (h == NULL) 3501 continue; 3502 3503 sz = (ctl3_handlers + ctl3_hsize - (h + 1)) * sizeof(*h); 3504 memmove(h, h + 1, sz); 3505 ctl3_hsize--; 3506 } 3507 3508 if (ctl3_hsize == 0) { 3509 if (ctl3_handlers != NULL) 3510 free(ctl3_handlers, M_IPFW); 3511 ctl3_handlers = NULL; 3512 } 3513 3514 ctl3_gencnt++; 3515 3516 CTL3_UNLOCK(); 3517 3518 return (0); 3519 } 3520 3521 /* 3522 * Writes data accumulated in @sd to sockopt buffer. 3523 * Zeroes internal @sd buffer. 3524 */ 3525 static int 3526 ipfw_flush_sopt_data(struct sockopt_data *sd) 3527 { 3528 struct sockopt *sopt; 3529 int error; 3530 size_t sz; 3531 3532 sz = sd->koff; 3533 if (sz == 0) 3534 return (0); 3535 3536 sopt = sd->sopt; 3537 3538 if (sopt->sopt_dir == SOPT_GET) { 3539 error = copyout(sd->kbuf, sopt->sopt_val, sz); 3540 if (error != 0) 3541 return (error); 3542 } 3543 3544 memset(sd->kbuf, 0, sd->ksize); 3545 sd->ktotal += sz; 3546 sd->koff = 0; 3547 if (sd->ktotal + sd->ksize < sd->valsize) 3548 sd->kavail = sd->ksize; 3549 else 3550 sd->kavail = sd->valsize - sd->ktotal; 3551 3552 /* Update sopt buffer data */ 3553 sopt->sopt_valsize = sd->ktotal; 3554 sopt->sopt_val = sd->sopt_val + sd->ktotal; 3555 3556 return (0); 3557 } 3558 3559 /* 3560 * Ensures that @sd buffer has contiguous @neeeded number of 3561 * bytes. 3562 * 3563 * Returns pointer to requested space or NULL. 3564 */ 3565 caddr_t 3566 ipfw_get_sopt_space(struct sockopt_data *sd, size_t needed) 3567 { 3568 int error; 3569 caddr_t addr; 3570 3571 if (sd->kavail < needed) { 3572 /* 3573 * Flush data and try another time. 3574 */ 3575 error = ipfw_flush_sopt_data(sd); 3576 3577 if (sd->kavail < needed || error != 0) 3578 return (NULL); 3579 } 3580 3581 addr = sd->kbuf + sd->koff; 3582 sd->koff += needed; 3583 sd->kavail -= needed; 3584 return (addr); 3585 } 3586 3587 /* 3588 * Requests @needed contiguous bytes from @sd buffer. 3589 * Function is used to notify subsystem that we are 3590 * interesed in first @needed bytes (request header) 3591 * and the rest buffer can be safely zeroed. 3592 * 3593 * Returns pointer to requested space or NULL. 3594 */ 3595 caddr_t 3596 ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed) 3597 { 3598 caddr_t addr; 3599 3600 if ((addr = ipfw_get_sopt_space(sd, needed)) == NULL) 3601 return (NULL); 3602 3603 if (sd->kavail > 0) 3604 memset(sd->kbuf + sd->koff, 0, sd->kavail); 3605 3606 return (addr); 3607 } 3608 3609 /* 3610 * New sockopt handler. 3611 */ 3612 int 3613 ipfw_ctl3(struct sockopt *sopt) 3614 { 3615 int error, locked; 3616 size_t size, valsize; 3617 struct ip_fw_chain *chain; 3618 char xbuf[256]; 3619 struct sockopt_data sdata; 3620 struct ipfw_sopt_handler h; 3621 ip_fw3_opheader *op3 = NULL; 3622 3623 error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW); 3624 if (error != 0) 3625 return (error); 3626 3627 if (sopt->sopt_name != IP_FW3) 3628 return (ipfw_ctl(sopt)); 3629 3630 chain = &V_layer3_chain; 3631 error = 0; 3632 3633 /* Save original valsize before it is altered via sooptcopyin() */ 3634 valsize = sopt->sopt_valsize; 3635 memset(&sdata, 0, sizeof(sdata)); 3636 /* Read op3 header first to determine actual operation */ 3637 op3 = (ip_fw3_opheader *)xbuf; 3638 error = sooptcopyin(sopt, op3, sizeof(*op3), sizeof(*op3)); 3639 if (error != 0) 3640 return (error); 3641 sopt->sopt_valsize = valsize; 3642 3643 /* 3644 * Find and reference command. 3645 */ 3646 error = find_ref_sh(op3->opcode, op3->version, &h); 3647 if (error != 0) 3648 return (error); 3649 3650 /* 3651 * Disallow modifications in really-really secure mode, but still allow 3652 * the logging counters to be reset. 3653 */ 3654 if ((h.dir & HDIR_SET) != 0 && h.opcode != IP_FW_XRESETLOG) { 3655 error = securelevel_ge(sopt->sopt_td->td_ucred, 3); 3656 if (error != 0) { 3657 find_unref_sh(&h); 3658 return (error); 3659 } 3660 } 3661 3662 /* 3663 * Fill in sockopt_data structure that may be useful for 3664 * IP_FW3 get requests. 3665 */ 3666 locked = 0; 3667 if (valsize <= sizeof(xbuf)) { 3668 /* use on-stack buffer */ 3669 sdata.kbuf = xbuf; 3670 sdata.ksize = sizeof(xbuf); 3671 sdata.kavail = valsize; 3672 } else { 3673 3674 /* 3675 * Determine opcode type/buffer size: 3676 * allocate sliding-window buf for data export or 3677 * contiguous buffer for special ops. 3678 */ 3679 if ((h.dir & HDIR_SET) != 0) { 3680 /* Set request. Allocate contigous buffer. */ 3681 if (valsize > CTL3_LARGEBUF) { 3682 find_unref_sh(&h); 3683 return (EFBIG); 3684 } 3685 3686 size = valsize; 3687 } else { 3688 /* Get request. Allocate sliding window buffer */ 3689 size = (valsize<CTL3_SMALLBUF) ? valsize:CTL3_SMALLBUF; 3690 3691 if (size < valsize) { 3692 /* We have to wire user buffer */ 3693 error = vslock(sopt->sopt_val, valsize); 3694 if (error != 0) 3695 return (error); 3696 locked = 1; 3697 } 3698 } 3699 3700 sdata.kbuf = malloc(size, M_TEMP, M_WAITOK | M_ZERO); 3701 sdata.ksize = size; 3702 sdata.kavail = size; 3703 } 3704 3705 sdata.sopt = sopt; 3706 sdata.sopt_val = sopt->sopt_val; 3707 sdata.valsize = valsize; 3708 3709 /* 3710 * Copy either all request (if valsize < bsize_max) 3711 * or first bsize_max bytes to guarantee most consumers 3712 * that all necessary data has been copied). 3713 * Anyway, copy not less than sizeof(ip_fw3_opheader). 3714 */ 3715 if ((error = sooptcopyin(sopt, sdata.kbuf, sdata.ksize, 3716 sizeof(ip_fw3_opheader))) != 0) 3717 return (error); 3718 op3 = (ip_fw3_opheader *)sdata.kbuf; 3719 3720 /* Finally, run handler */ 3721 error = h.handler(chain, op3, &sdata); 3722 find_unref_sh(&h); 3723 3724 /* Flush state and free buffers */ 3725 if (error == 0) 3726 error = ipfw_flush_sopt_data(&sdata); 3727 else 3728 ipfw_flush_sopt_data(&sdata); 3729 3730 if (locked != 0) 3731 vsunlock(sdata.sopt_val, valsize); 3732 3733 /* Restore original pointer and set number of bytes written */ 3734 sopt->sopt_val = sdata.sopt_val; 3735 sopt->sopt_valsize = sdata.ktotal; 3736 if (sdata.kbuf != xbuf) 3737 free(sdata.kbuf, M_TEMP); 3738 3739 return (error); 3740 } 3741 3742 /** 3743 * {set|get}sockopt parser. 3744 */ 3745 int 3746 ipfw_ctl(struct sockopt *sopt) 3747 { 3748 #define RULE_MAXSIZE (512*sizeof(u_int32_t)) 3749 int error; 3750 size_t size, valsize; 3751 struct ip_fw *buf; 3752 struct ip_fw_rule0 *rule; 3753 struct ip_fw_chain *chain; 3754 u_int32_t rulenum[2]; 3755 uint32_t opt; 3756 struct rule_check_info ci; 3757 IPFW_RLOCK_TRACKER; 3758 3759 chain = &V_layer3_chain; 3760 error = 0; 3761 3762 /* Save original valsize before it is altered via sooptcopyin() */ 3763 valsize = sopt->sopt_valsize; 3764 opt = sopt->sopt_name; 3765 3766 /* 3767 * Disallow modifications in really-really secure mode, but still allow 3768 * the logging counters to be reset. 3769 */ 3770 if (opt == IP_FW_ADD || 3771 (sopt->sopt_dir == SOPT_SET && opt != IP_FW_RESETLOG)) { 3772 error = securelevel_ge(sopt->sopt_td->td_ucred, 3); 3773 if (error != 0) 3774 return (error); 3775 } 3776 3777 switch (opt) { 3778 case IP_FW_GET: 3779 /* 3780 * pass up a copy of the current rules. Static rules 3781 * come first (the last of which has number IPFW_DEFAULT_RULE), 3782 * followed by a possibly empty list of dynamic rule. 3783 * The last dynamic rule has NULL in the "next" field. 3784 * 3785 * Note that the calculated size is used to bound the 3786 * amount of data returned to the user. The rule set may 3787 * change between calculating the size and returning the 3788 * data in which case we'll just return what fits. 3789 */ 3790 for (;;) { 3791 int len = 0, want; 3792 3793 size = chain->static_len; 3794 size += ipfw_dyn_len(); 3795 if (size >= sopt->sopt_valsize) 3796 break; 3797 buf = malloc(size, M_TEMP, M_WAITOK | M_ZERO); 3798 IPFW_UH_RLOCK(chain); 3799 /* check again how much space we need */ 3800 want = chain->static_len + ipfw_dyn_len(); 3801 if (size >= want) 3802 len = ipfw_getrules(chain, buf, size); 3803 IPFW_UH_RUNLOCK(chain); 3804 if (size >= want) 3805 error = sooptcopyout(sopt, buf, len); 3806 free(buf, M_TEMP); 3807 if (size >= want) 3808 break; 3809 } 3810 break; 3811 3812 case IP_FW_FLUSH: 3813 /* locking is done within del_entry() */ 3814 error = del_entry(chain, 0); /* special case, rule=0, cmd=0 means all */ 3815 break; 3816 3817 case IP_FW_ADD: 3818 rule = malloc(RULE_MAXSIZE, M_TEMP, M_WAITOK); 3819 error = sooptcopyin(sopt, rule, RULE_MAXSIZE, 3820 sizeof(struct ip_fw7) ); 3821 3822 memset(&ci, 0, sizeof(struct rule_check_info)); 3823 3824 /* 3825 * If the size of commands equals RULESIZE7 then we assume 3826 * a FreeBSD7.2 binary is talking to us (set is7=1). 3827 * is7 is persistent so the next 'ipfw list' command 3828 * will use this format. 3829 * NOTE: If wrong version is guessed (this can happen if 3830 * the first ipfw command is 'ipfw [pipe] list') 3831 * the ipfw binary may crash or loop infinitly... 3832 */ 3833 size = sopt->sopt_valsize; 3834 if (size == RULESIZE7(rule)) { 3835 is7 = 1; 3836 error = convert_rule_to_8(rule); 3837 if (error) { 3838 free(rule, M_TEMP); 3839 return error; 3840 } 3841 size = RULESIZE(rule); 3842 } else 3843 is7 = 0; 3844 if (error == 0) 3845 error = check_ipfw_rule0(rule, size, &ci); 3846 if (error == 0) { 3847 /* locking is done within add_rule() */ 3848 struct ip_fw *krule; 3849 krule = ipfw_alloc_rule(chain, RULEKSIZE0(rule)); 3850 ci.urule = (caddr_t)rule; 3851 ci.krule = krule; 3852 import_rule0(&ci); 3853 error = commit_rules(chain, &ci, 1); 3854 if (error != 0) 3855 free_rule(ci.krule); 3856 else if (sopt->sopt_dir == SOPT_GET) { 3857 if (is7) { 3858 error = convert_rule_to_7(rule); 3859 size = RULESIZE7(rule); 3860 if (error) { 3861 free(rule, M_TEMP); 3862 return error; 3863 } 3864 } 3865 error = sooptcopyout(sopt, rule, size); 3866 } 3867 } 3868 free(rule, M_TEMP); 3869 break; 3870 3871 case IP_FW_DEL: 3872 /* 3873 * IP_FW_DEL is used for deleting single rules or sets, 3874 * and (ab)used to atomically manipulate sets. Argument size 3875 * is used to distinguish between the two: 3876 * sizeof(u_int32_t) 3877 * delete single rule or set of rules, 3878 * or reassign rules (or sets) to a different set. 3879 * 2*sizeof(u_int32_t) 3880 * atomic disable/enable sets. 3881 * first u_int32_t contains sets to be disabled, 3882 * second u_int32_t contains sets to be enabled. 3883 */ 3884 error = sooptcopyin(sopt, rulenum, 3885 2*sizeof(u_int32_t), sizeof(u_int32_t)); 3886 if (error) 3887 break; 3888 size = sopt->sopt_valsize; 3889 if (size == sizeof(u_int32_t) && rulenum[0] != 0) { 3890 /* delete or reassign, locking done in del_entry() */ 3891 error = del_entry(chain, rulenum[0]); 3892 } else if (size == 2*sizeof(u_int32_t)) { /* set enable/disable */ 3893 IPFW_UH_WLOCK(chain); 3894 V_set_disable = 3895 (V_set_disable | rulenum[0]) & ~rulenum[1] & 3896 ~(1<<RESVD_SET); /* set RESVD_SET always enabled */ 3897 IPFW_UH_WUNLOCK(chain); 3898 } else 3899 error = EINVAL; 3900 break; 3901 3902 case IP_FW_ZERO: 3903 case IP_FW_RESETLOG: /* argument is an u_int_32, the rule number */ 3904 rulenum[0] = 0; 3905 if (sopt->sopt_val != 0) { 3906 error = sooptcopyin(sopt, rulenum, 3907 sizeof(u_int32_t), sizeof(u_int32_t)); 3908 if (error) 3909 break; 3910 } 3911 error = zero_entry(chain, rulenum[0], 3912 sopt->sopt_name == IP_FW_RESETLOG); 3913 break; 3914 3915 /*--- TABLE opcodes ---*/ 3916 case IP_FW_TABLE_ADD: 3917 case IP_FW_TABLE_DEL: 3918 { 3919 ipfw_table_entry ent; 3920 struct tentry_info tei; 3921 struct tid_info ti; 3922 struct table_value v; 3923 3924 error = sooptcopyin(sopt, &ent, 3925 sizeof(ent), sizeof(ent)); 3926 if (error) 3927 break; 3928 3929 memset(&tei, 0, sizeof(tei)); 3930 tei.paddr = &ent.addr; 3931 tei.subtype = AF_INET; 3932 tei.masklen = ent.masklen; 3933 ipfw_import_table_value_legacy(ent.value, &v); 3934 tei.pvalue = &v; 3935 memset(&ti, 0, sizeof(ti)); 3936 ti.uidx = ent.tbl; 3937 ti.type = IPFW_TABLE_CIDR; 3938 3939 error = (opt == IP_FW_TABLE_ADD) ? 3940 add_table_entry(chain, &ti, &tei, 0, 1) : 3941 del_table_entry(chain, &ti, &tei, 0, 1); 3942 } 3943 break; 3944 3945 3946 case IP_FW_TABLE_FLUSH: 3947 { 3948 u_int16_t tbl; 3949 struct tid_info ti; 3950 3951 error = sooptcopyin(sopt, &tbl, 3952 sizeof(tbl), sizeof(tbl)); 3953 if (error) 3954 break; 3955 memset(&ti, 0, sizeof(ti)); 3956 ti.uidx = tbl; 3957 error = flush_table(chain, &ti); 3958 } 3959 break; 3960 3961 case IP_FW_TABLE_GETSIZE: 3962 { 3963 u_int32_t tbl, cnt; 3964 struct tid_info ti; 3965 3966 if ((error = sooptcopyin(sopt, &tbl, sizeof(tbl), 3967 sizeof(tbl)))) 3968 break; 3969 memset(&ti, 0, sizeof(ti)); 3970 ti.uidx = tbl; 3971 IPFW_RLOCK(chain); 3972 error = ipfw_count_table(chain, &ti, &cnt); 3973 IPFW_RUNLOCK(chain); 3974 if (error) 3975 break; 3976 error = sooptcopyout(sopt, &cnt, sizeof(cnt)); 3977 } 3978 break; 3979 3980 case IP_FW_TABLE_LIST: 3981 { 3982 ipfw_table *tbl; 3983 struct tid_info ti; 3984 3985 if (sopt->sopt_valsize < sizeof(*tbl)) { 3986 error = EINVAL; 3987 break; 3988 } 3989 size = sopt->sopt_valsize; 3990 tbl = malloc(size, M_TEMP, M_WAITOK); 3991 error = sooptcopyin(sopt, tbl, size, sizeof(*tbl)); 3992 if (error) { 3993 free(tbl, M_TEMP); 3994 break; 3995 } 3996 tbl->size = (size - sizeof(*tbl)) / 3997 sizeof(ipfw_table_entry); 3998 memset(&ti, 0, sizeof(ti)); 3999 ti.uidx = tbl->tbl; 4000 IPFW_RLOCK(chain); 4001 error = ipfw_dump_table_legacy(chain, &ti, tbl); 4002 IPFW_RUNLOCK(chain); 4003 if (error) { 4004 free(tbl, M_TEMP); 4005 break; 4006 } 4007 error = sooptcopyout(sopt, tbl, size); 4008 free(tbl, M_TEMP); 4009 } 4010 break; 4011 4012 /*--- NAT operations are protected by the IPFW_LOCK ---*/ 4013 case IP_FW_NAT_CFG: 4014 if (IPFW_NAT_LOADED) 4015 error = ipfw_nat_cfg_ptr(sopt); 4016 else { 4017 printf("IP_FW_NAT_CFG: %s\n", 4018 "ipfw_nat not present, please load it"); 4019 error = EINVAL; 4020 } 4021 break; 4022 4023 case IP_FW_NAT_DEL: 4024 if (IPFW_NAT_LOADED) 4025 error = ipfw_nat_del_ptr(sopt); 4026 else { 4027 printf("IP_FW_NAT_DEL: %s\n", 4028 "ipfw_nat not present, please load it"); 4029 error = EINVAL; 4030 } 4031 break; 4032 4033 case IP_FW_NAT_GET_CONFIG: 4034 if (IPFW_NAT_LOADED) 4035 error = ipfw_nat_get_cfg_ptr(sopt); 4036 else { 4037 printf("IP_FW_NAT_GET_CFG: %s\n", 4038 "ipfw_nat not present, please load it"); 4039 error = EINVAL; 4040 } 4041 break; 4042 4043 case IP_FW_NAT_GET_LOG: 4044 if (IPFW_NAT_LOADED) 4045 error = ipfw_nat_get_log_ptr(sopt); 4046 else { 4047 printf("IP_FW_NAT_GET_LOG: %s\n", 4048 "ipfw_nat not present, please load it"); 4049 error = EINVAL; 4050 } 4051 break; 4052 4053 default: 4054 printf("ipfw: ipfw_ctl invalid option %d\n", sopt->sopt_name); 4055 error = EINVAL; 4056 } 4057 4058 return (error); 4059 #undef RULE_MAXSIZE 4060 } 4061 #define RULE_MAXSIZE (256*sizeof(u_int32_t)) 4062 4063 /* Functions to convert rules 7.2 <==> 8.0 */ 4064 static int 4065 convert_rule_to_7(struct ip_fw_rule0 *rule) 4066 { 4067 /* Used to modify original rule */ 4068 struct ip_fw7 *rule7 = (struct ip_fw7 *)rule; 4069 /* copy of original rule, version 8 */ 4070 struct ip_fw_rule0 *tmp; 4071 4072 /* Used to copy commands */ 4073 ipfw_insn *ccmd, *dst; 4074 int ll = 0, ccmdlen = 0; 4075 4076 tmp = malloc(RULE_MAXSIZE, M_TEMP, M_NOWAIT | M_ZERO); 4077 if (tmp == NULL) { 4078 return 1; //XXX error 4079 } 4080 bcopy(rule, tmp, RULE_MAXSIZE); 4081 4082 /* Copy fields */ 4083 //rule7->_pad = tmp->_pad; 4084 rule7->set = tmp->set; 4085 rule7->rulenum = tmp->rulenum; 4086 rule7->cmd_len = tmp->cmd_len; 4087 rule7->act_ofs = tmp->act_ofs; 4088 rule7->next_rule = (struct ip_fw7 *)tmp->next_rule; 4089 rule7->cmd_len = tmp->cmd_len; 4090 rule7->pcnt = tmp->pcnt; 4091 rule7->bcnt = tmp->bcnt; 4092 rule7->timestamp = tmp->timestamp; 4093 4094 /* Copy commands */ 4095 for (ll = tmp->cmd_len, ccmd = tmp->cmd, dst = rule7->cmd ; 4096 ll > 0 ; ll -= ccmdlen, ccmd += ccmdlen, dst += ccmdlen) { 4097 ccmdlen = F_LEN(ccmd); 4098 4099 bcopy(ccmd, dst, F_LEN(ccmd)*sizeof(uint32_t)); 4100 4101 if (dst->opcode > O_NAT) 4102 /* O_REASS doesn't exists in 7.2 version, so 4103 * decrement opcode if it is after O_REASS 4104 */ 4105 dst->opcode--; 4106 4107 if (ccmdlen > ll) { 4108 printf("ipfw: opcode %d size truncated\n", 4109 ccmd->opcode); 4110 return EINVAL; 4111 } 4112 } 4113 free(tmp, M_TEMP); 4114 4115 return 0; 4116 } 4117 4118 static int 4119 convert_rule_to_8(struct ip_fw_rule0 *rule) 4120 { 4121 /* Used to modify original rule */ 4122 struct ip_fw7 *rule7 = (struct ip_fw7 *) rule; 4123 4124 /* Used to copy commands */ 4125 ipfw_insn *ccmd, *dst; 4126 int ll = 0, ccmdlen = 0; 4127 4128 /* Copy of original rule */ 4129 struct ip_fw7 *tmp = malloc(RULE_MAXSIZE, M_TEMP, M_NOWAIT | M_ZERO); 4130 if (tmp == NULL) { 4131 return 1; //XXX error 4132 } 4133 4134 bcopy(rule7, tmp, RULE_MAXSIZE); 4135 4136 for (ll = tmp->cmd_len, ccmd = tmp->cmd, dst = rule->cmd ; 4137 ll > 0 ; ll -= ccmdlen, ccmd += ccmdlen, dst += ccmdlen) { 4138 ccmdlen = F_LEN(ccmd); 4139 4140 bcopy(ccmd, dst, F_LEN(ccmd)*sizeof(uint32_t)); 4141 4142 if (dst->opcode > O_NAT) 4143 /* O_REASS doesn't exists in 7.2 version, so 4144 * increment opcode if it is after O_REASS 4145 */ 4146 dst->opcode++; 4147 4148 if (ccmdlen > ll) { 4149 printf("ipfw: opcode %d size truncated\n", 4150 ccmd->opcode); 4151 return EINVAL; 4152 } 4153 } 4154 4155 rule->_pad = tmp->_pad; 4156 rule->set = tmp->set; 4157 rule->rulenum = tmp->rulenum; 4158 rule->cmd_len = tmp->cmd_len; 4159 rule->act_ofs = tmp->act_ofs; 4160 rule->next_rule = (struct ip_fw *)tmp->next_rule; 4161 rule->cmd_len = tmp->cmd_len; 4162 rule->id = 0; /* XXX see if is ok = 0 */ 4163 rule->pcnt = tmp->pcnt; 4164 rule->bcnt = tmp->bcnt; 4165 rule->timestamp = tmp->timestamp; 4166 4167 free (tmp, M_TEMP); 4168 return 0; 4169 } 4170 4171 /* 4172 * Named object api 4173 * 4174 */ 4175 4176 void 4177 ipfw_init_srv(struct ip_fw_chain *ch) 4178 { 4179 4180 ch->srvmap = ipfw_objhash_create(IPFW_OBJECTS_DEFAULT); 4181 ch->srvstate = malloc(sizeof(void *) * IPFW_OBJECTS_DEFAULT, 4182 M_IPFW, M_WAITOK | M_ZERO); 4183 } 4184 4185 void 4186 ipfw_destroy_srv(struct ip_fw_chain *ch) 4187 { 4188 4189 free(ch->srvstate, M_IPFW); 4190 ipfw_objhash_destroy(ch->srvmap); 4191 } 4192 4193 /* 4194 * Allocate new bitmask which can be used to enlarge/shrink 4195 * named instance index. 4196 */ 4197 void 4198 ipfw_objhash_bitmap_alloc(uint32_t items, void **idx, int *pblocks) 4199 { 4200 size_t size; 4201 int max_blocks; 4202 u_long *idx_mask; 4203 4204 KASSERT((items % BLOCK_ITEMS) == 0, 4205 ("bitmask size needs to power of 2 and greater or equal to %zu", 4206 BLOCK_ITEMS)); 4207 4208 max_blocks = items / BLOCK_ITEMS; 4209 size = items / 8; 4210 idx_mask = malloc(size * IPFW_MAX_SETS, M_IPFW, M_WAITOK); 4211 /* Mark all as free */ 4212 memset(idx_mask, 0xFF, size * IPFW_MAX_SETS); 4213 *idx_mask &= ~(u_long)1; /* Skip index 0 */ 4214 4215 *idx = idx_mask; 4216 *pblocks = max_blocks; 4217 } 4218 4219 /* 4220 * Copy current bitmask index to new one. 4221 */ 4222 void 4223 ipfw_objhash_bitmap_merge(struct namedobj_instance *ni, void **idx, int *blocks) 4224 { 4225 int old_blocks, new_blocks; 4226 u_long *old_idx, *new_idx; 4227 int i; 4228 4229 old_idx = ni->idx_mask; 4230 old_blocks = ni->max_blocks; 4231 new_idx = *idx; 4232 new_blocks = *blocks; 4233 4234 for (i = 0; i < IPFW_MAX_SETS; i++) { 4235 memcpy(&new_idx[new_blocks * i], &old_idx[old_blocks * i], 4236 old_blocks * sizeof(u_long)); 4237 } 4238 } 4239 4240 /* 4241 * Swaps current @ni index with new one. 4242 */ 4243 void 4244 ipfw_objhash_bitmap_swap(struct namedobj_instance *ni, void **idx, int *blocks) 4245 { 4246 int old_blocks; 4247 u_long *old_idx; 4248 4249 old_idx = ni->idx_mask; 4250 old_blocks = ni->max_blocks; 4251 4252 ni->idx_mask = *idx; 4253 ni->max_blocks = *blocks; 4254 4255 /* Save old values */ 4256 *idx = old_idx; 4257 *blocks = old_blocks; 4258 } 4259 4260 void 4261 ipfw_objhash_bitmap_free(void *idx, int blocks) 4262 { 4263 4264 free(idx, M_IPFW); 4265 } 4266 4267 /* 4268 * Creates named hash instance. 4269 * Must be called without holding any locks. 4270 * Return pointer to new instance. 4271 */ 4272 struct namedobj_instance * 4273 ipfw_objhash_create(uint32_t items) 4274 { 4275 struct namedobj_instance *ni; 4276 int i; 4277 size_t size; 4278 4279 size = sizeof(struct namedobj_instance) + 4280 sizeof(struct namedobjects_head) * NAMEDOBJ_HASH_SIZE + 4281 sizeof(struct namedobjects_head) * NAMEDOBJ_HASH_SIZE; 4282 4283 ni = malloc(size, M_IPFW, M_WAITOK | M_ZERO); 4284 ni->nn_size = NAMEDOBJ_HASH_SIZE; 4285 ni->nv_size = NAMEDOBJ_HASH_SIZE; 4286 4287 ni->names = (struct namedobjects_head *)(ni +1); 4288 ni->values = &ni->names[ni->nn_size]; 4289 4290 for (i = 0; i < ni->nn_size; i++) 4291 TAILQ_INIT(&ni->names[i]); 4292 4293 for (i = 0; i < ni->nv_size; i++) 4294 TAILQ_INIT(&ni->values[i]); 4295 4296 /* Set default hashing/comparison functions */ 4297 ni->hash_f = objhash_hash_name; 4298 ni->cmp_f = objhash_cmp_name; 4299 4300 /* Allocate bitmask separately due to possible resize */ 4301 ipfw_objhash_bitmap_alloc(items, (void*)&ni->idx_mask, &ni->max_blocks); 4302 4303 return (ni); 4304 } 4305 4306 void 4307 ipfw_objhash_destroy(struct namedobj_instance *ni) 4308 { 4309 4310 free(ni->idx_mask, M_IPFW); 4311 free(ni, M_IPFW); 4312 } 4313 4314 void 4315 ipfw_objhash_set_funcs(struct namedobj_instance *ni, objhash_hash_f *hash_f, 4316 objhash_cmp_f *cmp_f) 4317 { 4318 4319 ni->hash_f = hash_f; 4320 ni->cmp_f = cmp_f; 4321 } 4322 4323 static uint32_t 4324 objhash_hash_name(struct namedobj_instance *ni, const void *name, uint32_t set) 4325 { 4326 4327 return (fnv_32_str((const char *)name, FNV1_32_INIT)); 4328 } 4329 4330 static int 4331 objhash_cmp_name(struct named_object *no, const void *name, uint32_t set) 4332 { 4333 4334 if ((strcmp(no->name, (const char *)name) == 0) && (no->set == set)) 4335 return (0); 4336 4337 return (1); 4338 } 4339 4340 static uint32_t 4341 objhash_hash_idx(struct namedobj_instance *ni, uint32_t val) 4342 { 4343 uint32_t v; 4344 4345 v = val % (ni->nv_size - 1); 4346 4347 return (v); 4348 } 4349 4350 struct named_object * 4351 ipfw_objhash_lookup_name(struct namedobj_instance *ni, uint32_t set, char *name) 4352 { 4353 struct named_object *no; 4354 uint32_t hash; 4355 4356 hash = ni->hash_f(ni, name, set) % ni->nn_size; 4357 4358 TAILQ_FOREACH(no, &ni->names[hash], nn_next) { 4359 if (ni->cmp_f(no, name, set) == 0) 4360 return (no); 4361 } 4362 4363 return (NULL); 4364 } 4365 4366 /* 4367 * Find named object by @uid. 4368 * Check @tlvs for valid data inside. 4369 * 4370 * Returns pointer to found TLV or NULL. 4371 */ 4372 ipfw_obj_ntlv * 4373 ipfw_find_name_tlv_type(void *tlvs, int len, uint16_t uidx, uint32_t etlv) 4374 { 4375 ipfw_obj_ntlv *ntlv; 4376 uintptr_t pa, pe; 4377 int l; 4378 4379 pa = (uintptr_t)tlvs; 4380 pe = pa + len; 4381 l = 0; 4382 for (; pa < pe; pa += l) { 4383 ntlv = (ipfw_obj_ntlv *)pa; 4384 l = ntlv->head.length; 4385 4386 if (l != sizeof(*ntlv)) 4387 return (NULL); 4388 4389 if (ntlv->idx != uidx) 4390 continue; 4391 /* 4392 * When userland has specified zero TLV type, do 4393 * not compare it with eltv. In some cases userland 4394 * doesn't know what type should it have. Use only 4395 * uidx and name for search named_object. 4396 */ 4397 if (ntlv->head.type != 0 && 4398 ntlv->head.type != (uint16_t)etlv) 4399 continue; 4400 4401 if (ipfw_check_object_name_generic(ntlv->name) != 0) 4402 return (NULL); 4403 4404 return (ntlv); 4405 } 4406 4407 return (NULL); 4408 } 4409 4410 /* 4411 * Finds object config based on either legacy index 4412 * or name in ntlv. 4413 * Note @ti structure contains unchecked data from userland. 4414 * 4415 * Returns 0 in success and fills in @pno with found config 4416 */ 4417 int 4418 ipfw_objhash_find_type(struct namedobj_instance *ni, struct tid_info *ti, 4419 uint32_t etlv, struct named_object **pno) 4420 { 4421 char *name; 4422 ipfw_obj_ntlv *ntlv; 4423 uint32_t set; 4424 4425 if (ti->tlvs == NULL) 4426 return (EINVAL); 4427 4428 ntlv = ipfw_find_name_tlv_type(ti->tlvs, ti->tlen, ti->uidx, etlv); 4429 if (ntlv == NULL) 4430 return (EINVAL); 4431 name = ntlv->name; 4432 4433 /* 4434 * Use set provided by @ti instead of @ntlv one. 4435 * This is needed due to different sets behavior 4436 * controlled by V_fw_tables_sets. 4437 */ 4438 set = ti->set; 4439 *pno = ipfw_objhash_lookup_name(ni, set, name); 4440 if (*pno == NULL) 4441 return (ESRCH); 4442 return (0); 4443 } 4444 4445 /* 4446 * Find named object by name, considering also its TLV type. 4447 */ 4448 struct named_object * 4449 ipfw_objhash_lookup_name_type(struct namedobj_instance *ni, uint32_t set, 4450 uint32_t type, const char *name) 4451 { 4452 struct named_object *no; 4453 uint32_t hash; 4454 4455 hash = ni->hash_f(ni, name, set) % ni->nn_size; 4456 4457 TAILQ_FOREACH(no, &ni->names[hash], nn_next) { 4458 if (ni->cmp_f(no, name, set) == 0 && 4459 no->etlv == (uint16_t)type) 4460 return (no); 4461 } 4462 4463 return (NULL); 4464 } 4465 4466 struct named_object * 4467 ipfw_objhash_lookup_kidx(struct namedobj_instance *ni, uint16_t kidx) 4468 { 4469 struct named_object *no; 4470 uint32_t hash; 4471 4472 hash = objhash_hash_idx(ni, kidx); 4473 4474 TAILQ_FOREACH(no, &ni->values[hash], nv_next) { 4475 if (no->kidx == kidx) 4476 return (no); 4477 } 4478 4479 return (NULL); 4480 } 4481 4482 int 4483 ipfw_objhash_same_name(struct namedobj_instance *ni, struct named_object *a, 4484 struct named_object *b) 4485 { 4486 4487 if ((strcmp(a->name, b->name) == 0) && a->set == b->set) 4488 return (1); 4489 4490 return (0); 4491 } 4492 4493 void 4494 ipfw_objhash_add(struct namedobj_instance *ni, struct named_object *no) 4495 { 4496 uint32_t hash; 4497 4498 hash = ni->hash_f(ni, no->name, no->set) % ni->nn_size; 4499 TAILQ_INSERT_HEAD(&ni->names[hash], no, nn_next); 4500 4501 hash = objhash_hash_idx(ni, no->kidx); 4502 TAILQ_INSERT_HEAD(&ni->values[hash], no, nv_next); 4503 4504 ni->count++; 4505 } 4506 4507 void 4508 ipfw_objhash_del(struct namedobj_instance *ni, struct named_object *no) 4509 { 4510 uint32_t hash; 4511 4512 hash = ni->hash_f(ni, no->name, no->set) % ni->nn_size; 4513 TAILQ_REMOVE(&ni->names[hash], no, nn_next); 4514 4515 hash = objhash_hash_idx(ni, no->kidx); 4516 TAILQ_REMOVE(&ni->values[hash], no, nv_next); 4517 4518 ni->count--; 4519 } 4520 4521 uint32_t 4522 ipfw_objhash_count(struct namedobj_instance *ni) 4523 { 4524 4525 return (ni->count); 4526 } 4527 4528 uint32_t 4529 ipfw_objhash_count_type(struct namedobj_instance *ni, uint16_t type) 4530 { 4531 struct named_object *no; 4532 uint32_t count; 4533 int i; 4534 4535 count = 0; 4536 for (i = 0; i < ni->nn_size; i++) { 4537 TAILQ_FOREACH(no, &ni->names[i], nn_next) { 4538 if (no->etlv == type) 4539 count++; 4540 } 4541 } 4542 return (count); 4543 } 4544 4545 /* 4546 * Runs @func for each found named object. 4547 * It is safe to delete objects from callback 4548 */ 4549 int 4550 ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f, void *arg) 4551 { 4552 struct named_object *no, *no_tmp; 4553 int i, ret; 4554 4555 for (i = 0; i < ni->nn_size; i++) { 4556 TAILQ_FOREACH_SAFE(no, &ni->names[i], nn_next, no_tmp) { 4557 ret = f(ni, no, arg); 4558 if (ret != 0) 4559 return (ret); 4560 } 4561 } 4562 return (0); 4563 } 4564 4565 /* 4566 * Runs @f for each found named object with type @type. 4567 * It is safe to delete objects from callback 4568 */ 4569 int 4570 ipfw_objhash_foreach_type(struct namedobj_instance *ni, objhash_cb_t *f, 4571 void *arg, uint16_t type) 4572 { 4573 struct named_object *no, *no_tmp; 4574 int i, ret; 4575 4576 for (i = 0; i < ni->nn_size; i++) { 4577 TAILQ_FOREACH_SAFE(no, &ni->names[i], nn_next, no_tmp) { 4578 if (no->etlv != type) 4579 continue; 4580 ret = f(ni, no, arg); 4581 if (ret != 0) 4582 return (ret); 4583 } 4584 } 4585 return (0); 4586 } 4587 4588 /* 4589 * Removes index from given set. 4590 * Returns 0 on success. 4591 */ 4592 int 4593 ipfw_objhash_free_idx(struct namedobj_instance *ni, uint16_t idx) 4594 { 4595 u_long *mask; 4596 int i, v; 4597 4598 i = idx / BLOCK_ITEMS; 4599 v = idx % BLOCK_ITEMS; 4600 4601 if (i >= ni->max_blocks) 4602 return (1); 4603 4604 mask = &ni->idx_mask[i]; 4605 4606 if ((*mask & ((u_long)1 << v)) != 0) 4607 return (1); 4608 4609 /* Mark as free */ 4610 *mask |= (u_long)1 << v; 4611 4612 /* Update free offset */ 4613 if (ni->free_off[0] > i) 4614 ni->free_off[0] = i; 4615 4616 return (0); 4617 } 4618 4619 /* 4620 * Allocate new index in given instance and stores in in @pidx. 4621 * Returns 0 on success. 4622 */ 4623 int 4624 ipfw_objhash_alloc_idx(void *n, uint16_t *pidx) 4625 { 4626 struct namedobj_instance *ni; 4627 u_long *mask; 4628 int i, off, v; 4629 4630 ni = (struct namedobj_instance *)n; 4631 4632 off = ni->free_off[0]; 4633 mask = &ni->idx_mask[off]; 4634 4635 for (i = off; i < ni->max_blocks; i++, mask++) { 4636 if ((v = ffsl(*mask)) == 0) 4637 continue; 4638 4639 /* Mark as busy */ 4640 *mask &= ~ ((u_long)1 << (v - 1)); 4641 4642 ni->free_off[0] = i; 4643 4644 v = BLOCK_ITEMS * i + v - 1; 4645 4646 *pidx = v; 4647 return (0); 4648 } 4649 4650 return (1); 4651 } 4652 4653 /* end of file */ 4654