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_clear_rules(int, int, char *); 79 int pfctl_clear_nat(int, int, char *); 80 int pfctl_clear_altq(int, int); 81 int pfctl_clear_src_nodes(int, int); 82 int pfctl_clear_iface_states(int, const char *, int); 83 void pfctl_addrprefix(char *, struct pf_addr *); 84 int pfctl_kill_src_nodes(int, const char *, int); 85 int pfctl_net_kill_states(int, const char *, int); 86 int pfctl_gateway_kill_states(int, const char *, int); 87 int pfctl_label_kill_states(int, const char *, int); 88 int pfctl_id_kill_states(int, const char *, int); 89 void pfctl_init_options(struct pfctl *); 90 int pfctl_load_options(struct pfctl *); 91 int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); 92 int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); 93 int pfctl_load_debug(struct pfctl *, unsigned int); 94 int pfctl_load_logif(struct pfctl *, char *); 95 int pfctl_load_hostid(struct pfctl *, u_int32_t); 96 int pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int, 97 char *); 98 void pfctl_print_rule_counters(struct pfctl_rule *, int); 99 int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int); 100 int pfctl_show_nat(int, int, char *); 101 int pfctl_show_src_nodes(int, int); 102 int pfctl_show_states(int, const char *, int); 103 int pfctl_show_status(int, int); 104 int pfctl_show_running(int); 105 int pfctl_show_timeouts(int, int); 106 int pfctl_show_limits(int, int); 107 void pfctl_debug(int, u_int32_t, int); 108 int pfctl_test_altqsupport(int, int); 109 int pfctl_show_anchors(int, int, char *); 110 int pfctl_ruleset_trans(struct pfctl *, char *, struct pfctl_anchor *); 111 int pfctl_load_ruleset(struct pfctl *, char *, 112 struct pfctl_ruleset *, int, int); 113 int pfctl_load_rule(struct pfctl *, char *, struct pfctl_rule *, int); 114 const char *pfctl_lookup_option(char *, const char * const *); 115 116 static struct pfctl_anchor_global pf_anchors; 117 static struct pfctl_anchor pf_main_anchor; 118 static struct pfr_buffer skip_b; 119 120 static const char *clearopt; 121 static char *rulesopt; 122 static const char *showopt; 123 static const char *debugopt; 124 static char *anchoropt; 125 static const char *optiopt = NULL; 126 static const char *pf_device = "/dev/pf"; 127 static char *ifaceopt; 128 static char *tableopt; 129 static const char *tblcmdopt; 130 static int src_node_killers; 131 static char *src_node_kill[2]; 132 static int state_killers; 133 static char *state_kill[2]; 134 int loadopt; 135 int altqsupport; 136 137 int dev = -1; 138 static int first_title = 1; 139 static int labels = 0; 140 141 #define INDENT(d, o) do { \ 142 if (o) { \ 143 int i; \ 144 for (i=0; i < d; i++) \ 145 printf(" "); \ 146 } \ 147 } while (0); \ 148 149 150 static const struct { 151 const char *name; 152 int index; 153 } pf_limits[] = { 154 { "states", PF_LIMIT_STATES }, 155 { "src-nodes", PF_LIMIT_SRC_NODES }, 156 { "frags", PF_LIMIT_FRAGS }, 157 { "table-entries", PF_LIMIT_TABLE_ENTRIES }, 158 { NULL, 0 } 159 }; 160 161 struct pf_hint { 162 const char *name; 163 int timeout; 164 }; 165 static const struct pf_hint pf_hint_normal[] = { 166 { "tcp.first", 2 * 60 }, 167 { "tcp.opening", 30 }, 168 { "tcp.established", 24 * 60 * 60 }, 169 { "tcp.closing", 15 * 60 }, 170 { "tcp.finwait", 45 }, 171 { "tcp.closed", 90 }, 172 { "tcp.tsdiff", 30 }, 173 { NULL, 0 } 174 }; 175 static const struct pf_hint pf_hint_satellite[] = { 176 { "tcp.first", 3 * 60 }, 177 { "tcp.opening", 30 + 5 }, 178 { "tcp.established", 24 * 60 * 60 }, 179 { "tcp.closing", 15 * 60 + 5 }, 180 { "tcp.finwait", 45 + 5 }, 181 { "tcp.closed", 90 + 5 }, 182 { "tcp.tsdiff", 60 }, 183 { NULL, 0 } 184 }; 185 static const struct pf_hint pf_hint_conservative[] = { 186 { "tcp.first", 60 * 60 }, 187 { "tcp.opening", 15 * 60 }, 188 { "tcp.established", 5 * 24 * 60 * 60 }, 189 { "tcp.closing", 60 * 60 }, 190 { "tcp.finwait", 10 * 60 }, 191 { "tcp.closed", 3 * 60 }, 192 { "tcp.tsdiff", 60 }, 193 { NULL, 0 } 194 }; 195 static const struct pf_hint pf_hint_aggressive[] = { 196 { "tcp.first", 30 }, 197 { "tcp.opening", 5 }, 198 { "tcp.established", 5 * 60 * 60 }, 199 { "tcp.closing", 60 }, 200 { "tcp.finwait", 30 }, 201 { "tcp.closed", 30 }, 202 { "tcp.tsdiff", 10 }, 203 { NULL, 0 } 204 }; 205 206 static const struct { 207 const char *name; 208 const struct pf_hint *hint; 209 } pf_hints[] = { 210 { "normal", pf_hint_normal }, 211 { "satellite", pf_hint_satellite }, 212 { "high-latency", pf_hint_satellite }, 213 { "conservative", pf_hint_conservative }, 214 { "aggressive", pf_hint_aggressive }, 215 { NULL, NULL } 216 }; 217 218 static const char * const clearopt_list[] = { 219 "nat", "queue", "rules", "Sources", 220 "states", "info", "Tables", "osfp", "all", NULL 221 }; 222 223 static const char * const showopt_list[] = { 224 "nat", "queue", "rules", "Anchors", "Sources", "states", "info", 225 "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp", 226 "Running", "all", NULL 227 }; 228 229 static const char * const tblcmdopt_list[] = { 230 "kill", "flush", "add", "delete", "load", "replace", "show", 231 "test", "zero", "expire", NULL 232 }; 233 234 static const char * const debugopt_list[] = { 235 "none", "urgent", "misc", "loud", NULL 236 }; 237 238 static const char * const optiopt_list[] = { 239 "none", "basic", "profile", NULL 240 }; 241 242 void 243 usage(void) 244 { 245 extern char *__progname; 246 247 fprintf(stderr, 248 "usage: %s [-AdeghMmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n" 249 "\t[-f file] [-i interface] [-K host | network]\n" 250 "\t[-k host | network | gateway | label | id] [-o level] [-p device]\n" 251 "\t[-s modifier] [-t table -T command [address ...]] [-x level]\n", 252 __progname); 253 254 exit(1); 255 } 256 257 int 258 pfctl_enable(int dev, int opts) 259 { 260 if (ioctl(dev, DIOCSTART)) { 261 if (errno == EEXIST) 262 errx(1, "pf already enabled"); 263 else if (errno == ESRCH) 264 errx(1, "pfil registeration failed"); 265 else 266 err(1, "DIOCSTART"); 267 } 268 if ((opts & PF_OPT_QUIET) == 0) 269 fprintf(stderr, "pf enabled\n"); 270 271 if (altqsupport && ioctl(dev, DIOCSTARTALTQ)) 272 if (errno != EEXIST) 273 err(1, "DIOCSTARTALTQ"); 274 275 return (0); 276 } 277 278 int 279 pfctl_disable(int dev, int opts) 280 { 281 if (ioctl(dev, DIOCSTOP)) { 282 if (errno == ENOENT) 283 errx(1, "pf not enabled"); 284 else 285 err(1, "DIOCSTOP"); 286 } 287 if ((opts & PF_OPT_QUIET) == 0) 288 fprintf(stderr, "pf disabled\n"); 289 290 if (altqsupport && ioctl(dev, DIOCSTOPALTQ)) 291 if (errno != ENOENT) 292 err(1, "DIOCSTOPALTQ"); 293 294 return (0); 295 } 296 297 int 298 pfctl_clear_stats(int dev, int opts) 299 { 300 if (ioctl(dev, DIOCCLRSTATUS)) 301 err(1, "DIOCCLRSTATUS"); 302 if ((opts & PF_OPT_QUIET) == 0) 303 fprintf(stderr, "pf: statistics cleared\n"); 304 return (0); 305 } 306 307 int 308 pfctl_get_skip_ifaces(void) 309 { 310 bzero(&skip_b, sizeof(skip_b)); 311 skip_b.pfrb_type = PFRB_IFACES; 312 for (;;) { 313 pfr_buf_grow(&skip_b, skip_b.pfrb_size); 314 skip_b.pfrb_size = skip_b.pfrb_msize; 315 if (pfi_get_ifaces(NULL, skip_b.pfrb_caddr, &skip_b.pfrb_size)) 316 err(1, "pfi_get_ifaces"); 317 if (skip_b.pfrb_size <= skip_b.pfrb_msize) 318 break; 319 } 320 return (0); 321 } 322 323 int 324 pfctl_check_skip_ifaces(char *ifname) 325 { 326 struct pfi_kif *p; 327 struct node_host *h = NULL, *n = NULL; 328 329 PFRB_FOREACH(p, &skip_b) { 330 if (!strcmp(ifname, p->pfik_name) && 331 (p->pfik_flags & PFI_IFLAG_SKIP)) 332 p->pfik_flags &= ~PFI_IFLAG_SKIP; 333 if (!strcmp(ifname, p->pfik_name) && p->pfik_group != NULL) { 334 if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL) 335 continue; 336 337 for (n = h; n != NULL; n = n->next) { 338 if (p->pfik_ifp == NULL) 339 continue; 340 if (strncmp(p->pfik_name, ifname, IFNAMSIZ)) 341 continue; 342 343 p->pfik_flags &= ~PFI_IFLAG_SKIP; 344 } 345 } 346 } 347 return (0); 348 } 349 350 int 351 pfctl_adjust_skip_ifaces(struct pfctl *pf) 352 { 353 struct pfi_kif *p, *pp; 354 struct node_host *h = NULL, *n = NULL; 355 356 PFRB_FOREACH(p, &skip_b) { 357 if (p->pfik_group == NULL || !(p->pfik_flags & PFI_IFLAG_SKIP)) 358 continue; 359 360 pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0); 361 if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL) 362 continue; 363 364 for (n = h; n != NULL; n = n->next) 365 PFRB_FOREACH(pp, &skip_b) { 366 if (pp->pfik_ifp == NULL) 367 continue; 368 369 if (strncmp(pp->pfik_name, n->ifname, IFNAMSIZ)) 370 continue; 371 372 if (!(pp->pfik_flags & PFI_IFLAG_SKIP)) 373 pfctl_set_interface_flags(pf, 374 pp->pfik_name, PFI_IFLAG_SKIP, 1); 375 if (pp->pfik_flags & PFI_IFLAG_SKIP) 376 pp->pfik_flags &= ~PFI_IFLAG_SKIP; 377 } 378 } 379 380 PFRB_FOREACH(p, &skip_b) { 381 if (p->pfik_ifp == NULL || ! (p->pfik_flags & PFI_IFLAG_SKIP)) 382 continue; 383 384 pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0); 385 } 386 387 return (0); 388 } 389 390 int 391 pfctl_clear_interface_flags(int dev, int opts) 392 { 393 struct pfioc_iface pi; 394 395 if ((opts & PF_OPT_NOACTION) == 0) { 396 bzero(&pi, sizeof(pi)); 397 pi.pfiio_flags = PFI_IFLAG_SKIP; 398 399 if (ioctl(dev, DIOCCLRIFFLAG, &pi)) 400 err(1, "DIOCCLRIFFLAG"); 401 if ((opts & PF_OPT_QUIET) == 0) 402 fprintf(stderr, "pf: interface flags reset\n"); 403 } 404 return (0); 405 } 406 407 int 408 pfctl_clear_rules(int dev, int opts, char *anchorname) 409 { 410 struct pfr_buffer t; 411 412 memset(&t, 0, sizeof(t)); 413 t.pfrb_type = PFRB_TRANS; 414 if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname) || 415 pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) || 416 pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 417 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 418 err(1, "pfctl_clear_rules"); 419 if ((opts & PF_OPT_QUIET) == 0) 420 fprintf(stderr, "rules cleared\n"); 421 return (0); 422 } 423 424 int 425 pfctl_clear_nat(int dev, int opts, char *anchorname) 426 { 427 struct pfr_buffer t; 428 429 memset(&t, 0, sizeof(t)); 430 t.pfrb_type = PFRB_TRANS; 431 if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname) || 432 pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname) || 433 pfctl_add_trans(&t, PF_RULESET_RDR, anchorname) || 434 pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 435 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 436 err(1, "pfctl_clear_nat"); 437 if ((opts & PF_OPT_QUIET) == 0) 438 fprintf(stderr, "nat cleared\n"); 439 return (0); 440 } 441 442 int 443 pfctl_clear_altq(int dev, int opts) 444 { 445 struct pfr_buffer t; 446 447 if (!altqsupport) 448 return (-1); 449 memset(&t, 0, sizeof(t)); 450 t.pfrb_type = PFRB_TRANS; 451 if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") || 452 pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 453 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 454 err(1, "pfctl_clear_altq"); 455 if ((opts & PF_OPT_QUIET) == 0) 456 fprintf(stderr, "altq cleared\n"); 457 return (0); 458 } 459 460 int 461 pfctl_clear_src_nodes(int dev, int opts) 462 { 463 if (ioctl(dev, DIOCCLRSRCNODES)) 464 err(1, "DIOCCLRSRCNODES"); 465 if ((opts & PF_OPT_QUIET) == 0) 466 fprintf(stderr, "source tracking entries cleared\n"); 467 return (0); 468 } 469 470 int 471 pfctl_clear_iface_states(int dev, const char *iface, int opts) 472 { 473 struct pfctl_kill kill; 474 unsigned int killed; 475 476 memset(&kill, 0, sizeof(kill)); 477 if (iface != NULL && strlcpy(kill.ifname, iface, 478 sizeof(kill.ifname)) >= sizeof(kill.ifname)) 479 errx(1, "invalid interface: %s", iface); 480 481 if (opts & PF_OPT_KILLMATCH) 482 kill.kill_match = true; 483 484 if (pfctl_clear_states(dev, &kill, &killed)) 485 err(1, "DIOCCLRSTATES"); 486 if ((opts & PF_OPT_QUIET) == 0) 487 fprintf(stderr, "%d states cleared\n", killed); 488 return (0); 489 } 490 491 void 492 pfctl_addrprefix(char *addr, struct pf_addr *mask) 493 { 494 char *p; 495 const char *errstr; 496 int prefix, ret_ga, q, r; 497 struct addrinfo hints, *res; 498 499 if ((p = strchr(addr, '/')) == NULL) 500 return; 501 502 *p++ = '\0'; 503 prefix = strtonum(p, 0, 128, &errstr); 504 if (errstr) 505 errx(1, "prefix is %s: %s", errstr, p); 506 507 bzero(&hints, sizeof(hints)); 508 /* prefix only with numeric addresses */ 509 hints.ai_flags |= AI_NUMERICHOST; 510 511 if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) { 512 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 513 /* NOTREACHED */ 514 } 515 516 if (res->ai_family == AF_INET && prefix > 32) 517 errx(1, "prefix too long for AF_INET"); 518 else if (res->ai_family == AF_INET6 && prefix > 128) 519 errx(1, "prefix too long for AF_INET6"); 520 521 q = prefix >> 3; 522 r = prefix & 7; 523 switch (res->ai_family) { 524 case AF_INET: 525 bzero(&mask->v4, sizeof(mask->v4)); 526 mask->v4.s_addr = htonl((u_int32_t) 527 (0xffffffffffULL << (32 - prefix))); 528 break; 529 case AF_INET6: 530 bzero(&mask->v6, sizeof(mask->v6)); 531 if (q > 0) 532 memset((void *)&mask->v6, 0xff, q); 533 if (r > 0) 534 *((u_char *)&mask->v6 + q) = 535 (0xff00 >> r) & 0xff; 536 break; 537 } 538 freeaddrinfo(res); 539 } 540 541 int 542 pfctl_kill_src_nodes(int dev, const char *iface, int opts) 543 { 544 struct pfioc_src_node_kill psnk; 545 struct addrinfo *res[2], *resp[2]; 546 struct sockaddr last_src, last_dst; 547 int killed, sources, dests; 548 int ret_ga; 549 550 killed = sources = dests = 0; 551 552 memset(&psnk, 0, sizeof(psnk)); 553 memset(&psnk.psnk_src.addr.v.a.mask, 0xff, 554 sizeof(psnk.psnk_src.addr.v.a.mask)); 555 memset(&last_src, 0xff, sizeof(last_src)); 556 memset(&last_dst, 0xff, sizeof(last_dst)); 557 558 pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask); 559 560 if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) { 561 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 562 /* NOTREACHED */ 563 } 564 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 565 if (resp[0]->ai_addr == NULL) 566 continue; 567 /* We get lots of duplicates. Catch the easy ones */ 568 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 569 continue; 570 last_src = *(struct sockaddr *)resp[0]->ai_addr; 571 572 psnk.psnk_af = resp[0]->ai_family; 573 sources++; 574 575 if (psnk.psnk_af == AF_INET) 576 psnk.psnk_src.addr.v.a.addr.v4 = 577 ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 578 else if (psnk.psnk_af == AF_INET6) 579 psnk.psnk_src.addr.v.a.addr.v6 = 580 ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 581 sin6_addr; 582 else 583 errx(1, "Unknown address family %d", psnk.psnk_af); 584 585 if (src_node_killers > 1) { 586 dests = 0; 587 memset(&psnk.psnk_dst.addr.v.a.mask, 0xff, 588 sizeof(psnk.psnk_dst.addr.v.a.mask)); 589 memset(&last_dst, 0xff, sizeof(last_dst)); 590 pfctl_addrprefix(src_node_kill[1], 591 &psnk.psnk_dst.addr.v.a.mask); 592 if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL, 593 &res[1]))) { 594 errx(1, "getaddrinfo: %s", 595 gai_strerror(ret_ga)); 596 /* NOTREACHED */ 597 } 598 for (resp[1] = res[1]; resp[1]; 599 resp[1] = resp[1]->ai_next) { 600 if (resp[1]->ai_addr == NULL) 601 continue; 602 if (psnk.psnk_af != resp[1]->ai_family) 603 continue; 604 605 if (memcmp(&last_dst, resp[1]->ai_addr, 606 sizeof(last_dst)) == 0) 607 continue; 608 last_dst = *(struct sockaddr *)resp[1]->ai_addr; 609 610 dests++; 611 612 if (psnk.psnk_af == AF_INET) 613 psnk.psnk_dst.addr.v.a.addr.v4 = 614 ((struct sockaddr_in *)resp[1]-> 615 ai_addr)->sin_addr; 616 else if (psnk.psnk_af == AF_INET6) 617 psnk.psnk_dst.addr.v.a.addr.v6 = 618 ((struct sockaddr_in6 *)resp[1]-> 619 ai_addr)->sin6_addr; 620 else 621 errx(1, "Unknown address family %d", 622 psnk.psnk_af); 623 624 if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 625 err(1, "DIOCKILLSRCNODES"); 626 killed += psnk.psnk_killed; 627 } 628 freeaddrinfo(res[1]); 629 } else { 630 if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 631 err(1, "DIOCKILLSRCNODES"); 632 killed += psnk.psnk_killed; 633 } 634 } 635 636 freeaddrinfo(res[0]); 637 638 if ((opts & PF_OPT_QUIET) == 0) 639 fprintf(stderr, "killed %d src nodes from %d sources and %d " 640 "destinations\n", killed, sources, dests); 641 return (0); 642 } 643 644 int 645 pfctl_net_kill_states(int dev, const char *iface, int opts) 646 { 647 struct pfctl_kill kill; 648 struct addrinfo *res[2], *resp[2]; 649 struct sockaddr last_src, last_dst; 650 unsigned int newkilled; 651 int killed, sources, dests; 652 int ret_ga; 653 654 killed = sources = dests = 0; 655 656 memset(&kill, 0, sizeof(kill)); 657 memset(&kill.src.addr.v.a.mask, 0xff, 658 sizeof(kill.src.addr.v.a.mask)); 659 memset(&last_src, 0xff, sizeof(last_src)); 660 memset(&last_dst, 0xff, sizeof(last_dst)); 661 if (iface != NULL && strlcpy(kill.ifname, iface, 662 sizeof(kill.ifname)) >= sizeof(kill.ifname)) 663 errx(1, "invalid interface: %s", iface); 664 665 pfctl_addrprefix(state_kill[0], &kill.src.addr.v.a.mask); 666 667 if (opts & PF_OPT_KILLMATCH) 668 kill.kill_match = true; 669 670 if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) { 671 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 672 /* NOTREACHED */ 673 } 674 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 675 if (resp[0]->ai_addr == NULL) 676 continue; 677 /* We get lots of duplicates. Catch the easy ones */ 678 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 679 continue; 680 last_src = *(struct sockaddr *)resp[0]->ai_addr; 681 682 kill.af = resp[0]->ai_family; 683 sources++; 684 685 if (kill.af == AF_INET) 686 kill.src.addr.v.a.addr.v4 = 687 ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 688 else if (kill.af == AF_INET6) 689 kill.src.addr.v.a.addr.v6 = 690 ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 691 sin6_addr; 692 else 693 errx(1, "Unknown address family %d", kill.af); 694 695 if (state_killers > 1) { 696 dests = 0; 697 memset(&kill.dst.addr.v.a.mask, 0xff, 698 sizeof(kill.dst.addr.v.a.mask)); 699 memset(&last_dst, 0xff, sizeof(last_dst)); 700 pfctl_addrprefix(state_kill[1], 701 &kill.dst.addr.v.a.mask); 702 if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, 703 &res[1]))) { 704 errx(1, "getaddrinfo: %s", 705 gai_strerror(ret_ga)); 706 /* NOTREACHED */ 707 } 708 for (resp[1] = res[1]; resp[1]; 709 resp[1] = resp[1]->ai_next) { 710 if (resp[1]->ai_addr == NULL) 711 continue; 712 if (kill.af != resp[1]->ai_family) 713 continue; 714 715 if (memcmp(&last_dst, resp[1]->ai_addr, 716 sizeof(last_dst)) == 0) 717 continue; 718 last_dst = *(struct sockaddr *)resp[1]->ai_addr; 719 720 dests++; 721 722 if (kill.af == AF_INET) 723 kill.dst.addr.v.a.addr.v4 = 724 ((struct sockaddr_in *)resp[1]-> 725 ai_addr)->sin_addr; 726 else if (kill.af == AF_INET6) 727 kill.dst.addr.v.a.addr.v6 = 728 ((struct sockaddr_in6 *)resp[1]-> 729 ai_addr)->sin6_addr; 730 else 731 errx(1, "Unknown address family %d", 732 kill.af); 733 734 if (pfctl_kill_states(dev, &kill, &newkilled)) 735 err(1, "DIOCKILLSTATES"); 736 killed += newkilled; 737 } 738 freeaddrinfo(res[1]); 739 } else { 740 if (pfctl_kill_states(dev, &kill, &newkilled)) 741 err(1, "DIOCKILLSTATES"); 742 killed += newkilled; 743 } 744 } 745 746 freeaddrinfo(res[0]); 747 748 if ((opts & PF_OPT_QUIET) == 0) 749 fprintf(stderr, "killed %d states from %d sources and %d " 750 "destinations\n", killed, sources, dests); 751 return (0); 752 } 753 754 int 755 pfctl_gateway_kill_states(int dev, const char *iface, int opts) 756 { 757 struct pfctl_kill kill; 758 struct addrinfo *res, *resp; 759 struct sockaddr last_src; 760 unsigned int newkilled; 761 int killed = 0; 762 int ret_ga; 763 764 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 765 warnx("no gateway specified"); 766 usage(); 767 } 768 769 memset(&kill, 0, sizeof(kill)); 770 memset(&kill.rt_addr.addr.v.a.mask, 0xff, 771 sizeof(kill.rt_addr.addr.v.a.mask)); 772 memset(&last_src, 0xff, sizeof(last_src)); 773 if (iface != NULL && strlcpy(kill.ifname, iface, 774 sizeof(kill.ifname)) >= sizeof(kill.ifname)) 775 errx(1, "invalid interface: %s", iface); 776 777 if (opts & PF_OPT_KILLMATCH) 778 kill.kill_match = true; 779 780 pfctl_addrprefix(state_kill[1], &kill.rt_addr.addr.v.a.mask); 781 782 if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, &res))) { 783 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 784 /* NOTREACHED */ 785 } 786 for (resp = res; resp; resp = resp->ai_next) { 787 if (resp->ai_addr == NULL) 788 continue; 789 /* We get lots of duplicates. Catch the easy ones */ 790 if (memcmp(&last_src, resp->ai_addr, sizeof(last_src)) == 0) 791 continue; 792 last_src = *(struct sockaddr *)resp->ai_addr; 793 794 kill.af = resp->ai_family; 795 796 if (kill.af == AF_INET) 797 kill.rt_addr.addr.v.a.addr.v4 = 798 ((struct sockaddr_in *)resp->ai_addr)->sin_addr; 799 else if (kill.af == AF_INET6) 800 kill.rt_addr.addr.v.a.addr.v6 = 801 ((struct sockaddr_in6 *)resp->ai_addr)-> 802 sin6_addr; 803 else 804 errx(1, "Unknown address family %d", kill.af); 805 806 if (pfctl_kill_states(dev, &kill, &newkilled)) 807 err(1, "DIOCKILLSTATES"); 808 killed += newkilled; 809 } 810 811 freeaddrinfo(res); 812 813 if ((opts & PF_OPT_QUIET) == 0) 814 fprintf(stderr, "killed %d states\n", killed); 815 return (0); 816 } 817 818 int 819 pfctl_label_kill_states(int dev, const char *iface, int opts) 820 { 821 struct pfctl_kill kill; 822 unsigned int killed; 823 824 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 825 warnx("no label specified"); 826 usage(); 827 } 828 memset(&kill, 0, sizeof(kill)); 829 if (iface != NULL && strlcpy(kill.ifname, iface, 830 sizeof(kill.ifname)) >= sizeof(kill.ifname)) 831 errx(1, "invalid interface: %s", iface); 832 833 if (opts & PF_OPT_KILLMATCH) 834 kill.kill_match = true; 835 836 if (strlcpy(kill.label, state_kill[1], sizeof(kill.label)) >= 837 sizeof(kill.label)) 838 errx(1, "label too long: %s", state_kill[1]); 839 840 if (pfctl_kill_states(dev, &kill, &killed)) 841 err(1, "DIOCKILLSTATES"); 842 843 if ((opts & PF_OPT_QUIET) == 0) 844 fprintf(stderr, "killed %d states\n", killed); 845 846 return (0); 847 } 848 849 int 850 pfctl_id_kill_states(int dev, const char *iface, int opts) 851 { 852 struct pfctl_kill kill; 853 unsigned int killed; 854 855 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 856 warnx("no id specified"); 857 usage(); 858 } 859 860 memset(&kill, 0, sizeof(kill)); 861 862 if (opts & PF_OPT_KILLMATCH) 863 kill.kill_match = true; 864 865 if ((sscanf(state_kill[1], "%jx/%x", 866 &kill.cmp.id, &kill.cmp.creatorid)) == 2) 867 HTONL(kill.cmp.creatorid); 868 else if ((sscanf(state_kill[1], "%jx", &kill.cmp.id)) == 1) { 869 kill.cmp.creatorid = 0; 870 } else { 871 warnx("wrong id format specified"); 872 usage(); 873 } 874 if (kill.cmp.id == 0) { 875 warnx("cannot kill id 0"); 876 usage(); 877 } 878 879 kill.cmp.id = htobe64(kill.cmp.id); 880 if (pfctl_kill_states(dev, &kill, &killed)) 881 err(1, "DIOCKILLSTATES"); 882 883 if ((opts & PF_OPT_QUIET) == 0) 884 fprintf(stderr, "killed %d states\n", killed); 885 886 return (0); 887 } 888 889 int 890 pfctl_get_pool(int dev, struct pfctl_pool *pool, u_int32_t nr, 891 u_int32_t ticket, int r_action, char *anchorname) 892 { 893 struct pfioc_pooladdr pp; 894 struct pf_pooladdr *pa; 895 u_int32_t pnr, mpnr; 896 897 memset(&pp, 0, sizeof(pp)); 898 memcpy(pp.anchor, anchorname, sizeof(pp.anchor)); 899 pp.r_action = r_action; 900 pp.r_num = nr; 901 pp.ticket = ticket; 902 if (ioctl(dev, DIOCGETADDRS, &pp)) { 903 warn("DIOCGETADDRS"); 904 return (-1); 905 } 906 mpnr = pp.nr; 907 TAILQ_INIT(&pool->list); 908 for (pnr = 0; pnr < mpnr; ++pnr) { 909 pp.nr = pnr; 910 if (ioctl(dev, DIOCGETADDR, &pp)) { 911 warn("DIOCGETADDR"); 912 return (-1); 913 } 914 pa = calloc(1, sizeof(struct pf_pooladdr)); 915 if (pa == NULL) 916 err(1, "calloc"); 917 bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr)); 918 TAILQ_INSERT_TAIL(&pool->list, pa, entries); 919 } 920 921 return (0); 922 } 923 924 void 925 pfctl_move_pool(struct pfctl_pool *src, struct pfctl_pool *dst) 926 { 927 struct pf_pooladdr *pa; 928 929 while ((pa = TAILQ_FIRST(&src->list)) != NULL) { 930 TAILQ_REMOVE(&src->list, pa, entries); 931 TAILQ_INSERT_TAIL(&dst->list, pa, entries); 932 } 933 } 934 935 void 936 pfctl_clear_pool(struct pfctl_pool *pool) 937 { 938 struct pf_pooladdr *pa; 939 940 while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { 941 TAILQ_REMOVE(&pool->list, pa, entries); 942 free(pa); 943 } 944 } 945 946 void 947 pfctl_print_rule_counters(struct pfctl_rule *rule, int opts) 948 { 949 if (opts & PF_OPT_DEBUG) { 950 const char *t[PF_SKIP_COUNT] = { "i", "d", "f", 951 "p", "sa", "sp", "da", "dp" }; 952 int i; 953 954 printf(" [ Skip steps: "); 955 for (i = 0; i < PF_SKIP_COUNT; ++i) { 956 if (rule->skip[i].nr == rule->nr + 1) 957 continue; 958 printf("%s=", t[i]); 959 if (rule->skip[i].nr == -1) 960 printf("end "); 961 else 962 printf("%u ", rule->skip[i].nr); 963 } 964 printf("]\n"); 965 966 printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n", 967 rule->qname, rule->qid, rule->pqname, rule->pqid); 968 } 969 if (opts & PF_OPT_VERBOSE) { 970 printf(" [ Evaluations: %-8llu Packets: %-8llu " 971 "Bytes: %-10llu States: %-6ju]\n", 972 (unsigned long long)rule->evaluations, 973 (unsigned long long)(rule->packets[0] + 974 rule->packets[1]), 975 (unsigned long long)(rule->bytes[0] + 976 rule->bytes[1]), (uintmax_t)rule->states_cur); 977 if (!(opts & PF_OPT_DEBUG)) 978 printf(" [ Inserted: uid %u pid %u " 979 "State Creations: %-6ju]\n", 980 (unsigned)rule->cuid, (unsigned)rule->cpid, 981 (uintmax_t)rule->states_tot); 982 } 983 } 984 985 void 986 pfctl_print_title(char *title) 987 { 988 if (!first_title) 989 printf("\n"); 990 first_title = 0; 991 printf("%s\n", title); 992 } 993 994 int 995 pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, 996 char *anchorname, int depth) 997 { 998 struct pfioc_rule pr; 999 struct pfctl_rule rule; 1000 u_int32_t nr, mnr, header = 0; 1001 int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); 1002 int numeric = opts & PF_OPT_NUMERIC; 1003 int len = strlen(path); 1004 int brace; 1005 char *p; 1006 1007 if (path[0]) 1008 snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 1009 else 1010 snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 1011 1012 memset(&pr, 0, sizeof(pr)); 1013 memcpy(pr.anchor, path, sizeof(pr.anchor)); 1014 if (opts & PF_OPT_SHOWALL) { 1015 pr.rule.action = PF_PASS; 1016 if (ioctl(dev, DIOCGETRULES, &pr)) { 1017 warn("DIOCGETRULES"); 1018 goto error; 1019 } 1020 header++; 1021 } 1022 pr.rule.action = PF_SCRUB; 1023 if (ioctl(dev, DIOCGETRULES, &pr)) { 1024 warn("DIOCGETRULES"); 1025 goto error; 1026 } 1027 if (opts & PF_OPT_SHOWALL) { 1028 if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header)) 1029 pfctl_print_title("FILTER RULES:"); 1030 else if (format == PFCTL_SHOW_LABELS && labels) 1031 pfctl_print_title("LABEL COUNTERS:"); 1032 } 1033 mnr = pr.nr; 1034 1035 for (nr = 0; nr < mnr; ++nr) { 1036 pr.nr = nr; 1037 if (pfctl_get_clear_rule(dev, nr, pr.ticket, path, PF_SCRUB, 1038 &rule, pr.anchor_call, opts & PF_OPT_CLRRULECTRS)) { 1039 warn("DIOCGETRULENV"); 1040 goto error; 1041 } 1042 1043 if (pfctl_get_pool(dev, &rule.rpool, 1044 nr, pr.ticket, PF_SCRUB, path) != 0) 1045 goto error; 1046 1047 switch (format) { 1048 case PFCTL_SHOW_LABELS: 1049 break; 1050 case PFCTL_SHOW_RULES: 1051 if (rule.label[0] && (opts & PF_OPT_SHOWALL)) 1052 labels = 1; 1053 print_rule(&rule, pr.anchor_call, rule_numbers, numeric); 1054 printf("\n"); 1055 pfctl_print_rule_counters(&rule, opts); 1056 break; 1057 case PFCTL_SHOW_NOTHING: 1058 break; 1059 } 1060 pfctl_clear_pool(&rule.rpool); 1061 } 1062 pr.rule.action = PF_PASS; 1063 if (ioctl(dev, DIOCGETRULES, &pr)) { 1064 warn("DIOCGETRULES"); 1065 goto error; 1066 } 1067 mnr = pr.nr; 1068 for (nr = 0; nr < mnr; ++nr) { 1069 pr.nr = nr; 1070 if (pfctl_get_clear_rule(dev, nr, pr.ticket, path, PF_PASS, 1071 &rule, pr.anchor_call, opts & PF_OPT_CLRRULECTRS)) { 1072 warn("DIOCGETRULE"); 1073 goto error; 1074 } 1075 1076 if (pfctl_get_pool(dev, &rule.rpool, 1077 nr, pr.ticket, PF_PASS, path) != 0) 1078 goto error; 1079 1080 switch (format) { 1081 case PFCTL_SHOW_LABELS: { 1082 bool show = false; 1083 int i = 0; 1084 1085 while (rule.label[i][0]) { 1086 printf("%s ", rule.label[i++]); 1087 show = true; 1088 } 1089 1090 if (show) { 1091 printf("%llu %llu %llu %llu" 1092 " %llu %llu %llu %ju\n", 1093 (unsigned long long)rule.evaluations, 1094 (unsigned long long)(rule.packets[0] + 1095 rule.packets[1]), 1096 (unsigned long long)(rule.bytes[0] + 1097 rule.bytes[1]), 1098 (unsigned long long)rule.packets[0], 1099 (unsigned long long)rule.bytes[0], 1100 (unsigned long long)rule.packets[1], 1101 (unsigned long long)rule.bytes[1], 1102 (uintmax_t)rule.states_tot); 1103 } 1104 break; 1105 } 1106 case PFCTL_SHOW_RULES: 1107 brace = 0; 1108 if (rule.label[0] && (opts & PF_OPT_SHOWALL)) 1109 labels = 1; 1110 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1111 if (pr.anchor_call[0] && 1112 ((((p = strrchr(pr.anchor_call, '_')) != NULL) && 1113 ((void *)p == (void *)pr.anchor_call || 1114 *(--p) == '/')) || (opts & PF_OPT_RECURSE))) { 1115 brace++; 1116 if ((p = strrchr(pr.anchor_call, '/')) != 1117 NULL) 1118 p++; 1119 else 1120 p = &pr.anchor_call[0]; 1121 } else 1122 p = &pr.anchor_call[0]; 1123 1124 print_rule(&rule, p, rule_numbers, numeric); 1125 if (brace) 1126 printf(" {\n"); 1127 else 1128 printf("\n"); 1129 pfctl_print_rule_counters(&rule, opts); 1130 if (brace) { 1131 pfctl_show_rules(dev, path, opts, format, 1132 p, depth + 1); 1133 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1134 printf("}\n"); 1135 } 1136 break; 1137 case PFCTL_SHOW_NOTHING: 1138 break; 1139 } 1140 pfctl_clear_pool(&rule.rpool); 1141 } 1142 path[len] = '\0'; 1143 return (0); 1144 1145 error: 1146 path[len] = '\0'; 1147 return (-1); 1148 } 1149 1150 int 1151 pfctl_show_nat(int dev, int opts, char *anchorname) 1152 { 1153 struct pfioc_rule pr; 1154 struct pfctl_rule rule; 1155 u_int32_t mnr, nr; 1156 static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; 1157 int i, dotitle = opts & PF_OPT_SHOWALL; 1158 1159 memset(&pr, 0, sizeof(pr)); 1160 memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 1161 for (i = 0; i < 3; i++) { 1162 pr.rule.action = nattype[i]; 1163 if (ioctl(dev, DIOCGETRULES, &pr)) { 1164 warn("DIOCGETRULES"); 1165 return (-1); 1166 } 1167 mnr = pr.nr; 1168 for (nr = 0; nr < mnr; ++nr) { 1169 pr.nr = nr; 1170 if (pfctl_get_rule(dev, nr, pr.ticket, anchorname, 1171 nattype[i], &rule, pr.anchor_call)) { 1172 warn("DIOCGETRULE"); 1173 return (-1); 1174 } 1175 if (pfctl_get_pool(dev, &rule.rpool, nr, 1176 pr.ticket, nattype[i], anchorname) != 0) 1177 return (-1); 1178 if (dotitle) { 1179 pfctl_print_title("TRANSLATION RULES:"); 1180 dotitle = 0; 1181 } 1182 print_rule(&rule, pr.anchor_call, 1183 opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC); 1184 printf("\n"); 1185 pfctl_print_rule_counters(&rule, opts); 1186 pfctl_clear_pool(&rule.rpool); 1187 } 1188 } 1189 return (0); 1190 } 1191 1192 int 1193 pfctl_show_src_nodes(int dev, int opts) 1194 { 1195 struct pfioc_src_nodes psn; 1196 struct pf_src_node *p; 1197 char *inbuf = NULL, *newinbuf = NULL; 1198 unsigned int len = 0; 1199 int i; 1200 1201 memset(&psn, 0, sizeof(psn)); 1202 for (;;) { 1203 psn.psn_len = len; 1204 if (len) { 1205 newinbuf = realloc(inbuf, len); 1206 if (newinbuf == NULL) 1207 err(1, "realloc"); 1208 psn.psn_buf = inbuf = newinbuf; 1209 } 1210 if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) { 1211 warn("DIOCGETSRCNODES"); 1212 free(inbuf); 1213 return (-1); 1214 } 1215 if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len) 1216 break; 1217 if (len == 0 && psn.psn_len == 0) 1218 goto done; 1219 if (len == 0 && psn.psn_len != 0) 1220 len = psn.psn_len; 1221 if (psn.psn_len == 0) 1222 goto done; /* no src_nodes */ 1223 len *= 2; 1224 } 1225 p = psn.psn_src_nodes; 1226 if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL)) 1227 pfctl_print_title("SOURCE TRACKING NODES:"); 1228 for (i = 0; i < psn.psn_len; i += sizeof(*p)) { 1229 print_src_node(p, opts); 1230 p++; 1231 } 1232 done: 1233 free(inbuf); 1234 return (0); 1235 } 1236 1237 int 1238 pfctl_show_states(int dev, const char *iface, int opts) 1239 { 1240 struct pfctl_states states; 1241 struct pfctl_state *s; 1242 int dotitle = (opts & PF_OPT_SHOWALL); 1243 1244 memset(&states, 0, sizeof(states)); 1245 1246 if (pfctl_get_states(dev, &states)) 1247 return (-1); 1248 1249 TAILQ_FOREACH(s, &states.states, entry) { 1250 if (iface != NULL && strcmp(s->ifname, iface)) 1251 continue; 1252 if (dotitle) { 1253 pfctl_print_title("STATES:"); 1254 dotitle = 0; 1255 } 1256 print_state(s, opts); 1257 } 1258 1259 pfctl_free_states(&states); 1260 1261 return (0); 1262 } 1263 1264 int 1265 pfctl_show_status(int dev, int opts) 1266 { 1267 struct pf_status status; 1268 1269 if (ioctl(dev, DIOCGETSTATUS, &status)) { 1270 warn("DIOCGETSTATUS"); 1271 return (-1); 1272 } 1273 if (opts & PF_OPT_SHOWALL) 1274 pfctl_print_title("INFO:"); 1275 print_status(&status, opts); 1276 return (0); 1277 } 1278 1279 int 1280 pfctl_show_running(int dev) 1281 { 1282 struct pf_status status; 1283 1284 if (ioctl(dev, DIOCGETSTATUS, &status)) { 1285 warn("DIOCGETSTATUS"); 1286 return (-1); 1287 } 1288 1289 print_running(&status); 1290 return (!status.running); 1291 } 1292 1293 int 1294 pfctl_show_timeouts(int dev, int opts) 1295 { 1296 struct pfioc_tm pt; 1297 int i; 1298 1299 if (opts & PF_OPT_SHOWALL) 1300 pfctl_print_title("TIMEOUTS:"); 1301 memset(&pt, 0, sizeof(pt)); 1302 for (i = 0; pf_timeouts[i].name; i++) { 1303 pt.timeout = pf_timeouts[i].timeout; 1304 if (ioctl(dev, DIOCGETTIMEOUT, &pt)) 1305 err(1, "DIOCGETTIMEOUT"); 1306 printf("%-20s %10d", pf_timeouts[i].name, pt.seconds); 1307 if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && 1308 pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) 1309 printf(" states"); 1310 else 1311 printf("s"); 1312 printf("\n"); 1313 } 1314 return (0); 1315 1316 } 1317 1318 int 1319 pfctl_show_limits(int dev, int opts) 1320 { 1321 struct pfioc_limit pl; 1322 int i; 1323 1324 if (opts & PF_OPT_SHOWALL) 1325 pfctl_print_title("LIMITS:"); 1326 memset(&pl, 0, sizeof(pl)); 1327 for (i = 0; pf_limits[i].name; i++) { 1328 pl.index = pf_limits[i].index; 1329 if (ioctl(dev, DIOCGETLIMIT, &pl)) 1330 err(1, "DIOCGETLIMIT"); 1331 printf("%-13s ", pf_limits[i].name); 1332 if (pl.limit == UINT_MAX) 1333 printf("unlimited\n"); 1334 else 1335 printf("hard limit %8u\n", pl.limit); 1336 } 1337 return (0); 1338 } 1339 1340 /* callbacks for rule/nat/rdr/addr */ 1341 int 1342 pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af) 1343 { 1344 struct pf_pooladdr *pa; 1345 1346 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1347 if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) 1348 err(1, "DIOCBEGINADDRS"); 1349 } 1350 1351 pf->paddr.af = af; 1352 TAILQ_FOREACH(pa, &p->list, entries) { 1353 memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr)); 1354 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1355 if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) 1356 err(1, "DIOCADDADDR"); 1357 } 1358 } 1359 return (0); 1360 } 1361 1362 int 1363 pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r, 1364 const char *anchor_call) 1365 { 1366 u_int8_t rs_num; 1367 struct pfctl_rule *rule; 1368 struct pfctl_ruleset *rs; 1369 char *p; 1370 1371 rs_num = pf_get_ruleset_number(r->action); 1372 if (rs_num == PF_RULESET_MAX) 1373 errx(1, "Invalid rule type %d", r->action); 1374 1375 rs = &pf->anchor->ruleset; 1376 1377 if (anchor_call[0] && r->anchor == NULL) { 1378 /* 1379 * Don't make non-brace anchors part of the main anchor pool. 1380 */ 1381 if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 1382 err(1, "pfctl_append_rule: calloc"); 1383 1384 pf_init_ruleset(&r->anchor->ruleset); 1385 r->anchor->ruleset.anchor = r->anchor; 1386 if (strlcpy(r->anchor->path, anchor_call, 1387 sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 1388 errx(1, "pfctl_append_rule: strlcpy"); 1389 if ((p = strrchr(anchor_call, '/')) != NULL) { 1390 if (!strlen(p)) 1391 err(1, "pfctl_append_rule: bad anchor name %s", 1392 anchor_call); 1393 } else 1394 p = (char *)anchor_call; 1395 if (strlcpy(r->anchor->name, p, 1396 sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 1397 errx(1, "pfctl_append_rule: strlcpy"); 1398 } 1399 1400 if ((rule = calloc(1, sizeof(*rule))) == NULL) 1401 err(1, "calloc"); 1402 bcopy(r, rule, sizeof(*rule)); 1403 TAILQ_INIT(&rule->rpool.list); 1404 pfctl_move_pool(&r->rpool, &rule->rpool); 1405 1406 TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries); 1407 return (0); 1408 } 1409 1410 int 1411 pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pfctl_anchor *a) 1412 { 1413 int osize = pf->trans->pfrb_size; 1414 1415 if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { 1416 if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || 1417 pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || 1418 pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) 1419 return (1); 1420 } 1421 if (a == pf->astack[0] && ((altqsupport && 1422 (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) { 1423 if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path)) 1424 return (2); 1425 } 1426 if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) { 1427 if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) || 1428 pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path)) 1429 return (3); 1430 } 1431 if (pf->loadopt & PFCTL_FLAG_TABLE) 1432 if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path)) 1433 return (4); 1434 if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1435 return (5); 1436 1437 return (0); 1438 } 1439 1440 int 1441 pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs, 1442 int rs_num, int depth) 1443 { 1444 struct pfctl_rule *r; 1445 int error, len = strlen(path); 1446 int brace = 0; 1447 1448 pf->anchor = rs->anchor; 1449 1450 if (path[0]) 1451 snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name); 1452 else 1453 snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name); 1454 1455 if (depth) { 1456 if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) { 1457 brace++; 1458 if (pf->opts & PF_OPT_VERBOSE) 1459 printf(" {\n"); 1460 if ((pf->opts & PF_OPT_NOACTION) == 0 && 1461 (error = pfctl_ruleset_trans(pf, 1462 path, rs->anchor))) { 1463 printf("pfctl_load_rulesets: " 1464 "pfctl_ruleset_trans %d\n", error); 1465 goto error; 1466 } 1467 } else if (pf->opts & PF_OPT_VERBOSE) 1468 printf("\n"); 1469 1470 } 1471 1472 if (pf->optimize && rs_num == PF_RULESET_FILTER) 1473 pfctl_optimize_ruleset(pf, rs); 1474 1475 while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) { 1476 TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries); 1477 if ((error = pfctl_load_rule(pf, path, r, depth))) 1478 goto error; 1479 if (r->anchor) { 1480 if ((error = pfctl_load_ruleset(pf, path, 1481 &r->anchor->ruleset, rs_num, depth + 1))) 1482 goto error; 1483 } else if (pf->opts & PF_OPT_VERBOSE) 1484 printf("\n"); 1485 free(r); 1486 } 1487 if (brace && pf->opts & PF_OPT_VERBOSE) { 1488 INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1489 printf("}\n"); 1490 } 1491 path[len] = '\0'; 1492 return (0); 1493 1494 error: 1495 path[len] = '\0'; 1496 return (error); 1497 1498 } 1499 1500 int 1501 pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth) 1502 { 1503 u_int8_t rs_num = pf_get_ruleset_number(r->action); 1504 char *name; 1505 u_int32_t ticket; 1506 char anchor[PF_ANCHOR_NAME_SIZE]; 1507 int len = strlen(path); 1508 1509 /* set up anchor before adding to path for anchor_call */ 1510 if ((pf->opts & PF_OPT_NOACTION) == 0) 1511 ticket = pfctl_get_ticket(pf->trans, rs_num, path); 1512 if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor)) 1513 errx(1, "pfctl_load_rule: strlcpy"); 1514 1515 if (r->anchor) { 1516 if (r->anchor->match) { 1517 if (path[0]) 1518 snprintf(&path[len], MAXPATHLEN - len, 1519 "/%s", r->anchor->name); 1520 else 1521 snprintf(&path[len], MAXPATHLEN - len, 1522 "%s", r->anchor->name); 1523 name = r->anchor->name; 1524 } else 1525 name = r->anchor->path; 1526 } else 1527 name = ""; 1528 1529 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1530 if (pfctl_add_pool(pf, &r->rpool, r->af)) 1531 return (1); 1532 if (pfctl_add_rule(pf->dev, r, anchor, name, ticket, 1533 pf->paddr.ticket)) 1534 err(1, "DIOCADDRULENV"); 1535 } 1536 1537 if (pf->opts & PF_OPT_VERBOSE) { 1538 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 1539 print_rule(r, r->anchor ? r->anchor->name : "", 1540 pf->opts & PF_OPT_VERBOSE2, 1541 pf->opts & PF_OPT_NUMERIC); 1542 } 1543 path[len] = '\0'; 1544 pfctl_clear_pool(&r->rpool); 1545 return (0); 1546 } 1547 1548 int 1549 pfctl_add_altq(struct pfctl *pf, struct pf_altq *a) 1550 { 1551 if (altqsupport && 1552 (loadopt & PFCTL_FLAG_ALTQ) != 0) { 1553 memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq)); 1554 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1555 if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) { 1556 if (errno == ENXIO) 1557 errx(1, "qtype not configured"); 1558 else if (errno == ENODEV) 1559 errx(1, "%s: driver does not support " 1560 "altq", a->ifname); 1561 else 1562 err(1, "DIOCADDALTQ"); 1563 } 1564 } 1565 pfaltq_store(&pf->paltq->altq); 1566 } 1567 return (0); 1568 } 1569 1570 int 1571 pfctl_rules(int dev, char *filename, int opts, int optimize, 1572 char *anchorname, struct pfr_buffer *trans) 1573 { 1574 #define ERR(x) do { warn(x); goto _error; } while(0) 1575 #define ERRX(x) do { warnx(x); goto _error; } while(0) 1576 1577 struct pfr_buffer *t, buf; 1578 struct pfioc_altq pa; 1579 struct pfctl pf; 1580 struct pfctl_ruleset *rs; 1581 struct pfr_table trs; 1582 char *path; 1583 int osize; 1584 1585 RB_INIT(&pf_anchors); 1586 memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); 1587 pf_init_ruleset(&pf_main_anchor.ruleset); 1588 pf_main_anchor.ruleset.anchor = &pf_main_anchor; 1589 if (trans == NULL) { 1590 bzero(&buf, sizeof(buf)); 1591 buf.pfrb_type = PFRB_TRANS; 1592 t = &buf; 1593 osize = 0; 1594 } else { 1595 t = trans; 1596 osize = t->pfrb_size; 1597 } 1598 1599 memset(&pa, 0, sizeof(pa)); 1600 pa.version = PFIOC_ALTQ_VERSION; 1601 memset(&pf, 0, sizeof(pf)); 1602 memset(&trs, 0, sizeof(trs)); 1603 if ((path = calloc(1, MAXPATHLEN)) == NULL) 1604 ERRX("pfctl_rules: calloc"); 1605 if (strlcpy(trs.pfrt_anchor, anchorname, 1606 sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) 1607 ERRX("pfctl_rules: strlcpy"); 1608 pf.dev = dev; 1609 pf.opts = opts; 1610 pf.optimize = optimize; 1611 pf.loadopt = loadopt; 1612 1613 /* non-brace anchor, create without resolving the path */ 1614 if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) 1615 ERRX("pfctl_rules: calloc"); 1616 rs = &pf.anchor->ruleset; 1617 pf_init_ruleset(rs); 1618 rs->anchor = pf.anchor; 1619 if (strlcpy(pf.anchor->path, anchorname, 1620 sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 1621 errx(1, "pfctl_add_rule: strlcpy"); 1622 if (strlcpy(pf.anchor->name, anchorname, 1623 sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 1624 errx(1, "pfctl_add_rule: strlcpy"); 1625 1626 1627 pf.astack[0] = pf.anchor; 1628 pf.asd = 0; 1629 if (anchorname[0]) 1630 pf.loadopt &= ~PFCTL_FLAG_ALTQ; 1631 pf.paltq = &pa; 1632 pf.trans = t; 1633 pfctl_init_options(&pf); 1634 1635 if ((opts & PF_OPT_NOACTION) == 0) { 1636 /* 1637 * XXX For the time being we need to open transactions for 1638 * the main ruleset before parsing, because tables are still 1639 * loaded at parse time. 1640 */ 1641 if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor)) 1642 ERRX("pfctl_rules"); 1643 if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) 1644 pa.ticket = 1645 pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname); 1646 if (pf.loadopt & PFCTL_FLAG_TABLE) 1647 pf.astack[0]->ruleset.tticket = 1648 pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname); 1649 } 1650 1651 if (parse_config(filename, &pf) < 0) { 1652 if ((opts & PF_OPT_NOACTION) == 0) 1653 ERRX("Syntax error in config file: " 1654 "pf rules not loaded"); 1655 else 1656 goto _error; 1657 } 1658 if (loadopt & PFCTL_FLAG_OPTION) 1659 pfctl_adjust_skip_ifaces(&pf); 1660 1661 if ((pf.loadopt & PFCTL_FLAG_FILTER && 1662 (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) || 1663 (pf.loadopt & PFCTL_FLAG_NAT && 1664 (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) || 1665 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) || 1666 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) || 1667 (pf.loadopt & PFCTL_FLAG_FILTER && 1668 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) { 1669 if ((opts & PF_OPT_NOACTION) == 0) 1670 ERRX("Unable to load rules into kernel"); 1671 else 1672 goto _error; 1673 } 1674 1675 if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0)) 1676 if (check_commit_altq(dev, opts) != 0) 1677 ERRX("errors in altq config"); 1678 1679 /* process "load anchor" directives */ 1680 if (!anchorname[0]) 1681 if (pfctl_load_anchors(dev, &pf, t) == -1) 1682 ERRX("load anchors"); 1683 1684 if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) { 1685 if (!anchorname[0]) 1686 if (pfctl_load_options(&pf)) 1687 goto _error; 1688 if (pfctl_trans(dev, t, DIOCXCOMMIT, osize)) 1689 ERR("DIOCXCOMMIT"); 1690 } 1691 free(path); 1692 return (0); 1693 1694 _error: 1695 if (trans == NULL) { /* main ruleset */ 1696 if ((opts & PF_OPT_NOACTION) == 0) 1697 if (pfctl_trans(dev, t, DIOCXROLLBACK, osize)) 1698 err(1, "DIOCXROLLBACK"); 1699 exit(1); 1700 } else { /* sub ruleset */ 1701 free(path); 1702 return (-1); 1703 } 1704 1705 #undef ERR 1706 #undef ERRX 1707 } 1708 1709 FILE * 1710 pfctl_fopen(const char *name, const char *mode) 1711 { 1712 struct stat st; 1713 FILE *fp; 1714 1715 fp = fopen(name, mode); 1716 if (fp == NULL) 1717 return (NULL); 1718 if (fstat(fileno(fp), &st)) { 1719 fclose(fp); 1720 return (NULL); 1721 } 1722 if (S_ISDIR(st.st_mode)) { 1723 fclose(fp); 1724 errno = EISDIR; 1725 return (NULL); 1726 } 1727 return (fp); 1728 } 1729 1730 void 1731 pfctl_init_options(struct pfctl *pf) 1732 { 1733 1734 pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 1735 pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; 1736 pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 1737 pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; 1738 pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; 1739 pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; 1740 pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; 1741 pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; 1742 pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; 1743 pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; 1744 pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; 1745 pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; 1746 pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; 1747 pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; 1748 pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; 1749 pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; 1750 pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; 1751 pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; 1752 pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; 1753 pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; 1754 1755 pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; 1756 pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT; 1757 pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; 1758 pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; 1759 1760 pf->debug = PF_DEBUG_URGENT; 1761 } 1762 1763 int 1764 pfctl_load_options(struct pfctl *pf) 1765 { 1766 int i, error = 0; 1767 1768 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1769 return (0); 1770 1771 /* load limits */ 1772 for (i = 0; i < PF_LIMIT_MAX; i++) { 1773 if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i]) 1774 continue; 1775 if (pfctl_load_limit(pf, i, pf->limit[i])) 1776 error = 1; 1777 } 1778 1779 /* 1780 * If we've set the limit, but haven't explicitly set adaptive 1781 * timeouts, do it now with a start of 60% and end of 120%. 1782 */ 1783 if (pf->limit_set[PF_LIMIT_STATES] && 1784 !pf->timeout_set[PFTM_ADAPTIVE_START] && 1785 !pf->timeout_set[PFTM_ADAPTIVE_END]) { 1786 pf->timeout[PFTM_ADAPTIVE_START] = 1787 (pf->limit[PF_LIMIT_STATES] / 10) * 6; 1788 pf->timeout_set[PFTM_ADAPTIVE_START] = 1; 1789 pf->timeout[PFTM_ADAPTIVE_END] = 1790 (pf->limit[PF_LIMIT_STATES] / 10) * 12; 1791 pf->timeout_set[PFTM_ADAPTIVE_END] = 1; 1792 } 1793 1794 /* load timeouts */ 1795 for (i = 0; i < PFTM_MAX; i++) { 1796 if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i]) 1797 continue; 1798 if (pfctl_load_timeout(pf, i, pf->timeout[i])) 1799 error = 1; 1800 } 1801 1802 /* load debug */ 1803 if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set) 1804 if (pfctl_load_debug(pf, pf->debug)) 1805 error = 1; 1806 1807 /* load logif */ 1808 if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set) 1809 if (pfctl_load_logif(pf, pf->ifname)) 1810 error = 1; 1811 1812 /* load hostid */ 1813 if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set) 1814 if (pfctl_load_hostid(pf, pf->hostid)) 1815 error = 1; 1816 1817 /* load keepcounters */ 1818 if (pfctl_set_keepcounters(pf->dev, pf->keep_counters)) 1819 error = 1; 1820 1821 return (error); 1822 } 1823 1824 int 1825 pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) 1826 { 1827 int i; 1828 1829 1830 for (i = 0; pf_limits[i].name; i++) { 1831 if (strcasecmp(opt, pf_limits[i].name) == 0) { 1832 pf->limit[pf_limits[i].index] = limit; 1833 pf->limit_set[pf_limits[i].index] = 1; 1834 break; 1835 } 1836 } 1837 if (pf_limits[i].name == NULL) { 1838 warnx("Bad pool name."); 1839 return (1); 1840 } 1841 1842 if (pf->opts & PF_OPT_VERBOSE) 1843 printf("set limit %s %d\n", opt, limit); 1844 1845 return (0); 1846 } 1847 1848 int 1849 pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) 1850 { 1851 struct pfioc_limit pl; 1852 1853 memset(&pl, 0, sizeof(pl)); 1854 pl.index = index; 1855 pl.limit = limit; 1856 if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) { 1857 if (errno == EBUSY) 1858 warnx("Current pool size exceeds requested hard limit"); 1859 else 1860 warnx("DIOCSETLIMIT"); 1861 return (1); 1862 } 1863 return (0); 1864 } 1865 1866 int 1867 pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 1868 { 1869 int i; 1870 1871 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1872 return (0); 1873 1874 for (i = 0; pf_timeouts[i].name; i++) { 1875 if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 1876 pf->timeout[pf_timeouts[i].timeout] = seconds; 1877 pf->timeout_set[pf_timeouts[i].timeout] = 1; 1878 break; 1879 } 1880 } 1881 1882 if (pf_timeouts[i].name == NULL) { 1883 warnx("Bad timeout name."); 1884 return (1); 1885 } 1886 1887 1888 if (pf->opts & PF_OPT_VERBOSE && ! quiet) 1889 printf("set timeout %s %d\n", opt, seconds); 1890 1891 return (0); 1892 } 1893 1894 int 1895 pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) 1896 { 1897 struct pfioc_tm pt; 1898 1899 memset(&pt, 0, sizeof(pt)); 1900 pt.timeout = timeout; 1901 pt.seconds = seconds; 1902 if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) { 1903 warnx("DIOCSETTIMEOUT"); 1904 return (1); 1905 } 1906 return (0); 1907 } 1908 1909 int 1910 pfctl_set_optimization(struct pfctl *pf, const char *opt) 1911 { 1912 const struct pf_hint *hint; 1913 int i, r; 1914 1915 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1916 return (0); 1917 1918 for (i = 0; pf_hints[i].name; i++) 1919 if (strcasecmp(opt, pf_hints[i].name) == 0) 1920 break; 1921 1922 hint = pf_hints[i].hint; 1923 if (hint == NULL) { 1924 warnx("invalid state timeouts optimization"); 1925 return (1); 1926 } 1927 1928 for (i = 0; hint[i].name; i++) 1929 if ((r = pfctl_set_timeout(pf, hint[i].name, 1930 hint[i].timeout, 1))) 1931 return (r); 1932 1933 if (pf->opts & PF_OPT_VERBOSE) 1934 printf("set optimization %s\n", opt); 1935 1936 return (0); 1937 } 1938 1939 int 1940 pfctl_set_logif(struct pfctl *pf, char *ifname) 1941 { 1942 1943 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1944 return (0); 1945 1946 if (!strcmp(ifname, "none")) { 1947 free(pf->ifname); 1948 pf->ifname = NULL; 1949 } else { 1950 pf->ifname = strdup(ifname); 1951 if (!pf->ifname) 1952 errx(1, "pfctl_set_logif: strdup"); 1953 } 1954 pf->ifname_set = 1; 1955 1956 if (pf->opts & PF_OPT_VERBOSE) 1957 printf("set loginterface %s\n", ifname); 1958 1959 return (0); 1960 } 1961 1962 int 1963 pfctl_load_logif(struct pfctl *pf, char *ifname) 1964 { 1965 struct pfioc_if pi; 1966 1967 memset(&pi, 0, sizeof(pi)); 1968 if (ifname && strlcpy(pi.ifname, ifname, 1969 sizeof(pi.ifname)) >= sizeof(pi.ifname)) { 1970 warnx("pfctl_load_logif: strlcpy"); 1971 return (1); 1972 } 1973 if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) { 1974 warnx("DIOCSETSTATUSIF"); 1975 return (1); 1976 } 1977 return (0); 1978 } 1979 1980 int 1981 pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 1982 { 1983 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1984 return (0); 1985 1986 HTONL(hostid); 1987 1988 pf->hostid = hostid; 1989 pf->hostid_set = 1; 1990 1991 if (pf->opts & PF_OPT_VERBOSE) 1992 printf("set hostid 0x%08x\n", ntohl(hostid)); 1993 1994 return (0); 1995 } 1996 1997 int 1998 pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) 1999 { 2000 if (ioctl(dev, DIOCSETHOSTID, &hostid)) { 2001 warnx("DIOCSETHOSTID"); 2002 return (1); 2003 } 2004 return (0); 2005 } 2006 2007 int 2008 pfctl_set_debug(struct pfctl *pf, char *d) 2009 { 2010 u_int32_t level; 2011 2012 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2013 return (0); 2014 2015 if (!strcmp(d, "none")) 2016 pf->debug = PF_DEBUG_NONE; 2017 else if (!strcmp(d, "urgent")) 2018 pf->debug = PF_DEBUG_URGENT; 2019 else if (!strcmp(d, "misc")) 2020 pf->debug = PF_DEBUG_MISC; 2021 else if (!strcmp(d, "loud")) 2022 pf->debug = PF_DEBUG_NOISY; 2023 else { 2024 warnx("unknown debug level \"%s\"", d); 2025 return (-1); 2026 } 2027 2028 pf->debug_set = 1; 2029 level = pf->debug; 2030 2031 if ((pf->opts & PF_OPT_NOACTION) == 0) 2032 if (ioctl(dev, DIOCSETDEBUG, &level)) 2033 err(1, "DIOCSETDEBUG"); 2034 2035 if (pf->opts & PF_OPT_VERBOSE) 2036 printf("set debug %s\n", d); 2037 2038 return (0); 2039 } 2040 2041 int 2042 pfctl_load_debug(struct pfctl *pf, unsigned int level) 2043 { 2044 if (ioctl(pf->dev, DIOCSETDEBUG, &level)) { 2045 warnx("DIOCSETDEBUG"); 2046 return (1); 2047 } 2048 return (0); 2049 } 2050 2051 int 2052 pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) 2053 { 2054 struct pfioc_iface pi; 2055 struct node_host *h = NULL, *n = NULL; 2056 2057 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2058 return (0); 2059 2060 bzero(&pi, sizeof(pi)); 2061 2062 pi.pfiio_flags = flags; 2063 2064 /* Make sure our cache matches the kernel. If we set or clear the flag 2065 * for a group this applies to all members. */ 2066 h = ifa_grouplookup(ifname, 0); 2067 for (n = h; n != NULL; n = n->next) 2068 pfctl_set_interface_flags(pf, n->ifname, flags, how); 2069 2070 if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= 2071 sizeof(pi.pfiio_name)) 2072 errx(1, "pfctl_set_interface_flags: strlcpy"); 2073 2074 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2075 if (how == 0) { 2076 if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi)) 2077 err(1, "DIOCCLRIFFLAG"); 2078 } else { 2079 if (ioctl(pf->dev, DIOCSETIFFLAG, &pi)) 2080 err(1, "DIOCSETIFFLAG"); 2081 pfctl_check_skip_ifaces(ifname); 2082 } 2083 } 2084 return (0); 2085 } 2086 2087 void 2088 pfctl_debug(int dev, u_int32_t level, int opts) 2089 { 2090 if (ioctl(dev, DIOCSETDEBUG, &level)) 2091 err(1, "DIOCSETDEBUG"); 2092 if ((opts & PF_OPT_QUIET) == 0) { 2093 fprintf(stderr, "debug level set to '"); 2094 switch (level) { 2095 case PF_DEBUG_NONE: 2096 fprintf(stderr, "none"); 2097 break; 2098 case PF_DEBUG_URGENT: 2099 fprintf(stderr, "urgent"); 2100 break; 2101 case PF_DEBUG_MISC: 2102 fprintf(stderr, "misc"); 2103 break; 2104 case PF_DEBUG_NOISY: 2105 fprintf(stderr, "loud"); 2106 break; 2107 default: 2108 fprintf(stderr, "<invalid>"); 2109 break; 2110 } 2111 fprintf(stderr, "'\n"); 2112 } 2113 } 2114 2115 int 2116 pfctl_test_altqsupport(int dev, int opts) 2117 { 2118 struct pfioc_altq pa; 2119 2120 pa.version = PFIOC_ALTQ_VERSION; 2121 if (ioctl(dev, DIOCGETALTQS, &pa)) { 2122 if (errno == ENODEV) { 2123 if (opts & PF_OPT_VERBOSE) 2124 fprintf(stderr, "No ALTQ support in kernel\n" 2125 "ALTQ related functions disabled\n"); 2126 return (0); 2127 } else 2128 err(1, "DIOCGETALTQS"); 2129 } 2130 return (1); 2131 } 2132 2133 int 2134 pfctl_show_anchors(int dev, int opts, char *anchorname) 2135 { 2136 struct pfioc_ruleset pr; 2137 u_int32_t mnr, nr; 2138 2139 memset(&pr, 0, sizeof(pr)); 2140 memcpy(pr.path, anchorname, sizeof(pr.path)); 2141 if (ioctl(dev, DIOCGETRULESETS, &pr)) { 2142 if (errno == EINVAL) 2143 fprintf(stderr, "Anchor '%s' not found.\n", 2144 anchorname); 2145 else 2146 err(1, "DIOCGETRULESETS"); 2147 return (-1); 2148 } 2149 mnr = pr.nr; 2150 for (nr = 0; nr < mnr; ++nr) { 2151 char sub[MAXPATHLEN]; 2152 2153 pr.nr = nr; 2154 if (ioctl(dev, DIOCGETRULESET, &pr)) 2155 err(1, "DIOCGETRULESET"); 2156 if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) 2157 continue; 2158 sub[0] = 0; 2159 if (pr.path[0]) { 2160 strlcat(sub, pr.path, sizeof(sub)); 2161 strlcat(sub, "/", sizeof(sub)); 2162 } 2163 strlcat(sub, pr.name, sizeof(sub)); 2164 if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 2165 printf(" %s\n", sub); 2166 if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub)) 2167 return (-1); 2168 } 2169 return (0); 2170 } 2171 2172 const char * 2173 pfctl_lookup_option(char *cmd, const char * const *list) 2174 { 2175 if (cmd != NULL && *cmd) 2176 for (; *list; list++) 2177 if (!strncmp(cmd, *list, strlen(cmd))) 2178 return (*list); 2179 return (NULL); 2180 } 2181 2182 int 2183 main(int argc, char *argv[]) 2184 { 2185 int error = 0; 2186 int ch; 2187 int mode = O_RDONLY; 2188 int opts = 0; 2189 int optimize = PF_OPTIMIZE_BASIC; 2190 char anchorname[MAXPATHLEN]; 2191 char *path; 2192 2193 if (argc < 2) 2194 usage(); 2195 2196 while ((ch = getopt(argc, argv, 2197 "a:AdD:eqf:F:ghi:k:K:mMnNOo:Pp:rRs:t:T:vx:z")) != -1) { 2198 switch (ch) { 2199 case 'a': 2200 anchoropt = optarg; 2201 break; 2202 case 'd': 2203 opts |= PF_OPT_DISABLE; 2204 mode = O_RDWR; 2205 break; 2206 case 'D': 2207 if (pfctl_cmdline_symset(optarg) < 0) 2208 warnx("could not parse macro definition %s", 2209 optarg); 2210 break; 2211 case 'e': 2212 opts |= PF_OPT_ENABLE; 2213 mode = O_RDWR; 2214 break; 2215 case 'q': 2216 opts |= PF_OPT_QUIET; 2217 break; 2218 case 'F': 2219 clearopt = pfctl_lookup_option(optarg, clearopt_list); 2220 if (clearopt == NULL) { 2221 warnx("Unknown flush modifier '%s'", optarg); 2222 usage(); 2223 } 2224 mode = O_RDWR; 2225 break; 2226 case 'i': 2227 ifaceopt = optarg; 2228 break; 2229 case 'k': 2230 if (state_killers >= 2) { 2231 warnx("can only specify -k twice"); 2232 usage(); 2233 /* NOTREACHED */ 2234 } 2235 state_kill[state_killers++] = optarg; 2236 mode = O_RDWR; 2237 break; 2238 case 'K': 2239 if (src_node_killers >= 2) { 2240 warnx("can only specify -K twice"); 2241 usage(); 2242 /* NOTREACHED */ 2243 } 2244 src_node_kill[src_node_killers++] = optarg; 2245 mode = O_RDWR; 2246 break; 2247 case 'm': 2248 opts |= PF_OPT_MERGE; 2249 break; 2250 case 'M': 2251 opts |= PF_OPT_KILLMATCH; 2252 break; 2253 case 'n': 2254 opts |= PF_OPT_NOACTION; 2255 break; 2256 case 'N': 2257 loadopt |= PFCTL_FLAG_NAT; 2258 break; 2259 case 'r': 2260 opts |= PF_OPT_USEDNS; 2261 break; 2262 case 'f': 2263 rulesopt = optarg; 2264 mode = O_RDWR; 2265 break; 2266 case 'g': 2267 opts |= PF_OPT_DEBUG; 2268 break; 2269 case 'A': 2270 loadopt |= PFCTL_FLAG_ALTQ; 2271 break; 2272 case 'R': 2273 loadopt |= PFCTL_FLAG_FILTER; 2274 break; 2275 case 'o': 2276 optiopt = pfctl_lookup_option(optarg, optiopt_list); 2277 if (optiopt == NULL) { 2278 warnx("Unknown optimization '%s'", optarg); 2279 usage(); 2280 } 2281 opts |= PF_OPT_OPTIMIZE; 2282 break; 2283 case 'O': 2284 loadopt |= PFCTL_FLAG_OPTION; 2285 break; 2286 case 'p': 2287 pf_device = optarg; 2288 break; 2289 case 'P': 2290 opts |= PF_OPT_NUMERIC; 2291 break; 2292 case 's': 2293 showopt = pfctl_lookup_option(optarg, showopt_list); 2294 if (showopt == NULL) { 2295 warnx("Unknown show modifier '%s'", optarg); 2296 usage(); 2297 } 2298 break; 2299 case 't': 2300 tableopt = optarg; 2301 break; 2302 case 'T': 2303 tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 2304 if (tblcmdopt == NULL) { 2305 warnx("Unknown table command '%s'", optarg); 2306 usage(); 2307 } 2308 break; 2309 case 'v': 2310 if (opts & PF_OPT_VERBOSE) 2311 opts |= PF_OPT_VERBOSE2; 2312 opts |= PF_OPT_VERBOSE; 2313 break; 2314 case 'x': 2315 debugopt = pfctl_lookup_option(optarg, debugopt_list); 2316 if (debugopt == NULL) { 2317 warnx("Unknown debug level '%s'", optarg); 2318 usage(); 2319 } 2320 mode = O_RDWR; 2321 break; 2322 case 'z': 2323 opts |= PF_OPT_CLRRULECTRS; 2324 mode = O_RDWR; 2325 break; 2326 case 'h': 2327 /* FALLTHROUGH */ 2328 default: 2329 usage(); 2330 /* NOTREACHED */ 2331 } 2332 } 2333 2334 if (tblcmdopt != NULL) { 2335 argc -= optind; 2336 argv += optind; 2337 ch = *tblcmdopt; 2338 if (ch == 'l') { 2339 loadopt |= PFCTL_FLAG_TABLE; 2340 tblcmdopt = NULL; 2341 } else 2342 mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY; 2343 } else if (argc != optind) { 2344 warnx("unknown command line argument: %s ...", argv[optind]); 2345 usage(); 2346 /* NOTREACHED */ 2347 } 2348 if (loadopt == 0) 2349 loadopt = ~0; 2350 2351 if ((path = calloc(1, MAXPATHLEN)) == NULL) 2352 errx(1, "pfctl: calloc"); 2353 memset(anchorname, 0, sizeof(anchorname)); 2354 if (anchoropt != NULL) { 2355 int len = strlen(anchoropt); 2356 2357 if (anchoropt[len - 1] == '*') { 2358 if (len >= 2 && anchoropt[len - 2] == '/') 2359 anchoropt[len - 2] = '\0'; 2360 else 2361 anchoropt[len - 1] = '\0'; 2362 opts |= PF_OPT_RECURSE; 2363 } 2364 if (strlcpy(anchorname, anchoropt, 2365 sizeof(anchorname)) >= sizeof(anchorname)) 2366 errx(1, "anchor name '%s' too long", 2367 anchoropt); 2368 loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE; 2369 } 2370 2371 if ((opts & PF_OPT_NOACTION) == 0) { 2372 dev = open(pf_device, mode); 2373 if (dev == -1) 2374 err(1, "%s", pf_device); 2375 altqsupport = pfctl_test_altqsupport(dev, opts); 2376 } else { 2377 dev = open(pf_device, O_RDONLY); 2378 if (dev >= 0) 2379 opts |= PF_OPT_DUMMYACTION; 2380 /* turn off options */ 2381 opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 2382 clearopt = showopt = debugopt = NULL; 2383 #if !defined(ENABLE_ALTQ) 2384 altqsupport = 0; 2385 #else 2386 altqsupport = 1; 2387 #endif 2388 } 2389 2390 if (opts & PF_OPT_DISABLE) 2391 if (pfctl_disable(dev, opts)) 2392 error = 1; 2393 2394 if (showopt != NULL) { 2395 switch (*showopt) { 2396 case 'A': 2397 pfctl_show_anchors(dev, opts, anchorname); 2398 break; 2399 case 'r': 2400 pfctl_load_fingerprints(dev, opts); 2401 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 2402 anchorname, 0); 2403 break; 2404 case 'l': 2405 pfctl_load_fingerprints(dev, opts); 2406 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 2407 anchorname, 0); 2408 break; 2409 case 'n': 2410 pfctl_load_fingerprints(dev, opts); 2411 pfctl_show_nat(dev, opts, anchorname); 2412 break; 2413 case 'q': 2414 pfctl_show_altq(dev, ifaceopt, opts, 2415 opts & PF_OPT_VERBOSE2); 2416 break; 2417 case 's': 2418 pfctl_show_states(dev, ifaceopt, opts); 2419 break; 2420 case 'S': 2421 pfctl_show_src_nodes(dev, opts); 2422 break; 2423 case 'i': 2424 pfctl_show_status(dev, opts); 2425 break; 2426 case 'R': 2427 error = pfctl_show_running(dev); 2428 break; 2429 case 't': 2430 pfctl_show_timeouts(dev, opts); 2431 break; 2432 case 'm': 2433 pfctl_show_limits(dev, opts); 2434 break; 2435 case 'a': 2436 opts |= PF_OPT_SHOWALL; 2437 pfctl_load_fingerprints(dev, opts); 2438 2439 pfctl_show_nat(dev, opts, anchorname); 2440 pfctl_show_rules(dev, path, opts, 0, anchorname, 0); 2441 pfctl_show_altq(dev, ifaceopt, opts, 0); 2442 pfctl_show_states(dev, ifaceopt, opts); 2443 pfctl_show_src_nodes(dev, opts); 2444 pfctl_show_status(dev, opts); 2445 pfctl_show_rules(dev, path, opts, 1, anchorname, 0); 2446 pfctl_show_timeouts(dev, opts); 2447 pfctl_show_limits(dev, opts); 2448 pfctl_show_tables(anchorname, opts); 2449 pfctl_show_fingerprints(opts); 2450 break; 2451 case 'T': 2452 pfctl_show_tables(anchorname, opts); 2453 break; 2454 case 'o': 2455 pfctl_load_fingerprints(dev, opts); 2456 pfctl_show_fingerprints(opts); 2457 break; 2458 case 'I': 2459 pfctl_show_ifaces(ifaceopt, opts); 2460 break; 2461 } 2462 } 2463 2464 if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) 2465 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 2466 anchorname, 0); 2467 2468 if (clearopt != NULL) { 2469 if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 2470 errx(1, "anchor names beginning with '_' cannot " 2471 "be modified from the command line"); 2472 2473 switch (*clearopt) { 2474 case 'r': 2475 pfctl_clear_rules(dev, opts, anchorname); 2476 break; 2477 case 'n': 2478 pfctl_clear_nat(dev, opts, anchorname); 2479 break; 2480 case 'q': 2481 pfctl_clear_altq(dev, opts); 2482 break; 2483 case 's': 2484 pfctl_clear_iface_states(dev, ifaceopt, opts); 2485 break; 2486 case 'S': 2487 pfctl_clear_src_nodes(dev, opts); 2488 break; 2489 case 'i': 2490 pfctl_clear_stats(dev, opts); 2491 break; 2492 case 'a': 2493 pfctl_clear_rules(dev, opts, anchorname); 2494 pfctl_clear_nat(dev, opts, anchorname); 2495 pfctl_clear_tables(anchorname, opts); 2496 if (!*anchorname) { 2497 pfctl_clear_altq(dev, opts); 2498 pfctl_clear_iface_states(dev, ifaceopt, opts); 2499 pfctl_clear_src_nodes(dev, opts); 2500 pfctl_clear_stats(dev, opts); 2501 pfctl_clear_fingerprints(dev, opts); 2502 pfctl_clear_interface_flags(dev, opts); 2503 } 2504 break; 2505 case 'o': 2506 pfctl_clear_fingerprints(dev, opts); 2507 break; 2508 case 'T': 2509 pfctl_clear_tables(anchorname, opts); 2510 break; 2511 } 2512 } 2513 if (state_killers) { 2514 if (!strcmp(state_kill[0], "label")) 2515 pfctl_label_kill_states(dev, ifaceopt, opts); 2516 else if (!strcmp(state_kill[0], "id")) 2517 pfctl_id_kill_states(dev, ifaceopt, opts); 2518 else if (!strcmp(state_kill[0], "gateway")) 2519 pfctl_gateway_kill_states(dev, ifaceopt, opts); 2520 else 2521 pfctl_net_kill_states(dev, ifaceopt, opts); 2522 } 2523 2524 if (src_node_killers) 2525 pfctl_kill_src_nodes(dev, ifaceopt, opts); 2526 2527 if (tblcmdopt != NULL) { 2528 error = pfctl_command_tables(argc, argv, tableopt, 2529 tblcmdopt, rulesopt, anchorname, opts); 2530 rulesopt = NULL; 2531 } 2532 if (optiopt != NULL) { 2533 switch (*optiopt) { 2534 case 'n': 2535 optimize = 0; 2536 break; 2537 case 'b': 2538 optimize |= PF_OPTIMIZE_BASIC; 2539 break; 2540 case 'o': 2541 case 'p': 2542 optimize |= PF_OPTIMIZE_PROFILE; 2543 break; 2544 } 2545 } 2546 2547 if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) && 2548 !anchorname[0] && !(opts & PF_OPT_NOACTION)) 2549 if (pfctl_get_skip_ifaces()) 2550 error = 1; 2551 2552 if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) && 2553 !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION)) 2554 if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 2555 error = 1; 2556 2557 if (rulesopt != NULL) { 2558 if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 2559 errx(1, "anchor names beginning with '_' cannot " 2560 "be modified from the command line"); 2561 if (pfctl_rules(dev, rulesopt, opts, optimize, 2562 anchorname, NULL)) 2563 error = 1; 2564 else if (!(opts & PF_OPT_NOACTION) && 2565 (loadopt & PFCTL_FLAG_TABLE)) 2566 warn_namespace_collision(NULL); 2567 } 2568 2569 if (opts & PF_OPT_ENABLE) 2570 if (pfctl_enable(dev, opts)) 2571 error = 1; 2572 2573 if (debugopt != NULL) { 2574 switch (*debugopt) { 2575 case 'n': 2576 pfctl_debug(dev, PF_DEBUG_NONE, opts); 2577 break; 2578 case 'u': 2579 pfctl_debug(dev, PF_DEBUG_URGENT, opts); 2580 break; 2581 case 'm': 2582 pfctl_debug(dev, PF_DEBUG_MISC, opts); 2583 break; 2584 case 'l': 2585 pfctl_debug(dev, PF_DEBUG_NOISY, opts); 2586 break; 2587 } 2588 } 2589 2590 exit(error); 2591 } 2592