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