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