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