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