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