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