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