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 1371 if (anchor_call[0] && 1372 (((p = strrchr(anchor_call, '/')) ? 1373 p[1] == '_' : anchor_call[0] == '_') || 1374 opts & PF_OPT_RECURSE)) { 1375 pfctl_show_rules(dev, npath, opts, format, 1376 anchor_call, depth, rule.anchor_wildcard); 1377 } 1378 break; 1379 } 1380 case PFCTL_SHOW_RULES: 1381 if (rule.label[0][0] && (opts & PF_OPT_SHOWALL)) 1382 labels = 1; 1383 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1384 print_rule(&rule, anchor_call, rule_numbers, numeric); 1385 1386 /* 1387 * If this is a 'unnamed' brace notation 1388 * anchor, OR the user has explicitly requested 1389 * recursion, print it recursively. 1390 */ 1391 if (anchor_call[0] && 1392 (((p = strrchr(anchor_call, '/')) ? 1393 p[1] == '_' : anchor_call[0] == '_') || 1394 opts & PF_OPT_RECURSE)) { 1395 printf(" {\n"); 1396 pfctl_print_rule_counters(&rule, opts); 1397 pfctl_show_rules(dev, npath, opts, format, 1398 anchor_call, depth + 1, 1399 rule.anchor_wildcard); 1400 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1401 printf("}\n"); 1402 } else { 1403 printf("\n"); 1404 pfctl_print_rule_counters(&rule, opts); 1405 } 1406 break; 1407 case PFCTL_SHOW_NOTHING: 1408 break; 1409 } 1410 pfctl_clear_pool(&rule.rpool); 1411 } 1412 1413 error: 1414 path[len] = '\0'; 1415 return (ret); 1416 } 1417 1418 int 1419 pfctl_show_nat(int dev, char *path, int opts, char *anchorname, int depth) 1420 { 1421 struct pfctl_rules_info ri; 1422 struct pfctl_rule rule; 1423 char anchor_call[MAXPATHLEN]; 1424 u_int32_t nr; 1425 static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; 1426 int i, dotitle = opts & PF_OPT_SHOWALL; 1427 int brace, ret; 1428 int len = strlen(path); 1429 char *p; 1430 1431 if (path[0]) 1432 snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 1433 else 1434 snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 1435 1436 for (i = 0; i < 3; i++) { 1437 ret = pfctl_get_rules_info(dev, &ri, nattype[i], path); 1438 if (ret != 0) { 1439 warn("DIOCGETRULES"); 1440 return (-1); 1441 } 1442 for (nr = 0; nr < ri.nr; ++nr) { 1443 brace = 0; 1444 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1445 1446 if (pfctl_get_rule(dev, nr, ri.ticket, path, 1447 nattype[i], &rule, anchor_call)) { 1448 warn("DIOCGETRULE"); 1449 return (-1); 1450 } 1451 if (pfctl_get_pool(dev, &rule.rpool, nr, 1452 ri.ticket, nattype[i], path) != 0) 1453 return (-1); 1454 1455 if (anchor_call[0] && 1456 ((((p = strrchr(anchor_call, '_')) != NULL) && 1457 (p == anchor_call || 1458 *(--p) == '/')) || (opts & PF_OPT_RECURSE))) { 1459 brace++; 1460 if ((p = strrchr(anchor_call, '/')) != 1461 NULL) 1462 p++; 1463 else 1464 p = &anchor_call[0]; 1465 } else 1466 p = &anchor_call[0]; 1467 1468 if (dotitle) { 1469 pfctl_print_title("TRANSLATION RULES:"); 1470 dotitle = 0; 1471 } 1472 print_rule(&rule, anchor_call, 1473 opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC); 1474 if (brace) 1475 printf(" {\n"); 1476 else 1477 printf("\n"); 1478 pfctl_print_rule_counters(&rule, opts); 1479 pfctl_clear_pool(&rule.rpool); 1480 if (brace) { 1481 pfctl_show_nat(dev, path, opts, p, depth + 1); 1482 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1483 printf("}\n"); 1484 } 1485 } 1486 } 1487 return (0); 1488 } 1489 1490 int 1491 pfctl_show_src_nodes(int dev, int opts) 1492 { 1493 struct pfioc_src_nodes psn; 1494 struct pf_src_node *p; 1495 char *inbuf = NULL, *newinbuf = NULL; 1496 unsigned int len = 0; 1497 int i; 1498 1499 memset(&psn, 0, sizeof(psn)); 1500 for (;;) { 1501 psn.psn_len = len; 1502 if (len) { 1503 newinbuf = realloc(inbuf, len); 1504 if (newinbuf == NULL) 1505 err(1, "realloc"); 1506 psn.psn_buf = inbuf = newinbuf; 1507 } 1508 if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) { 1509 warn("DIOCGETSRCNODES"); 1510 free(inbuf); 1511 return (-1); 1512 } 1513 if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len) 1514 break; 1515 if (len == 0 && psn.psn_len == 0) 1516 goto done; 1517 if (len == 0 && psn.psn_len != 0) 1518 len = psn.psn_len; 1519 if (psn.psn_len == 0) 1520 goto done; /* no src_nodes */ 1521 len *= 2; 1522 } 1523 p = psn.psn_src_nodes; 1524 if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL)) 1525 pfctl_print_title("SOURCE TRACKING NODES:"); 1526 for (i = 0; i < psn.psn_len; i += sizeof(*p)) { 1527 print_src_node(p, opts); 1528 p++; 1529 } 1530 done: 1531 free(inbuf); 1532 return (0); 1533 } 1534 1535 struct pfctl_show_state_arg { 1536 int opts; 1537 int dotitle; 1538 const char *iface; 1539 }; 1540 1541 static int 1542 pfctl_show_state(struct pfctl_state *s, void *arg) 1543 { 1544 struct pfctl_show_state_arg *a = (struct pfctl_show_state_arg *)arg; 1545 1546 if (a->dotitle) { 1547 pfctl_print_title("STATES:"); 1548 a->dotitle = 0; 1549 } 1550 print_state(s, a->opts); 1551 1552 return (0); 1553 } 1554 1555 int 1556 pfctl_show_states(int dev, const char *iface, int opts) 1557 { 1558 struct pfctl_show_state_arg arg; 1559 struct pfctl_state_filter filter = {}; 1560 1561 if (iface != NULL) 1562 strncpy(filter.ifname, iface, IFNAMSIZ); 1563 1564 arg.opts = opts; 1565 arg.dotitle = opts & PF_OPT_SHOWALL; 1566 arg.iface = iface; 1567 1568 if (pfctl_get_filtered_states_iter(&filter, pfctl_show_state, &arg)) 1569 return (-1); 1570 1571 return (0); 1572 } 1573 1574 int 1575 pfctl_show_status(int dev, int opts) 1576 { 1577 struct pfctl_status *status; 1578 struct pfctl_syncookies cookies; 1579 1580 if ((status = pfctl_get_status(dev)) == NULL) { 1581 warn("DIOCGETSTATUS"); 1582 return (-1); 1583 } 1584 if (pfctl_get_syncookies(dev, &cookies)) { 1585 pfctl_free_status(status); 1586 warn("DIOCGETSYNCOOKIES"); 1587 return (-1); 1588 } 1589 if (opts & PF_OPT_SHOWALL) 1590 pfctl_print_title("INFO:"); 1591 print_status(status, &cookies, opts); 1592 pfctl_free_status(status); 1593 return (0); 1594 } 1595 1596 int 1597 pfctl_show_running(int dev) 1598 { 1599 struct pfctl_status *status; 1600 int running; 1601 1602 if ((status = pfctl_get_status(dev)) == NULL) { 1603 warn("DIOCGETSTATUS"); 1604 return (-1); 1605 } 1606 1607 running = status->running; 1608 1609 print_running(status); 1610 pfctl_free_status(status); 1611 return (!running); 1612 } 1613 1614 int 1615 pfctl_show_timeouts(int dev, int opts) 1616 { 1617 struct pfioc_tm pt; 1618 int i; 1619 1620 if (opts & PF_OPT_SHOWALL) 1621 pfctl_print_title("TIMEOUTS:"); 1622 memset(&pt, 0, sizeof(pt)); 1623 for (i = 0; pf_timeouts[i].name; i++) { 1624 pt.timeout = pf_timeouts[i].timeout; 1625 if (ioctl(dev, DIOCGETTIMEOUT, &pt)) 1626 err(1, "DIOCGETTIMEOUT"); 1627 printf("%-20s %10d", pf_timeouts[i].name, pt.seconds); 1628 if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && 1629 pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) 1630 printf(" states"); 1631 else 1632 printf("s"); 1633 printf("\n"); 1634 } 1635 return (0); 1636 1637 } 1638 1639 int 1640 pfctl_show_limits(int dev, int opts) 1641 { 1642 struct pfioc_limit pl; 1643 int i; 1644 1645 if (opts & PF_OPT_SHOWALL) 1646 pfctl_print_title("LIMITS:"); 1647 memset(&pl, 0, sizeof(pl)); 1648 for (i = 0; pf_limits[i].name; i++) { 1649 pl.index = pf_limits[i].index; 1650 if (ioctl(dev, DIOCGETLIMIT, &pl)) 1651 err(1, "DIOCGETLIMIT"); 1652 printf("%-13s ", pf_limits[i].name); 1653 if (pl.limit == UINT_MAX) 1654 printf("unlimited\n"); 1655 else 1656 printf("hard limit %8u\n", pl.limit); 1657 } 1658 return (0); 1659 } 1660 1661 void 1662 pfctl_show_creators(int opts) 1663 { 1664 int ret; 1665 uint32_t creators[16]; 1666 size_t count = nitems(creators); 1667 1668 ret = pfctl_get_creatorids(creators, &count); 1669 if (ret != 0) 1670 errx(ret, "Failed to retrieve creators"); 1671 1672 printf("Creator IDs:\n"); 1673 for (size_t i = 0; i < count; i++) 1674 printf("%08x\n", creators[i]); 1675 } 1676 1677 /* callbacks for rule/nat/rdr/addr */ 1678 int 1679 pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af) 1680 { 1681 struct pf_pooladdr *pa; 1682 1683 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1684 if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) 1685 err(1, "DIOCBEGINADDRS"); 1686 } 1687 1688 pf->paddr.af = af; 1689 TAILQ_FOREACH(pa, &p->list, entries) { 1690 memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr)); 1691 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1692 if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) 1693 err(1, "DIOCADDADDR"); 1694 } 1695 } 1696 return (0); 1697 } 1698 1699 int 1700 pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r, 1701 const char *anchor_call) 1702 { 1703 u_int8_t rs_num; 1704 struct pfctl_rule *rule; 1705 struct pfctl_ruleset *rs; 1706 char *p; 1707 1708 rs_num = pf_get_ruleset_number(r->action); 1709 if (rs_num == PF_RULESET_MAX) 1710 errx(1, "Invalid rule type %d", r->action); 1711 1712 rs = &pf->anchor->ruleset; 1713 1714 if (anchor_call[0] && r->anchor == NULL) { 1715 /* 1716 * Don't make non-brace anchors part of the main anchor pool. 1717 */ 1718 if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 1719 err(1, "pfctl_append_rule: calloc"); 1720 1721 pf_init_ruleset(&r->anchor->ruleset); 1722 r->anchor->ruleset.anchor = r->anchor; 1723 if (strlcpy(r->anchor->path, anchor_call, 1724 sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 1725 errx(1, "pfctl_append_rule: strlcpy"); 1726 if ((p = strrchr(anchor_call, '/')) != NULL) { 1727 if (!strlen(p)) 1728 err(1, "pfctl_append_rule: bad anchor name %s", 1729 anchor_call); 1730 } else 1731 p = (char *)anchor_call; 1732 if (strlcpy(r->anchor->name, p, 1733 sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 1734 errx(1, "pfctl_append_rule: strlcpy"); 1735 } 1736 1737 if ((rule = calloc(1, sizeof(*rule))) == NULL) 1738 err(1, "calloc"); 1739 bcopy(r, rule, sizeof(*rule)); 1740 TAILQ_INIT(&rule->rpool.list); 1741 pfctl_move_pool(&r->rpool, &rule->rpool); 1742 1743 TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries); 1744 return (0); 1745 } 1746 1747 int 1748 pfctl_append_eth_rule(struct pfctl *pf, struct pfctl_eth_rule *r, 1749 const char *anchor_call) 1750 { 1751 struct pfctl_eth_rule *rule; 1752 struct pfctl_eth_ruleset *rs; 1753 char *p; 1754 1755 rs = &pf->eanchor->ruleset; 1756 1757 if (anchor_call[0] && r->anchor == NULL) { 1758 /* 1759 * Don't make non-brace anchors part of the main anchor pool. 1760 */ 1761 if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 1762 err(1, "pfctl_append_rule: calloc"); 1763 1764 pf_init_eth_ruleset(&r->anchor->ruleset); 1765 r->anchor->ruleset.anchor = r->anchor; 1766 if (strlcpy(r->anchor->path, anchor_call, 1767 sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 1768 errx(1, "pfctl_append_rule: strlcpy"); 1769 if ((p = strrchr(anchor_call, '/')) != NULL) { 1770 if (!strlen(p)) 1771 err(1, "pfctl_append_eth_rule: bad anchor name %s", 1772 anchor_call); 1773 } else 1774 p = (char *)anchor_call; 1775 if (strlcpy(r->anchor->name, p, 1776 sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 1777 errx(1, "pfctl_append_eth_rule: strlcpy"); 1778 } 1779 1780 if ((rule = calloc(1, sizeof(*rule))) == NULL) 1781 err(1, "calloc"); 1782 bcopy(r, rule, sizeof(*rule)); 1783 1784 TAILQ_INSERT_TAIL(&rs->rules, rule, entries); 1785 return (0); 1786 } 1787 1788 int 1789 pfctl_eth_ruleset_trans(struct pfctl *pf, char *path, 1790 struct pfctl_eth_anchor *a) 1791 { 1792 int osize = pf->trans->pfrb_size; 1793 1794 if ((pf->loadopt & PFCTL_FLAG_ETH) != 0) { 1795 if (pfctl_add_trans(pf->trans, PF_RULESET_ETH, path)) 1796 return (1); 1797 } 1798 if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1799 return (5); 1800 1801 return (0); 1802 } 1803 1804 int 1805 pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pfctl_anchor *a, bool do_eth) 1806 { 1807 int osize = pf->trans->pfrb_size; 1808 1809 if ((pf->loadopt & PFCTL_FLAG_ETH) != 0 && do_eth) { 1810 if (pfctl_add_trans(pf->trans, PF_RULESET_ETH, path)) 1811 return (1); 1812 } 1813 if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { 1814 if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || 1815 pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || 1816 pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) 1817 return (1); 1818 } 1819 if (a == pf->astack[0] && ((altqsupport && 1820 (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) { 1821 if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path)) 1822 return (2); 1823 } 1824 if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) { 1825 if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) || 1826 pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path)) 1827 return (3); 1828 } 1829 if (pf->loadopt & PFCTL_FLAG_TABLE) 1830 if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path)) 1831 return (4); 1832 if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1833 return (5); 1834 1835 return (0); 1836 } 1837 1838 int 1839 pfctl_load_eth_ruleset(struct pfctl *pf, char *path, 1840 struct pfctl_eth_ruleset *rs, int depth) 1841 { 1842 struct pfctl_eth_rule *r; 1843 int error, len = strlen(path); 1844 int brace = 0; 1845 1846 pf->eanchor = rs->anchor; 1847 if (path[0]) 1848 snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->eanchor->name); 1849 else 1850 snprintf(&path[len], MAXPATHLEN - len, "%s", pf->eanchor->name); 1851 1852 if (depth) { 1853 if (TAILQ_FIRST(&rs->rules) != NULL) { 1854 brace++; 1855 if (pf->opts & PF_OPT_VERBOSE) 1856 printf(" {\n"); 1857 if ((pf->opts & PF_OPT_NOACTION) == 0 && 1858 (error = pfctl_eth_ruleset_trans(pf, 1859 path, rs->anchor))) { 1860 printf("pfctl_load_eth_rulesets: " 1861 "pfctl_eth_ruleset_trans %d\n", error); 1862 goto error; 1863 } 1864 } else if (pf->opts & PF_OPT_VERBOSE) 1865 printf("\n"); 1866 } 1867 1868 while ((r = TAILQ_FIRST(&rs->rules)) != NULL) { 1869 TAILQ_REMOVE(&rs->rules, r, entries); 1870 1871 error = pfctl_load_eth_rule(pf, path, r, depth); 1872 if (error) 1873 return (error); 1874 1875 if (r->anchor) { 1876 if ((error = pfctl_load_eth_ruleset(pf, path, 1877 &r->anchor->ruleset, depth + 1))) 1878 return (error); 1879 } else if (pf->opts & PF_OPT_VERBOSE) 1880 printf("\n"); 1881 free(r); 1882 } 1883 if (brace && pf->opts & PF_OPT_VERBOSE) { 1884 INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1885 printf("}\n"); 1886 } 1887 path[len] = '\0'; 1888 1889 return (0); 1890 error: 1891 path[len] = '\0'; 1892 return (error); 1893 } 1894 1895 int 1896 pfctl_load_eth_rule(struct pfctl *pf, char *path, struct pfctl_eth_rule *r, 1897 int depth) 1898 { 1899 char *name; 1900 char anchor[PF_ANCHOR_NAME_SIZE]; 1901 int len = strlen(path); 1902 1903 if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor)) 1904 errx(1, "pfctl_load_eth_rule: strlcpy"); 1905 1906 if (r->anchor) { 1907 if (r->anchor->match) { 1908 if (path[0]) 1909 snprintf(&path[len], MAXPATHLEN - len, 1910 "/%s", r->anchor->name); 1911 else 1912 snprintf(&path[len], MAXPATHLEN - len, 1913 "%s", r->anchor->name); 1914 name = r->anchor->name; 1915 } else 1916 name = r->anchor->path; 1917 } else 1918 name = ""; 1919 1920 if ((pf->opts & PF_OPT_NOACTION) == 0) 1921 if (pfctl_add_eth_rule(pf->dev, r, anchor, name, 1922 pf->eth_ticket)) 1923 err(1, "DIOCADDETHRULENV"); 1924 1925 if (pf->opts & PF_OPT_VERBOSE) { 1926 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 1927 print_eth_rule(r, r->anchor ? r->anchor->name : "", 1928 pf->opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG)); 1929 } 1930 1931 path[len] = '\0'; 1932 1933 return (0); 1934 } 1935 1936 int 1937 pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs, 1938 int rs_num, int depth) 1939 { 1940 struct pfctl_rule *r; 1941 int error, len = strlen(path); 1942 int brace = 0; 1943 1944 pf->anchor = rs->anchor; 1945 1946 if (path[0]) 1947 snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name); 1948 else 1949 snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name); 1950 1951 if (depth) { 1952 if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) { 1953 brace++; 1954 if (pf->opts & PF_OPT_VERBOSE) 1955 printf(" {\n"); 1956 if ((pf->opts & PF_OPT_NOACTION) == 0 && 1957 (error = pfctl_ruleset_trans(pf, 1958 path, rs->anchor, false))) { 1959 printf("pfctl_load_rulesets: " 1960 "pfctl_ruleset_trans %d\n", error); 1961 goto error; 1962 } 1963 } else if (pf->opts & PF_OPT_VERBOSE) 1964 printf("\n"); 1965 1966 } 1967 1968 if (pf->optimize && rs_num == PF_RULESET_FILTER) 1969 pfctl_optimize_ruleset(pf, rs); 1970 1971 while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) { 1972 TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries); 1973 1974 for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) 1975 expand_label(r->label[i], PF_RULE_LABEL_SIZE, r); 1976 expand_label(r->tagname, PF_TAG_NAME_SIZE, r); 1977 expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r); 1978 1979 if ((error = pfctl_load_rule(pf, path, r, depth))) 1980 goto error; 1981 if (r->anchor) { 1982 if ((error = pfctl_load_ruleset(pf, path, 1983 &r->anchor->ruleset, rs_num, depth + 1))) 1984 goto error; 1985 } else if (pf->opts & PF_OPT_VERBOSE) 1986 printf("\n"); 1987 free(r); 1988 } 1989 if (brace && pf->opts & PF_OPT_VERBOSE) { 1990 INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1991 printf("}\n"); 1992 } 1993 path[len] = '\0'; 1994 return (0); 1995 1996 error: 1997 path[len] = '\0'; 1998 return (error); 1999 2000 } 2001 2002 int 2003 pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth) 2004 { 2005 u_int8_t rs_num = pf_get_ruleset_number(r->action); 2006 char *name; 2007 u_int32_t ticket; 2008 char anchor[PF_ANCHOR_NAME_SIZE]; 2009 int len = strlen(path); 2010 int error; 2011 bool was_present; 2012 2013 /* set up anchor before adding to path for anchor_call */ 2014 if ((pf->opts & PF_OPT_NOACTION) == 0) 2015 ticket = pfctl_get_ticket(pf->trans, rs_num, path); 2016 if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor)) 2017 errx(1, "pfctl_load_rule: strlcpy"); 2018 2019 if (r->anchor) { 2020 if (r->anchor->match) { 2021 if (path[0]) 2022 snprintf(&path[len], MAXPATHLEN - len, 2023 "/%s", r->anchor->name); 2024 else 2025 snprintf(&path[len], MAXPATHLEN - len, 2026 "%s", r->anchor->name); 2027 name = r->anchor->name; 2028 } else 2029 name = r->anchor->path; 2030 } else 2031 name = ""; 2032 2033 was_present = false; 2034 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2035 if (pfctl_add_pool(pf, &r->rpool, r->af)) 2036 return (1); 2037 error = pfctl_add_rule(pf->dev, r, anchor, name, ticket, 2038 pf->paddr.ticket); 2039 switch (error) { 2040 case 0: 2041 /* things worked, do nothing */ 2042 break; 2043 case EEXIST: 2044 /* an identical rule is already present */ 2045 was_present = true; 2046 break; 2047 default: 2048 err(1, "DIOCADDRULENV"); 2049 } 2050 } 2051 2052 if (pf->opts & PF_OPT_VERBOSE) { 2053 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 2054 print_rule(r, name, 2055 pf->opts & PF_OPT_VERBOSE2, 2056 pf->opts & PF_OPT_NUMERIC); 2057 if (was_present) 2058 printf(" -- rule was already present"); 2059 } 2060 path[len] = '\0'; 2061 pfctl_clear_pool(&r->rpool); 2062 return (0); 2063 } 2064 2065 int 2066 pfctl_add_altq(struct pfctl *pf, struct pf_altq *a) 2067 { 2068 if (altqsupport && 2069 (loadopt & PFCTL_FLAG_ALTQ) != 0) { 2070 memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq)); 2071 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2072 if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) { 2073 if (errno == ENXIO) 2074 errx(1, "qtype not configured"); 2075 else if (errno == ENODEV) 2076 errx(1, "%s: driver does not support " 2077 "altq", a->ifname); 2078 else 2079 err(1, "DIOCADDALTQ"); 2080 } 2081 } 2082 pfaltq_store(&pf->paltq->altq); 2083 } 2084 return (0); 2085 } 2086 2087 int 2088 pfctl_rules(int dev, char *filename, int opts, int optimize, 2089 char *anchorname, struct pfr_buffer *trans) 2090 { 2091 #define ERR(x) do { warn(x); goto _error; } while(0) 2092 #define ERRX(x) do { warnx(x); goto _error; } while(0) 2093 2094 struct pfr_buffer *t, buf; 2095 struct pfioc_altq pa; 2096 struct pfctl pf; 2097 struct pfctl_ruleset *rs; 2098 struct pfctl_eth_ruleset *ethrs; 2099 struct pfr_table trs; 2100 char *path; 2101 int osize; 2102 2103 RB_INIT(&pf_anchors); 2104 memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); 2105 pf_init_ruleset(&pf_main_anchor.ruleset); 2106 pf_main_anchor.ruleset.anchor = &pf_main_anchor; 2107 2108 memset(&pf_eth_main_anchor, 0, sizeof(pf_eth_main_anchor)); 2109 pf_init_eth_ruleset(&pf_eth_main_anchor.ruleset); 2110 pf_eth_main_anchor.ruleset.anchor = &pf_eth_main_anchor; 2111 2112 if (trans == NULL) { 2113 bzero(&buf, sizeof(buf)); 2114 buf.pfrb_type = PFRB_TRANS; 2115 t = &buf; 2116 osize = 0; 2117 } else { 2118 t = trans; 2119 osize = t->pfrb_size; 2120 } 2121 2122 memset(&pa, 0, sizeof(pa)); 2123 pa.version = PFIOC_ALTQ_VERSION; 2124 memset(&pf, 0, sizeof(pf)); 2125 memset(&trs, 0, sizeof(trs)); 2126 if ((path = calloc(1, MAXPATHLEN)) == NULL) 2127 ERRX("pfctl_rules: calloc"); 2128 if (strlcpy(trs.pfrt_anchor, anchorname, 2129 sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) 2130 ERRX("pfctl_rules: strlcpy"); 2131 pf.dev = dev; 2132 pf.opts = opts; 2133 pf.optimize = optimize; 2134 pf.loadopt = loadopt; 2135 2136 /* non-brace anchor, create without resolving the path */ 2137 if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) 2138 ERRX("pfctl_rules: calloc"); 2139 rs = &pf.anchor->ruleset; 2140 pf_init_ruleset(rs); 2141 rs->anchor = pf.anchor; 2142 if (strlcpy(pf.anchor->path, anchorname, 2143 sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 2144 errx(1, "pfctl_rules: strlcpy"); 2145 if (strlcpy(pf.anchor->name, anchorname, 2146 sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 2147 errx(1, "pfctl_rules: strlcpy"); 2148 2149 2150 pf.astack[0] = pf.anchor; 2151 pf.asd = 0; 2152 if (anchorname[0]) 2153 pf.loadopt &= ~PFCTL_FLAG_ALTQ; 2154 pf.paltq = &pa; 2155 pf.trans = t; 2156 pfctl_init_options(&pf); 2157 2158 /* Set up ethernet anchor */ 2159 if ((pf.eanchor = calloc(1, sizeof(*pf.eanchor))) == NULL) 2160 ERRX("pfctl_rules: calloc"); 2161 2162 if (strlcpy(pf.eanchor->path, anchorname, 2163 sizeof(pf.eanchor->path)) >= sizeof(pf.eanchor->path)) 2164 errx(1, "pfctl_rules: strlcpy"); 2165 if (strlcpy(pf.eanchor->name, anchorname, 2166 sizeof(pf.eanchor->name)) >= sizeof(pf.eanchor->name)) 2167 errx(1, "pfctl_rules: strlcpy"); 2168 2169 ethrs = &pf.eanchor->ruleset; 2170 pf_init_eth_ruleset(ethrs); 2171 ethrs->anchor = pf.eanchor; 2172 pf.eastack[0] = pf.eanchor; 2173 2174 if ((opts & PF_OPT_NOACTION) == 0) { 2175 /* 2176 * XXX For the time being we need to open transactions for 2177 * the main ruleset before parsing, because tables are still 2178 * loaded at parse time. 2179 */ 2180 if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor, true)) 2181 ERRX("pfctl_rules"); 2182 if (pf.loadopt & PFCTL_FLAG_ETH) 2183 pf.eth_ticket = pfctl_get_ticket(t, PF_RULESET_ETH, anchorname); 2184 if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) 2185 pa.ticket = 2186 pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname); 2187 if (pf.loadopt & PFCTL_FLAG_TABLE) 2188 pf.astack[0]->ruleset.tticket = 2189 pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname); 2190 } 2191 2192 if (parse_config(filename, &pf) < 0) { 2193 if ((opts & PF_OPT_NOACTION) == 0) 2194 ERRX("Syntax error in config file: " 2195 "pf rules not loaded"); 2196 else 2197 goto _error; 2198 } 2199 if (loadopt & PFCTL_FLAG_OPTION) 2200 pfctl_adjust_skip_ifaces(&pf); 2201 2202 if ((pf.loadopt & PFCTL_FLAG_FILTER && 2203 (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) || 2204 (pf.loadopt & PFCTL_FLAG_ETH && 2205 (pfctl_load_eth_ruleset(&pf, path, ethrs, 0))) || 2206 (pf.loadopt & PFCTL_FLAG_NAT && 2207 (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) || 2208 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) || 2209 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) || 2210 (pf.loadopt & PFCTL_FLAG_FILTER && 2211 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) { 2212 if ((opts & PF_OPT_NOACTION) == 0) 2213 ERRX("Unable to load rules into kernel"); 2214 else 2215 goto _error; 2216 } 2217 2218 if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0)) 2219 if (check_commit_altq(dev, opts) != 0) 2220 ERRX("errors in altq config"); 2221 2222 /* process "load anchor" directives */ 2223 if (!anchorname[0]) 2224 if (pfctl_load_anchors(dev, &pf, t) == -1) 2225 ERRX("load anchors"); 2226 2227 if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) { 2228 if (!anchorname[0]) 2229 if (pfctl_load_options(&pf)) 2230 goto _error; 2231 if (pfctl_trans(dev, t, DIOCXCOMMIT, osize)) 2232 ERR("DIOCXCOMMIT"); 2233 } 2234 free(path); 2235 return (0); 2236 2237 _error: 2238 if (trans == NULL) { /* main ruleset */ 2239 if ((opts & PF_OPT_NOACTION) == 0) 2240 if (pfctl_trans(dev, t, DIOCXROLLBACK, osize)) 2241 err(1, "DIOCXROLLBACK"); 2242 exit(1); 2243 } else { /* sub ruleset */ 2244 free(path); 2245 return (-1); 2246 } 2247 2248 #undef ERR 2249 #undef ERRX 2250 } 2251 2252 FILE * 2253 pfctl_fopen(const char *name, const char *mode) 2254 { 2255 struct stat st; 2256 FILE *fp; 2257 2258 fp = fopen(name, mode); 2259 if (fp == NULL) 2260 return (NULL); 2261 if (fstat(fileno(fp), &st)) { 2262 fclose(fp); 2263 return (NULL); 2264 } 2265 if (S_ISDIR(st.st_mode)) { 2266 fclose(fp); 2267 errno = EISDIR; 2268 return (NULL); 2269 } 2270 return (fp); 2271 } 2272 2273 void 2274 pfctl_init_options(struct pfctl *pf) 2275 { 2276 2277 pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 2278 pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; 2279 pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 2280 pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; 2281 pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; 2282 pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; 2283 pf->timeout[PFTM_SCTP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 2284 pf->timeout[PFTM_SCTP_OPENING] = PFTM_TCP_OPENING_VAL; 2285 pf->timeout[PFTM_SCTP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 2286 pf->timeout[PFTM_SCTP_CLOSING] = PFTM_TCP_CLOSING_VAL; 2287 pf->timeout[PFTM_SCTP_CLOSED] = PFTM_TCP_CLOSED_VAL; 2288 pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; 2289 pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; 2290 pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; 2291 pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; 2292 pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; 2293 pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; 2294 pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; 2295 pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; 2296 pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; 2297 pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; 2298 pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; 2299 pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; 2300 pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; 2301 pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; 2302 2303 pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; 2304 pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT; 2305 pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; 2306 pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; 2307 2308 pf->debug = PF_DEBUG_URGENT; 2309 pf->reassemble = 0; 2310 2311 pf->syncookies = false; 2312 pf->syncookieswat[0] = PF_SYNCOOKIES_LOWATPCT; 2313 pf->syncookieswat[1] = PF_SYNCOOKIES_HIWATPCT; 2314 } 2315 2316 int 2317 pfctl_load_options(struct pfctl *pf) 2318 { 2319 int i, error = 0; 2320 2321 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2322 return (0); 2323 2324 /* load limits */ 2325 for (i = 0; i < PF_LIMIT_MAX; i++) { 2326 if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i]) 2327 continue; 2328 if (pfctl_load_limit(pf, i, pf->limit[i])) 2329 error = 1; 2330 } 2331 2332 /* 2333 * If we've set the limit, but haven't explicitly set adaptive 2334 * timeouts, do it now with a start of 60% and end of 120%. 2335 */ 2336 if (pf->limit_set[PF_LIMIT_STATES] && 2337 !pf->timeout_set[PFTM_ADAPTIVE_START] && 2338 !pf->timeout_set[PFTM_ADAPTIVE_END]) { 2339 pf->timeout[PFTM_ADAPTIVE_START] = 2340 (pf->limit[PF_LIMIT_STATES] / 10) * 6; 2341 pf->timeout_set[PFTM_ADAPTIVE_START] = 1; 2342 pf->timeout[PFTM_ADAPTIVE_END] = 2343 (pf->limit[PF_LIMIT_STATES] / 10) * 12; 2344 pf->timeout_set[PFTM_ADAPTIVE_END] = 1; 2345 } 2346 2347 /* load timeouts */ 2348 for (i = 0; i < PFTM_MAX; i++) { 2349 if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i]) 2350 continue; 2351 if (pfctl_load_timeout(pf, i, pf->timeout[i])) 2352 error = 1; 2353 } 2354 2355 /* load debug */ 2356 if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set) 2357 if (pfctl_load_debug(pf, pf->debug)) 2358 error = 1; 2359 2360 /* load logif */ 2361 if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set) 2362 if (pfctl_load_logif(pf, pf->ifname)) 2363 error = 1; 2364 2365 /* load hostid */ 2366 if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set) 2367 if (pfctl_load_hostid(pf, pf->hostid)) 2368 error = 1; 2369 2370 /* load reassembly settings */ 2371 if (!(pf->opts & PF_OPT_MERGE) || pf->reass_set) 2372 if (pfctl_load_reassembly(pf, pf->reassemble)) 2373 error = 1; 2374 2375 /* load keepcounters */ 2376 if (pfctl_set_keepcounters(pf->dev, pf->keep_counters)) 2377 error = 1; 2378 2379 /* load syncookies settings */ 2380 if (pfctl_load_syncookies(pf, pf->syncookies)) 2381 error = 1; 2382 2383 return (error); 2384 } 2385 2386 int 2387 pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) 2388 { 2389 int i; 2390 2391 2392 for (i = 0; pf_limits[i].name; i++) { 2393 if (strcasecmp(opt, pf_limits[i].name) == 0) { 2394 pf->limit[pf_limits[i].index] = limit; 2395 pf->limit_set[pf_limits[i].index] = 1; 2396 break; 2397 } 2398 } 2399 if (pf_limits[i].name == NULL) { 2400 warnx("Bad pool name."); 2401 return (1); 2402 } 2403 2404 if (pf->opts & PF_OPT_VERBOSE) 2405 printf("set limit %s %d\n", opt, limit); 2406 2407 return (0); 2408 } 2409 2410 int 2411 pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) 2412 { 2413 struct pfioc_limit pl; 2414 2415 memset(&pl, 0, sizeof(pl)); 2416 pl.index = index; 2417 pl.limit = limit; 2418 if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) { 2419 if (errno == EBUSY) 2420 warnx("Current pool size exceeds requested hard limit"); 2421 else 2422 warnx("DIOCSETLIMIT"); 2423 return (1); 2424 } 2425 return (0); 2426 } 2427 2428 int 2429 pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 2430 { 2431 int i; 2432 2433 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2434 return (0); 2435 2436 for (i = 0; pf_timeouts[i].name; i++) { 2437 if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 2438 pf->timeout[pf_timeouts[i].timeout] = seconds; 2439 pf->timeout_set[pf_timeouts[i].timeout] = 1; 2440 break; 2441 } 2442 } 2443 2444 if (pf_timeouts[i].name == NULL) { 2445 warnx("Bad timeout name."); 2446 return (1); 2447 } 2448 2449 2450 if (pf->opts & PF_OPT_VERBOSE && ! quiet) 2451 printf("set timeout %s %d\n", opt, seconds); 2452 2453 return (0); 2454 } 2455 2456 int 2457 pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) 2458 { 2459 struct pfioc_tm pt; 2460 2461 memset(&pt, 0, sizeof(pt)); 2462 pt.timeout = timeout; 2463 pt.seconds = seconds; 2464 if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) { 2465 warnx("DIOCSETTIMEOUT"); 2466 return (1); 2467 } 2468 return (0); 2469 } 2470 2471 int 2472 pfctl_set_reassembly(struct pfctl *pf, int on, int nodf) 2473 { 2474 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2475 return (0); 2476 2477 pf->reass_set = 1; 2478 if (on) { 2479 pf->reassemble = PF_REASS_ENABLED; 2480 if (nodf) 2481 pf->reassemble |= PF_REASS_NODF; 2482 } else { 2483 pf->reassemble = 0; 2484 } 2485 2486 if (pf->opts & PF_OPT_VERBOSE) 2487 printf("set reassemble %s %s\n", on ? "yes" : "no", 2488 nodf ? "no-df" : ""); 2489 2490 return (0); 2491 } 2492 2493 int 2494 pfctl_set_optimization(struct pfctl *pf, const char *opt) 2495 { 2496 const struct pf_hint *hint; 2497 int i, r; 2498 2499 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2500 return (0); 2501 2502 for (i = 0; pf_hints[i].name; i++) 2503 if (strcasecmp(opt, pf_hints[i].name) == 0) 2504 break; 2505 2506 hint = pf_hints[i].hint; 2507 if (hint == NULL) { 2508 warnx("invalid state timeouts optimization"); 2509 return (1); 2510 } 2511 2512 for (i = 0; hint[i].name; i++) 2513 if ((r = pfctl_set_timeout(pf, hint[i].name, 2514 hint[i].timeout, 1))) 2515 return (r); 2516 2517 if (pf->opts & PF_OPT_VERBOSE) 2518 printf("set optimization %s\n", opt); 2519 2520 return (0); 2521 } 2522 2523 int 2524 pfctl_set_logif(struct pfctl *pf, char *ifname) 2525 { 2526 2527 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2528 return (0); 2529 2530 if (!strcmp(ifname, "none")) { 2531 free(pf->ifname); 2532 pf->ifname = NULL; 2533 } else { 2534 pf->ifname = strdup(ifname); 2535 if (!pf->ifname) 2536 errx(1, "pfctl_set_logif: strdup"); 2537 } 2538 pf->ifname_set = 1; 2539 2540 if (pf->opts & PF_OPT_VERBOSE) 2541 printf("set loginterface %s\n", ifname); 2542 2543 return (0); 2544 } 2545 2546 int 2547 pfctl_load_logif(struct pfctl *pf, char *ifname) 2548 { 2549 struct pfioc_if pi; 2550 2551 memset(&pi, 0, sizeof(pi)); 2552 if (ifname && strlcpy(pi.ifname, ifname, 2553 sizeof(pi.ifname)) >= sizeof(pi.ifname)) { 2554 warnx("pfctl_load_logif: strlcpy"); 2555 return (1); 2556 } 2557 if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) { 2558 warnx("DIOCSETSTATUSIF"); 2559 return (1); 2560 } 2561 return (0); 2562 } 2563 2564 int 2565 pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 2566 { 2567 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2568 return (0); 2569 2570 HTONL(hostid); 2571 2572 pf->hostid = hostid; 2573 pf->hostid_set = 1; 2574 2575 if (pf->opts & PF_OPT_VERBOSE) 2576 printf("set hostid 0x%08x\n", ntohl(hostid)); 2577 2578 return (0); 2579 } 2580 2581 int 2582 pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) 2583 { 2584 if (ioctl(dev, DIOCSETHOSTID, &hostid)) { 2585 warnx("DIOCSETHOSTID"); 2586 return (1); 2587 } 2588 return (0); 2589 } 2590 2591 int 2592 pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly) 2593 { 2594 if (ioctl(dev, DIOCSETREASS, &reassembly)) { 2595 warnx("DIOCSETREASS"); 2596 return (1); 2597 } 2598 return (0); 2599 } 2600 2601 int 2602 pfctl_load_syncookies(struct pfctl *pf, u_int8_t val) 2603 { 2604 struct pfctl_syncookies cookies; 2605 2606 bzero(&cookies, sizeof(cookies)); 2607 2608 cookies.mode = val; 2609 cookies.lowwater = pf->syncookieswat[0]; 2610 cookies.highwater = pf->syncookieswat[1]; 2611 2612 if (pfctl_set_syncookies(dev, &cookies)) { 2613 warnx("DIOCSETSYNCOOKIES"); 2614 return (1); 2615 } 2616 return (0); 2617 } 2618 2619 int 2620 pfctl_cfg_syncookies(struct pfctl *pf, uint8_t val, struct pfctl_watermarks *w) 2621 { 2622 if (val != PF_SYNCOOKIES_ADAPTIVE && w != NULL) { 2623 warnx("syncookies start/end only apply to adaptive"); 2624 return (1); 2625 } 2626 if (val == PF_SYNCOOKIES_ADAPTIVE && w != NULL) { 2627 if (!w->hi) 2628 w->hi = PF_SYNCOOKIES_HIWATPCT; 2629 if (!w->lo) 2630 w->lo = w->hi / 2; 2631 if (w->lo >= w->hi) { 2632 warnx("start must be higher than end"); 2633 return (1); 2634 } 2635 pf->syncookieswat[0] = w->lo; 2636 pf->syncookieswat[1] = w->hi; 2637 pf->syncookieswat_set = 1; 2638 } 2639 2640 if (pf->opts & PF_OPT_VERBOSE) { 2641 if (val == PF_SYNCOOKIES_NEVER) 2642 printf("set syncookies never\n"); 2643 else if (val == PF_SYNCOOKIES_ALWAYS) 2644 printf("set syncookies always\n"); 2645 else if (val == PF_SYNCOOKIES_ADAPTIVE) { 2646 if (pf->syncookieswat_set) 2647 printf("set syncookies adaptive (start %u%%, " 2648 "end %u%%)\n", pf->syncookieswat[1], 2649 pf->syncookieswat[0]); 2650 else 2651 printf("set syncookies adaptive\n"); 2652 } else { /* cannot happen */ 2653 warnx("king bula ate all syncookies"); 2654 return (1); 2655 } 2656 } 2657 2658 pf->syncookies = val; 2659 return (0); 2660 } 2661 2662 int 2663 pfctl_set_debug(struct pfctl *pf, char *d) 2664 { 2665 u_int32_t level; 2666 2667 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2668 return (0); 2669 2670 if (!strcmp(d, "none")) 2671 pf->debug = PF_DEBUG_NONE; 2672 else if (!strcmp(d, "urgent")) 2673 pf->debug = PF_DEBUG_URGENT; 2674 else if (!strcmp(d, "misc")) 2675 pf->debug = PF_DEBUG_MISC; 2676 else if (!strcmp(d, "loud")) 2677 pf->debug = PF_DEBUG_NOISY; 2678 else { 2679 warnx("unknown debug level \"%s\"", d); 2680 return (-1); 2681 } 2682 2683 pf->debug_set = 1; 2684 level = pf->debug; 2685 2686 if ((pf->opts & PF_OPT_NOACTION) == 0) 2687 if (ioctl(dev, DIOCSETDEBUG, &level)) 2688 err(1, "DIOCSETDEBUG"); 2689 2690 if (pf->opts & PF_OPT_VERBOSE) 2691 printf("set debug %s\n", d); 2692 2693 return (0); 2694 } 2695 2696 int 2697 pfctl_load_debug(struct pfctl *pf, unsigned int level) 2698 { 2699 if (ioctl(pf->dev, DIOCSETDEBUG, &level)) { 2700 warnx("DIOCSETDEBUG"); 2701 return (1); 2702 } 2703 return (0); 2704 } 2705 2706 int 2707 pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) 2708 { 2709 struct pfioc_iface pi; 2710 struct node_host *h = NULL, *n = NULL; 2711 2712 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2713 return (0); 2714 2715 bzero(&pi, sizeof(pi)); 2716 2717 pi.pfiio_flags = flags; 2718 2719 /* Make sure our cache matches the kernel. If we set or clear the flag 2720 * for a group this applies to all members. */ 2721 h = ifa_grouplookup(ifname, 0); 2722 for (n = h; n != NULL; n = n->next) 2723 pfctl_set_interface_flags(pf, n->ifname, flags, how); 2724 2725 if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= 2726 sizeof(pi.pfiio_name)) 2727 errx(1, "pfctl_set_interface_flags: strlcpy"); 2728 2729 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2730 if (how == 0) { 2731 if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi)) 2732 err(1, "DIOCCLRIFFLAG"); 2733 } else { 2734 if (ioctl(pf->dev, DIOCSETIFFLAG, &pi)) 2735 err(1, "DIOCSETIFFLAG"); 2736 pfctl_check_skip_ifaces(ifname); 2737 } 2738 } 2739 return (0); 2740 } 2741 2742 void 2743 pfctl_debug(int dev, u_int32_t level, int opts) 2744 { 2745 if (ioctl(dev, DIOCSETDEBUG, &level)) 2746 err(1, "DIOCSETDEBUG"); 2747 if ((opts & PF_OPT_QUIET) == 0) { 2748 fprintf(stderr, "debug level set to '"); 2749 switch (level) { 2750 case PF_DEBUG_NONE: 2751 fprintf(stderr, "none"); 2752 break; 2753 case PF_DEBUG_URGENT: 2754 fprintf(stderr, "urgent"); 2755 break; 2756 case PF_DEBUG_MISC: 2757 fprintf(stderr, "misc"); 2758 break; 2759 case PF_DEBUG_NOISY: 2760 fprintf(stderr, "loud"); 2761 break; 2762 default: 2763 fprintf(stderr, "<invalid>"); 2764 break; 2765 } 2766 fprintf(stderr, "'\n"); 2767 } 2768 } 2769 2770 int 2771 pfctl_test_altqsupport(int dev, int opts) 2772 { 2773 struct pfioc_altq pa; 2774 2775 pa.version = PFIOC_ALTQ_VERSION; 2776 if (ioctl(dev, DIOCGETALTQS, &pa)) { 2777 if (errno == ENODEV) { 2778 if (opts & PF_OPT_VERBOSE) 2779 fprintf(stderr, "No ALTQ support in kernel\n" 2780 "ALTQ related functions disabled\n"); 2781 return (0); 2782 } else 2783 err(1, "DIOCGETALTQS"); 2784 } 2785 return (1); 2786 } 2787 2788 int 2789 pfctl_show_anchors(int dev, int opts, char *anchorname) 2790 { 2791 struct pfioc_ruleset pr; 2792 u_int32_t mnr, nr; 2793 2794 memset(&pr, 0, sizeof(pr)); 2795 memcpy(pr.path, anchorname, sizeof(pr.path)); 2796 if (ioctl(dev, DIOCGETRULESETS, &pr)) { 2797 if (errno == EINVAL) 2798 fprintf(stderr, "Anchor '%s' not found.\n", 2799 anchorname); 2800 else 2801 err(1, "DIOCGETRULESETS"); 2802 return (-1); 2803 } 2804 mnr = pr.nr; 2805 for (nr = 0; nr < mnr; ++nr) { 2806 char sub[MAXPATHLEN]; 2807 2808 pr.nr = nr; 2809 if (ioctl(dev, DIOCGETRULESET, &pr)) 2810 err(1, "DIOCGETRULESET"); 2811 if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) 2812 continue; 2813 sub[0] = 0; 2814 if (pr.path[0]) { 2815 strlcat(sub, pr.path, sizeof(sub)); 2816 strlcat(sub, "/", sizeof(sub)); 2817 } 2818 strlcat(sub, pr.name, sizeof(sub)); 2819 if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 2820 printf(" %s\n", sub); 2821 if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub)) 2822 return (-1); 2823 } 2824 return (0); 2825 } 2826 2827 int 2828 pfctl_show_eth_anchors(int dev, int opts, char *anchorname) 2829 { 2830 struct pfctl_eth_rulesets_info ri; 2831 struct pfctl_eth_ruleset_info rs; 2832 int ret; 2833 2834 if ((ret = pfctl_get_eth_rulesets_info(dev, &ri, anchorname)) != 0) { 2835 if (ret == ENOENT) 2836 fprintf(stderr, "Anchor '%s' not found.\n", 2837 anchorname); 2838 else 2839 err(1, "DIOCGETETHRULESETS"); 2840 return (-1); 2841 } 2842 2843 for (int nr = 0; nr < ri.nr; nr++) { 2844 char sub[MAXPATHLEN]; 2845 2846 if (pfctl_get_eth_ruleset(dev, anchorname, nr, &rs) != 0) 2847 err(1, "DIOCGETETHRULESET"); 2848 2849 if (!strcmp(rs.name, PF_RESERVED_ANCHOR)) 2850 continue; 2851 sub[0] = 0; 2852 if (rs.path[0]) { 2853 strlcat(sub, rs.path, sizeof(sub)); 2854 strlcat(sub, "/", sizeof(sub)); 2855 } 2856 strlcat(sub, rs.name, sizeof(sub)); 2857 if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 2858 printf(" %s\n", sub); 2859 if ((opts & PF_OPT_VERBOSE) && pfctl_show_eth_anchors(dev, opts, sub)) 2860 return (-1); 2861 } 2862 return (0); 2863 } 2864 2865 const char * 2866 pfctl_lookup_option(char *cmd, const char * const *list) 2867 { 2868 if (cmd != NULL && *cmd) 2869 for (; *list; list++) 2870 if (!strncmp(cmd, *list, strlen(cmd))) 2871 return (*list); 2872 return (NULL); 2873 } 2874 2875 int 2876 main(int argc, char *argv[]) 2877 { 2878 int error = 0; 2879 int ch; 2880 int mode = O_RDONLY; 2881 int opts = 0; 2882 int optimize = PF_OPTIMIZE_BASIC; 2883 char anchorname[MAXPATHLEN]; 2884 char *path; 2885 2886 if (argc < 2) 2887 usage(); 2888 2889 while ((ch = getopt(argc, argv, 2890 "a:AdD:eqf:F:ghi:k:K:mMnNOo:Pp:rRs:t:T:vx:z")) != -1) { 2891 switch (ch) { 2892 case 'a': 2893 anchoropt = optarg; 2894 break; 2895 case 'd': 2896 opts |= PF_OPT_DISABLE; 2897 mode = O_RDWR; 2898 break; 2899 case 'D': 2900 if (pfctl_cmdline_symset(optarg) < 0) 2901 warnx("could not parse macro definition %s", 2902 optarg); 2903 break; 2904 case 'e': 2905 opts |= PF_OPT_ENABLE; 2906 mode = O_RDWR; 2907 break; 2908 case 'q': 2909 opts |= PF_OPT_QUIET; 2910 break; 2911 case 'F': 2912 clearopt = pfctl_lookup_option(optarg, clearopt_list); 2913 if (clearopt == NULL) { 2914 warnx("Unknown flush modifier '%s'", optarg); 2915 usage(); 2916 } 2917 mode = O_RDWR; 2918 break; 2919 case 'i': 2920 ifaceopt = optarg; 2921 break; 2922 case 'k': 2923 if (state_killers >= 2) { 2924 warnx("can only specify -k twice"); 2925 usage(); 2926 /* NOTREACHED */ 2927 } 2928 state_kill[state_killers++] = optarg; 2929 mode = O_RDWR; 2930 break; 2931 case 'K': 2932 if (src_node_killers >= 2) { 2933 warnx("can only specify -K twice"); 2934 usage(); 2935 /* NOTREACHED */ 2936 } 2937 src_node_kill[src_node_killers++] = optarg; 2938 mode = O_RDWR; 2939 break; 2940 case 'm': 2941 opts |= PF_OPT_MERGE; 2942 break; 2943 case 'M': 2944 opts |= PF_OPT_KILLMATCH; 2945 break; 2946 case 'n': 2947 opts |= PF_OPT_NOACTION; 2948 break; 2949 case 'N': 2950 loadopt |= PFCTL_FLAG_NAT; 2951 break; 2952 case 'r': 2953 opts |= PF_OPT_USEDNS; 2954 break; 2955 case 'f': 2956 rulesopt = optarg; 2957 mode = O_RDWR; 2958 break; 2959 case 'g': 2960 opts |= PF_OPT_DEBUG; 2961 break; 2962 case 'A': 2963 loadopt |= PFCTL_FLAG_ALTQ; 2964 break; 2965 case 'R': 2966 loadopt |= PFCTL_FLAG_FILTER; 2967 break; 2968 case 'o': 2969 optiopt = pfctl_lookup_option(optarg, optiopt_list); 2970 if (optiopt == NULL) { 2971 warnx("Unknown optimization '%s'", optarg); 2972 usage(); 2973 } 2974 opts |= PF_OPT_OPTIMIZE; 2975 break; 2976 case 'O': 2977 loadopt |= PFCTL_FLAG_OPTION; 2978 break; 2979 case 'p': 2980 pf_device = optarg; 2981 break; 2982 case 'P': 2983 opts |= PF_OPT_NUMERIC; 2984 break; 2985 case 's': 2986 showopt = pfctl_lookup_option(optarg, showopt_list); 2987 if (showopt == NULL) { 2988 warnx("Unknown show modifier '%s'", optarg); 2989 usage(); 2990 } 2991 break; 2992 case 't': 2993 tableopt = optarg; 2994 break; 2995 case 'T': 2996 tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 2997 if (tblcmdopt == NULL) { 2998 warnx("Unknown table command '%s'", optarg); 2999 usage(); 3000 } 3001 break; 3002 case 'v': 3003 if (opts & PF_OPT_VERBOSE) 3004 opts |= PF_OPT_VERBOSE2; 3005 opts |= PF_OPT_VERBOSE; 3006 break; 3007 case 'x': 3008 debugopt = pfctl_lookup_option(optarg, debugopt_list); 3009 if (debugopt == NULL) { 3010 warnx("Unknown debug level '%s'", optarg); 3011 usage(); 3012 } 3013 mode = O_RDWR; 3014 break; 3015 case 'z': 3016 opts |= PF_OPT_CLRRULECTRS; 3017 mode = O_RDWR; 3018 break; 3019 case 'h': 3020 /* FALLTHROUGH */ 3021 default: 3022 usage(); 3023 /* NOTREACHED */ 3024 } 3025 } 3026 3027 if (tblcmdopt != NULL) { 3028 argc -= optind; 3029 argv += optind; 3030 ch = *tblcmdopt; 3031 if (ch == 'l') { 3032 loadopt |= PFCTL_FLAG_TABLE; 3033 tblcmdopt = NULL; 3034 } else 3035 mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY; 3036 } else if (argc != optind) { 3037 warnx("unknown command line argument: %s ...", argv[optind]); 3038 usage(); 3039 /* NOTREACHED */ 3040 } 3041 if (loadopt == 0) 3042 loadopt = ~0; 3043 3044 if ((path = calloc(1, MAXPATHLEN)) == NULL) 3045 errx(1, "pfctl: calloc"); 3046 memset(anchorname, 0, sizeof(anchorname)); 3047 if (anchoropt != NULL) { 3048 int len = strlen(anchoropt); 3049 3050 if (len >= 1 && anchoropt[len - 1] == '*') { 3051 if (len >= 2 && anchoropt[len - 2] == '/') 3052 anchoropt[len - 2] = '\0'; 3053 else 3054 anchoropt[len - 1] = '\0'; 3055 opts |= PF_OPT_RECURSE; 3056 } 3057 if (strlcpy(anchorname, anchoropt, 3058 sizeof(anchorname)) >= sizeof(anchorname)) 3059 errx(1, "anchor name '%s' too long", 3060 anchoropt); 3061 loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE|PFCTL_FLAG_ETH; 3062 } 3063 3064 if ((opts & PF_OPT_NOACTION) == 0) { 3065 dev = open(pf_device, mode); 3066 if (dev == -1) 3067 err(1, "%s", pf_device); 3068 altqsupport = pfctl_test_altqsupport(dev, opts); 3069 } else { 3070 dev = open(pf_device, O_RDONLY); 3071 if (dev >= 0) 3072 opts |= PF_OPT_DUMMYACTION; 3073 /* turn off options */ 3074 opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 3075 clearopt = showopt = debugopt = NULL; 3076 #if !defined(ENABLE_ALTQ) 3077 altqsupport = 0; 3078 #else 3079 altqsupport = 1; 3080 #endif 3081 } 3082 3083 if (opts & PF_OPT_DISABLE) 3084 if (pfctl_disable(dev, opts)) 3085 error = 1; 3086 3087 if (showopt != NULL) { 3088 switch (*showopt) { 3089 case 'A': 3090 pfctl_show_anchors(dev, opts, anchorname); 3091 if (opts & PF_OPT_VERBOSE2) 3092 printf("Ethernet:\n"); 3093 pfctl_show_eth_anchors(dev, opts, anchorname); 3094 break; 3095 case 'r': 3096 pfctl_load_fingerprints(dev, opts); 3097 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 3098 anchorname, 0, 0); 3099 break; 3100 case 'l': 3101 pfctl_load_fingerprints(dev, opts); 3102 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 3103 anchorname, 0, 0); 3104 break; 3105 case 'n': 3106 pfctl_load_fingerprints(dev, opts); 3107 pfctl_show_nat(dev, path, opts, anchorname, 0); 3108 break; 3109 case 'q': 3110 pfctl_show_altq(dev, ifaceopt, opts, 3111 opts & PF_OPT_VERBOSE2); 3112 break; 3113 case 's': 3114 pfctl_show_states(dev, ifaceopt, opts); 3115 break; 3116 case 'S': 3117 pfctl_show_src_nodes(dev, opts); 3118 break; 3119 case 'i': 3120 pfctl_show_status(dev, opts); 3121 break; 3122 case 'R': 3123 error = pfctl_show_running(dev); 3124 break; 3125 case 't': 3126 pfctl_show_timeouts(dev, opts); 3127 break; 3128 case 'm': 3129 pfctl_show_limits(dev, opts); 3130 break; 3131 case 'e': 3132 pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0, 3133 0); 3134 break; 3135 case 'a': 3136 opts |= PF_OPT_SHOWALL; 3137 pfctl_load_fingerprints(dev, opts); 3138 3139 pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0, 3140 0); 3141 3142 pfctl_show_nat(dev, path, opts, anchorname, 0); 3143 pfctl_show_rules(dev, path, opts, 0, anchorname, 0, 0); 3144 pfctl_show_altq(dev, ifaceopt, opts, 0); 3145 pfctl_show_states(dev, ifaceopt, opts); 3146 pfctl_show_src_nodes(dev, opts); 3147 pfctl_show_status(dev, opts); 3148 pfctl_show_rules(dev, path, opts, 1, anchorname, 0, 0); 3149 pfctl_show_timeouts(dev, opts); 3150 pfctl_show_limits(dev, opts); 3151 pfctl_show_tables(anchorname, opts); 3152 pfctl_show_fingerprints(opts); 3153 break; 3154 case 'T': 3155 pfctl_show_tables(anchorname, opts); 3156 break; 3157 case 'o': 3158 pfctl_load_fingerprints(dev, opts); 3159 pfctl_show_fingerprints(opts); 3160 break; 3161 case 'I': 3162 pfctl_show_ifaces(ifaceopt, opts); 3163 break; 3164 case 'c': 3165 pfctl_show_creators(opts); 3166 break; 3167 } 3168 } 3169 3170 if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) { 3171 pfctl_show_eth_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 3172 anchorname, 0, 0); 3173 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 3174 anchorname, 0, 0); 3175 } 3176 3177 if (clearopt != NULL) { 3178 if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 3179 errx(1, "anchor names beginning with '_' cannot " 3180 "be modified from the command line"); 3181 3182 switch (*clearopt) { 3183 case 'e': 3184 pfctl_flush_eth_rules(dev, opts, anchorname); 3185 break; 3186 case 'r': 3187 pfctl_flush_rules(dev, opts, anchorname); 3188 break; 3189 case 'n': 3190 pfctl_flush_nat(dev, opts, anchorname); 3191 break; 3192 case 'q': 3193 pfctl_clear_altq(dev, opts); 3194 break; 3195 case 's': 3196 pfctl_clear_iface_states(dev, ifaceopt, opts); 3197 break; 3198 case 'S': 3199 pfctl_clear_src_nodes(dev, opts); 3200 break; 3201 case 'i': 3202 pfctl_clear_stats(dev, opts); 3203 break; 3204 case 'a': 3205 pfctl_flush_eth_rules(dev, opts, anchorname); 3206 pfctl_flush_rules(dev, opts, anchorname); 3207 pfctl_flush_nat(dev, opts, anchorname); 3208 pfctl_clear_tables(anchorname, opts); 3209 if (!*anchorname) { 3210 pfctl_clear_altq(dev, opts); 3211 pfctl_clear_iface_states(dev, ifaceopt, opts); 3212 pfctl_clear_src_nodes(dev, opts); 3213 pfctl_clear_stats(dev, opts); 3214 pfctl_clear_fingerprints(dev, opts); 3215 pfctl_clear_interface_flags(dev, opts); 3216 } 3217 break; 3218 case 'o': 3219 pfctl_clear_fingerprints(dev, opts); 3220 break; 3221 case 'T': 3222 pfctl_clear_tables(anchorname, opts); 3223 break; 3224 } 3225 } 3226 if (state_killers) { 3227 if (!strcmp(state_kill[0], "label")) 3228 pfctl_label_kill_states(dev, ifaceopt, opts); 3229 else if (!strcmp(state_kill[0], "id")) 3230 pfctl_id_kill_states(dev, ifaceopt, opts); 3231 else if (!strcmp(state_kill[0], "gateway")) 3232 pfctl_gateway_kill_states(dev, ifaceopt, opts); 3233 else 3234 pfctl_net_kill_states(dev, ifaceopt, opts); 3235 } 3236 3237 if (src_node_killers) 3238 pfctl_kill_src_nodes(dev, ifaceopt, opts); 3239 3240 if (tblcmdopt != NULL) { 3241 error = pfctl_command_tables(argc, argv, tableopt, 3242 tblcmdopt, rulesopt, anchorname, opts); 3243 rulesopt = NULL; 3244 } 3245 if (optiopt != NULL) { 3246 switch (*optiopt) { 3247 case 'n': 3248 optimize = 0; 3249 break; 3250 case 'b': 3251 optimize |= PF_OPTIMIZE_BASIC; 3252 break; 3253 case 'o': 3254 case 'p': 3255 optimize |= PF_OPTIMIZE_PROFILE; 3256 break; 3257 } 3258 } 3259 3260 if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) && 3261 !anchorname[0] && !(opts & PF_OPT_NOACTION)) 3262 if (pfctl_get_skip_ifaces()) 3263 error = 1; 3264 3265 if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) && 3266 !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION)) 3267 if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 3268 error = 1; 3269 3270 if (rulesopt != NULL) { 3271 if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 3272 errx(1, "anchor names beginning with '_' cannot " 3273 "be modified from the command line"); 3274 if (pfctl_rules(dev, rulesopt, opts, optimize, 3275 anchorname, NULL)) 3276 error = 1; 3277 else if (!(opts & PF_OPT_NOACTION) && 3278 (loadopt & PFCTL_FLAG_TABLE)) 3279 warn_namespace_collision(NULL); 3280 } 3281 3282 if (opts & PF_OPT_ENABLE) 3283 if (pfctl_enable(dev, opts)) 3284 error = 1; 3285 3286 if (debugopt != NULL) { 3287 switch (*debugopt) { 3288 case 'n': 3289 pfctl_debug(dev, PF_DEBUG_NONE, opts); 3290 break; 3291 case 'u': 3292 pfctl_debug(dev, PF_DEBUG_URGENT, opts); 3293 break; 3294 case 'm': 3295 pfctl_debug(dev, PF_DEBUG_MISC, opts); 3296 break; 3297 case 'l': 3298 pfctl_debug(dev, PF_DEBUG_NOISY, opts); 3299 break; 3300 } 3301 } 3302 3303 exit(error); 3304 } 3305