1 /* $OpenBSD: pfctl.c,v 1.278 2008/08/31 20:18:17 jmc Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2001 Daniel Hartmeier 7 * Copyright (c) 2002,2003 Henning Brauer 8 * All rights reserved. 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 * 14 * - Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * - Redistributions in binary form must reproduce the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer in the documentation and/or other materials provided 19 * with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 * 34 */ 35 36 #include <sys/cdefs.h> 37 #define PFIOC_USE_LATEST 38 39 #include <sys/types.h> 40 #include <sys/ioctl.h> 41 #include <sys/socket.h> 42 #include <sys/stat.h> 43 #include <sys/endian.h> 44 45 #include <net/if.h> 46 #include <netinet/in.h> 47 #include <net/pfvar.h> 48 #include <arpa/inet.h> 49 #include <net/altq/altq.h> 50 51 #include <err.h> 52 #include <errno.h> 53 #include <fcntl.h> 54 #include <libpfctl.h> 55 #include <limits.h> 56 #include <netdb.h> 57 #include <stdint.h> 58 #include <stdio.h> 59 #include <stdlib.h> 60 #include <string.h> 61 #include <unistd.h> 62 63 #include "pfctl_parser.h" 64 #include "pfctl.h" 65 66 void usage(void); 67 int pfctl_enable(int, int); 68 int pfctl_disable(int, int); 69 int pfctl_clear_stats(int, int); 70 int pfctl_get_skip_ifaces(void); 71 int pfctl_check_skip_ifaces(char *); 72 int pfctl_adjust_skip_ifaces(struct pfctl *); 73 int pfctl_clear_interface_flags(int, int); 74 int pfctl_flush_eth_rules(int, int, char *); 75 int pfctl_flush_rules(int, int, char *); 76 int pfctl_flush_nat(int, int, char *); 77 int pfctl_clear_altq(int, int); 78 int pfctl_clear_src_nodes(int, int); 79 int pfctl_clear_iface_states(int, const char *, int); 80 void pfctl_addrprefix(char *, struct pf_addr *); 81 int pfctl_kill_src_nodes(int, const char *, int); 82 int pfctl_net_kill_states(int, const char *, int); 83 int pfctl_gateway_kill_states(int, const char *, int); 84 int pfctl_label_kill_states(int, const char *, int); 85 int pfctl_id_kill_states(int, const char *, int); 86 void pfctl_init_options(struct pfctl *); 87 int pfctl_load_options(struct pfctl *); 88 int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); 89 int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); 90 int pfctl_load_debug(struct pfctl *, unsigned int); 91 int pfctl_load_logif(struct pfctl *, char *); 92 int pfctl_load_hostid(struct pfctl *, u_int32_t); 93 int pfctl_load_reassembly(struct pfctl *, u_int32_t); 94 int pfctl_load_syncookies(struct pfctl *, u_int8_t); 95 int pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int, 96 char *); 97 void pfctl_print_eth_rule_counters(struct pfctl_eth_rule *, int); 98 void pfctl_print_rule_counters(struct pfctl_rule *, int); 99 int pfctl_show_eth_rules(int, char *, int, enum pfctl_show, char *, int, int); 100 int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int); 101 int pfctl_show_nat(int, char *, int, char *, int); 102 int pfctl_show_src_nodes(int, int); 103 int pfctl_show_states(int, const char *, int); 104 int pfctl_show_status(int, int); 105 int pfctl_show_running(int); 106 int pfctl_show_timeouts(int, int); 107 int pfctl_show_limits(int, int); 108 void pfctl_debug(int, u_int32_t, int); 109 int pfctl_test_altqsupport(int, int); 110 int pfctl_show_anchors(int, int, char *); 111 int pfctl_show_eth_anchors(int, int, char *); 112 int pfctl_ruleset_trans(struct pfctl *, char *, struct pfctl_anchor *, bool); 113 int pfctl_eth_ruleset_trans(struct pfctl *, char *, 114 struct pfctl_eth_anchor *); 115 int pfctl_load_eth_ruleset(struct pfctl *, char *, 116 struct pfctl_eth_ruleset *, int); 117 int pfctl_load_eth_rule(struct pfctl *, char *, struct pfctl_eth_rule *, 118 int); 119 int pfctl_load_ruleset(struct pfctl *, char *, 120 struct pfctl_ruleset *, int, int); 121 int pfctl_load_rule(struct pfctl *, char *, struct pfctl_rule *, int); 122 const char *pfctl_lookup_option(char *, const char * const *); 123 124 static struct pfctl_anchor_global pf_anchors; 125 struct pfctl_anchor pf_main_anchor; 126 struct pfctl_eth_anchor pf_eth_main_anchor; 127 static struct pfr_buffer skip_b; 128 129 static const char *clearopt; 130 static char *rulesopt; 131 static const char *showopt; 132 static const char *debugopt; 133 static char *anchoropt; 134 static const char *optiopt = NULL; 135 static const char *pf_device = "/dev/pf"; 136 static char *ifaceopt; 137 static char *tableopt; 138 static const char *tblcmdopt; 139 static int src_node_killers; 140 static char *src_node_kill[2]; 141 static int state_killers; 142 static char *state_kill[2]; 143 int loadopt; 144 int altqsupport; 145 146 int dev = -1; 147 static int first_title = 1; 148 static int labels = 0; 149 150 #define INDENT(d, o) do { \ 151 if (o) { \ 152 int i; \ 153 for (i=0; i < d; i++) \ 154 printf(" "); \ 155 } \ 156 } while (0); \ 157 158 159 static const struct { 160 const char *name; 161 int index; 162 } pf_limits[] = { 163 { "states", PF_LIMIT_STATES }, 164 { "src-nodes", PF_LIMIT_SRC_NODES }, 165 { "frags", PF_LIMIT_FRAGS }, 166 { "table-entries", PF_LIMIT_TABLE_ENTRIES }, 167 { NULL, 0 } 168 }; 169 170 struct pf_hint { 171 const char *name; 172 int timeout; 173 }; 174 static const struct pf_hint pf_hint_normal[] = { 175 { "tcp.first", 2 * 60 }, 176 { "tcp.opening", 30 }, 177 { "tcp.established", 24 * 60 * 60 }, 178 { "tcp.closing", 15 * 60 }, 179 { "tcp.finwait", 45 }, 180 { "tcp.closed", 90 }, 181 { "tcp.tsdiff", 30 }, 182 { NULL, 0 } 183 }; 184 static const struct pf_hint pf_hint_satellite[] = { 185 { "tcp.first", 3 * 60 }, 186 { "tcp.opening", 30 + 5 }, 187 { "tcp.established", 24 * 60 * 60 }, 188 { "tcp.closing", 15 * 60 + 5 }, 189 { "tcp.finwait", 45 + 5 }, 190 { "tcp.closed", 90 + 5 }, 191 { "tcp.tsdiff", 60 }, 192 { NULL, 0 } 193 }; 194 static const struct pf_hint pf_hint_conservative[] = { 195 { "tcp.first", 60 * 60 }, 196 { "tcp.opening", 15 * 60 }, 197 { "tcp.established", 5 * 24 * 60 * 60 }, 198 { "tcp.closing", 60 * 60 }, 199 { "tcp.finwait", 10 * 60 }, 200 { "tcp.closed", 3 * 60 }, 201 { "tcp.tsdiff", 60 }, 202 { NULL, 0 } 203 }; 204 static const struct pf_hint pf_hint_aggressive[] = { 205 { "tcp.first", 30 }, 206 { "tcp.opening", 5 }, 207 { "tcp.established", 5 * 60 * 60 }, 208 { "tcp.closing", 60 }, 209 { "tcp.finwait", 30 }, 210 { "tcp.closed", 30 }, 211 { "tcp.tsdiff", 10 }, 212 { NULL, 0 } 213 }; 214 215 static const struct { 216 const char *name; 217 const struct pf_hint *hint; 218 } pf_hints[] = { 219 { "normal", pf_hint_normal }, 220 { "satellite", pf_hint_satellite }, 221 { "high-latency", pf_hint_satellite }, 222 { "conservative", pf_hint_conservative }, 223 { "aggressive", pf_hint_aggressive }, 224 { NULL, NULL } 225 }; 226 227 static const char * const clearopt_list[] = { 228 "nat", "queue", "rules", "Sources", 229 "states", "info", "Tables", "osfp", "all", 230 "ethernet", NULL 231 }; 232 233 static const char * const showopt_list[] = { 234 "ether", "nat", "queue", "rules", "Anchors", "Sources", "states", 235 "info", "Interfaces", "labels", "timeouts", "memory", "Tables", 236 "osfp", "Running", "all", "creatorids", NULL 237 }; 238 239 static const char * const tblcmdopt_list[] = { 240 "kill", "flush", "add", "delete", "load", "replace", "show", 241 "test", "zero", "expire", NULL 242 }; 243 244 static const char * const debugopt_list[] = { 245 "none", "urgent", "misc", "loud", NULL 246 }; 247 248 static const char * const optiopt_list[] = { 249 "none", "basic", "profile", NULL 250 }; 251 252 void 253 usage(void) 254 { 255 extern char *__progname; 256 257 fprintf(stderr, 258 "usage: %s [-AdeghMmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n" 259 "\t[-f file] [-i interface] [-K host | network]\n" 260 "\t[-k host | network | gateway | label | id] [-o level] [-p device]\n" 261 "\t[-s modifier] [-t table -T command [address ...]] [-x level]\n", 262 __progname); 263 264 exit(1); 265 } 266 267 /* 268 * Cache protocol number to name translations. 269 * 270 * Translation is performed a lot e.g., when dumping states and 271 * getprotobynumber is incredibly expensive. 272 * 273 * Note from the getprotobynumber(3) manpage: 274 * <quote> 275 * These functions use a thread-specific data space; if the data is needed 276 * for future use, it should be copied before any subsequent calls overwrite 277 * it. Only the Internet protocols are currently understood. 278 * </quote> 279 * 280 * Consequently we only cache the name and strdup it for safety. 281 * 282 * At the time of writing this comment the last entry in /etc/protocols is: 283 * divert 258 DIVERT # Divert pseudo-protocol [non IANA] 284 */ 285 const char * 286 pfctl_proto2name(int proto) 287 { 288 static const char *pfctl_proto_cache[259]; 289 struct protoent *p; 290 291 if (proto >= nitems(pfctl_proto_cache)) { 292 p = getprotobynumber(proto); 293 if (p == NULL) { 294 return (NULL); 295 } 296 return (p->p_name); 297 } 298 299 if (pfctl_proto_cache[proto] == NULL) { 300 p = getprotobynumber(proto); 301 if (p == NULL) { 302 return (NULL); 303 } 304 pfctl_proto_cache[proto] = strdup(p->p_name); 305 } 306 307 return (pfctl_proto_cache[proto]); 308 } 309 310 int 311 pfctl_enable(int dev, int opts) 312 { 313 int ret; 314 315 if ((ret = pfctl_startstop(1)) != 0) { 316 if (ret == EEXIST) 317 errx(1, "pf already enabled"); 318 else if (ret == ESRCH) 319 errx(1, "pfil registeration failed"); 320 else 321 err(1, "DIOCSTART"); 322 } 323 if ((opts & PF_OPT_QUIET) == 0) 324 fprintf(stderr, "pf enabled\n"); 325 326 if (altqsupport && ioctl(dev, DIOCSTARTALTQ)) 327 if (errno != EEXIST) 328 err(1, "DIOCSTARTALTQ"); 329 330 return (0); 331 } 332 333 int 334 pfctl_disable(int dev, int opts) 335 { 336 int ret; 337 338 if ((ret = pfctl_startstop(0)) != 0) { 339 if (ret == ENOENT) 340 errx(1, "pf not enabled"); 341 else 342 err(1, "DIOCSTOP"); 343 } 344 if ((opts & PF_OPT_QUIET) == 0) 345 fprintf(stderr, "pf disabled\n"); 346 347 if (altqsupport && ioctl(dev, DIOCSTOPALTQ)) 348 if (errno != ENOENT) 349 err(1, "DIOCSTOPALTQ"); 350 351 return (0); 352 } 353 354 int 355 pfctl_clear_stats(int dev, int opts) 356 { 357 if (ioctl(dev, DIOCCLRSTATUS)) 358 err(1, "DIOCCLRSTATUS"); 359 if ((opts & PF_OPT_QUIET) == 0) 360 fprintf(stderr, "pf: statistics cleared\n"); 361 return (0); 362 } 363 364 int 365 pfctl_get_skip_ifaces(void) 366 { 367 bzero(&skip_b, sizeof(skip_b)); 368 skip_b.pfrb_type = PFRB_IFACES; 369 for (;;) { 370 pfr_buf_grow(&skip_b, skip_b.pfrb_size); 371 skip_b.pfrb_size = skip_b.pfrb_msize; 372 if (pfi_get_ifaces(NULL, skip_b.pfrb_caddr, &skip_b.pfrb_size)) 373 err(1, "pfi_get_ifaces"); 374 if (skip_b.pfrb_size <= skip_b.pfrb_msize) 375 break; 376 } 377 return (0); 378 } 379 380 int 381 pfctl_check_skip_ifaces(char *ifname) 382 { 383 struct pfi_kif *p; 384 struct node_host *h = NULL, *n = NULL; 385 386 PFRB_FOREACH(p, &skip_b) { 387 if (!strcmp(ifname, p->pfik_name) && 388 (p->pfik_flags & PFI_IFLAG_SKIP)) 389 p->pfik_flags &= ~PFI_IFLAG_SKIP; 390 if (!strcmp(ifname, p->pfik_name) && p->pfik_group != NULL) { 391 if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL) 392 continue; 393 394 for (n = h; n != NULL; n = n->next) { 395 if (p->pfik_ifp == NULL) 396 continue; 397 if (strncmp(p->pfik_name, ifname, IFNAMSIZ)) 398 continue; 399 400 p->pfik_flags &= ~PFI_IFLAG_SKIP; 401 } 402 } 403 } 404 return (0); 405 } 406 407 int 408 pfctl_adjust_skip_ifaces(struct pfctl *pf) 409 { 410 struct pfi_kif *p, *pp; 411 struct node_host *h = NULL, *n = NULL; 412 413 PFRB_FOREACH(p, &skip_b) { 414 if (p->pfik_group == NULL || !(p->pfik_flags & PFI_IFLAG_SKIP)) 415 continue; 416 417 pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0); 418 if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL) 419 continue; 420 421 for (n = h; n != NULL; n = n->next) 422 PFRB_FOREACH(pp, &skip_b) { 423 if (pp->pfik_ifp == NULL) 424 continue; 425 426 if (strncmp(pp->pfik_name, n->ifname, IFNAMSIZ)) 427 continue; 428 429 if (!(pp->pfik_flags & PFI_IFLAG_SKIP)) 430 pfctl_set_interface_flags(pf, 431 pp->pfik_name, PFI_IFLAG_SKIP, 1); 432 if (pp->pfik_flags & PFI_IFLAG_SKIP) 433 pp->pfik_flags &= ~PFI_IFLAG_SKIP; 434 } 435 } 436 437 PFRB_FOREACH(p, &skip_b) { 438 if (p->pfik_ifp == NULL || ! (p->pfik_flags & PFI_IFLAG_SKIP)) 439 continue; 440 441 pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0); 442 } 443 444 return (0); 445 } 446 447 int 448 pfctl_clear_interface_flags(int dev, int opts) 449 { 450 struct pfioc_iface pi; 451 452 if ((opts & PF_OPT_NOACTION) == 0) { 453 bzero(&pi, sizeof(pi)); 454 pi.pfiio_flags = PFI_IFLAG_SKIP; 455 456 if (ioctl(dev, DIOCCLRIFFLAG, &pi)) 457 err(1, "DIOCCLRIFFLAG"); 458 if ((opts & PF_OPT_QUIET) == 0) 459 fprintf(stderr, "pf: interface flags reset\n"); 460 } 461 return (0); 462 } 463 464 int 465 pfctl_flush_eth_rules(int dev, int opts, char *anchorname) 466 { 467 int ret; 468 469 ret = pfctl_clear_eth_rules(dev, anchorname); 470 if (ret != 0) 471 err(1, "pfctl_clear_eth_rules"); 472 473 if ((opts & PF_OPT_QUIET) == 0) 474 fprintf(stderr, "Ethernet rules cleared\n"); 475 476 return (ret); 477 } 478 479 int 480 pfctl_flush_rules(int dev, int opts, char *anchorname) 481 { 482 int ret; 483 484 ret = pfctl_clear_rules(dev, anchorname); 485 if (ret != 0) 486 err(1, "pfctl_clear_rules"); 487 if ((opts & PF_OPT_QUIET) == 0) 488 fprintf(stderr, "rules cleared\n"); 489 return (0); 490 } 491 492 int 493 pfctl_flush_nat(int dev, int opts, char *anchorname) 494 { 495 int ret; 496 497 ret = pfctl_clear_nat(dev, anchorname); 498 if (ret != 0) 499 err(1, "pfctl_clear_nat"); 500 if ((opts & PF_OPT_QUIET) == 0) 501 fprintf(stderr, "nat cleared\n"); 502 return (0); 503 } 504 505 int 506 pfctl_clear_altq(int dev, int opts) 507 { 508 struct pfr_buffer t; 509 510 if (!altqsupport) 511 return (-1); 512 memset(&t, 0, sizeof(t)); 513 t.pfrb_type = PFRB_TRANS; 514 if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") || 515 pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 516 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 517 err(1, "pfctl_clear_altq"); 518 if ((opts & PF_OPT_QUIET) == 0) 519 fprintf(stderr, "altq cleared\n"); 520 return (0); 521 } 522 523 int 524 pfctl_clear_src_nodes(int dev, int opts) 525 { 526 if (ioctl(dev, DIOCCLRSRCNODES)) 527 err(1, "DIOCCLRSRCNODES"); 528 if ((opts & PF_OPT_QUIET) == 0) 529 fprintf(stderr, "source tracking entries cleared\n"); 530 return (0); 531 } 532 533 int 534 pfctl_clear_iface_states(int dev, const char *iface, int opts) 535 { 536 struct pfctl_kill kill; 537 unsigned int killed; 538 539 memset(&kill, 0, sizeof(kill)); 540 if (iface != NULL && strlcpy(kill.ifname, iface, 541 sizeof(kill.ifname)) >= sizeof(kill.ifname)) 542 errx(1, "invalid interface: %s", iface); 543 544 if (opts & PF_OPT_KILLMATCH) 545 kill.kill_match = true; 546 547 if (pfctl_clear_states(dev, &kill, &killed)) 548 err(1, "DIOCCLRSTATES"); 549 if ((opts & PF_OPT_QUIET) == 0) 550 fprintf(stderr, "%d states cleared\n", killed); 551 return (0); 552 } 553 554 void 555 pfctl_addrprefix(char *addr, struct pf_addr *mask) 556 { 557 char *p; 558 const char *errstr; 559 int prefix, ret_ga, q, r; 560 struct addrinfo hints, *res; 561 562 if ((p = strchr(addr, '/')) == NULL) 563 return; 564 565 *p++ = '\0'; 566 prefix = strtonum(p, 0, 128, &errstr); 567 if (errstr) 568 errx(1, "prefix is %s: %s", errstr, p); 569 570 bzero(&hints, sizeof(hints)); 571 /* prefix only with numeric addresses */ 572 hints.ai_flags |= AI_NUMERICHOST; 573 574 if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) { 575 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 576 /* NOTREACHED */ 577 } 578 579 if (res->ai_family == AF_INET && prefix > 32) 580 errx(1, "prefix too long for AF_INET"); 581 else if (res->ai_family == AF_INET6 && prefix > 128) 582 errx(1, "prefix too long for AF_INET6"); 583 584 q = prefix >> 3; 585 r = prefix & 7; 586 switch (res->ai_family) { 587 case AF_INET: 588 bzero(&mask->v4, sizeof(mask->v4)); 589 mask->v4.s_addr = htonl((u_int32_t) 590 (0xffffffffffULL << (32 - prefix))); 591 break; 592 case AF_INET6: 593 bzero(&mask->v6, sizeof(mask->v6)); 594 if (q > 0) 595 memset((void *)&mask->v6, 0xff, q); 596 if (r > 0) 597 *((u_char *)&mask->v6 + q) = 598 (0xff00 >> r) & 0xff; 599 break; 600 } 601 freeaddrinfo(res); 602 } 603 604 int 605 pfctl_kill_src_nodes(int dev, const char *iface, int opts) 606 { 607 struct pfioc_src_node_kill psnk; 608 struct addrinfo *res[2], *resp[2]; 609 struct sockaddr last_src, last_dst; 610 int killed, sources, dests; 611 int ret_ga; 612 613 killed = sources = dests = 0; 614 615 memset(&psnk, 0, sizeof(psnk)); 616 memset(&psnk.psnk_src.addr.v.a.mask, 0xff, 617 sizeof(psnk.psnk_src.addr.v.a.mask)); 618 memset(&last_src, 0xff, sizeof(last_src)); 619 memset(&last_dst, 0xff, sizeof(last_dst)); 620 621 pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask); 622 623 if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) { 624 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 625 /* NOTREACHED */ 626 } 627 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 628 if (resp[0]->ai_addr == NULL) 629 continue; 630 /* We get lots of duplicates. Catch the easy ones */ 631 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 632 continue; 633 last_src = *(struct sockaddr *)resp[0]->ai_addr; 634 635 psnk.psnk_af = resp[0]->ai_family; 636 sources++; 637 638 if (psnk.psnk_af == AF_INET) 639 psnk.psnk_src.addr.v.a.addr.v4 = 640 ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 641 else if (psnk.psnk_af == AF_INET6) 642 psnk.psnk_src.addr.v.a.addr.v6 = 643 ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 644 sin6_addr; 645 else 646 errx(1, "Unknown address family %d", psnk.psnk_af); 647 648 if (src_node_killers > 1) { 649 dests = 0; 650 memset(&psnk.psnk_dst.addr.v.a.mask, 0xff, 651 sizeof(psnk.psnk_dst.addr.v.a.mask)); 652 memset(&last_dst, 0xff, sizeof(last_dst)); 653 pfctl_addrprefix(src_node_kill[1], 654 &psnk.psnk_dst.addr.v.a.mask); 655 if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL, 656 &res[1]))) { 657 errx(1, "getaddrinfo: %s", 658 gai_strerror(ret_ga)); 659 /* NOTREACHED */ 660 } 661 for (resp[1] = res[1]; resp[1]; 662 resp[1] = resp[1]->ai_next) { 663 if (resp[1]->ai_addr == NULL) 664 continue; 665 if (psnk.psnk_af != resp[1]->ai_family) 666 continue; 667 668 if (memcmp(&last_dst, resp[1]->ai_addr, 669 sizeof(last_dst)) == 0) 670 continue; 671 last_dst = *(struct sockaddr *)resp[1]->ai_addr; 672 673 dests++; 674 675 if (psnk.psnk_af == AF_INET) 676 psnk.psnk_dst.addr.v.a.addr.v4 = 677 ((struct sockaddr_in *)resp[1]-> 678 ai_addr)->sin_addr; 679 else if (psnk.psnk_af == AF_INET6) 680 psnk.psnk_dst.addr.v.a.addr.v6 = 681 ((struct sockaddr_in6 *)resp[1]-> 682 ai_addr)->sin6_addr; 683 else 684 errx(1, "Unknown address family %d", 685 psnk.psnk_af); 686 687 if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 688 err(1, "DIOCKILLSRCNODES"); 689 killed += psnk.psnk_killed; 690 } 691 freeaddrinfo(res[1]); 692 } else { 693 if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 694 err(1, "DIOCKILLSRCNODES"); 695 killed += psnk.psnk_killed; 696 } 697 } 698 699 freeaddrinfo(res[0]); 700 701 if ((opts & PF_OPT_QUIET) == 0) 702 fprintf(stderr, "killed %d src nodes from %d sources and %d " 703 "destinations\n", killed, sources, dests); 704 return (0); 705 } 706 707 int 708 pfctl_net_kill_states(int dev, const char *iface, int opts) 709 { 710 struct pfctl_kill kill; 711 struct addrinfo *res[2], *resp[2]; 712 struct sockaddr last_src, last_dst; 713 unsigned int newkilled; 714 int killed, sources, dests; 715 int ret_ga; 716 717 killed = sources = dests = 0; 718 719 memset(&kill, 0, sizeof(kill)); 720 memset(&kill.src.addr.v.a.mask, 0xff, 721 sizeof(kill.src.addr.v.a.mask)); 722 memset(&last_src, 0xff, sizeof(last_src)); 723 memset(&last_dst, 0xff, sizeof(last_dst)); 724 if (iface != NULL && strlcpy(kill.ifname, iface, 725 sizeof(kill.ifname)) >= sizeof(kill.ifname)) 726 errx(1, "invalid interface: %s", iface); 727 728 if (state_killers == 2 && (strcmp(state_kill[0], "nat") == 0)) { 729 kill.nat = true; 730 state_kill[0] = state_kill[1]; 731 state_killers = 1; 732 } 733 734 pfctl_addrprefix(state_kill[0], &kill.src.addr.v.a.mask); 735 736 if (opts & PF_OPT_KILLMATCH) 737 kill.kill_match = true; 738 739 if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) { 740 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 741 /* NOTREACHED */ 742 } 743 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 744 if (resp[0]->ai_addr == NULL) 745 continue; 746 /* We get lots of duplicates. Catch the easy ones */ 747 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 748 continue; 749 last_src = *(struct sockaddr *)resp[0]->ai_addr; 750 751 kill.af = resp[0]->ai_family; 752 sources++; 753 754 if (kill.af == AF_INET) 755 kill.src.addr.v.a.addr.v4 = 756 ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 757 else if (kill.af == AF_INET6) 758 kill.src.addr.v.a.addr.v6 = 759 ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 760 sin6_addr; 761 else 762 errx(1, "Unknown address family %d", kill.af); 763 764 if (state_killers > 1) { 765 dests = 0; 766 memset(&kill.dst.addr.v.a.mask, 0xff, 767 sizeof(kill.dst.addr.v.a.mask)); 768 memset(&last_dst, 0xff, sizeof(last_dst)); 769 pfctl_addrprefix(state_kill[1], 770 &kill.dst.addr.v.a.mask); 771 if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, 772 &res[1]))) { 773 errx(1, "getaddrinfo: %s", 774 gai_strerror(ret_ga)); 775 /* NOTREACHED */ 776 } 777 for (resp[1] = res[1]; resp[1]; 778 resp[1] = resp[1]->ai_next) { 779 if (resp[1]->ai_addr == NULL) 780 continue; 781 if (kill.af != resp[1]->ai_family) 782 continue; 783 784 if (memcmp(&last_dst, resp[1]->ai_addr, 785 sizeof(last_dst)) == 0) 786 continue; 787 last_dst = *(struct sockaddr *)resp[1]->ai_addr; 788 789 dests++; 790 791 if (kill.af == AF_INET) 792 kill.dst.addr.v.a.addr.v4 = 793 ((struct sockaddr_in *)resp[1]-> 794 ai_addr)->sin_addr; 795 else if (kill.af == AF_INET6) 796 kill.dst.addr.v.a.addr.v6 = 797 ((struct sockaddr_in6 *)resp[1]-> 798 ai_addr)->sin6_addr; 799 else 800 errx(1, "Unknown address family %d", 801 kill.af); 802 803 if (pfctl_kill_states(dev, &kill, &newkilled)) 804 err(1, "DIOCKILLSTATES"); 805 killed += newkilled; 806 } 807 freeaddrinfo(res[1]); 808 } else { 809 if (pfctl_kill_states(dev, &kill, &newkilled)) 810 err(1, "DIOCKILLSTATES"); 811 killed += newkilled; 812 } 813 } 814 815 freeaddrinfo(res[0]); 816 817 if ((opts & PF_OPT_QUIET) == 0) 818 fprintf(stderr, "killed %d states from %d sources and %d " 819 "destinations\n", killed, sources, dests); 820 return (0); 821 } 822 823 int 824 pfctl_gateway_kill_states(int dev, const char *iface, int opts) 825 { 826 struct pfctl_kill kill; 827 struct addrinfo *res, *resp; 828 struct sockaddr last_src; 829 unsigned int newkilled; 830 int killed = 0; 831 int ret_ga; 832 833 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 834 warnx("no gateway specified"); 835 usage(); 836 } 837 838 memset(&kill, 0, sizeof(kill)); 839 memset(&kill.rt_addr.addr.v.a.mask, 0xff, 840 sizeof(kill.rt_addr.addr.v.a.mask)); 841 memset(&last_src, 0xff, sizeof(last_src)); 842 if (iface != NULL && strlcpy(kill.ifname, iface, 843 sizeof(kill.ifname)) >= sizeof(kill.ifname)) 844 errx(1, "invalid interface: %s", iface); 845 846 if (opts & PF_OPT_KILLMATCH) 847 kill.kill_match = true; 848 849 pfctl_addrprefix(state_kill[1], &kill.rt_addr.addr.v.a.mask); 850 851 if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, &res))) { 852 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 853 /* NOTREACHED */ 854 } 855 for (resp = res; resp; resp = resp->ai_next) { 856 if (resp->ai_addr == NULL) 857 continue; 858 /* We get lots of duplicates. Catch the easy ones */ 859 if (memcmp(&last_src, resp->ai_addr, sizeof(last_src)) == 0) 860 continue; 861 last_src = *(struct sockaddr *)resp->ai_addr; 862 863 kill.af = resp->ai_family; 864 865 if (kill.af == AF_INET) 866 kill.rt_addr.addr.v.a.addr.v4 = 867 ((struct sockaddr_in *)resp->ai_addr)->sin_addr; 868 else if (kill.af == AF_INET6) 869 kill.rt_addr.addr.v.a.addr.v6 = 870 ((struct sockaddr_in6 *)resp->ai_addr)-> 871 sin6_addr; 872 else 873 errx(1, "Unknown address family %d", kill.af); 874 875 if (pfctl_kill_states(dev, &kill, &newkilled)) 876 err(1, "DIOCKILLSTATES"); 877 killed += newkilled; 878 } 879 880 freeaddrinfo(res); 881 882 if ((opts & PF_OPT_QUIET) == 0) 883 fprintf(stderr, "killed %d states\n", killed); 884 return (0); 885 } 886 887 int 888 pfctl_label_kill_states(int dev, const char *iface, int opts) 889 { 890 struct pfctl_kill kill; 891 unsigned int killed; 892 893 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 894 warnx("no label specified"); 895 usage(); 896 } 897 memset(&kill, 0, sizeof(kill)); 898 if (iface != NULL && strlcpy(kill.ifname, iface, 899 sizeof(kill.ifname)) >= sizeof(kill.ifname)) 900 errx(1, "invalid interface: %s", iface); 901 902 if (opts & PF_OPT_KILLMATCH) 903 kill.kill_match = true; 904 905 if (strlcpy(kill.label, state_kill[1], sizeof(kill.label)) >= 906 sizeof(kill.label)) 907 errx(1, "label too long: %s", state_kill[1]); 908 909 if (pfctl_kill_states(dev, &kill, &killed)) 910 err(1, "DIOCKILLSTATES"); 911 912 if ((opts & PF_OPT_QUIET) == 0) 913 fprintf(stderr, "killed %d states\n", killed); 914 915 return (0); 916 } 917 918 int 919 pfctl_id_kill_states(int dev, const char *iface, int opts) 920 { 921 struct pfctl_kill kill; 922 unsigned int killed; 923 924 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 925 warnx("no id specified"); 926 usage(); 927 } 928 929 memset(&kill, 0, sizeof(kill)); 930 931 if (opts & PF_OPT_KILLMATCH) 932 kill.kill_match = true; 933 934 if ((sscanf(state_kill[1], "%jx/%x", 935 &kill.cmp.id, &kill.cmp.creatorid)) == 2) { 936 } 937 else if ((sscanf(state_kill[1], "%jx", &kill.cmp.id)) == 1) { 938 kill.cmp.creatorid = 0; 939 } else { 940 warnx("wrong id format specified"); 941 usage(); 942 } 943 if (kill.cmp.id == 0) { 944 warnx("cannot kill id 0"); 945 usage(); 946 } 947 948 if (pfctl_kill_states(dev, &kill, &killed)) 949 err(1, "DIOCKILLSTATES"); 950 951 if ((opts & PF_OPT_QUIET) == 0) 952 fprintf(stderr, "killed %d states\n", killed); 953 954 return (0); 955 } 956 957 int 958 pfctl_get_pool(int dev, struct pfctl_pool *pool, u_int32_t nr, 959 u_int32_t ticket, int r_action, char *anchorname) 960 { 961 struct pfioc_pooladdr pp; 962 struct pf_pooladdr *pa; 963 u_int32_t pnr, mpnr; 964 965 memset(&pp, 0, sizeof(pp)); 966 memcpy(pp.anchor, anchorname, sizeof(pp.anchor)); 967 pp.r_action = r_action; 968 pp.r_num = nr; 969 pp.ticket = ticket; 970 if (ioctl(dev, DIOCGETADDRS, &pp)) { 971 warn("DIOCGETADDRS"); 972 return (-1); 973 } 974 mpnr = pp.nr; 975 TAILQ_INIT(&pool->list); 976 for (pnr = 0; pnr < mpnr; ++pnr) { 977 pp.nr = pnr; 978 if (ioctl(dev, DIOCGETADDR, &pp)) { 979 warn("DIOCGETADDR"); 980 return (-1); 981 } 982 pa = calloc(1, sizeof(struct pf_pooladdr)); 983 if (pa == NULL) 984 err(1, "calloc"); 985 bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr)); 986 TAILQ_INSERT_TAIL(&pool->list, pa, entries); 987 } 988 989 return (0); 990 } 991 992 void 993 pfctl_move_pool(struct pfctl_pool *src, struct pfctl_pool *dst) 994 { 995 struct pf_pooladdr *pa; 996 997 while ((pa = TAILQ_FIRST(&src->list)) != NULL) { 998 TAILQ_REMOVE(&src->list, pa, entries); 999 TAILQ_INSERT_TAIL(&dst->list, pa, entries); 1000 } 1001 } 1002 1003 void 1004 pfctl_clear_pool(struct pfctl_pool *pool) 1005 { 1006 struct pf_pooladdr *pa; 1007 1008 while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { 1009 TAILQ_REMOVE(&pool->list, pa, entries); 1010 free(pa); 1011 } 1012 } 1013 1014 void 1015 pfctl_print_eth_rule_counters(struct pfctl_eth_rule *rule, int opts) 1016 { 1017 if (opts & PF_OPT_VERBOSE) { 1018 printf(" [ Evaluations: %-8llu Packets: %-8llu " 1019 "Bytes: %-10llu]\n", 1020 (unsigned long long)rule->evaluations, 1021 (unsigned long long)(rule->packets[0] + 1022 rule->packets[1]), 1023 (unsigned long long)(rule->bytes[0] + 1024 rule->bytes[1])); 1025 } 1026 if (opts & PF_OPT_VERBOSE2) { 1027 char timestr[30]; 1028 1029 if (rule->last_active_timestamp != 0) { 1030 bcopy(ctime(&rule->last_active_timestamp), timestr, 1031 sizeof(timestr)); 1032 *strchr(timestr, '\n') = '\0'; 1033 } else { 1034 snprintf(timestr, sizeof(timestr), "N/A"); 1035 } 1036 printf(" [ Last Active Time: %s ]\n", timestr); 1037 } 1038 } 1039 1040 void 1041 pfctl_print_rule_counters(struct pfctl_rule *rule, int opts) 1042 { 1043 if (opts & PF_OPT_DEBUG) { 1044 const char *t[PF_SKIP_COUNT] = { "i", "d", "f", 1045 "p", "sa", "sp", "da", "dp" }; 1046 int i; 1047 1048 printf(" [ Skip steps: "); 1049 for (i = 0; i < PF_SKIP_COUNT; ++i) { 1050 if (rule->skip[i].nr == rule->nr + 1) 1051 continue; 1052 printf("%s=", t[i]); 1053 if (rule->skip[i].nr == -1) 1054 printf("end "); 1055 else 1056 printf("%u ", rule->skip[i].nr); 1057 } 1058 printf("]\n"); 1059 1060 printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n", 1061 rule->qname, rule->qid, rule->pqname, rule->pqid); 1062 } 1063 if (opts & PF_OPT_VERBOSE) { 1064 printf(" [ Evaluations: %-8llu Packets: %-8llu " 1065 "Bytes: %-10llu States: %-6ju]\n", 1066 (unsigned long long)rule->evaluations, 1067 (unsigned long long)(rule->packets[0] + 1068 rule->packets[1]), 1069 (unsigned long long)(rule->bytes[0] + 1070 rule->bytes[1]), (uintmax_t)rule->states_cur); 1071 if (!(opts & PF_OPT_DEBUG)) 1072 printf(" [ Inserted: uid %u pid %u " 1073 "State Creations: %-6ju]\n", 1074 (unsigned)rule->cuid, (unsigned)rule->cpid, 1075 (uintmax_t)rule->states_tot); 1076 } 1077 if (opts & PF_OPT_VERBOSE2) { 1078 char timestr[30]; 1079 if (rule->last_active_timestamp != 0) { 1080 bcopy(ctime(&rule->last_active_timestamp), timestr, 1081 sizeof(timestr)); 1082 *strchr(timestr, '\n') = '\0'; 1083 } else { 1084 snprintf(timestr, sizeof(timestr), "N/A"); 1085 } 1086 printf(" [ Last Active Time: %s ]\n", timestr); 1087 } 1088 } 1089 1090 void 1091 pfctl_print_title(char *title) 1092 { 1093 if (!first_title) 1094 printf("\n"); 1095 first_title = 0; 1096 printf("%s\n", title); 1097 } 1098 1099 int 1100 pfctl_show_eth_rules(int dev, char *path, int opts, enum pfctl_show format, 1101 char *anchorname, int depth, int wildcard) 1102 { 1103 char anchor_call[MAXPATHLEN]; 1104 struct pfctl_eth_rules_info info; 1105 struct pfctl_eth_rule rule; 1106 int brace; 1107 int dotitle = opts & PF_OPT_SHOWALL; 1108 int len = strlen(path); 1109 char *npath, *p; 1110 1111 /* 1112 * Truncate a trailing / and * on an anchorname before searching for 1113 * the ruleset, this is syntactic sugar that doesn't actually make it 1114 * to the kernel. 1115 */ 1116 if ((p = strrchr(anchorname, '/')) != NULL && 1117 p[1] == '*' && p[2] == '\0') { 1118 p[0] = '\0'; 1119 } 1120 1121 if (anchorname[0] == '/') { 1122 if ((npath = calloc(1, MAXPATHLEN)) == NULL) 1123 errx(1, "pfctl_rules: calloc"); 1124 snprintf(npath, MAXPATHLEN, "%s", anchorname); 1125 } else { 1126 if (path[0]) 1127 snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 1128 else 1129 snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 1130 npath = path; 1131 } 1132 1133 /* 1134 * If this anchor was called with a wildcard path, go through 1135 * the rulesets in the anchor rather than the rules. 1136 */ 1137 if (wildcard && (opts & PF_OPT_RECURSE)) { 1138 struct pfctl_eth_rulesets_info ri; 1139 u_int32_t mnr, nr; 1140 1141 if (pfctl_get_eth_rulesets_info(dev, &ri, npath)) { 1142 if (errno == EINVAL) { 1143 fprintf(stderr, "Anchor '%s' " 1144 "not found.\n", anchorname); 1145 } else { 1146 warn("DIOCGETETHRULESETS"); 1147 return (-1); 1148 } 1149 } 1150 mnr = ri.nr; 1151 1152 pfctl_print_eth_rule_counters(&rule, opts); 1153 for (nr = 0; nr < mnr; ++nr) { 1154 struct pfctl_eth_ruleset_info rs; 1155 1156 if (pfctl_get_eth_ruleset(dev, npath, nr, &rs)) 1157 err(1, "DIOCGETETHRULESET"); 1158 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1159 printf("anchor \"%s\" all {\n", rs.name); 1160 pfctl_show_eth_rules(dev, npath, opts, 1161 format, rs.name, depth + 1, 0); 1162 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1163 printf("}\n"); 1164 } 1165 path[len] = '\0'; 1166 return (0); 1167 } 1168 1169 if (pfctl_get_eth_rules_info(dev, &info, path)) { 1170 warn("DIOCGETETHRULES"); 1171 return (-1); 1172 } 1173 for (int nr = 0; nr < info.nr; nr++) { 1174 brace = 0; 1175 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1176 if (pfctl_get_eth_rule(dev, nr, info.ticket, path, &rule, 1177 opts & PF_OPT_CLRRULECTRS, anchor_call) != 0) { 1178 warn("DIOCGETETHRULE"); 1179 return (-1); 1180 } 1181 if (anchor_call[0] && 1182 ((((p = strrchr(anchor_call, '_')) != NULL) && 1183 (p == anchor_call || 1184 *(--p) == '/')) || (opts & PF_OPT_RECURSE))) { 1185 brace++; 1186 int aclen = strlen(anchor_call); 1187 if (anchor_call[aclen - 1] == '*') 1188 anchor_call[aclen - 2] = '\0'; 1189 } 1190 p = &anchor_call[0]; 1191 if (dotitle) { 1192 pfctl_print_title("ETH RULES:"); 1193 dotitle = 0; 1194 } 1195 print_eth_rule(&rule, anchor_call, 1196 opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG)); 1197 if (brace) 1198 printf(" {\n"); 1199 else 1200 printf("\n"); 1201 pfctl_print_eth_rule_counters(&rule, opts); 1202 if (brace) { 1203 pfctl_show_eth_rules(dev, path, opts, format, 1204 p, depth + 1, rule.anchor_wildcard); 1205 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1206 printf("}\n"); 1207 } 1208 } 1209 1210 path[len] = '\0'; 1211 return (0); 1212 } 1213 1214 int 1215 pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, 1216 char *anchorname, int depth, int wildcard) 1217 { 1218 struct pfctl_rules_info ri; 1219 struct pfctl_rule rule; 1220 char anchor_call[MAXPATHLEN]; 1221 u_int32_t nr, header = 0; 1222 int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); 1223 int numeric = opts & PF_OPT_NUMERIC; 1224 int len = strlen(path), ret = 0; 1225 char *npath, *p; 1226 1227 /* 1228 * Truncate a trailing / and * on an anchorname before searching for 1229 * the ruleset, this is syntactic sugar that doesn't actually make it 1230 * to the kernel. 1231 */ 1232 if ((p = strrchr(anchorname, '/')) != NULL && 1233 p[1] == '*' && p[2] == '\0') { 1234 p[0] = '\0'; 1235 } 1236 1237 if (anchorname[0] == '/') { 1238 if ((npath = calloc(1, MAXPATHLEN)) == NULL) 1239 errx(1, "pfctl_rules: calloc"); 1240 snprintf(npath, MAXPATHLEN, "%s", anchorname); 1241 } else { 1242 if (path[0]) 1243 snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 1244 else 1245 snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 1246 npath = path; 1247 } 1248 1249 /* 1250 * If this anchor was called with a wildcard path, go through 1251 * the rulesets in the anchor rather than the rules. 1252 */ 1253 if (wildcard && (opts & PF_OPT_RECURSE)) { 1254 struct pfioc_ruleset prs; 1255 u_int32_t mnr, nr; 1256 1257 memset(&prs, 0, sizeof(prs)); 1258 memcpy(prs.path, npath, sizeof(prs.path)); 1259 if (ioctl(dev, DIOCGETRULESETS, &prs)) { 1260 if (errno == EINVAL) 1261 fprintf(stderr, "Anchor '%s' " 1262 "not found.\n", anchorname); 1263 else 1264 err(1, "DIOCGETRULESETS"); 1265 } 1266 mnr = prs.nr; 1267 1268 pfctl_print_rule_counters(&rule, opts); 1269 for (nr = 0; nr < mnr; ++nr) { 1270 prs.nr = nr; 1271 if (ioctl(dev, DIOCGETRULESET, &prs)) 1272 err(1, "DIOCGETRULESET"); 1273 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1274 printf("anchor \"%s\" all {\n", prs.name); 1275 pfctl_show_rules(dev, npath, opts, 1276 format, prs.name, depth + 1, 0); 1277 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1278 printf("}\n"); 1279 } 1280 path[len] = '\0'; 1281 return (0); 1282 } 1283 1284 if (opts & PF_OPT_SHOWALL) { 1285 ret = pfctl_get_rules_info(dev, &ri, PF_PASS, path); 1286 if (ret != 0) { 1287 warn("DIOCGETRULES"); 1288 goto error; 1289 } 1290 header++; 1291 } 1292 ret = pfctl_get_rules_info(dev, &ri, PF_SCRUB, path); 1293 if (ret != 0) { 1294 warn("DIOCGETRULES"); 1295 goto error; 1296 } 1297 if (opts & PF_OPT_SHOWALL) { 1298 if (format == PFCTL_SHOW_RULES && (ri.nr > 0 || header)) 1299 pfctl_print_title("FILTER RULES:"); 1300 else if (format == PFCTL_SHOW_LABELS && labels) 1301 pfctl_print_title("LABEL COUNTERS:"); 1302 } 1303 1304 for (nr = 0; nr < ri.nr; ++nr) { 1305 if (pfctl_get_clear_rule(dev, nr, ri.ticket, path, PF_SCRUB, 1306 &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) { 1307 warn("DIOCGETRULENV"); 1308 goto error; 1309 } 1310 1311 if (pfctl_get_pool(dev, &rule.rpool, 1312 nr, ri.ticket, PF_SCRUB, path) != 0) 1313 goto error; 1314 1315 switch (format) { 1316 case PFCTL_SHOW_LABELS: 1317 break; 1318 case PFCTL_SHOW_RULES: 1319 if (rule.label[0][0] && (opts & PF_OPT_SHOWALL)) 1320 labels = 1; 1321 print_rule(&rule, anchor_call, rule_numbers, numeric); 1322 printf("\n"); 1323 pfctl_print_rule_counters(&rule, opts); 1324 break; 1325 case PFCTL_SHOW_NOTHING: 1326 break; 1327 } 1328 pfctl_clear_pool(&rule.rpool); 1329 } 1330 ret = pfctl_get_rules_info(dev, &ri, PF_PASS, path); 1331 if (ret != 0) { 1332 warn("DIOCGETRULES"); 1333 goto error; 1334 } 1335 for (nr = 0; nr < ri.nr; ++nr) { 1336 if (pfctl_get_clear_rule(dev, nr, ri.ticket, path, PF_PASS, 1337 &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) { 1338 warn("DIOCGETRULE"); 1339 goto error; 1340 } 1341 1342 if (pfctl_get_pool(dev, &rule.rpool, 1343 nr, ri.ticket, PF_PASS, path) != 0) 1344 goto error; 1345 1346 switch (format) { 1347 case PFCTL_SHOW_LABELS: { 1348 bool show = false; 1349 int i = 0; 1350 1351 while (rule.label[i][0]) { 1352 printf("%s ", rule.label[i++]); 1353 show = true; 1354 } 1355 1356 if (show) { 1357 printf("%llu %llu %llu %llu" 1358 " %llu %llu %llu %ju\n", 1359 (unsigned long long)rule.evaluations, 1360 (unsigned long long)(rule.packets[0] + 1361 rule.packets[1]), 1362 (unsigned long long)(rule.bytes[0] + 1363 rule.bytes[1]), 1364 (unsigned long long)rule.packets[0], 1365 (unsigned long long)rule.bytes[0], 1366 (unsigned long long)rule.packets[1], 1367 (unsigned long long)rule.bytes[1], 1368 (uintmax_t)rule.states_tot); 1369 } 1370 break; 1371 } 1372 case PFCTL_SHOW_RULES: 1373 if (rule.label[0][0] && (opts & PF_OPT_SHOWALL)) 1374 labels = 1; 1375 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1376 print_rule(&rule, anchor_call, rule_numbers, numeric); 1377 1378 /* 1379 * If this is a 'unnamed' brace notation 1380 * anchor, OR the user has explicitly requested 1381 * recursion, print it recursively. 1382 */ 1383 if (anchor_call[0] && 1384 (((p = strrchr(anchor_call, '/')) ? 1385 p[1] == '_' : anchor_call[0] == '_') || 1386 opts & PF_OPT_RECURSE)) { 1387 printf(" {\n"); 1388 pfctl_print_rule_counters(&rule, opts); 1389 pfctl_show_rules(dev, npath, opts, format, 1390 anchor_call, depth + 1, 1391 rule.anchor_wildcard); 1392 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1393 printf("}\n"); 1394 } else { 1395 printf("\n"); 1396 pfctl_print_rule_counters(&rule, opts); 1397 } 1398 break; 1399 case PFCTL_SHOW_NOTHING: 1400 break; 1401 } 1402 pfctl_clear_pool(&rule.rpool); 1403 } 1404 1405 error: 1406 path[len] = '\0'; 1407 return (ret); 1408 } 1409 1410 int 1411 pfctl_show_nat(int dev, char *path, int opts, char *anchorname, int depth) 1412 { 1413 struct pfctl_rules_info ri; 1414 struct pfctl_rule rule; 1415 char anchor_call[MAXPATHLEN]; 1416 u_int32_t nr; 1417 static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; 1418 int i, dotitle = opts & PF_OPT_SHOWALL; 1419 int brace, ret; 1420 int len = strlen(path); 1421 char *p; 1422 1423 if (path[0]) 1424 snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 1425 else 1426 snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 1427 1428 for (i = 0; i < 3; i++) { 1429 ret = pfctl_get_rules_info(dev, &ri, nattype[i], path); 1430 if (ret != 0) { 1431 warn("DIOCGETRULES"); 1432 return (-1); 1433 } 1434 for (nr = 0; nr < ri.nr; ++nr) { 1435 brace = 0; 1436 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1437 1438 if (pfctl_get_rule(dev, nr, ri.ticket, path, 1439 nattype[i], &rule, anchor_call)) { 1440 warn("DIOCGETRULE"); 1441 return (-1); 1442 } 1443 if (pfctl_get_pool(dev, &rule.rpool, nr, 1444 ri.ticket, nattype[i], path) != 0) 1445 return (-1); 1446 1447 if (anchor_call[0] && 1448 ((((p = strrchr(anchor_call, '_')) != NULL) && 1449 (p == anchor_call || 1450 *(--p) == '/')) || (opts & PF_OPT_RECURSE))) { 1451 brace++; 1452 if ((p = strrchr(anchor_call, '/')) != 1453 NULL) 1454 p++; 1455 else 1456 p = &anchor_call[0]; 1457 } else 1458 p = &anchor_call[0]; 1459 1460 if (dotitle) { 1461 pfctl_print_title("TRANSLATION RULES:"); 1462 dotitle = 0; 1463 } 1464 print_rule(&rule, anchor_call, 1465 opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC); 1466 if (brace) 1467 printf(" {\n"); 1468 else 1469 printf("\n"); 1470 pfctl_print_rule_counters(&rule, opts); 1471 pfctl_clear_pool(&rule.rpool); 1472 if (brace) { 1473 pfctl_show_nat(dev, path, opts, p, depth + 1); 1474 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1475 printf("}\n"); 1476 } 1477 } 1478 } 1479 return (0); 1480 } 1481 1482 int 1483 pfctl_show_src_nodes(int dev, int opts) 1484 { 1485 struct pfioc_src_nodes psn; 1486 struct pf_src_node *p; 1487 char *inbuf = NULL, *newinbuf = NULL; 1488 unsigned int len = 0; 1489 int i; 1490 1491 memset(&psn, 0, sizeof(psn)); 1492 for (;;) { 1493 psn.psn_len = len; 1494 if (len) { 1495 newinbuf = realloc(inbuf, len); 1496 if (newinbuf == NULL) 1497 err(1, "realloc"); 1498 psn.psn_buf = inbuf = newinbuf; 1499 } 1500 if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) { 1501 warn("DIOCGETSRCNODES"); 1502 free(inbuf); 1503 return (-1); 1504 } 1505 if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len) 1506 break; 1507 if (len == 0 && psn.psn_len == 0) 1508 goto done; 1509 if (len == 0 && psn.psn_len != 0) 1510 len = psn.psn_len; 1511 if (psn.psn_len == 0) 1512 goto done; /* no src_nodes */ 1513 len *= 2; 1514 } 1515 p = psn.psn_src_nodes; 1516 if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL)) 1517 pfctl_print_title("SOURCE TRACKING NODES:"); 1518 for (i = 0; i < psn.psn_len; i += sizeof(*p)) { 1519 print_src_node(p, opts); 1520 p++; 1521 } 1522 done: 1523 free(inbuf); 1524 return (0); 1525 } 1526 1527 struct pfctl_show_state_arg { 1528 int opts; 1529 int dotitle; 1530 const char *iface; 1531 }; 1532 1533 static int 1534 pfctl_show_state(struct pfctl_state *s, void *arg) 1535 { 1536 struct pfctl_show_state_arg *a = (struct pfctl_show_state_arg *)arg; 1537 1538 if (a->dotitle) { 1539 pfctl_print_title("STATES:"); 1540 a->dotitle = 0; 1541 } 1542 print_state(s, a->opts); 1543 1544 return (0); 1545 } 1546 1547 int 1548 pfctl_show_states(int dev, const char *iface, int opts) 1549 { 1550 struct pfctl_show_state_arg arg; 1551 struct pfctl_state_filter filter = {}; 1552 1553 if (iface != NULL) 1554 strncpy(filter.ifname, iface, IFNAMSIZ); 1555 1556 arg.opts = opts; 1557 arg.dotitle = opts & PF_OPT_SHOWALL; 1558 arg.iface = iface; 1559 1560 if (pfctl_get_filtered_states_iter(&filter, pfctl_show_state, &arg)) 1561 return (-1); 1562 1563 return (0); 1564 } 1565 1566 int 1567 pfctl_show_status(int dev, int opts) 1568 { 1569 struct pfctl_status *status; 1570 struct pfctl_syncookies cookies; 1571 1572 if ((status = pfctl_get_status(dev)) == NULL) { 1573 warn("DIOCGETSTATUS"); 1574 return (-1); 1575 } 1576 if (pfctl_get_syncookies(dev, &cookies)) { 1577 pfctl_free_status(status); 1578 warn("DIOCGETSYNCOOKIES"); 1579 return (-1); 1580 } 1581 if (opts & PF_OPT_SHOWALL) 1582 pfctl_print_title("INFO:"); 1583 print_status(status, &cookies, opts); 1584 pfctl_free_status(status); 1585 return (0); 1586 } 1587 1588 int 1589 pfctl_show_running(int dev) 1590 { 1591 struct pfctl_status *status; 1592 int running; 1593 1594 if ((status = pfctl_get_status(dev)) == NULL) { 1595 warn("DIOCGETSTATUS"); 1596 return (-1); 1597 } 1598 1599 running = status->running; 1600 1601 print_running(status); 1602 pfctl_free_status(status); 1603 return (!running); 1604 } 1605 1606 int 1607 pfctl_show_timeouts(int dev, int opts) 1608 { 1609 struct pfioc_tm pt; 1610 int i; 1611 1612 if (opts & PF_OPT_SHOWALL) 1613 pfctl_print_title("TIMEOUTS:"); 1614 memset(&pt, 0, sizeof(pt)); 1615 for (i = 0; pf_timeouts[i].name; i++) { 1616 pt.timeout = pf_timeouts[i].timeout; 1617 if (ioctl(dev, DIOCGETTIMEOUT, &pt)) 1618 err(1, "DIOCGETTIMEOUT"); 1619 printf("%-20s %10d", pf_timeouts[i].name, pt.seconds); 1620 if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && 1621 pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) 1622 printf(" states"); 1623 else 1624 printf("s"); 1625 printf("\n"); 1626 } 1627 return (0); 1628 1629 } 1630 1631 int 1632 pfctl_show_limits(int dev, int opts) 1633 { 1634 struct pfioc_limit pl; 1635 int i; 1636 1637 if (opts & PF_OPT_SHOWALL) 1638 pfctl_print_title("LIMITS:"); 1639 memset(&pl, 0, sizeof(pl)); 1640 for (i = 0; pf_limits[i].name; i++) { 1641 pl.index = pf_limits[i].index; 1642 if (ioctl(dev, DIOCGETLIMIT, &pl)) 1643 err(1, "DIOCGETLIMIT"); 1644 printf("%-13s ", pf_limits[i].name); 1645 if (pl.limit == UINT_MAX) 1646 printf("unlimited\n"); 1647 else 1648 printf("hard limit %8u\n", pl.limit); 1649 } 1650 return (0); 1651 } 1652 1653 void 1654 pfctl_show_creators(int opts) 1655 { 1656 int ret; 1657 uint32_t creators[16]; 1658 size_t count = nitems(creators); 1659 1660 ret = pfctl_get_creatorids(creators, &count); 1661 if (ret != 0) 1662 errx(ret, "Failed to retrieve creators"); 1663 1664 printf("Creator IDs:\n"); 1665 for (size_t i = 0; i < count; i++) 1666 printf("%08x\n", creators[i]); 1667 } 1668 1669 /* callbacks for rule/nat/rdr/addr */ 1670 int 1671 pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af) 1672 { 1673 struct pf_pooladdr *pa; 1674 1675 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1676 if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) 1677 err(1, "DIOCBEGINADDRS"); 1678 } 1679 1680 pf->paddr.af = af; 1681 TAILQ_FOREACH(pa, &p->list, entries) { 1682 memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr)); 1683 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1684 if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) 1685 err(1, "DIOCADDADDR"); 1686 } 1687 } 1688 return (0); 1689 } 1690 1691 int 1692 pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r, 1693 const char *anchor_call) 1694 { 1695 u_int8_t rs_num; 1696 struct pfctl_rule *rule; 1697 struct pfctl_ruleset *rs; 1698 char *p; 1699 1700 rs_num = pf_get_ruleset_number(r->action); 1701 if (rs_num == PF_RULESET_MAX) 1702 errx(1, "Invalid rule type %d", r->action); 1703 1704 rs = &pf->anchor->ruleset; 1705 1706 if (anchor_call[0] && r->anchor == NULL) { 1707 /* 1708 * Don't make non-brace anchors part of the main anchor pool. 1709 */ 1710 if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 1711 err(1, "pfctl_append_rule: calloc"); 1712 1713 pf_init_ruleset(&r->anchor->ruleset); 1714 r->anchor->ruleset.anchor = r->anchor; 1715 if (strlcpy(r->anchor->path, anchor_call, 1716 sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 1717 errx(1, "pfctl_append_rule: strlcpy"); 1718 if ((p = strrchr(anchor_call, '/')) != NULL) { 1719 if (!strlen(p)) 1720 err(1, "pfctl_append_rule: bad anchor name %s", 1721 anchor_call); 1722 } else 1723 p = (char *)anchor_call; 1724 if (strlcpy(r->anchor->name, p, 1725 sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 1726 errx(1, "pfctl_append_rule: strlcpy"); 1727 } 1728 1729 if ((rule = calloc(1, sizeof(*rule))) == NULL) 1730 err(1, "calloc"); 1731 bcopy(r, rule, sizeof(*rule)); 1732 TAILQ_INIT(&rule->rpool.list); 1733 pfctl_move_pool(&r->rpool, &rule->rpool); 1734 1735 TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries); 1736 return (0); 1737 } 1738 1739 int 1740 pfctl_append_eth_rule(struct pfctl *pf, struct pfctl_eth_rule *r, 1741 const char *anchor_call) 1742 { 1743 struct pfctl_eth_rule *rule; 1744 struct pfctl_eth_ruleset *rs; 1745 char *p; 1746 1747 rs = &pf->eanchor->ruleset; 1748 1749 if (anchor_call[0] && r->anchor == NULL) { 1750 /* 1751 * Don't make non-brace anchors part of the main anchor pool. 1752 */ 1753 if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 1754 err(1, "pfctl_append_rule: calloc"); 1755 1756 pf_init_eth_ruleset(&r->anchor->ruleset); 1757 r->anchor->ruleset.anchor = r->anchor; 1758 if (strlcpy(r->anchor->path, anchor_call, 1759 sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 1760 errx(1, "pfctl_append_rule: strlcpy"); 1761 if ((p = strrchr(anchor_call, '/')) != NULL) { 1762 if (!strlen(p)) 1763 err(1, "pfctl_append_eth_rule: bad anchor name %s", 1764 anchor_call); 1765 } else 1766 p = (char *)anchor_call; 1767 if (strlcpy(r->anchor->name, p, 1768 sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 1769 errx(1, "pfctl_append_eth_rule: strlcpy"); 1770 } 1771 1772 if ((rule = calloc(1, sizeof(*rule))) == NULL) 1773 err(1, "calloc"); 1774 bcopy(r, rule, sizeof(*rule)); 1775 1776 TAILQ_INSERT_TAIL(&rs->rules, rule, entries); 1777 return (0); 1778 } 1779 1780 int 1781 pfctl_eth_ruleset_trans(struct pfctl *pf, char *path, 1782 struct pfctl_eth_anchor *a) 1783 { 1784 int osize = pf->trans->pfrb_size; 1785 1786 if ((pf->loadopt & PFCTL_FLAG_ETH) != 0) { 1787 if (pfctl_add_trans(pf->trans, PF_RULESET_ETH, path)) 1788 return (1); 1789 } 1790 if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1791 return (5); 1792 1793 return (0); 1794 } 1795 1796 int 1797 pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pfctl_anchor *a, bool do_eth) 1798 { 1799 int osize = pf->trans->pfrb_size; 1800 1801 if ((pf->loadopt & PFCTL_FLAG_ETH) != 0 && do_eth) { 1802 if (pfctl_add_trans(pf->trans, PF_RULESET_ETH, path)) 1803 return (1); 1804 } 1805 if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { 1806 if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || 1807 pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || 1808 pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) 1809 return (1); 1810 } 1811 if (a == pf->astack[0] && ((altqsupport && 1812 (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) { 1813 if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path)) 1814 return (2); 1815 } 1816 if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) { 1817 if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) || 1818 pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path)) 1819 return (3); 1820 } 1821 if (pf->loadopt & PFCTL_FLAG_TABLE) 1822 if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path)) 1823 return (4); 1824 if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1825 return (5); 1826 1827 return (0); 1828 } 1829 1830 int 1831 pfctl_load_eth_ruleset(struct pfctl *pf, char *path, 1832 struct pfctl_eth_ruleset *rs, int depth) 1833 { 1834 struct pfctl_eth_rule *r; 1835 int error, len = strlen(path); 1836 int brace = 0; 1837 1838 pf->eanchor = rs->anchor; 1839 if (path[0]) 1840 snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->eanchor->name); 1841 else 1842 snprintf(&path[len], MAXPATHLEN - len, "%s", pf->eanchor->name); 1843 1844 if (depth) { 1845 if (TAILQ_FIRST(&rs->rules) != NULL) { 1846 brace++; 1847 if (pf->opts & PF_OPT_VERBOSE) 1848 printf(" {\n"); 1849 if ((pf->opts & PF_OPT_NOACTION) == 0 && 1850 (error = pfctl_eth_ruleset_trans(pf, 1851 path, rs->anchor))) { 1852 printf("pfctl_load_eth_rulesets: " 1853 "pfctl_eth_ruleset_trans %d\n", error); 1854 goto error; 1855 } 1856 } else if (pf->opts & PF_OPT_VERBOSE) 1857 printf("\n"); 1858 } 1859 1860 while ((r = TAILQ_FIRST(&rs->rules)) != NULL) { 1861 TAILQ_REMOVE(&rs->rules, r, entries); 1862 1863 error = pfctl_load_eth_rule(pf, path, r, depth); 1864 if (error) 1865 return (error); 1866 1867 if (r->anchor) { 1868 if ((error = pfctl_load_eth_ruleset(pf, path, 1869 &r->anchor->ruleset, depth + 1))) 1870 return (error); 1871 } else if (pf->opts & PF_OPT_VERBOSE) 1872 printf("\n"); 1873 free(r); 1874 } 1875 if (brace && pf->opts & PF_OPT_VERBOSE) { 1876 INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1877 printf("}\n"); 1878 } 1879 path[len] = '\0'; 1880 1881 return (0); 1882 error: 1883 path[len] = '\0'; 1884 return (error); 1885 } 1886 1887 int 1888 pfctl_load_eth_rule(struct pfctl *pf, char *path, struct pfctl_eth_rule *r, 1889 int depth) 1890 { 1891 char *name; 1892 char anchor[PF_ANCHOR_NAME_SIZE]; 1893 int len = strlen(path); 1894 1895 if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor)) 1896 errx(1, "pfctl_load_eth_rule: strlcpy"); 1897 1898 if (r->anchor) { 1899 if (r->anchor->match) { 1900 if (path[0]) 1901 snprintf(&path[len], MAXPATHLEN - len, 1902 "/%s", r->anchor->name); 1903 else 1904 snprintf(&path[len], MAXPATHLEN - len, 1905 "%s", r->anchor->name); 1906 name = r->anchor->name; 1907 } else 1908 name = r->anchor->path; 1909 } else 1910 name = ""; 1911 1912 if ((pf->opts & PF_OPT_NOACTION) == 0) 1913 if (pfctl_add_eth_rule(pf->dev, r, anchor, name, 1914 pf->eth_ticket)) 1915 err(1, "DIOCADDETHRULENV"); 1916 1917 if (pf->opts & PF_OPT_VERBOSE) { 1918 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 1919 print_eth_rule(r, r->anchor ? r->anchor->name : "", 1920 pf->opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG)); 1921 } 1922 1923 path[len] = '\0'; 1924 1925 return (0); 1926 } 1927 1928 int 1929 pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs, 1930 int rs_num, int depth) 1931 { 1932 struct pfctl_rule *r; 1933 int error, len = strlen(path); 1934 int brace = 0; 1935 1936 pf->anchor = rs->anchor; 1937 1938 if (path[0]) 1939 snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name); 1940 else 1941 snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name); 1942 1943 if (depth) { 1944 if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) { 1945 brace++; 1946 if (pf->opts & PF_OPT_VERBOSE) 1947 printf(" {\n"); 1948 if ((pf->opts & PF_OPT_NOACTION) == 0 && 1949 (error = pfctl_ruleset_trans(pf, 1950 path, rs->anchor, false))) { 1951 printf("pfctl_load_rulesets: " 1952 "pfctl_ruleset_trans %d\n", error); 1953 goto error; 1954 } 1955 } else if (pf->opts & PF_OPT_VERBOSE) 1956 printf("\n"); 1957 1958 } 1959 1960 if (pf->optimize && rs_num == PF_RULESET_FILTER) 1961 pfctl_optimize_ruleset(pf, rs); 1962 1963 while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) { 1964 TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries); 1965 1966 for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) 1967 expand_label(r->label[i], PF_RULE_LABEL_SIZE, r); 1968 expand_label(r->tagname, PF_TAG_NAME_SIZE, r); 1969 expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r); 1970 1971 if ((error = pfctl_load_rule(pf, path, r, depth))) 1972 goto error; 1973 if (r->anchor) { 1974 if ((error = pfctl_load_ruleset(pf, path, 1975 &r->anchor->ruleset, rs_num, depth + 1))) 1976 goto error; 1977 } else if (pf->opts & PF_OPT_VERBOSE) 1978 printf("\n"); 1979 free(r); 1980 } 1981 if (brace && pf->opts & PF_OPT_VERBOSE) { 1982 INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1983 printf("}\n"); 1984 } 1985 path[len] = '\0'; 1986 return (0); 1987 1988 error: 1989 path[len] = '\0'; 1990 return (error); 1991 1992 } 1993 1994 int 1995 pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth) 1996 { 1997 u_int8_t rs_num = pf_get_ruleset_number(r->action); 1998 char *name; 1999 u_int32_t ticket; 2000 char anchor[PF_ANCHOR_NAME_SIZE]; 2001 int len = strlen(path); 2002 int error; 2003 bool was_present; 2004 2005 /* set up anchor before adding to path for anchor_call */ 2006 if ((pf->opts & PF_OPT_NOACTION) == 0) 2007 ticket = pfctl_get_ticket(pf->trans, rs_num, path); 2008 if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor)) 2009 errx(1, "pfctl_load_rule: strlcpy"); 2010 2011 if (r->anchor) { 2012 if (r->anchor->match) { 2013 if (path[0]) 2014 snprintf(&path[len], MAXPATHLEN - len, 2015 "/%s", r->anchor->name); 2016 else 2017 snprintf(&path[len], MAXPATHLEN - len, 2018 "%s", r->anchor->name); 2019 name = r->anchor->name; 2020 } else 2021 name = r->anchor->path; 2022 } else 2023 name = ""; 2024 2025 was_present = false; 2026 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2027 if (pfctl_add_pool(pf, &r->rpool, r->af)) 2028 return (1); 2029 error = pfctl_add_rule(pf->dev, r, anchor, name, ticket, 2030 pf->paddr.ticket); 2031 switch (error) { 2032 case 0: 2033 /* things worked, do nothing */ 2034 break; 2035 case EEXIST: 2036 /* an identical rule is already present */ 2037 was_present = true; 2038 break; 2039 default: 2040 err(1, "DIOCADDRULENV"); 2041 } 2042 } 2043 2044 if (pf->opts & PF_OPT_VERBOSE) { 2045 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 2046 print_rule(r, name, 2047 pf->opts & PF_OPT_VERBOSE2, 2048 pf->opts & PF_OPT_NUMERIC); 2049 if (was_present) 2050 printf(" -- rule was already present"); 2051 } 2052 path[len] = '\0'; 2053 pfctl_clear_pool(&r->rpool); 2054 return (0); 2055 } 2056 2057 int 2058 pfctl_add_altq(struct pfctl *pf, struct pf_altq *a) 2059 { 2060 if (altqsupport && 2061 (loadopt & PFCTL_FLAG_ALTQ) != 0) { 2062 memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq)); 2063 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2064 if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) { 2065 if (errno == ENXIO) 2066 errx(1, "qtype not configured"); 2067 else if (errno == ENODEV) 2068 errx(1, "%s: driver does not support " 2069 "altq", a->ifname); 2070 else 2071 err(1, "DIOCADDALTQ"); 2072 } 2073 } 2074 pfaltq_store(&pf->paltq->altq); 2075 } 2076 return (0); 2077 } 2078 2079 int 2080 pfctl_rules(int dev, char *filename, int opts, int optimize, 2081 char *anchorname, struct pfr_buffer *trans) 2082 { 2083 #define ERR(x) do { warn(x); goto _error; } while(0) 2084 #define ERRX(x) do { warnx(x); goto _error; } while(0) 2085 2086 struct pfr_buffer *t, buf; 2087 struct pfioc_altq pa; 2088 struct pfctl pf; 2089 struct pfctl_ruleset *rs; 2090 struct pfctl_eth_ruleset *ethrs; 2091 struct pfr_table trs; 2092 char *path; 2093 int osize; 2094 2095 RB_INIT(&pf_anchors); 2096 memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); 2097 pf_init_ruleset(&pf_main_anchor.ruleset); 2098 pf_main_anchor.ruleset.anchor = &pf_main_anchor; 2099 2100 memset(&pf_eth_main_anchor, 0, sizeof(pf_eth_main_anchor)); 2101 pf_init_eth_ruleset(&pf_eth_main_anchor.ruleset); 2102 pf_eth_main_anchor.ruleset.anchor = &pf_eth_main_anchor; 2103 2104 if (trans == NULL) { 2105 bzero(&buf, sizeof(buf)); 2106 buf.pfrb_type = PFRB_TRANS; 2107 t = &buf; 2108 osize = 0; 2109 } else { 2110 t = trans; 2111 osize = t->pfrb_size; 2112 } 2113 2114 memset(&pa, 0, sizeof(pa)); 2115 pa.version = PFIOC_ALTQ_VERSION; 2116 memset(&pf, 0, sizeof(pf)); 2117 memset(&trs, 0, sizeof(trs)); 2118 if ((path = calloc(1, MAXPATHLEN)) == NULL) 2119 ERRX("pfctl_rules: calloc"); 2120 if (strlcpy(trs.pfrt_anchor, anchorname, 2121 sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) 2122 ERRX("pfctl_rules: strlcpy"); 2123 pf.dev = dev; 2124 pf.opts = opts; 2125 pf.optimize = optimize; 2126 pf.loadopt = loadopt; 2127 2128 /* non-brace anchor, create without resolving the path */ 2129 if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) 2130 ERRX("pfctl_rules: calloc"); 2131 rs = &pf.anchor->ruleset; 2132 pf_init_ruleset(rs); 2133 rs->anchor = pf.anchor; 2134 if (strlcpy(pf.anchor->path, anchorname, 2135 sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 2136 errx(1, "pfctl_rules: strlcpy"); 2137 if (strlcpy(pf.anchor->name, anchorname, 2138 sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 2139 errx(1, "pfctl_rules: strlcpy"); 2140 2141 2142 pf.astack[0] = pf.anchor; 2143 pf.asd = 0; 2144 if (anchorname[0]) 2145 pf.loadopt &= ~PFCTL_FLAG_ALTQ; 2146 pf.paltq = &pa; 2147 pf.trans = t; 2148 pfctl_init_options(&pf); 2149 2150 /* Set up ethernet anchor */ 2151 if ((pf.eanchor = calloc(1, sizeof(*pf.eanchor))) == NULL) 2152 ERRX("pfctl_rules: calloc"); 2153 2154 if (strlcpy(pf.eanchor->path, anchorname, 2155 sizeof(pf.eanchor->path)) >= sizeof(pf.eanchor->path)) 2156 errx(1, "pfctl_rules: strlcpy"); 2157 if (strlcpy(pf.eanchor->name, anchorname, 2158 sizeof(pf.eanchor->name)) >= sizeof(pf.eanchor->name)) 2159 errx(1, "pfctl_rules: strlcpy"); 2160 2161 ethrs = &pf.eanchor->ruleset; 2162 pf_init_eth_ruleset(ethrs); 2163 ethrs->anchor = pf.eanchor; 2164 pf.eastack[0] = pf.eanchor; 2165 2166 if ((opts & PF_OPT_NOACTION) == 0) { 2167 /* 2168 * XXX For the time being we need to open transactions for 2169 * the main ruleset before parsing, because tables are still 2170 * loaded at parse time. 2171 */ 2172 if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor, true)) 2173 ERRX("pfctl_rules"); 2174 if (pf.loadopt & PFCTL_FLAG_ETH) 2175 pf.eth_ticket = pfctl_get_ticket(t, PF_RULESET_ETH, anchorname); 2176 if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) 2177 pa.ticket = 2178 pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname); 2179 if (pf.loadopt & PFCTL_FLAG_TABLE) 2180 pf.astack[0]->ruleset.tticket = 2181 pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname); 2182 } 2183 2184 if (parse_config(filename, &pf) < 0) { 2185 if ((opts & PF_OPT_NOACTION) == 0) 2186 ERRX("Syntax error in config file: " 2187 "pf rules not loaded"); 2188 else 2189 goto _error; 2190 } 2191 if (loadopt & PFCTL_FLAG_OPTION) 2192 pfctl_adjust_skip_ifaces(&pf); 2193 2194 if ((pf.loadopt & PFCTL_FLAG_FILTER && 2195 (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) || 2196 (pf.loadopt & PFCTL_FLAG_ETH && 2197 (pfctl_load_eth_ruleset(&pf, path, ethrs, 0))) || 2198 (pf.loadopt & PFCTL_FLAG_NAT && 2199 (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) || 2200 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) || 2201 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) || 2202 (pf.loadopt & PFCTL_FLAG_FILTER && 2203 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) { 2204 if ((opts & PF_OPT_NOACTION) == 0) 2205 ERRX("Unable to load rules into kernel"); 2206 else 2207 goto _error; 2208 } 2209 2210 if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0)) 2211 if (check_commit_altq(dev, opts) != 0) 2212 ERRX("errors in altq config"); 2213 2214 /* process "load anchor" directives */ 2215 if (!anchorname[0]) 2216 if (pfctl_load_anchors(dev, &pf, t) == -1) 2217 ERRX("load anchors"); 2218 2219 if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) { 2220 if (!anchorname[0]) 2221 if (pfctl_load_options(&pf)) 2222 goto _error; 2223 if (pfctl_trans(dev, t, DIOCXCOMMIT, osize)) 2224 ERR("DIOCXCOMMIT"); 2225 } 2226 free(path); 2227 return (0); 2228 2229 _error: 2230 if (trans == NULL) { /* main ruleset */ 2231 if ((opts & PF_OPT_NOACTION) == 0) 2232 if (pfctl_trans(dev, t, DIOCXROLLBACK, osize)) 2233 err(1, "DIOCXROLLBACK"); 2234 exit(1); 2235 } else { /* sub ruleset */ 2236 free(path); 2237 return (-1); 2238 } 2239 2240 #undef ERR 2241 #undef ERRX 2242 } 2243 2244 FILE * 2245 pfctl_fopen(const char *name, const char *mode) 2246 { 2247 struct stat st; 2248 FILE *fp; 2249 2250 fp = fopen(name, mode); 2251 if (fp == NULL) 2252 return (NULL); 2253 if (fstat(fileno(fp), &st)) { 2254 fclose(fp); 2255 return (NULL); 2256 } 2257 if (S_ISDIR(st.st_mode)) { 2258 fclose(fp); 2259 errno = EISDIR; 2260 return (NULL); 2261 } 2262 return (fp); 2263 } 2264 2265 void 2266 pfctl_init_options(struct pfctl *pf) 2267 { 2268 2269 pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 2270 pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; 2271 pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 2272 pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; 2273 pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; 2274 pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; 2275 pf->timeout[PFTM_SCTP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 2276 pf->timeout[PFTM_SCTP_OPENING] = PFTM_TCP_OPENING_VAL; 2277 pf->timeout[PFTM_SCTP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 2278 pf->timeout[PFTM_SCTP_CLOSING] = PFTM_TCP_CLOSING_VAL; 2279 pf->timeout[PFTM_SCTP_CLOSED] = PFTM_TCP_CLOSED_VAL; 2280 pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; 2281 pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; 2282 pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; 2283 pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; 2284 pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; 2285 pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; 2286 pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; 2287 pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; 2288 pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; 2289 pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; 2290 pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; 2291 pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; 2292 pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; 2293 pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; 2294 2295 pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; 2296 pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT; 2297 pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; 2298 pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; 2299 2300 pf->debug = PF_DEBUG_URGENT; 2301 pf->reassemble = 0; 2302 2303 pf->syncookies = false; 2304 pf->syncookieswat[0] = PF_SYNCOOKIES_LOWATPCT; 2305 pf->syncookieswat[1] = PF_SYNCOOKIES_HIWATPCT; 2306 } 2307 2308 int 2309 pfctl_load_options(struct pfctl *pf) 2310 { 2311 int i, error = 0; 2312 2313 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2314 return (0); 2315 2316 /* load limits */ 2317 for (i = 0; i < PF_LIMIT_MAX; i++) { 2318 if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i]) 2319 continue; 2320 if (pfctl_load_limit(pf, i, pf->limit[i])) 2321 error = 1; 2322 } 2323 2324 /* 2325 * If we've set the limit, but haven't explicitly set adaptive 2326 * timeouts, do it now with a start of 60% and end of 120%. 2327 */ 2328 if (pf->limit_set[PF_LIMIT_STATES] && 2329 !pf->timeout_set[PFTM_ADAPTIVE_START] && 2330 !pf->timeout_set[PFTM_ADAPTIVE_END]) { 2331 pf->timeout[PFTM_ADAPTIVE_START] = 2332 (pf->limit[PF_LIMIT_STATES] / 10) * 6; 2333 pf->timeout_set[PFTM_ADAPTIVE_START] = 1; 2334 pf->timeout[PFTM_ADAPTIVE_END] = 2335 (pf->limit[PF_LIMIT_STATES] / 10) * 12; 2336 pf->timeout_set[PFTM_ADAPTIVE_END] = 1; 2337 } 2338 2339 /* load timeouts */ 2340 for (i = 0; i < PFTM_MAX; i++) { 2341 if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i]) 2342 continue; 2343 if (pfctl_load_timeout(pf, i, pf->timeout[i])) 2344 error = 1; 2345 } 2346 2347 /* load debug */ 2348 if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set) 2349 if (pfctl_load_debug(pf, pf->debug)) 2350 error = 1; 2351 2352 /* load logif */ 2353 if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set) 2354 if (pfctl_load_logif(pf, pf->ifname)) 2355 error = 1; 2356 2357 /* load hostid */ 2358 if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set) 2359 if (pfctl_load_hostid(pf, pf->hostid)) 2360 error = 1; 2361 2362 /* load reassembly settings */ 2363 if (!(pf->opts & PF_OPT_MERGE) || pf->reass_set) 2364 if (pfctl_load_reassembly(pf, pf->reassemble)) 2365 error = 1; 2366 2367 /* load keepcounters */ 2368 if (pfctl_set_keepcounters(pf->dev, pf->keep_counters)) 2369 error = 1; 2370 2371 /* load syncookies settings */ 2372 if (pfctl_load_syncookies(pf, pf->syncookies)) 2373 error = 1; 2374 2375 return (error); 2376 } 2377 2378 int 2379 pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) 2380 { 2381 int i; 2382 2383 2384 for (i = 0; pf_limits[i].name; i++) { 2385 if (strcasecmp(opt, pf_limits[i].name) == 0) { 2386 pf->limit[pf_limits[i].index] = limit; 2387 pf->limit_set[pf_limits[i].index] = 1; 2388 break; 2389 } 2390 } 2391 if (pf_limits[i].name == NULL) { 2392 warnx("Bad pool name."); 2393 return (1); 2394 } 2395 2396 if (pf->opts & PF_OPT_VERBOSE) 2397 printf("set limit %s %d\n", opt, limit); 2398 2399 return (0); 2400 } 2401 2402 int 2403 pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) 2404 { 2405 struct pfioc_limit pl; 2406 2407 memset(&pl, 0, sizeof(pl)); 2408 pl.index = index; 2409 pl.limit = limit; 2410 if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) { 2411 if (errno == EBUSY) 2412 warnx("Current pool size exceeds requested hard limit"); 2413 else 2414 warnx("DIOCSETLIMIT"); 2415 return (1); 2416 } 2417 return (0); 2418 } 2419 2420 int 2421 pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 2422 { 2423 int i; 2424 2425 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2426 return (0); 2427 2428 for (i = 0; pf_timeouts[i].name; i++) { 2429 if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 2430 pf->timeout[pf_timeouts[i].timeout] = seconds; 2431 pf->timeout_set[pf_timeouts[i].timeout] = 1; 2432 break; 2433 } 2434 } 2435 2436 if (pf_timeouts[i].name == NULL) { 2437 warnx("Bad timeout name."); 2438 return (1); 2439 } 2440 2441 2442 if (pf->opts & PF_OPT_VERBOSE && ! quiet) 2443 printf("set timeout %s %d\n", opt, seconds); 2444 2445 return (0); 2446 } 2447 2448 int 2449 pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) 2450 { 2451 struct pfioc_tm pt; 2452 2453 memset(&pt, 0, sizeof(pt)); 2454 pt.timeout = timeout; 2455 pt.seconds = seconds; 2456 if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) { 2457 warnx("DIOCSETTIMEOUT"); 2458 return (1); 2459 } 2460 return (0); 2461 } 2462 2463 int 2464 pfctl_set_reassembly(struct pfctl *pf, int on, int nodf) 2465 { 2466 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2467 return (0); 2468 2469 pf->reass_set = 1; 2470 if (on) { 2471 pf->reassemble = PF_REASS_ENABLED; 2472 if (nodf) 2473 pf->reassemble |= PF_REASS_NODF; 2474 } else { 2475 pf->reassemble = 0; 2476 } 2477 2478 if (pf->opts & PF_OPT_VERBOSE) 2479 printf("set reassemble %s %s\n", on ? "yes" : "no", 2480 nodf ? "no-df" : ""); 2481 2482 return (0); 2483 } 2484 2485 int 2486 pfctl_set_optimization(struct pfctl *pf, const char *opt) 2487 { 2488 const struct pf_hint *hint; 2489 int i, r; 2490 2491 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2492 return (0); 2493 2494 for (i = 0; pf_hints[i].name; i++) 2495 if (strcasecmp(opt, pf_hints[i].name) == 0) 2496 break; 2497 2498 hint = pf_hints[i].hint; 2499 if (hint == NULL) { 2500 warnx("invalid state timeouts optimization"); 2501 return (1); 2502 } 2503 2504 for (i = 0; hint[i].name; i++) 2505 if ((r = pfctl_set_timeout(pf, hint[i].name, 2506 hint[i].timeout, 1))) 2507 return (r); 2508 2509 if (pf->opts & PF_OPT_VERBOSE) 2510 printf("set optimization %s\n", opt); 2511 2512 return (0); 2513 } 2514 2515 int 2516 pfctl_set_logif(struct pfctl *pf, char *ifname) 2517 { 2518 2519 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2520 return (0); 2521 2522 if (!strcmp(ifname, "none")) { 2523 free(pf->ifname); 2524 pf->ifname = NULL; 2525 } else { 2526 pf->ifname = strdup(ifname); 2527 if (!pf->ifname) 2528 errx(1, "pfctl_set_logif: strdup"); 2529 } 2530 pf->ifname_set = 1; 2531 2532 if (pf->opts & PF_OPT_VERBOSE) 2533 printf("set loginterface %s\n", ifname); 2534 2535 return (0); 2536 } 2537 2538 int 2539 pfctl_load_logif(struct pfctl *pf, char *ifname) 2540 { 2541 struct pfioc_if pi; 2542 2543 memset(&pi, 0, sizeof(pi)); 2544 if (ifname && strlcpy(pi.ifname, ifname, 2545 sizeof(pi.ifname)) >= sizeof(pi.ifname)) { 2546 warnx("pfctl_load_logif: strlcpy"); 2547 return (1); 2548 } 2549 if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) { 2550 warnx("DIOCSETSTATUSIF"); 2551 return (1); 2552 } 2553 return (0); 2554 } 2555 2556 int 2557 pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 2558 { 2559 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2560 return (0); 2561 2562 HTONL(hostid); 2563 2564 pf->hostid = hostid; 2565 pf->hostid_set = 1; 2566 2567 if (pf->opts & PF_OPT_VERBOSE) 2568 printf("set hostid 0x%08x\n", ntohl(hostid)); 2569 2570 return (0); 2571 } 2572 2573 int 2574 pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) 2575 { 2576 if (ioctl(dev, DIOCSETHOSTID, &hostid)) { 2577 warnx("DIOCSETHOSTID"); 2578 return (1); 2579 } 2580 return (0); 2581 } 2582 2583 int 2584 pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly) 2585 { 2586 if (ioctl(dev, DIOCSETREASS, &reassembly)) { 2587 warnx("DIOCSETREASS"); 2588 return (1); 2589 } 2590 return (0); 2591 } 2592 2593 int 2594 pfctl_load_syncookies(struct pfctl *pf, u_int8_t val) 2595 { 2596 struct pfctl_syncookies cookies; 2597 2598 bzero(&cookies, sizeof(cookies)); 2599 2600 cookies.mode = val; 2601 cookies.lowwater = pf->syncookieswat[0]; 2602 cookies.highwater = pf->syncookieswat[1]; 2603 2604 if (pfctl_set_syncookies(dev, &cookies)) { 2605 warnx("DIOCSETSYNCOOKIES"); 2606 return (1); 2607 } 2608 return (0); 2609 } 2610 2611 int 2612 pfctl_cfg_syncookies(struct pfctl *pf, uint8_t val, struct pfctl_watermarks *w) 2613 { 2614 if (val != PF_SYNCOOKIES_ADAPTIVE && w != NULL) { 2615 warnx("syncookies start/end only apply to adaptive"); 2616 return (1); 2617 } 2618 if (val == PF_SYNCOOKIES_ADAPTIVE && w != NULL) { 2619 if (!w->hi) 2620 w->hi = PF_SYNCOOKIES_HIWATPCT; 2621 if (!w->lo) 2622 w->lo = w->hi / 2; 2623 if (w->lo >= w->hi) { 2624 warnx("start must be higher than end"); 2625 return (1); 2626 } 2627 pf->syncookieswat[0] = w->lo; 2628 pf->syncookieswat[1] = w->hi; 2629 pf->syncookieswat_set = 1; 2630 } 2631 2632 if (pf->opts & PF_OPT_VERBOSE) { 2633 if (val == PF_SYNCOOKIES_NEVER) 2634 printf("set syncookies never\n"); 2635 else if (val == PF_SYNCOOKIES_ALWAYS) 2636 printf("set syncookies always\n"); 2637 else if (val == PF_SYNCOOKIES_ADAPTIVE) { 2638 if (pf->syncookieswat_set) 2639 printf("set syncookies adaptive (start %u%%, " 2640 "end %u%%)\n", pf->syncookieswat[1], 2641 pf->syncookieswat[0]); 2642 else 2643 printf("set syncookies adaptive\n"); 2644 } else { /* cannot happen */ 2645 warnx("king bula ate all syncookies"); 2646 return (1); 2647 } 2648 } 2649 2650 pf->syncookies = val; 2651 return (0); 2652 } 2653 2654 int 2655 pfctl_set_debug(struct pfctl *pf, char *d) 2656 { 2657 u_int32_t level; 2658 2659 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2660 return (0); 2661 2662 if (!strcmp(d, "none")) 2663 pf->debug = PF_DEBUG_NONE; 2664 else if (!strcmp(d, "urgent")) 2665 pf->debug = PF_DEBUG_URGENT; 2666 else if (!strcmp(d, "misc")) 2667 pf->debug = PF_DEBUG_MISC; 2668 else if (!strcmp(d, "loud")) 2669 pf->debug = PF_DEBUG_NOISY; 2670 else { 2671 warnx("unknown debug level \"%s\"", d); 2672 return (-1); 2673 } 2674 2675 pf->debug_set = 1; 2676 level = pf->debug; 2677 2678 if ((pf->opts & PF_OPT_NOACTION) == 0) 2679 if (ioctl(dev, DIOCSETDEBUG, &level)) 2680 err(1, "DIOCSETDEBUG"); 2681 2682 if (pf->opts & PF_OPT_VERBOSE) 2683 printf("set debug %s\n", d); 2684 2685 return (0); 2686 } 2687 2688 int 2689 pfctl_load_debug(struct pfctl *pf, unsigned int level) 2690 { 2691 if (ioctl(pf->dev, DIOCSETDEBUG, &level)) { 2692 warnx("DIOCSETDEBUG"); 2693 return (1); 2694 } 2695 return (0); 2696 } 2697 2698 int 2699 pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) 2700 { 2701 struct pfioc_iface pi; 2702 struct node_host *h = NULL, *n = NULL; 2703 2704 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2705 return (0); 2706 2707 bzero(&pi, sizeof(pi)); 2708 2709 pi.pfiio_flags = flags; 2710 2711 /* Make sure our cache matches the kernel. If we set or clear the flag 2712 * for a group this applies to all members. */ 2713 h = ifa_grouplookup(ifname, 0); 2714 for (n = h; n != NULL; n = n->next) 2715 pfctl_set_interface_flags(pf, n->ifname, flags, how); 2716 2717 if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= 2718 sizeof(pi.pfiio_name)) 2719 errx(1, "pfctl_set_interface_flags: strlcpy"); 2720 2721 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2722 if (how == 0) { 2723 if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi)) 2724 err(1, "DIOCCLRIFFLAG"); 2725 } else { 2726 if (ioctl(pf->dev, DIOCSETIFFLAG, &pi)) 2727 err(1, "DIOCSETIFFLAG"); 2728 pfctl_check_skip_ifaces(ifname); 2729 } 2730 } 2731 return (0); 2732 } 2733 2734 void 2735 pfctl_debug(int dev, u_int32_t level, int opts) 2736 { 2737 if (ioctl(dev, DIOCSETDEBUG, &level)) 2738 err(1, "DIOCSETDEBUG"); 2739 if ((opts & PF_OPT_QUIET) == 0) { 2740 fprintf(stderr, "debug level set to '"); 2741 switch (level) { 2742 case PF_DEBUG_NONE: 2743 fprintf(stderr, "none"); 2744 break; 2745 case PF_DEBUG_URGENT: 2746 fprintf(stderr, "urgent"); 2747 break; 2748 case PF_DEBUG_MISC: 2749 fprintf(stderr, "misc"); 2750 break; 2751 case PF_DEBUG_NOISY: 2752 fprintf(stderr, "loud"); 2753 break; 2754 default: 2755 fprintf(stderr, "<invalid>"); 2756 break; 2757 } 2758 fprintf(stderr, "'\n"); 2759 } 2760 } 2761 2762 int 2763 pfctl_test_altqsupport(int dev, int opts) 2764 { 2765 struct pfioc_altq pa; 2766 2767 pa.version = PFIOC_ALTQ_VERSION; 2768 if (ioctl(dev, DIOCGETALTQS, &pa)) { 2769 if (errno == ENODEV) { 2770 if (opts & PF_OPT_VERBOSE) 2771 fprintf(stderr, "No ALTQ support in kernel\n" 2772 "ALTQ related functions disabled\n"); 2773 return (0); 2774 } else 2775 err(1, "DIOCGETALTQS"); 2776 } 2777 return (1); 2778 } 2779 2780 int 2781 pfctl_show_anchors(int dev, int opts, char *anchorname) 2782 { 2783 struct pfioc_ruleset pr; 2784 u_int32_t mnr, nr; 2785 2786 memset(&pr, 0, sizeof(pr)); 2787 memcpy(pr.path, anchorname, sizeof(pr.path)); 2788 if (ioctl(dev, DIOCGETRULESETS, &pr)) { 2789 if (errno == EINVAL) 2790 fprintf(stderr, "Anchor '%s' not found.\n", 2791 anchorname); 2792 else 2793 err(1, "DIOCGETRULESETS"); 2794 return (-1); 2795 } 2796 mnr = pr.nr; 2797 for (nr = 0; nr < mnr; ++nr) { 2798 char sub[MAXPATHLEN]; 2799 2800 pr.nr = nr; 2801 if (ioctl(dev, DIOCGETRULESET, &pr)) 2802 err(1, "DIOCGETRULESET"); 2803 if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) 2804 continue; 2805 sub[0] = 0; 2806 if (pr.path[0]) { 2807 strlcat(sub, pr.path, sizeof(sub)); 2808 strlcat(sub, "/", sizeof(sub)); 2809 } 2810 strlcat(sub, pr.name, sizeof(sub)); 2811 if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 2812 printf(" %s\n", sub); 2813 if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub)) 2814 return (-1); 2815 } 2816 return (0); 2817 } 2818 2819 int 2820 pfctl_show_eth_anchors(int dev, int opts, char *anchorname) 2821 { 2822 struct pfctl_eth_rulesets_info ri; 2823 struct pfctl_eth_ruleset_info rs; 2824 int ret; 2825 2826 if ((ret = pfctl_get_eth_rulesets_info(dev, &ri, anchorname)) != 0) { 2827 if (ret == ENOENT) 2828 fprintf(stderr, "Anchor '%s' not found.\n", 2829 anchorname); 2830 else 2831 err(1, "DIOCGETETHRULESETS"); 2832 return (-1); 2833 } 2834 2835 for (int nr = 0; nr < ri.nr; nr++) { 2836 char sub[MAXPATHLEN]; 2837 2838 if (pfctl_get_eth_ruleset(dev, anchorname, nr, &rs) != 0) 2839 err(1, "DIOCGETETHRULESET"); 2840 2841 if (!strcmp(rs.name, PF_RESERVED_ANCHOR)) 2842 continue; 2843 sub[0] = 0; 2844 if (rs.path[0]) { 2845 strlcat(sub, rs.path, sizeof(sub)); 2846 strlcat(sub, "/", sizeof(sub)); 2847 } 2848 strlcat(sub, rs.name, sizeof(sub)); 2849 if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 2850 printf(" %s\n", sub); 2851 if ((opts & PF_OPT_VERBOSE) && pfctl_show_eth_anchors(dev, opts, sub)) 2852 return (-1); 2853 } 2854 return (0); 2855 } 2856 2857 const char * 2858 pfctl_lookup_option(char *cmd, const char * const *list) 2859 { 2860 if (cmd != NULL && *cmd) 2861 for (; *list; list++) 2862 if (!strncmp(cmd, *list, strlen(cmd))) 2863 return (*list); 2864 return (NULL); 2865 } 2866 2867 int 2868 main(int argc, char *argv[]) 2869 { 2870 int error = 0; 2871 int ch; 2872 int mode = O_RDONLY; 2873 int opts = 0; 2874 int optimize = PF_OPTIMIZE_BASIC; 2875 char anchorname[MAXPATHLEN]; 2876 char *path; 2877 2878 if (argc < 2) 2879 usage(); 2880 2881 while ((ch = getopt(argc, argv, 2882 "a:AdD:eqf:F:ghi:k:K:mMnNOo:Pp:rRs:t:T:vx:z")) != -1) { 2883 switch (ch) { 2884 case 'a': 2885 anchoropt = optarg; 2886 break; 2887 case 'd': 2888 opts |= PF_OPT_DISABLE; 2889 mode = O_RDWR; 2890 break; 2891 case 'D': 2892 if (pfctl_cmdline_symset(optarg) < 0) 2893 warnx("could not parse macro definition %s", 2894 optarg); 2895 break; 2896 case 'e': 2897 opts |= PF_OPT_ENABLE; 2898 mode = O_RDWR; 2899 break; 2900 case 'q': 2901 opts |= PF_OPT_QUIET; 2902 break; 2903 case 'F': 2904 clearopt = pfctl_lookup_option(optarg, clearopt_list); 2905 if (clearopt == NULL) { 2906 warnx("Unknown flush modifier '%s'", optarg); 2907 usage(); 2908 } 2909 mode = O_RDWR; 2910 break; 2911 case 'i': 2912 ifaceopt = optarg; 2913 break; 2914 case 'k': 2915 if (state_killers >= 2) { 2916 warnx("can only specify -k twice"); 2917 usage(); 2918 /* NOTREACHED */ 2919 } 2920 state_kill[state_killers++] = optarg; 2921 mode = O_RDWR; 2922 break; 2923 case 'K': 2924 if (src_node_killers >= 2) { 2925 warnx("can only specify -K twice"); 2926 usage(); 2927 /* NOTREACHED */ 2928 } 2929 src_node_kill[src_node_killers++] = optarg; 2930 mode = O_RDWR; 2931 break; 2932 case 'm': 2933 opts |= PF_OPT_MERGE; 2934 break; 2935 case 'M': 2936 opts |= PF_OPT_KILLMATCH; 2937 break; 2938 case 'n': 2939 opts |= PF_OPT_NOACTION; 2940 break; 2941 case 'N': 2942 loadopt |= PFCTL_FLAG_NAT; 2943 break; 2944 case 'r': 2945 opts |= PF_OPT_USEDNS; 2946 break; 2947 case 'f': 2948 rulesopt = optarg; 2949 mode = O_RDWR; 2950 break; 2951 case 'g': 2952 opts |= PF_OPT_DEBUG; 2953 break; 2954 case 'A': 2955 loadopt |= PFCTL_FLAG_ALTQ; 2956 break; 2957 case 'R': 2958 loadopt |= PFCTL_FLAG_FILTER; 2959 break; 2960 case 'o': 2961 optiopt = pfctl_lookup_option(optarg, optiopt_list); 2962 if (optiopt == NULL) { 2963 warnx("Unknown optimization '%s'", optarg); 2964 usage(); 2965 } 2966 opts |= PF_OPT_OPTIMIZE; 2967 break; 2968 case 'O': 2969 loadopt |= PFCTL_FLAG_OPTION; 2970 break; 2971 case 'p': 2972 pf_device = optarg; 2973 break; 2974 case 'P': 2975 opts |= PF_OPT_NUMERIC; 2976 break; 2977 case 's': 2978 showopt = pfctl_lookup_option(optarg, showopt_list); 2979 if (showopt == NULL) { 2980 warnx("Unknown show modifier '%s'", optarg); 2981 usage(); 2982 } 2983 break; 2984 case 't': 2985 tableopt = optarg; 2986 break; 2987 case 'T': 2988 tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 2989 if (tblcmdopt == NULL) { 2990 warnx("Unknown table command '%s'", optarg); 2991 usage(); 2992 } 2993 break; 2994 case 'v': 2995 if (opts & PF_OPT_VERBOSE) 2996 opts |= PF_OPT_VERBOSE2; 2997 opts |= PF_OPT_VERBOSE; 2998 break; 2999 case 'x': 3000 debugopt = pfctl_lookup_option(optarg, debugopt_list); 3001 if (debugopt == NULL) { 3002 warnx("Unknown debug level '%s'", optarg); 3003 usage(); 3004 } 3005 mode = O_RDWR; 3006 break; 3007 case 'z': 3008 opts |= PF_OPT_CLRRULECTRS; 3009 mode = O_RDWR; 3010 break; 3011 case 'h': 3012 /* FALLTHROUGH */ 3013 default: 3014 usage(); 3015 /* NOTREACHED */ 3016 } 3017 } 3018 3019 if (tblcmdopt != NULL) { 3020 argc -= optind; 3021 argv += optind; 3022 ch = *tblcmdopt; 3023 if (ch == 'l') { 3024 loadopt |= PFCTL_FLAG_TABLE; 3025 tblcmdopt = NULL; 3026 } else 3027 mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY; 3028 } else if (argc != optind) { 3029 warnx("unknown command line argument: %s ...", argv[optind]); 3030 usage(); 3031 /* NOTREACHED */ 3032 } 3033 if (loadopt == 0) 3034 loadopt = ~0; 3035 3036 if ((path = calloc(1, MAXPATHLEN)) == NULL) 3037 errx(1, "pfctl: calloc"); 3038 memset(anchorname, 0, sizeof(anchorname)); 3039 if (anchoropt != NULL) { 3040 int len = strlen(anchoropt); 3041 3042 if (len >= 1 && anchoropt[len - 1] == '*') { 3043 if (len >= 2 && anchoropt[len - 2] == '/') 3044 anchoropt[len - 2] = '\0'; 3045 else 3046 anchoropt[len - 1] = '\0'; 3047 opts |= PF_OPT_RECURSE; 3048 } 3049 if (strlcpy(anchorname, anchoropt, 3050 sizeof(anchorname)) >= sizeof(anchorname)) 3051 errx(1, "anchor name '%s' too long", 3052 anchoropt); 3053 loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE|PFCTL_FLAG_ETH; 3054 } 3055 3056 if ((opts & PF_OPT_NOACTION) == 0) { 3057 dev = open(pf_device, mode); 3058 if (dev == -1) 3059 err(1, "%s", pf_device); 3060 altqsupport = pfctl_test_altqsupport(dev, opts); 3061 } else { 3062 dev = open(pf_device, O_RDONLY); 3063 if (dev >= 0) 3064 opts |= PF_OPT_DUMMYACTION; 3065 /* turn off options */ 3066 opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 3067 clearopt = showopt = debugopt = NULL; 3068 #if !defined(ENABLE_ALTQ) 3069 altqsupport = 0; 3070 #else 3071 altqsupport = 1; 3072 #endif 3073 } 3074 3075 if (opts & PF_OPT_DISABLE) 3076 if (pfctl_disable(dev, opts)) 3077 error = 1; 3078 3079 if (showopt != NULL) { 3080 switch (*showopt) { 3081 case 'A': 3082 pfctl_show_anchors(dev, opts, anchorname); 3083 if (opts & PF_OPT_VERBOSE2) 3084 printf("Ethernet:\n"); 3085 pfctl_show_eth_anchors(dev, opts, anchorname); 3086 break; 3087 case 'r': 3088 pfctl_load_fingerprints(dev, opts); 3089 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 3090 anchorname, 0, 0); 3091 break; 3092 case 'l': 3093 pfctl_load_fingerprints(dev, opts); 3094 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 3095 anchorname, 0, 0); 3096 break; 3097 case 'n': 3098 pfctl_load_fingerprints(dev, opts); 3099 pfctl_show_nat(dev, path, opts, anchorname, 0); 3100 break; 3101 case 'q': 3102 pfctl_show_altq(dev, ifaceopt, opts, 3103 opts & PF_OPT_VERBOSE2); 3104 break; 3105 case 's': 3106 pfctl_show_states(dev, ifaceopt, opts); 3107 break; 3108 case 'S': 3109 pfctl_show_src_nodes(dev, opts); 3110 break; 3111 case 'i': 3112 pfctl_show_status(dev, opts); 3113 break; 3114 case 'R': 3115 error = pfctl_show_running(dev); 3116 break; 3117 case 't': 3118 pfctl_show_timeouts(dev, opts); 3119 break; 3120 case 'm': 3121 pfctl_show_limits(dev, opts); 3122 break; 3123 case 'e': 3124 pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0, 3125 0); 3126 break; 3127 case 'a': 3128 opts |= PF_OPT_SHOWALL; 3129 pfctl_load_fingerprints(dev, opts); 3130 3131 pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0, 3132 0); 3133 3134 pfctl_show_nat(dev, path, opts, anchorname, 0); 3135 pfctl_show_rules(dev, path, opts, 0, anchorname, 0, 0); 3136 pfctl_show_altq(dev, ifaceopt, opts, 0); 3137 pfctl_show_states(dev, ifaceopt, opts); 3138 pfctl_show_src_nodes(dev, opts); 3139 pfctl_show_status(dev, opts); 3140 pfctl_show_rules(dev, path, opts, 1, anchorname, 0, 0); 3141 pfctl_show_timeouts(dev, opts); 3142 pfctl_show_limits(dev, opts); 3143 pfctl_show_tables(anchorname, opts); 3144 pfctl_show_fingerprints(opts); 3145 break; 3146 case 'T': 3147 pfctl_show_tables(anchorname, opts); 3148 break; 3149 case 'o': 3150 pfctl_load_fingerprints(dev, opts); 3151 pfctl_show_fingerprints(opts); 3152 break; 3153 case 'I': 3154 pfctl_show_ifaces(ifaceopt, opts); 3155 break; 3156 case 'c': 3157 pfctl_show_creators(opts); 3158 break; 3159 } 3160 } 3161 3162 if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) { 3163 pfctl_show_eth_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 3164 anchorname, 0, 0); 3165 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 3166 anchorname, 0, 0); 3167 } 3168 3169 if (clearopt != NULL) { 3170 if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 3171 errx(1, "anchor names beginning with '_' cannot " 3172 "be modified from the command line"); 3173 3174 switch (*clearopt) { 3175 case 'e': 3176 pfctl_flush_eth_rules(dev, opts, anchorname); 3177 break; 3178 case 'r': 3179 pfctl_flush_rules(dev, opts, anchorname); 3180 break; 3181 case 'n': 3182 pfctl_flush_nat(dev, opts, anchorname); 3183 break; 3184 case 'q': 3185 pfctl_clear_altq(dev, opts); 3186 break; 3187 case 's': 3188 pfctl_clear_iface_states(dev, ifaceopt, opts); 3189 break; 3190 case 'S': 3191 pfctl_clear_src_nodes(dev, opts); 3192 break; 3193 case 'i': 3194 pfctl_clear_stats(dev, opts); 3195 break; 3196 case 'a': 3197 pfctl_flush_eth_rules(dev, opts, anchorname); 3198 pfctl_flush_rules(dev, opts, anchorname); 3199 pfctl_flush_nat(dev, opts, anchorname); 3200 pfctl_clear_tables(anchorname, opts); 3201 if (!*anchorname) { 3202 pfctl_clear_altq(dev, opts); 3203 pfctl_clear_iface_states(dev, ifaceopt, opts); 3204 pfctl_clear_src_nodes(dev, opts); 3205 pfctl_clear_stats(dev, opts); 3206 pfctl_clear_fingerprints(dev, opts); 3207 pfctl_clear_interface_flags(dev, opts); 3208 } 3209 break; 3210 case 'o': 3211 pfctl_clear_fingerprints(dev, opts); 3212 break; 3213 case 'T': 3214 pfctl_clear_tables(anchorname, opts); 3215 break; 3216 } 3217 } 3218 if (state_killers) { 3219 if (!strcmp(state_kill[0], "label")) 3220 pfctl_label_kill_states(dev, ifaceopt, opts); 3221 else if (!strcmp(state_kill[0], "id")) 3222 pfctl_id_kill_states(dev, ifaceopt, opts); 3223 else if (!strcmp(state_kill[0], "gateway")) 3224 pfctl_gateway_kill_states(dev, ifaceopt, opts); 3225 else 3226 pfctl_net_kill_states(dev, ifaceopt, opts); 3227 } 3228 3229 if (src_node_killers) 3230 pfctl_kill_src_nodes(dev, ifaceopt, opts); 3231 3232 if (tblcmdopt != NULL) { 3233 error = pfctl_command_tables(argc, argv, tableopt, 3234 tblcmdopt, rulesopt, anchorname, opts); 3235 rulesopt = NULL; 3236 } 3237 if (optiopt != NULL) { 3238 switch (*optiopt) { 3239 case 'n': 3240 optimize = 0; 3241 break; 3242 case 'b': 3243 optimize |= PF_OPTIMIZE_BASIC; 3244 break; 3245 case 'o': 3246 case 'p': 3247 optimize |= PF_OPTIMIZE_PROFILE; 3248 break; 3249 } 3250 } 3251 3252 if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) && 3253 !anchorname[0] && !(opts & PF_OPT_NOACTION)) 3254 if (pfctl_get_skip_ifaces()) 3255 error = 1; 3256 3257 if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) && 3258 !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION)) 3259 if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 3260 error = 1; 3261 3262 if (rulesopt != NULL) { 3263 if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 3264 errx(1, "anchor names beginning with '_' cannot " 3265 "be modified from the command line"); 3266 if (pfctl_rules(dev, rulesopt, opts, optimize, 3267 anchorname, NULL)) 3268 error = 1; 3269 else if (!(opts & PF_OPT_NOACTION) && 3270 (loadopt & PFCTL_FLAG_TABLE)) 3271 warn_namespace_collision(NULL); 3272 } 3273 3274 if (opts & PF_OPT_ENABLE) 3275 if (pfctl_enable(dev, opts)) 3276 error = 1; 3277 3278 if (debugopt != NULL) { 3279 switch (*debugopt) { 3280 case 'n': 3281 pfctl_debug(dev, PF_DEBUG_NONE, opts); 3282 break; 3283 case 'u': 3284 pfctl_debug(dev, PF_DEBUG_URGENT, opts); 3285 break; 3286 case 'm': 3287 pfctl_debug(dev, PF_DEBUG_MISC, opts); 3288 break; 3289 case 'l': 3290 pfctl_debug(dev, PF_DEBUG_NOISY, opts); 3291 break; 3292 } 3293 } 3294 3295 exit(error); 3296 } 3297