1 /* $OpenBSD: pfctl.c,v 1.387 2022/07/21 05:26:10 mbuhl Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Daniel Hartmeier 5 * Copyright (c) 2002 - 2013 Henning Brauer <henning@openbsd.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * - Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * - Redistributions in binary form must reproduce the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer in the documentation and/or other materials provided 17 * with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 * 32 */ 33 34 #include <sys/types.h> 35 #include <sys/ioctl.h> 36 #include <sys/socket.h> 37 #include <sys/stat.h> 38 39 #include <net/if.h> 40 #include <netinet/in.h> 41 #include <net/pfvar.h> 42 #include <arpa/inet.h> 43 #include <sys/sysctl.h> 44 45 #include <err.h> 46 #include <errno.h> 47 #include <fcntl.h> 48 #include <limits.h> 49 #include <netdb.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <unistd.h> 54 #include <syslog.h> 55 #include <stdarg.h> 56 #include <libgen.h> 57 58 #include "pfctl_parser.h" 59 #include "pfctl.h" 60 61 void usage(void); 62 int pfctl_enable(int, int); 63 int pfctl_disable(int, int); 64 void pfctl_clear_queues(struct pf_qihead *); 65 void pfctl_clear_stats(int, const char *, int); 66 void pfctl_clear_interface_flags(int, int); 67 int pfctl_clear_rules(int, int, char *); 68 void pfctl_clear_src_nodes(int, int); 69 void pfctl_clear_states(int, const char *, int); 70 struct addrinfo * 71 pfctl_addrprefix(char *, struct pf_addr *, int); 72 void pfctl_kill_src_nodes(int, int); 73 void pfctl_net_kill_states(int, const char *, int, int); 74 void pfctl_label_kill_states(int, const char *, int, int); 75 void pfctl_id_kill_states(int, int); 76 void pfctl_key_kill_states(int, const char *, int, int); 77 int pfctl_parse_host(char *, struct pf_rule_addr *); 78 void pfctl_init_options(struct pfctl *); 79 int pfctl_load_options(struct pfctl *); 80 int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); 81 int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); 82 int pfctl_load_debug(struct pfctl *, unsigned int); 83 int pfctl_load_logif(struct pfctl *, char *); 84 int pfctl_load_hostid(struct pfctl *, unsigned int); 85 int pfctl_load_reassembly(struct pfctl *, u_int32_t); 86 int pfctl_load_syncookies(struct pfctl *, u_int8_t); 87 int pfctl_set_synflwats(struct pfctl *, u_int32_t, u_int32_t); 88 void pfctl_print_rule_counters(struct pf_rule *, int); 89 int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int, 90 long); 91 int pfctl_show_src_nodes(int, int); 92 int pfctl_show_states(int, const char *, int, long); 93 int pfctl_show_status(int, int); 94 int pfctl_show_timeouts(int, int); 95 int pfctl_show_limits(int, int); 96 void pfctl_debug(int, u_int32_t, int); 97 int pfctl_show_anchors(int, int, char *); 98 int pfctl_ruleset_trans(struct pfctl *, char *, struct pf_anchor *); 99 u_int pfctl_find_childqs(struct pfctl_qsitem *); 100 void pfctl_load_queue(struct pfctl *, u_int32_t, struct pfctl_qsitem *); 101 int pfctl_load_queues(struct pfctl *); 102 u_int pfctl_leafqueue_check(char *); 103 u_int pfctl_check_qassignments(struct pf_ruleset *); 104 int pfctl_load_ruleset(struct pfctl *, char *, struct pf_ruleset *, int); 105 int pfctl_load_rule(struct pfctl *, char *, struct pf_rule *, int); 106 const char *pfctl_lookup_option(char *, const char **); 107 void pfctl_state_store(int, const char *); 108 void pfctl_state_load(int, const char *); 109 void pfctl_reset(int, int); 110 int pfctl_walk_show(int, struct pfioc_ruleset *, void *); 111 int pfctl_walk_get(int, struct pfioc_ruleset *, void *); 112 int pfctl_walk_anchors(int, int, const char *, 113 int(*)(int, struct pfioc_ruleset *, void *), void *); 114 struct pfr_anchors * 115 pfctl_get_anchors(int, const char *, int); 116 int pfctl_recurse(int, int, const char *, 117 int(*)(int, int, struct pfr_anchoritem *)); 118 int pfctl_call_clearrules(int, int, struct pfr_anchoritem *); 119 int pfctl_call_cleartables(int, int, struct pfr_anchoritem *); 120 int pfctl_call_clearanchors(int, int, struct pfr_anchoritem *); 121 122 const char *clearopt; 123 char *rulesopt; 124 const char *showopt; 125 const char *debugopt; 126 char *anchoropt; 127 const char *optiopt = NULL; 128 char *pf_device = "/dev/pf"; 129 char *ifaceopt; 130 char *tableopt; 131 const char *tblcmdopt; 132 int src_node_killers; 133 char *src_node_kill[2]; 134 int state_killers; 135 char *state_kill[2]; 136 137 int dev = -1; 138 int first_title = 1; 139 int labels = 0; 140 int exit_val = 0; 141 142 #define INDENT(d, o) do { \ 143 if (o) { \ 144 int i; \ 145 for (i=0; i < d; i++) \ 146 printf(" "); \ 147 } \ 148 } while (0) \ 149 150 151 static const struct { 152 const char *name; 153 int index; 154 } pf_limits[] = { 155 { "states", PF_LIMIT_STATES }, 156 { "src-nodes", PF_LIMIT_SRC_NODES }, 157 { "frags", PF_LIMIT_FRAGS }, 158 { "tables", PF_LIMIT_TABLES }, 159 { "table-entries", PF_LIMIT_TABLE_ENTRIES }, 160 { "pktdelay-pkts", PF_LIMIT_PKTDELAY_PKTS }, 161 { "anchors", PF_LIMIT_ANCHORS }, 162 { NULL, 0 } 163 }; 164 165 struct pf_hint { 166 const char *name; 167 int timeout; 168 }; 169 static const struct pf_hint pf_hint_normal[] = { 170 { "tcp.first", 2 * 60 }, 171 { "tcp.opening", 30 }, 172 { "tcp.established", 24 * 60 * 60 }, 173 { "tcp.closing", 15 * 60 }, 174 { "tcp.finwait", 45 }, 175 { "tcp.closed", 90 }, 176 { "tcp.tsdiff", 30 }, 177 { NULL, 0 } 178 }; 179 static const struct pf_hint pf_hint_satellite[] = { 180 { "tcp.first", 3 * 60 }, 181 { "tcp.opening", 30 + 5 }, 182 { "tcp.established", 24 * 60 * 60 }, 183 { "tcp.closing", 15 * 60 + 5 }, 184 { "tcp.finwait", 45 + 5 }, 185 { "tcp.closed", 90 + 5 }, 186 { "tcp.tsdiff", 60 }, 187 { NULL, 0 } 188 }; 189 static const struct pf_hint pf_hint_conservative[] = { 190 { "tcp.first", 60 * 60 }, 191 { "tcp.opening", 15 * 60 }, 192 { "tcp.established", 5 * 24 * 60 * 60 }, 193 { "tcp.closing", 60 * 60 }, 194 { "tcp.finwait", 10 * 60 }, 195 { "tcp.closed", 3 * 60 }, 196 { "tcp.tsdiff", 60 }, 197 { NULL, 0 } 198 }; 199 static const struct pf_hint pf_hint_aggressive[] = { 200 { "tcp.first", 30 }, 201 { "tcp.opening", 5 }, 202 { "tcp.established", 5 * 60 * 60 }, 203 { "tcp.closing", 60 }, 204 { "tcp.finwait", 30 }, 205 { "tcp.closed", 30 }, 206 { "tcp.tsdiff", 10 }, 207 { NULL, 0 } 208 }; 209 210 static const struct { 211 const char *name; 212 const struct pf_hint *hint; 213 } pf_hints[] = { 214 { "normal", pf_hint_normal }, 215 { "satellite", pf_hint_satellite }, 216 { "high-latency", pf_hint_satellite }, 217 { "conservative", pf_hint_conservative }, 218 { "aggressive", pf_hint_aggressive }, 219 { NULL, NULL } 220 }; 221 222 static const char *clearopt_list[] = { 223 "rules", "Sources", "states", "info", "Tables", "osfp", "Reset", 224 "all", NULL 225 }; 226 227 static const char *showopt_list[] = { 228 "queue", "rules", "Anchors", "Sources", "states", "info", 229 "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp", 230 "all", NULL 231 }; 232 233 static const char *tblcmdopt_list[] = { 234 "kill", "flush", "add", "delete", "replace", "show", 235 "test", "zero", "expire", NULL 236 }; 237 238 static const char *debugopt_list[] = { 239 "debug", "info", "notice", "warning", 240 "error", "crit", "alert", "emerg", 241 NULL 242 }; 243 244 static const char *optiopt_list[] = { 245 "none", "basic", "profile", NULL 246 }; 247 248 struct pf_qihead qspecs = TAILQ_HEAD_INITIALIZER(qspecs); 249 struct pf_qihead rootqs = TAILQ_HEAD_INITIALIZER(rootqs); 250 251 __dead void 252 usage(void) 253 { 254 extern char *__progname; 255 256 fprintf(stderr, "usage: %s [-deghNnPqrvz] ", __progname); 257 fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]"); 258 fprintf(stderr, " [-f file]\n"); 259 fprintf(stderr, "\t[-i interface] [-K key] [-k key] [-L statefile]"); 260 fprintf(stderr, " [-o level]\n"); 261 fprintf(stderr, "\t[-p device] [-S statefile] [-s modifier [-R id]]\n"); 262 fprintf(stderr, "\t[-t table -T command [address ...]]"); 263 fprintf(stderr, " [-V rdomain] [-x level]\n"); 264 exit(1); 265 } 266 267 void 268 pfctl_err(int opts, int eval, const char *fmt, ...) 269 { 270 va_list ap; 271 272 va_start(ap, fmt); 273 274 if ((opts & PF_OPT_IGNFAIL) == 0) 275 verr(eval, fmt, ap); 276 else 277 vwarn(fmt, ap); 278 279 va_end(ap); 280 281 exit_val = eval; 282 } 283 284 void 285 pfctl_errx(int opts, int eval, const char *fmt, ...) 286 { 287 va_list ap; 288 289 va_start(ap, fmt); 290 291 if ((opts & PF_OPT_IGNFAIL) == 0) 292 verrx(eval, fmt, ap); 293 else 294 vwarnx(fmt, ap); 295 296 va_end(ap); 297 298 exit_val = eval; 299 } 300 301 int 302 pfctl_enable(int dev, int opts) 303 { 304 if (ioctl(dev, DIOCSTART) == -1) { 305 if (errno == EEXIST) 306 errx(1, "pf already enabled"); 307 else 308 err(1, "DIOCSTART"); 309 } 310 if ((opts & PF_OPT_QUIET) == 0) 311 fprintf(stderr, "pf enabled\n"); 312 313 return (0); 314 } 315 316 int 317 pfctl_disable(int dev, int opts) 318 { 319 if (ioctl(dev, DIOCSTOP) == -1) { 320 if (errno == ENOENT) 321 errx(1, "pf not enabled"); 322 else 323 err(1, "DIOCSTOP"); 324 } 325 if ((opts & PF_OPT_QUIET) == 0) 326 fprintf(stderr, "pf disabled\n"); 327 328 return (0); 329 } 330 331 void 332 pfctl_clear_stats(int dev, const char *iface, int opts) 333 { 334 struct pfioc_iface pi; 335 336 memset(&pi, 0, sizeof(pi)); 337 if (iface != NULL && strlcpy(pi.pfiio_name, iface, 338 sizeof(pi.pfiio_name)) >= sizeof(pi.pfiio_name)) 339 pfctl_errx(opts, 1, "invalid interface: %s", iface); 340 341 if (ioctl(dev, DIOCCLRSTATUS, &pi) == -1) 342 pfctl_err(opts, 1, "DIOCCLRSTATUS"); 343 if ((opts & PF_OPT_QUIET) == 0) { 344 fprintf(stderr, "pf: statistics cleared"); 345 if (iface != NULL) 346 fprintf(stderr, " for interface %s", iface); 347 fprintf(stderr, "\n"); 348 } 349 } 350 351 void 352 pfctl_clear_interface_flags(int dev, int opts) 353 { 354 struct pfioc_iface pi; 355 356 if ((opts & PF_OPT_NOACTION) == 0) { 357 bzero(&pi, sizeof(pi)); 358 pi.pfiio_flags = PFI_IFLAG_SKIP; 359 360 if (ioctl(dev, DIOCCLRIFFLAG, &pi) == -1) 361 pfctl_err(opts, 1, "DIOCCLRIFFLAG"); 362 if ((opts & PF_OPT_QUIET) == 0) 363 fprintf(stderr, "pf: interface flags reset\n"); 364 } 365 } 366 367 int 368 pfctl_clear_rules(int dev, int opts, char *anchorname) 369 { 370 struct pfr_buffer t; 371 372 memset(&t, 0, sizeof(t)); 373 t.pfrb_type = PFRB_TRANS; 374 if (pfctl_add_trans(&t, PF_TRANS_RULESET, anchorname) || 375 pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 376 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) { 377 pfctl_err(opts, 1, "%s", __func__); 378 return (1); 379 } else if ((opts & PF_OPT_QUIET) == 0) 380 fprintf(stderr, "rules cleared\n"); 381 382 return (0); 383 } 384 385 void 386 pfctl_clear_src_nodes(int dev, int opts) 387 { 388 if (ioctl(dev, DIOCCLRSRCNODES) == -1) 389 pfctl_err(opts, 1, "DIOCCLRSRCNODES"); 390 if ((opts & PF_OPT_QUIET) == 0) 391 fprintf(stderr, "source tracking entries cleared\n"); 392 } 393 394 void 395 pfctl_clear_states(int dev, const char *iface, int opts) 396 { 397 struct pfioc_state_kill psk; 398 399 memset(&psk, 0, sizeof(psk)); 400 if (iface != NULL && strlcpy(psk.psk_ifname, iface, 401 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 402 pfctl_errx(opts, 1, "invalid interface: %s", iface); 403 404 if (ioctl(dev, DIOCCLRSTATES, &psk) == -1) 405 pfctl_err(opts, 1, "DIOCCLRSTATES"); 406 if ((opts & PF_OPT_QUIET) == 0) 407 fprintf(stderr, "%d states cleared\n", psk.psk_killed); 408 } 409 410 struct addrinfo * 411 pfctl_addrprefix(char *addr, struct pf_addr *mask, int numeric) 412 { 413 char *p; 414 const char *errstr; 415 int prefix, ret_ga, q, r; 416 struct addrinfo hints, *res; 417 418 bzero(&hints, sizeof(hints)); 419 hints.ai_socktype = SOCK_DGRAM; /* dummy */ 420 if (numeric) 421 hints.ai_flags = AI_NUMERICHOST; 422 423 if ((p = strchr(addr, '/')) != NULL) { 424 *p++ = '\0'; 425 /* prefix only with numeric addresses */ 426 hints.ai_flags |= AI_NUMERICHOST; 427 } 428 429 if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) { 430 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 431 /* NOTREACHED */ 432 } 433 434 if (p == NULL) 435 return res; 436 437 prefix = strtonum(p, 0, res->ai_family == AF_INET6 ? 128 : 32, &errstr); 438 if (errstr) 439 errx(1, "prefix is %s: %s", errstr, p); 440 441 q = prefix >> 3; 442 r = prefix & 7; 443 switch (res->ai_family) { 444 case AF_INET: 445 bzero(&mask->v4, sizeof(mask->v4)); 446 mask->v4.s_addr = htonl((u_int32_t) 447 (0xffffffffffULL << (32 - prefix))); 448 break; 449 case AF_INET6: 450 bzero(&mask->v6, sizeof(mask->v6)); 451 if (q > 0) 452 memset((void *)&mask->v6, 0xff, q); 453 if (r > 0) 454 *((u_char *)&mask->v6 + q) = 455 (0xff00 >> r) & 0xff; 456 break; 457 } 458 459 return res; 460 } 461 462 void 463 pfctl_kill_src_nodes(int dev, int opts) 464 { 465 struct pfioc_src_node_kill psnk; 466 struct addrinfo *res[2], *resp[2]; 467 struct sockaddr last_src, last_dst; 468 int killed, sources, dests; 469 470 killed = sources = dests = 0; 471 472 memset(&psnk, 0, sizeof(psnk)); 473 memset(&psnk.psnk_src.addr.v.a.mask, 0xff, 474 sizeof(psnk.psnk_src.addr.v.a.mask)); 475 memset(&last_src, 0xff, sizeof(last_src)); 476 memset(&last_dst, 0xff, sizeof(last_dst)); 477 478 res[0] = pfctl_addrprefix(src_node_kill[0], 479 &psnk.psnk_src.addr.v.a.mask, (opts & PF_OPT_NODNS)); 480 481 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 482 if (resp[0]->ai_addr == NULL) 483 continue; 484 /* We get lots of duplicates. Catch the easy ones */ 485 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 486 continue; 487 last_src = *(struct sockaddr *)resp[0]->ai_addr; 488 489 psnk.psnk_af = resp[0]->ai_family; 490 sources++; 491 492 copy_satopfaddr(&psnk.psnk_src.addr.v.a.addr, resp[0]->ai_addr); 493 494 if (src_node_killers > 1) { 495 dests = 0; 496 memset(&psnk.psnk_dst.addr.v.a.mask, 0xff, 497 sizeof(psnk.psnk_dst.addr.v.a.mask)); 498 memset(&last_dst, 0xff, sizeof(last_dst)); 499 res[1] = pfctl_addrprefix(src_node_kill[1], 500 &psnk.psnk_dst.addr.v.a.mask, 501 (opts & PF_OPT_NODNS)); 502 for (resp[1] = res[1]; resp[1]; 503 resp[1] = resp[1]->ai_next) { 504 if (resp[1]->ai_addr == NULL) 505 continue; 506 if (psnk.psnk_af != resp[1]->ai_family) 507 continue; 508 509 if (memcmp(&last_dst, resp[1]->ai_addr, 510 sizeof(last_dst)) == 0) 511 continue; 512 last_dst = *(struct sockaddr *)resp[1]->ai_addr; 513 514 dests++; 515 516 copy_satopfaddr(&psnk.psnk_src.addr.v.a.addr, 517 resp[1]->ai_addr); 518 519 if (ioctl(dev, DIOCKILLSRCNODES, &psnk) == -1) 520 err(1, "DIOCKILLSRCNODES"); 521 killed += psnk.psnk_killed; 522 } 523 freeaddrinfo(res[1]); 524 } else { 525 if (ioctl(dev, DIOCKILLSRCNODES, &psnk) == -1) 526 err(1, "DIOCKILLSRCNODES"); 527 killed += psnk.psnk_killed; 528 } 529 } 530 531 freeaddrinfo(res[0]); 532 533 if ((opts & PF_OPT_QUIET) == 0) 534 fprintf(stderr, "killed %d src nodes from %d sources and %d " 535 "destinations\n", killed, sources, dests); 536 } 537 538 void 539 pfctl_net_kill_states(int dev, const char *iface, int opts, int rdomain) 540 { 541 struct pfioc_state_kill psk; 542 struct addrinfo *res[2], *resp[2]; 543 struct sockaddr last_src, last_dst; 544 int killed, sources, dests; 545 546 killed = sources = dests = 0; 547 548 memset(&psk, 0, sizeof(psk)); 549 memset(&psk.psk_src.addr.v.a.mask, 0xff, 550 sizeof(psk.psk_src.addr.v.a.mask)); 551 memset(&last_src, 0xff, sizeof(last_src)); 552 memset(&last_dst, 0xff, sizeof(last_dst)); 553 if (iface != NULL && strlcpy(psk.psk_ifname, iface, 554 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 555 errx(1, "invalid interface: %s", iface); 556 557 psk.psk_rdomain = rdomain; 558 559 res[0] = pfctl_addrprefix(state_kill[0], 560 &psk.psk_src.addr.v.a.mask, (opts & PF_OPT_NODNS)); 561 562 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 563 if (resp[0]->ai_addr == NULL) 564 continue; 565 /* We get lots of duplicates. Catch the easy ones */ 566 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 567 continue; 568 last_src = *(struct sockaddr *)resp[0]->ai_addr; 569 570 psk.psk_af = resp[0]->ai_family; 571 sources++; 572 573 copy_satopfaddr(&psk.psk_src.addr.v.a.addr, resp[0]->ai_addr); 574 575 if (state_killers > 1) { 576 dests = 0; 577 memset(&psk.psk_dst.addr.v.a.mask, 0xff, 578 sizeof(psk.psk_dst.addr.v.a.mask)); 579 memset(&last_dst, 0xff, sizeof(last_dst)); 580 res[1] = pfctl_addrprefix(state_kill[1], 581 &psk.psk_dst.addr.v.a.mask, 582 (opts & PF_OPT_NODNS)); 583 for (resp[1] = res[1]; resp[1]; 584 resp[1] = resp[1]->ai_next) { 585 if (resp[1]->ai_addr == NULL) 586 continue; 587 if (psk.psk_af != resp[1]->ai_family) 588 continue; 589 590 if (memcmp(&last_dst, resp[1]->ai_addr, 591 sizeof(last_dst)) == 0) 592 continue; 593 last_dst = *(struct sockaddr *)resp[1]->ai_addr; 594 595 dests++; 596 597 copy_satopfaddr(&psk.psk_src.addr.v.a.addr, 598 resp[1]->ai_addr); 599 600 if (ioctl(dev, DIOCKILLSTATES, &psk) == -1) 601 err(1, "DIOCKILLSTATES"); 602 killed += psk.psk_killed; 603 } 604 freeaddrinfo(res[1]); 605 } else { 606 if (ioctl(dev, DIOCKILLSTATES, &psk) == -1) 607 err(1, "DIOCKILLSTATES"); 608 killed += psk.psk_killed; 609 } 610 } 611 612 freeaddrinfo(res[0]); 613 614 if ((opts & PF_OPT_QUIET) == 0) 615 fprintf(stderr, "killed %d states from %d sources and %d " 616 "destinations\n", killed, sources, dests); 617 } 618 619 void 620 pfctl_label_kill_states(int dev, const char *iface, int opts, int rdomain) 621 { 622 struct pfioc_state_kill psk; 623 624 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 625 warnx("no label specified"); 626 usage(); 627 } 628 memset(&psk, 0, sizeof(psk)); 629 if (iface != NULL && strlcpy(psk.psk_ifname, iface, 630 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 631 errx(1, "invalid interface: %s", iface); 632 633 if (strlcpy(psk.psk_label, state_kill[1], sizeof(psk.psk_label)) >= 634 sizeof(psk.psk_label)) 635 errx(1, "label too long: %s", state_kill[1]); 636 637 psk.psk_rdomain = rdomain; 638 639 if (ioctl(dev, DIOCKILLSTATES, &psk) == -1) 640 err(1, "DIOCKILLSTATES"); 641 642 if ((opts & PF_OPT_QUIET) == 0) 643 fprintf(stderr, "killed %d states\n", psk.psk_killed); 644 } 645 646 void 647 pfctl_id_kill_states(int dev, int opts) 648 { 649 struct pfioc_state_kill psk; 650 651 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 652 warnx("no id specified"); 653 usage(); 654 } 655 656 memset(&psk, 0, sizeof(psk)); 657 if ((sscanf(state_kill[1], "%llx/%x", 658 &psk.psk_pfcmp.id, &psk.psk_pfcmp.creatorid)) == 2) 659 HTONL(psk.psk_pfcmp.creatorid); 660 else if ((sscanf(state_kill[1], "%llx", &psk.psk_pfcmp.id)) == 1) { 661 psk.psk_pfcmp.creatorid = 0; 662 } else { 663 warnx("wrong id format specified"); 664 usage(); 665 } 666 if (psk.psk_pfcmp.id == 0) { 667 warnx("cannot kill id 0"); 668 usage(); 669 } 670 671 psk.psk_pfcmp.id = htobe64(psk.psk_pfcmp.id); 672 if (ioctl(dev, DIOCKILLSTATES, &psk) == -1) 673 err(1, "DIOCKILLSTATES"); 674 675 if ((opts & PF_OPT_QUIET) == 0) 676 fprintf(stderr, "killed %d states\n", psk.psk_killed); 677 } 678 679 void 680 pfctl_key_kill_states(int dev, const char *iface, int opts, int rdomain) 681 { 682 struct pfioc_state_kill psk; 683 char *s, *token, *tokens[4]; 684 struct protoent *p; 685 u_int i, sidx, didx; 686 687 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 688 warnx("no key specified"); 689 usage(); 690 } 691 memset(&psk, 0, sizeof(psk)); 692 693 if (iface != NULL && strlcpy(psk.psk_ifname, iface, 694 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 695 errx(1, "invalid interface: %s", iface); 696 697 psk.psk_rdomain = rdomain; 698 699 s = strdup(state_kill[1]); 700 if (!s) 701 errx(1, "pfctl_key_kill_states: strdup"); 702 i = 0; 703 while ((token = strsep(&s, " \t")) != NULL) 704 if (*token != '\0') { 705 if (i < 4) 706 tokens[i] = token; 707 i++; 708 } 709 if (i != 4) 710 errx(1, "pfctl_key_kill_states: key must be " 711 "\"protocol host1:port1 direction host2:port2\" format"); 712 713 if ((p = getprotobyname(tokens[0])) == NULL) 714 errx(1, "invalid protocol: %s", tokens[0]); 715 psk.psk_proto = p->p_proto; 716 717 if (strcmp(tokens[2], "->") == 0) { 718 sidx = 1; 719 didx = 3; 720 } else if (strcmp(tokens[2], "<-") == 0) { 721 sidx = 3; 722 didx = 1; 723 } else 724 errx(1, "invalid direction: %s", tokens[2]); 725 726 if (pfctl_parse_host(tokens[sidx], &psk.psk_src) == -1) 727 errx(1, "invalid host: %s", tokens[sidx]); 728 if (pfctl_parse_host(tokens[didx], &psk.psk_dst) == -1) 729 errx(1, "invalid host: %s", tokens[didx]); 730 731 if (ioctl(dev, DIOCKILLSTATES, &psk) == -1) 732 err(1, "DIOCKILLSTATES"); 733 734 if ((opts & PF_OPT_QUIET) == 0) 735 fprintf(stderr, "killed %d states\n", psk.psk_killed); 736 } 737 738 int 739 pfctl_parse_host(char *str, struct pf_rule_addr *addr) 740 { 741 char *s = NULL, *sbs, *sbe; 742 struct addrinfo hints, *ai; 743 744 s = strdup(str); 745 if (!s) 746 errx(1, "pfctl_parse_host: strdup"); 747 748 memset(&hints, 0, sizeof(hints)); 749 hints.ai_socktype = SOCK_DGRAM; /* dummy */ 750 hints.ai_flags = AI_NUMERICHOST; 751 752 if ((sbs = strchr(s, '[')) != NULL && (sbe = strrchr(s, ']')) != NULL) { 753 hints.ai_family = AF_INET6; 754 *(sbs++) = *sbe = '\0'; 755 } else if ((sbs = strchr(s, ':')) != NULL) { 756 hints.ai_family = AF_INET; 757 *(sbs++) = '\0'; 758 } else 759 goto error; 760 761 if (getaddrinfo(s, sbs, &hints, &ai) != 0) 762 goto error; 763 764 copy_satopfaddr(&addr->addr.v.a.addr, ai->ai_addr); 765 addr->port[0] = ai->ai_family == AF_INET6 ? 766 ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port : 767 ((struct sockaddr_in *)ai->ai_addr)->sin_port; 768 769 freeaddrinfo(ai); 770 free(s); 771 772 memset(&addr->addr.v.a.mask, 0xff, sizeof(struct pf_addr)); 773 addr->port_op = PF_OP_EQ; 774 addr->addr.type = PF_ADDR_ADDRMASK; 775 776 return (0); 777 778 error: 779 free(s); 780 return (-1); 781 } 782 783 void 784 pfctl_print_rule_counters(struct pf_rule *rule, int opts) 785 { 786 if (opts & PF_OPT_DEBUG) { 787 const char *t[PF_SKIP_COUNT] = { "i", "d", "r", "f", 788 "p", "sa", "da", "sp", "dp" }; 789 int i; 790 791 printf(" [ Skip steps: "); 792 for (i = 0; i < PF_SKIP_COUNT; ++i) { 793 if (rule->skip[i].nr == rule->nr + 1) 794 continue; 795 printf("%s=", t[i]); 796 if (rule->skip[i].nr == -1) 797 printf("end "); 798 else 799 printf("%u ", rule->skip[i].nr); 800 } 801 printf("]\n"); 802 803 printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n", 804 rule->qname, rule->qid, rule->pqname, rule->pqid); 805 } 806 if (opts & PF_OPT_VERBOSE) { 807 printf(" [ Evaluations: %-8llu Packets: %-8llu " 808 "Bytes: %-10llu States: %-6u]\n", 809 (unsigned long long)rule->evaluations, 810 (unsigned long long)(rule->packets[0] + 811 rule->packets[1]), 812 (unsigned long long)(rule->bytes[0] + 813 rule->bytes[1]), rule->states_cur); 814 if (!(opts & PF_OPT_DEBUG)) 815 printf(" [ Inserted: uid %lu pid %lu " 816 "State Creations: %-6u]\n", 817 (unsigned long)rule->cuid, (unsigned long)rule->cpid, 818 rule->states_tot); 819 } 820 } 821 822 void 823 pfctl_print_title(char *title) 824 { 825 if (!first_title) 826 printf("\n"); 827 first_title = 0; 828 printf("%s\n", title); 829 } 830 831 int 832 pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, 833 char *anchorname, int depth, int wildcard, long shownr) 834 { 835 struct pfioc_rule pr; 836 u_int32_t nr, mnr, header = 0; 837 int len = strlen(path), ret = 0; 838 char *npath, *p; 839 840 /* 841 * Truncate a trailing / and * on an anchorname before searching for 842 * the ruleset, this is syntactic sugar that doesn't actually make it 843 * to the kernel. 844 */ 845 if ((p = strrchr(anchorname, '/')) != NULL && 846 p[1] == '*' && p[2] == '\0') { 847 p[0] = '\0'; 848 } 849 850 memset(&pr, 0, sizeof(pr)); 851 if (anchorname[0] == '/') { 852 if ((npath = calloc(1, PATH_MAX)) == NULL) 853 err(1, "calloc"); 854 strlcpy(npath, anchorname, PATH_MAX); 855 } else { 856 if (path[0]) 857 snprintf(&path[len], PATH_MAX - len, "/%s", anchorname); 858 else 859 snprintf(&path[len], PATH_MAX - len, "%s", anchorname); 860 npath = path; 861 } 862 863 memcpy(pr.anchor, npath, sizeof(pr.anchor)); 864 if (opts & PF_OPT_SHOWALL) { 865 pr.rule.action = PF_PASS; 866 if (ioctl(dev, DIOCGETRULES, &pr) == -1) { 867 warnx("%s", pf_strerror(errno)); 868 ret = -1; 869 goto error; 870 } 871 header++; 872 if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header)) 873 pfctl_print_title("FILTER RULES:"); 874 else if (format == PFCTL_SHOW_LABELS && labels) 875 pfctl_print_title("LABEL COUNTERS:"); 876 } 877 if (opts & PF_OPT_CLRRULECTRS) 878 pr.action = PF_GET_CLR_CNTR; 879 880 pr.rule.action = PF_PASS; 881 if (ioctl(dev, DIOCGETRULES, &pr) == -1) { 882 warnx("%s", pf_strerror(errno)); 883 ret = -1; 884 goto error; 885 } 886 887 if (shownr < 0) { 888 mnr = pr.nr; 889 nr = 0; 890 } else if (shownr < pr.nr) { 891 nr = shownr; 892 mnr = shownr + 1; 893 } else { 894 warnx("rule %ld not found", shownr); 895 ret = -1; 896 goto error; 897 } 898 for (; nr < mnr; ++nr) { 899 pr.nr = nr; 900 if (ioctl(dev, DIOCGETRULE, &pr) == -1) { 901 warn("DIOCGETRULE"); 902 ret = -1; 903 goto error; 904 } 905 906 /* anchor is the same for all rules in it */ 907 if (pr.rule.anchor_wildcard == 0) 908 wildcard = 0; 909 910 switch (format) { 911 case PFCTL_SHOW_LABELS: 912 if (pr.rule.label[0]) { 913 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 914 printf("%s %llu %llu %llu %llu" 915 " %llu %llu %llu %llu\n", 916 pr.rule.label, 917 (unsigned long long)pr.rule.evaluations, 918 (unsigned long long)(pr.rule.packets[0] + 919 pr.rule.packets[1]), 920 (unsigned long long)(pr.rule.bytes[0] + 921 pr.rule.bytes[1]), 922 (unsigned long long)pr.rule.packets[0], 923 (unsigned long long)pr.rule.bytes[0], 924 (unsigned long long)pr.rule.packets[1], 925 (unsigned long long)pr.rule.bytes[1], 926 (unsigned long long)pr.rule.states_tot); 927 } 928 break; 929 case PFCTL_SHOW_RULES: 930 if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) 931 labels = 1; 932 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 933 print_rule(&pr.rule, pr.anchor_call, opts); 934 935 /* 936 * If this is an 'unnamed' brace notation anchor OR 937 * the user has explicitly requested recursion, 938 * print it recursively. 939 */ 940 if (pr.anchor_call[0] && 941 (((p = strrchr(pr.anchor_call, '/')) ? 942 p[1] == '_' : pr.anchor_call[0] == '_') || 943 opts & PF_OPT_RECURSE)) { 944 printf(" {\n"); 945 pfctl_print_rule_counters(&pr.rule, opts); 946 pfctl_show_rules(dev, npath, opts, format, 947 pr.anchor_call, depth + 1, 948 pr.rule.anchor_wildcard, -1); 949 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 950 printf("}\n"); 951 } else { 952 printf("\n"); 953 pfctl_print_rule_counters(&pr.rule, opts); 954 } 955 break; 956 case PFCTL_SHOW_NOTHING: 957 break; 958 } 959 } 960 961 /* 962 * If this anchor was called with a wildcard path, go through 963 * the rulesets in the anchor rather than the rules. 964 */ 965 if (wildcard && (opts & PF_OPT_RECURSE)) { 966 struct pfioc_ruleset prs; 967 u_int32_t mnr, nr; 968 969 memset(&prs, 0, sizeof(prs)); 970 memcpy(prs.path, npath, sizeof(prs.path)); 971 if (ioctl(dev, DIOCGETRULESETS, &prs) == -1) 972 errx(1, "%s", pf_strerror(errno)); 973 mnr = prs.nr; 974 975 for (nr = 0; nr < mnr; ++nr) { 976 prs.nr = nr; 977 if (ioctl(dev, DIOCGETRULESET, &prs) == -1) 978 errx(1, "%s", pf_strerror(errno)); 979 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 980 printf("anchor \"%s\" all {\n", prs.name); 981 pfctl_show_rules(dev, npath, opts, 982 format, prs.name, depth + 1, 0, shownr); 983 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 984 printf("}\n"); 985 } 986 path[len] = '\0'; 987 return (0); 988 } 989 990 error: 991 if (path != npath) 992 free(npath); 993 path[len] = '\0'; 994 return (ret); 995 } 996 997 int 998 pfctl_show_src_nodes(int dev, int opts) 999 { 1000 struct pfioc_src_nodes psn; 1001 struct pf_src_node *p; 1002 char *inbuf = NULL, *newinbuf = NULL; 1003 size_t i, len = 0; 1004 1005 memset(&psn, 0, sizeof(psn)); 1006 for (;;) { 1007 psn.psn_len = len; 1008 if (len) { 1009 newinbuf = realloc(inbuf, len); 1010 if (newinbuf == NULL) 1011 err(1, "realloc"); 1012 psn.psn_buf = inbuf = newinbuf; 1013 } 1014 if (ioctl(dev, DIOCGETSRCNODES, &psn) == -1) { 1015 warn("DIOCGETSRCNODES"); 1016 free(inbuf); 1017 return (-1); 1018 } 1019 if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len) 1020 break; 1021 if (len == 0 && psn.psn_len == 0) 1022 goto done; 1023 if (len == 0 && psn.psn_len != 0) 1024 len = psn.psn_len; 1025 if (psn.psn_len == 0) 1026 goto done; /* no src_nodes */ 1027 len *= 2; 1028 } 1029 p = psn.psn_src_nodes; 1030 if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL)) 1031 pfctl_print_title("SOURCE TRACKING NODES:"); 1032 for (i = 0; i < psn.psn_len; i += sizeof(*p)) { 1033 print_src_node(p, opts); 1034 p++; 1035 } 1036 done: 1037 free(inbuf); 1038 return (0); 1039 } 1040 1041 int 1042 pfctl_show_states(int dev, const char *iface, int opts, long shownr) 1043 { 1044 struct pfioc_states ps; 1045 struct pfsync_state *p; 1046 char *inbuf = NULL, *newinbuf = NULL; 1047 size_t i, len = 0; 1048 int dotitle = (opts & PF_OPT_SHOWALL); 1049 1050 memset(&ps, 0, sizeof(ps)); 1051 for (;;) { 1052 ps.ps_len = len; 1053 if (len) { 1054 newinbuf = realloc(inbuf, len); 1055 if (newinbuf == NULL) 1056 err(1, "realloc"); 1057 ps.ps_buf = inbuf = newinbuf; 1058 } 1059 if (ioctl(dev, DIOCGETSTATES, &ps) == -1) { 1060 warn("DIOCGETSTATES"); 1061 free(inbuf); 1062 return (-1); 1063 } 1064 if (ps.ps_len + sizeof(struct pfioc_states) < len) 1065 break; 1066 if (len == 0 && ps.ps_len == 0) 1067 goto done; 1068 if (len == 0 && ps.ps_len != 0) 1069 len = ps.ps_len; 1070 if (ps.ps_len == 0) 1071 goto done; /* no states */ 1072 len *= 2; 1073 } 1074 p = ps.ps_states; 1075 for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) { 1076 if (iface != NULL && strcmp(p->ifname, iface)) 1077 continue; 1078 if (dotitle) { 1079 pfctl_print_title("STATES:"); 1080 dotitle = 0; 1081 } 1082 if (shownr < 0 || ntohl(p->rule) == shownr) 1083 print_state(p, opts); 1084 } 1085 done: 1086 free(inbuf); 1087 return (0); 1088 } 1089 1090 int 1091 pfctl_show_status(int dev, int opts) 1092 { 1093 struct pf_status status; 1094 struct pfctl_watermarks wats; 1095 struct pfioc_synflwats iocwats; 1096 1097 if (ioctl(dev, DIOCGETSTATUS, &status) == -1) { 1098 warn("DIOCGETSTATUS"); 1099 return (-1); 1100 } 1101 if (ioctl(dev, DIOCGETSYNFLWATS, &iocwats) == -1) { 1102 warn("DIOCGETSYNFLWATS"); 1103 return (-1); 1104 } 1105 wats.hi = iocwats.hiwat; 1106 wats.lo = iocwats.lowat; 1107 if (opts & PF_OPT_SHOWALL) 1108 pfctl_print_title("INFO:"); 1109 print_status(&status, &wats, opts); 1110 return (0); 1111 } 1112 1113 int 1114 pfctl_show_timeouts(int dev, int opts) 1115 { 1116 struct pfioc_tm pt; 1117 int i; 1118 1119 if (opts & PF_OPT_SHOWALL) 1120 pfctl_print_title("TIMEOUTS:"); 1121 memset(&pt, 0, sizeof(pt)); 1122 for (i = 0; pf_timeouts[i].name; i++) { 1123 pt.timeout = pf_timeouts[i].timeout; 1124 if (ioctl(dev, DIOCGETTIMEOUT, &pt) == -1) 1125 err(1, "DIOCGETTIMEOUT"); 1126 printf("%-20s %10d", pf_timeouts[i].name, pt.seconds); 1127 if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && 1128 pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) 1129 printf(" states"); 1130 else 1131 printf("s"); 1132 printf("\n"); 1133 } 1134 return (0); 1135 1136 } 1137 1138 int 1139 pfctl_show_limits(int dev, int opts) 1140 { 1141 struct pfioc_limit pl; 1142 int i; 1143 1144 if (opts & PF_OPT_SHOWALL) 1145 pfctl_print_title("LIMITS:"); 1146 memset(&pl, 0, sizeof(pl)); 1147 for (i = 0; pf_limits[i].name; i++) { 1148 pl.index = pf_limits[i].index; 1149 if (ioctl(dev, DIOCGETLIMIT, &pl) == -1) 1150 err(1, "DIOCGETLIMIT"); 1151 printf("%-13s ", pf_limits[i].name); 1152 if (pl.limit == UINT_MAX) 1153 printf("unlimited\n"); 1154 else 1155 printf("hard limit %8u\n", pl.limit); 1156 } 1157 return (0); 1158 } 1159 1160 /* callbacks for rule/nat/rdr/addr */ 1161 void 1162 pfctl_add_rule(struct pfctl *pf, struct pf_rule *r) 1163 { 1164 struct pf_rule *rule; 1165 struct pf_ruleset *rs; 1166 1167 rs = &pf->anchor->ruleset; 1168 1169 if ((rule = calloc(1, sizeof(*rule))) == NULL) 1170 err(1, "calloc"); 1171 bcopy(r, rule, sizeof(*rule)); 1172 1173 TAILQ_INSERT_TAIL(rs->rules.active.ptr, rule, entries); 1174 } 1175 1176 int 1177 pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a) 1178 { 1179 int osize = pf->trans->pfrb_size; 1180 1181 if (pfctl_add_trans(pf->trans, PF_TRANS_RULESET, path)) 1182 return (3); 1183 if (pfctl_add_trans(pf->trans, PF_TRANS_TABLE, path)) 1184 return (4); 1185 if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1186 return (5); 1187 1188 return (0); 1189 } 1190 1191 int 1192 pfctl_add_queue(struct pfctl *pf, struct pf_queuespec *q) 1193 { 1194 struct pfctl_qsitem *qi; 1195 1196 if (pf->anchor->name[0]) { 1197 printf("must not have queue definitions in an anchor\n"); 1198 return (1); 1199 } 1200 1201 if (q->parent[0] == '\0') { 1202 TAILQ_FOREACH(qi, &rootqs, entries) { 1203 if (strcmp(q->ifname, qi->qs.ifname)) 1204 continue; 1205 printf("A root queue is already defined on %s\n", 1206 qi->qs.ifname); 1207 return (1); 1208 } 1209 } 1210 1211 if ((qi = calloc(1, sizeof(*qi))) == NULL) 1212 err(1, "calloc"); 1213 bcopy(q, &qi->qs, sizeof(qi->qs)); 1214 TAILQ_INIT(&qi->children); 1215 1216 if (qi->qs.parent[0]) 1217 TAILQ_INSERT_TAIL(&qspecs, qi, entries); 1218 else 1219 TAILQ_INSERT_TAIL(&rootqs, qi, entries); 1220 1221 return (0); 1222 } 1223 1224 struct pfctl_qsitem * 1225 pfctl_find_queue(char *what, struct pf_qihead *where) 1226 { 1227 struct pfctl_qsitem *q; 1228 1229 TAILQ_FOREACH(q, where, entries) 1230 if (strcmp(q->qs.qname, what) == 0) 1231 return (q); 1232 1233 return (NULL); 1234 } 1235 1236 u_int 1237 pfctl_find_childqs(struct pfctl_qsitem *qi) 1238 { 1239 struct pfctl_qsitem *n, *p, *q; 1240 u_int flags = qi->qs.flags; 1241 1242 TAILQ_FOREACH(p, &qspecs, entries) { 1243 if (strcmp(p->qs.parent, qi->qs.qname)) 1244 continue; 1245 if (p->qs.ifname[0] && strcmp(p->qs.ifname, qi->qs.ifname)) 1246 continue; 1247 if (++p->matches > 10000) 1248 errx(1, "pfctl_find_childqs: excessive matches, loop?"); 1249 1250 if ((q = pfctl_find_queue(p->qs.qname, &qi->children)) == NULL) { 1251 /* insert */ 1252 if ((n = calloc(1, sizeof(*n))) == NULL) 1253 err(1, "calloc"); 1254 TAILQ_INIT(&n->children); 1255 bcopy(&p->qs, &n->qs, sizeof(n->qs)); 1256 TAILQ_INSERT_TAIL(&qi->children, n, entries); 1257 } else { 1258 if ((q->qs.ifname[0] && p->qs.ifname[0])) 1259 errx(1, "queue %s on %s respecified", 1260 q->qs.qname, q->qs.ifname); 1261 if (!q->qs.ifname[0] && !p->qs.ifname[0]) 1262 errx(1, "queue %s respecified", 1263 q->qs.qname); 1264 /* ifbound beats floating */ 1265 if (!q->qs.ifname[0]) 1266 bcopy(&p->qs, &q->qs, sizeof(q->qs)); 1267 } 1268 } 1269 1270 TAILQ_FOREACH(p, &qi->children, entries) 1271 flags |= pfctl_find_childqs(p); 1272 1273 if (!TAILQ_EMPTY(&qi->children)) { 1274 if (qi->qs.flags & PFQS_DEFAULT) 1275 errx(1, "default queue %s is not a leaf queue", 1276 qi->qs.qname); 1277 if (qi->qs.flags & PFQS_FLOWQUEUE) 1278 errx(1, "flow queue %s is not a leaf queue", 1279 qi->qs.qname); 1280 } 1281 1282 return (flags); 1283 } 1284 1285 void 1286 pfctl_load_queue(struct pfctl *pf, u_int32_t ticket, struct pfctl_qsitem *qi) 1287 { 1288 struct pfioc_queue q; 1289 struct pfctl_qsitem *p; 1290 1291 q.ticket = ticket; 1292 bcopy(&qi->qs, &q.queue, sizeof(q.queue)); 1293 if ((pf->opts & PF_OPT_NOACTION) == 0) 1294 if (ioctl(pf->dev, DIOCADDQUEUE, &q) == -1) 1295 err(1, "DIOCADDQUEUE"); 1296 if (pf->opts & PF_OPT_VERBOSE) 1297 print_queuespec(&qi->qs); 1298 1299 TAILQ_FOREACH(p, &qi->children, entries) { 1300 strlcpy(p->qs.ifname, qi->qs.ifname, IFNAMSIZ); 1301 pfctl_load_queue(pf, ticket, p); 1302 } 1303 } 1304 1305 int 1306 pfctl_load_queues(struct pfctl *pf) 1307 { 1308 struct pfctl_qsitem *qi, *tempqi; 1309 struct pf_queue_scspec *rtsc, *lssc, *ulsc; 1310 u_int32_t ticket; 1311 1312 TAILQ_FOREACH(qi, &qspecs, entries) { 1313 if (qi->matches == 0) 1314 errx(1, "queue %s: parent %s not found", qi->qs.qname, 1315 qi->qs.parent); 1316 1317 rtsc = &qi->qs.realtime; 1318 lssc = &qi->qs.linkshare; 1319 ulsc = &qi->qs.upperlimit; 1320 1321 if (rtsc->m1.percent || rtsc->m2.percent || 1322 lssc->m1.percent || lssc->m2.percent || 1323 ulsc->m1.percent || ulsc->m2.percent) 1324 errx(1, "only absolute bandwidth specs for now"); 1325 1326 /* Link sharing policy must be specified for child classes */ 1327 if (qi->qs.parent[0] != '\0' && 1328 lssc->m1.absolute == 0 && lssc->m2.absolute == 0) 1329 errx(1, "queue %s: no bandwidth was specified", 1330 qi->qs.qname); 1331 } 1332 1333 if ((pf->opts & PF_OPT_NOACTION) == 0) 1334 ticket = pfctl_get_ticket(pf->trans, PF_TRANS_RULESET, ""); 1335 1336 TAILQ_FOREACH_SAFE(qi, &rootqs, entries, tempqi) { 1337 TAILQ_REMOVE(&rootqs, qi, entries); 1338 pfctl_load_queue(pf, ticket, qi); 1339 TAILQ_INSERT_HEAD(&rootqs, qi, entries); 1340 } 1341 1342 return (0); 1343 } 1344 1345 void 1346 pfctl_clear_queues(struct pf_qihead *head) 1347 { 1348 struct pfctl_qsitem *qi; 1349 1350 while ((qi = TAILQ_FIRST(head)) != NULL) { 1351 TAILQ_REMOVE(head, qi, entries); 1352 pfctl_clear_queues(&qi->children); 1353 free(qi); 1354 } 1355 } 1356 1357 u_int 1358 pfctl_leafqueue_check(char *qname) 1359 { 1360 struct pfctl_qsitem *qi; 1361 if (qname == NULL || qname[0] == 0) 1362 return (0); 1363 1364 TAILQ_FOREACH(qi, &rootqs, entries) { 1365 if (strcmp(qname, qi->qs.qname)) 1366 continue; 1367 if (!TAILQ_EMPTY(&qi->children)) { 1368 printf("queue %s: packets must be assigned to leaf " 1369 "queues only\n", qname); 1370 return (1); 1371 } 1372 } 1373 TAILQ_FOREACH(qi, &qspecs, entries) { 1374 if (strcmp(qname, qi->qs.qname)) 1375 continue; 1376 if (!TAILQ_EMPTY(&qi->children)) { 1377 printf("queue %s: packets must be assigned to leaf " 1378 "queues only\n", qname); 1379 return (1); 1380 } 1381 } 1382 return (0); 1383 } 1384 1385 u_int 1386 pfctl_check_qassignments(struct pf_ruleset *rs) 1387 { 1388 struct pf_rule *r; 1389 struct pfctl_qsitem *qi; 1390 u_int flags, errs = 0; 1391 1392 /* main ruleset: need find_childqs to populate qi->children */ 1393 if (rs->anchor->path[0] == 0) { 1394 TAILQ_FOREACH(qi, &rootqs, entries) { 1395 flags = pfctl_find_childqs(qi); 1396 if (!(qi->qs.flags & PFQS_ROOTCLASS) && 1397 !TAILQ_EMPTY(&qi->children)) { 1398 if (qi->qs.flags & PFQS_FLOWQUEUE) 1399 errx(1, "root queue %s doesn't " 1400 "support hierarchy", 1401 qi->qs.qname); 1402 else 1403 errx(1, "no bandwidth was specified " 1404 "for root queue %s", qi->qs.qname); 1405 } 1406 if ((qi->qs.flags & PFQS_ROOTCLASS) && 1407 !(flags & PFQS_DEFAULT)) 1408 errx(1, "no default queue specified"); 1409 } 1410 } 1411 1412 TAILQ_FOREACH(r, rs->rules.active.ptr, entries) { 1413 if (r->anchor) 1414 errs += pfctl_check_qassignments(&r->anchor->ruleset); 1415 if (pfctl_leafqueue_check(r->qname) || 1416 pfctl_leafqueue_check(r->pqname)) 1417 errs++; 1418 } 1419 return (errs); 1420 } 1421 1422 int 1423 pfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs, 1424 int depth) 1425 { 1426 struct pf_rule *r; 1427 int error, len = strlen(path); 1428 int brace = 0; 1429 unsigned int rno = 0; 1430 1431 pf->anchor = rs->anchor; 1432 1433 if (path[0]) 1434 snprintf(&path[len], PATH_MAX - len, "/%s", pf->anchor->name); 1435 else 1436 snprintf(&path[len], PATH_MAX - len, "%s", pf->anchor->path); 1437 1438 if (depth) { 1439 if (TAILQ_FIRST(rs->rules.active.ptr) != NULL) { 1440 brace++; 1441 if (pf->opts & PF_OPT_VERBOSE) 1442 printf(" {\n"); 1443 if ((pf->opts & PF_OPT_NOACTION) == 0 && 1444 (error = pfctl_ruleset_trans(pf, 1445 path, rs->anchor))) { 1446 printf("pfctl_load_ruleset: " 1447 "pfctl_ruleset_trans %d\n", error); 1448 goto error; 1449 } 1450 } else if (pf->opts & PF_OPT_VERBOSE) 1451 printf("\n"); 1452 } 1453 1454 if (pf->optimize) 1455 pfctl_optimize_ruleset(pf, rs); 1456 1457 while ((r = TAILQ_FIRST(rs->rules.active.ptr)) != NULL) { 1458 TAILQ_REMOVE(rs->rules.active.ptr, r, entries); 1459 pfctl_expand_label_nr(r, rno); 1460 rno++; 1461 if ((error = pfctl_load_rule(pf, path, r, depth))) 1462 goto error; 1463 if (r->anchor) { 1464 if ((error = pfctl_load_ruleset(pf, path, 1465 &r->anchor->ruleset, depth + 1))) 1466 goto error; 1467 } else if (pf->opts & PF_OPT_VERBOSE) 1468 printf("\n"); 1469 free(r); 1470 } 1471 if (brace && pf->opts & PF_OPT_VERBOSE) { 1472 INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1473 printf("}\n"); 1474 } 1475 path[len] = '\0'; 1476 return (0); 1477 1478 error: 1479 path[len] = '\0'; 1480 return (error); 1481 1482 } 1483 1484 int 1485 pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) 1486 { 1487 char *name; 1488 struct pfioc_rule pr; 1489 int len = strlen(path); 1490 1491 bzero(&pr, sizeof(pr)); 1492 /* set up anchor before adding to path for anchor_call */ 1493 if ((pf->opts & PF_OPT_NOACTION) == 0) 1494 pr.ticket = pfctl_get_ticket(pf->trans, PF_TRANS_RULESET, path); 1495 if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >= sizeof(pr.anchor)) 1496 errx(1, "pfctl_load_rule: strlcpy"); 1497 1498 if (r->anchor) { 1499 if (r->anchor->match) { 1500 if (path[0]) 1501 snprintf(&path[len], PATH_MAX - len, 1502 "/%s", r->anchor->name); 1503 else 1504 snprintf(&path[len], PATH_MAX - len, 1505 "%s", r->anchor->name); 1506 name = r->anchor->name; 1507 } else 1508 name = r->anchor->path; 1509 } else 1510 name = ""; 1511 1512 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1513 memcpy(&pr.rule, r, sizeof(pr.rule)); 1514 if (r->anchor && strlcpy(pr.anchor_call, name, 1515 sizeof(pr.anchor_call)) >= sizeof(pr.anchor_call)) 1516 errx(1, "pfctl_load_rule: strlcpy"); 1517 if (ioctl(pf->dev, DIOCADDRULE, &pr) == -1) 1518 err(1, "DIOCADDRULE"); 1519 } 1520 1521 if (pf->opts & PF_OPT_VERBOSE) { 1522 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 1523 print_rule(r, name, pf->opts); 1524 } 1525 path[len] = '\0'; 1526 return (0); 1527 } 1528 1529 int 1530 pfctl_rules(int dev, char *filename, int opts, int optimize, 1531 char *anchorname, struct pfr_buffer *trans) 1532 { 1533 #define ERR(x) do { warn(x); goto _error; } while(0) 1534 #define ERRX(x) do { warnx(x); goto _error; } while(0) 1535 1536 struct pfr_buffer *t, buf; 1537 struct pfctl pf; 1538 struct pf_ruleset *rs; 1539 struct pfr_table trs; 1540 char *path = NULL; 1541 int osize; 1542 char *p; 1543 1544 bzero(&pf, sizeof(pf)); 1545 RB_INIT(&pf_anchors); 1546 memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); 1547 pf_init_ruleset(&pf_main_anchor.ruleset); 1548 if (trans == NULL) { 1549 bzero(&buf, sizeof(buf)); 1550 buf.pfrb_type = PFRB_TRANS; 1551 t = &buf; 1552 osize = 0; 1553 } else { 1554 t = trans; 1555 osize = t->pfrb_size; 1556 } 1557 1558 memset(&pf, 0, sizeof(pf)); 1559 memset(&trs, 0, sizeof(trs)); 1560 if ((path = calloc(1, PATH_MAX)) == NULL) 1561 ERRX("pfctl_rules: calloc"); 1562 if (strlcpy(trs.pfrt_anchor, anchorname, 1563 sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) 1564 ERRX("pfctl_rules: strlcpy"); 1565 pf.dev = dev; 1566 pf.opts = opts; 1567 pf.optimize = optimize; 1568 1569 /* non-brace anchor, create without resolving the path */ 1570 if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) 1571 ERRX("pfctl_rules: calloc"); 1572 rs = &pf.anchor->ruleset; 1573 pf_init_ruleset(rs); 1574 rs->anchor = pf.anchor; 1575 if (strlcpy(pf.anchor->path, anchorname, 1576 sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 1577 errx(1, "%s: strlcpy", __func__); 1578 1579 if ((p = strrchr(anchorname, '/')) != NULL) { 1580 if (strlen(p) == 1) 1581 errx(1, "%s: bad anchor name %s", __func__, anchorname); 1582 } else 1583 p = anchorname; 1584 1585 if (strlcpy(pf.anchor->name, p, 1586 sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 1587 errx(1, "%s: strlcpy", __func__); 1588 1589 pf.astack[0] = pf.anchor; 1590 pf.asd = 0; 1591 pf.trans = t; 1592 pfctl_init_options(&pf); 1593 1594 if ((opts & PF_OPT_NOACTION) == 0) { 1595 /* 1596 * XXX For the time being we need to open transactions for 1597 * the main ruleset before parsing, because tables are still 1598 * loaded at parse time. 1599 */ 1600 if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor)) 1601 ERRX("pfctl_rules"); 1602 pf.astack[0]->ruleset.tticket = 1603 pfctl_get_ticket(t, PF_TRANS_TABLE, anchorname); 1604 } 1605 1606 if (parse_config(filename, &pf) < 0) { 1607 if ((opts & PF_OPT_NOACTION) == 0) 1608 ERRX("Syntax error in config file: " 1609 "pf rules not loaded"); 1610 else 1611 goto _error; 1612 } 1613 1614 if (!anchorname[0] && (pfctl_check_qassignments(&pf.anchor->ruleset) || 1615 pfctl_load_queues(&pf))) { 1616 if ((opts & PF_OPT_NOACTION) == 0) 1617 ERRX("Unable to load queues into kernel"); 1618 else 1619 goto _error; 1620 } 1621 1622 if (pfctl_load_ruleset(&pf, path, rs, 0)) { 1623 if ((opts & PF_OPT_NOACTION) == 0) 1624 ERRX("Unable to load rules into kernel"); 1625 else 1626 goto _error; 1627 } 1628 1629 free(path); 1630 path = NULL; 1631 1632 if (trans == NULL) { 1633 /* 1634 * process "load anchor" directives that might have used queues 1635 */ 1636 if (pfctl_load_anchors(dev, &pf, t) == -1) 1637 ERRX("load anchors"); 1638 pfctl_clear_queues(&qspecs); 1639 pfctl_clear_queues(&rootqs); 1640 1641 if ((opts & PF_OPT_NOACTION) == 0) { 1642 if (!anchorname[0] && pfctl_load_options(&pf)) 1643 goto _error; 1644 if (pfctl_trans(dev, t, DIOCXCOMMIT, osize)) 1645 ERR("DIOCXCOMMIT"); 1646 } 1647 } 1648 return (0); 1649 1650 _error: 1651 if (trans == NULL) { /* main ruleset */ 1652 if ((opts & PF_OPT_NOACTION) == 0) 1653 if (pfctl_trans(dev, t, DIOCXROLLBACK, osize)) 1654 err(1, "DIOCXROLLBACK"); 1655 exit(1); 1656 } else { /* sub ruleset */ 1657 free(path); 1658 return (-1); 1659 } 1660 1661 #undef ERR 1662 #undef ERRX 1663 } 1664 1665 FILE * 1666 pfctl_fopen(const char *name, const char *mode) 1667 { 1668 struct stat st; 1669 FILE *fp; 1670 1671 fp = fopen(name, mode); 1672 if (fp == NULL) 1673 return (NULL); 1674 if (fstat(fileno(fp), &st) == -1) { 1675 fclose(fp); 1676 return (NULL); 1677 } 1678 if (S_ISDIR(st.st_mode)) { 1679 fclose(fp); 1680 errno = EISDIR; 1681 return (NULL); 1682 } 1683 return (fp); 1684 } 1685 1686 void 1687 pfctl_init_options(struct pfctl *pf) 1688 { 1689 int64_t mem; 1690 int mib[2], mcl; 1691 size_t size; 1692 1693 pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 1694 pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; 1695 pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 1696 pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; 1697 pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; 1698 pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; 1699 pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; 1700 pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; 1701 pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; 1702 pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; 1703 pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; 1704 pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; 1705 pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; 1706 pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; 1707 pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; 1708 pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; 1709 pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; 1710 pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; 1711 pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; 1712 pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; 1713 1714 pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; 1715 1716 pf->syncookieswat[0] = PF_SYNCOOKIES_LOWATPCT; 1717 pf->syncookieswat[1] = PF_SYNCOOKIES_HIWATPCT; 1718 1719 mib[0] = CTL_KERN; 1720 mib[1] = KERN_MAXCLUSTERS; 1721 size = sizeof(mcl); 1722 if (sysctl(mib, 2, &mcl, &size, NULL, 0) == -1) 1723 err(1, "sysctl"); 1724 pf->limit[PF_LIMIT_FRAGS] = mcl / 4; 1725 1726 pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; 1727 pf->limit[PF_LIMIT_TABLES] = PFR_KTABLE_HIWAT; 1728 pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; 1729 pf->limit[PF_LIMIT_PKTDELAY_PKTS] = PF_PKTDELAY_MAXPKTS; 1730 pf->limit[PF_LIMIT_ANCHORS] = PF_ANCHOR_HIWAT; 1731 1732 mib[0] = CTL_HW; 1733 mib[1] = HW_PHYSMEM64; 1734 size = sizeof(mem); 1735 if (sysctl(mib, 2, &mem, &size, NULL, 0) == -1) 1736 err(1, "sysctl"); 1737 if (mem <= 100*1024*1024) 1738 pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT_SMALL; 1739 1740 pf->debug = LOG_ERR; 1741 pf->debug_set = 0; 1742 pf->reassemble = PF_REASS_ENABLED; 1743 } 1744 1745 int 1746 pfctl_load_options(struct pfctl *pf) 1747 { 1748 int i, error = 0; 1749 1750 /* load limits */ 1751 for (i = 0; i < PF_LIMIT_MAX; i++) 1752 if (pfctl_load_limit(pf, i, pf->limit[i])) 1753 error = 1; 1754 1755 /* 1756 * If we've set the states limit, but haven't explicitly set adaptive 1757 * timeouts, do it now with a start of 60% and end of 120%. 1758 */ 1759 if (pf->limit_set[PF_LIMIT_STATES] && 1760 !pf->timeout_set[PFTM_ADAPTIVE_START] && 1761 !pf->timeout_set[PFTM_ADAPTIVE_END]) { 1762 pf->timeout[PFTM_ADAPTIVE_START] = 1763 (pf->limit[PF_LIMIT_STATES] / 10) * 6; 1764 pf->timeout_set[PFTM_ADAPTIVE_START] = 1; 1765 pf->timeout[PFTM_ADAPTIVE_END] = 1766 (pf->limit[PF_LIMIT_STATES] / 10) * 12; 1767 pf->timeout_set[PFTM_ADAPTIVE_END] = 1; 1768 } 1769 1770 /* load timeouts */ 1771 for (i = 0; i < PFTM_MAX; i++) 1772 if (pfctl_load_timeout(pf, i, pf->timeout[i])) 1773 error = 1; 1774 1775 /* load debug */ 1776 if (pf->debug_set && pfctl_load_debug(pf, pf->debug)) 1777 error = 1; 1778 1779 /* load logif */ 1780 if (pf->ifname_set && pfctl_load_logif(pf, pf->ifname)) 1781 error = 1; 1782 1783 /* load hostid */ 1784 if (pf->hostid_set && pfctl_load_hostid(pf, pf->hostid)) 1785 error = 1; 1786 1787 /* load reassembly settings */ 1788 if (pf->reass_set && pfctl_load_reassembly(pf, pf->reassemble)) 1789 error = 1; 1790 1791 /* load syncookies settings */ 1792 if (pf->syncookies_set && pfctl_load_syncookies(pf, pf->syncookies)) 1793 error = 1; 1794 if (pf->syncookieswat_set) { 1795 struct pfioc_limit pl; 1796 unsigned curlim; 1797 1798 if (pf->limit_set[PF_LIMIT_STATES]) 1799 curlim = pf->limit[PF_LIMIT_STATES]; 1800 else { 1801 memset(&pl, 0, sizeof(pl)); 1802 pl.index = pf_limits[PF_LIMIT_STATES].index; 1803 if (ioctl(dev, DIOCGETLIMIT, &pl) == -1) 1804 err(1, "DIOCGETLIMIT"); 1805 curlim = pl.limit; 1806 } 1807 if (pfctl_set_synflwats(pf, curlim * pf->syncookieswat[0]/100, 1808 curlim * pf->syncookieswat[1]/100)) 1809 error = 1; 1810 } 1811 1812 return (error); 1813 } 1814 1815 int 1816 pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) 1817 { 1818 int i; 1819 1820 for (i = 0; pf_limits[i].name; i++) { 1821 if (strcasecmp(opt, pf_limits[i].name) == 0) { 1822 pf->limit[pf_limits[i].index] = limit; 1823 pf->limit_set[pf_limits[i].index] = 1; 1824 break; 1825 } 1826 } 1827 if (pf_limits[i].name == NULL) { 1828 warnx("Bad pool name."); 1829 return (1); 1830 } 1831 1832 if (pf->opts & PF_OPT_VERBOSE) 1833 printf("set limit %s %d\n", opt, limit); 1834 1835 return (0); 1836 } 1837 1838 int 1839 pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) 1840 { 1841 struct pfioc_limit pl; 1842 1843 memset(&pl, 0, sizeof(pl)); 1844 pl.index = index; 1845 pl.limit = limit; 1846 if (ioctl(pf->dev, DIOCSETLIMIT, &pl) == -1) { 1847 if (errno == EBUSY) 1848 warnx("Current pool size exceeds requested %s limit %u", 1849 pf_limits[index].name, limit); 1850 else 1851 warnx("Cannot set %s limit to %u", 1852 pf_limits[index].name, limit); 1853 return (1); 1854 } 1855 return (0); 1856 } 1857 1858 int 1859 pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 1860 { 1861 int i; 1862 1863 for (i = 0; pf_timeouts[i].name; i++) { 1864 if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 1865 pf->timeout[pf_timeouts[i].timeout] = seconds; 1866 pf->timeout_set[pf_timeouts[i].timeout] = 1; 1867 break; 1868 } 1869 } 1870 1871 if (pf_timeouts[i].name == NULL) { 1872 warnx("Bad timeout name."); 1873 return (1); 1874 } 1875 1876 1877 if (pf->opts & PF_OPT_VERBOSE && ! quiet) 1878 printf("set timeout %s %d\n", opt, seconds); 1879 1880 return (0); 1881 } 1882 1883 int 1884 pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) 1885 { 1886 struct pfioc_tm pt; 1887 1888 memset(&pt, 0, sizeof(pt)); 1889 pt.timeout = timeout; 1890 pt.seconds = seconds; 1891 if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt) == -1) { 1892 warnx("DIOCSETTIMEOUT"); 1893 return (1); 1894 } 1895 return (0); 1896 } 1897 1898 int 1899 pfctl_set_synflwats(struct pfctl *pf, u_int32_t lowat, u_int32_t hiwat) 1900 { 1901 struct pfioc_synflwats ps; 1902 1903 memset(&ps, 0, sizeof(ps)); 1904 ps.hiwat = hiwat; 1905 ps.lowat = lowat; 1906 1907 if (ioctl(pf->dev, DIOCSETSYNFLWATS, &ps) == -1) { 1908 warnx("Cannot set synflood detection watermarks"); 1909 return (1); 1910 } 1911 return (0); 1912 } 1913 1914 int 1915 pfctl_set_reassembly(struct pfctl *pf, int on, int nodf) 1916 { 1917 pf->reass_set = 1; 1918 if (on) { 1919 pf->reassemble = PF_REASS_ENABLED; 1920 if (nodf) 1921 pf->reassemble |= PF_REASS_NODF; 1922 } else { 1923 pf->reassemble = 0; 1924 } 1925 1926 if (pf->opts & PF_OPT_VERBOSE) 1927 printf("set reassemble %s %s\n", on ? "yes" : "no", 1928 nodf ? "no-df" : ""); 1929 1930 return (0); 1931 } 1932 1933 int 1934 pfctl_set_syncookies(struct pfctl *pf, u_int8_t val, struct pfctl_watermarks *w) 1935 { 1936 if (val != PF_SYNCOOKIES_ADAPTIVE && w != NULL) { 1937 warnx("syncookies start/end only apply to adaptive"); 1938 return (1); 1939 } 1940 if (val == PF_SYNCOOKIES_ADAPTIVE && w != NULL) { 1941 if (!w->hi) 1942 w->hi = PF_SYNCOOKIES_HIWATPCT; 1943 if (!w->lo) 1944 w->lo = w->hi / 2; 1945 if (w->lo >= w->hi) { 1946 warnx("start must be higher than end"); 1947 return (1); 1948 } 1949 pf->syncookieswat[0] = w->lo; 1950 pf->syncookieswat[1] = w->hi; 1951 pf->syncookieswat_set = 1; 1952 } 1953 1954 if (pf->opts & PF_OPT_VERBOSE) { 1955 if (val == PF_SYNCOOKIES_NEVER) 1956 printf("set syncookies never\n"); 1957 else if (val == PF_SYNCOOKIES_ALWAYS) 1958 printf("set syncookies always\n"); 1959 else if (val == PF_SYNCOOKIES_ADAPTIVE) { 1960 if (pf->syncookieswat_set) 1961 printf("set syncookies adaptive (start %u%%, " 1962 "end %u%%)\n", pf->syncookieswat[1], 1963 pf->syncookieswat[0]); 1964 else 1965 printf("set syncookies adaptive\n"); 1966 } else { /* cannot happen */ 1967 warnx("king bula ate all syncookies"); 1968 return (1); 1969 } 1970 } 1971 1972 pf->syncookies_set = 1; 1973 pf->syncookies = val; 1974 return (0); 1975 } 1976 1977 int 1978 pfctl_set_optimization(struct pfctl *pf, const char *opt) 1979 { 1980 const struct pf_hint *hint; 1981 int i, r; 1982 1983 for (i = 0; pf_hints[i].name; i++) 1984 if (strcasecmp(opt, pf_hints[i].name) == 0) 1985 break; 1986 1987 hint = pf_hints[i].hint; 1988 if (hint == NULL) { 1989 warnx("invalid state timeouts optimization"); 1990 return (1); 1991 } 1992 1993 for (i = 0; hint[i].name; i++) 1994 if ((r = pfctl_set_timeout(pf, hint[i].name, 1995 hint[i].timeout, 1))) 1996 return (r); 1997 1998 if (pf->opts & PF_OPT_VERBOSE) 1999 printf("set optimization %s\n", opt); 2000 2001 return (0); 2002 } 2003 2004 int 2005 pfctl_set_logif(struct pfctl *pf, char *ifname) 2006 { 2007 if (!strcmp(ifname, "none")) { 2008 free(pf->ifname); 2009 pf->ifname = NULL; 2010 } else { 2011 pf->ifname = strdup(ifname); 2012 if (!pf->ifname) 2013 errx(1, "pfctl_set_logif: strdup"); 2014 } 2015 pf->ifname_set = 1; 2016 2017 if (pf->opts & PF_OPT_VERBOSE) 2018 printf("set loginterface %s\n", ifname); 2019 2020 return (0); 2021 } 2022 2023 int 2024 pfctl_load_logif(struct pfctl *pf, char *ifname) 2025 { 2026 struct pfioc_iface pi; 2027 2028 memset(&pi, 0, sizeof(pi)); 2029 if (ifname && strlcpy(pi.pfiio_name, ifname, 2030 sizeof(pi.pfiio_name)) >= sizeof(pi.pfiio_name)) { 2031 warnx("pfctl_load_logif: strlcpy"); 2032 return (1); 2033 } 2034 if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi) == -1) { 2035 warnx("DIOCSETSTATUSIF"); 2036 return (1); 2037 } 2038 return (0); 2039 } 2040 2041 void 2042 pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 2043 { 2044 HTONL(hostid); 2045 2046 pf->hostid = hostid; 2047 pf->hostid_set = 1; 2048 2049 if (pf->opts & PF_OPT_VERBOSE) 2050 printf("set hostid 0x%08x\n", ntohl(hostid)); 2051 } 2052 2053 int 2054 pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) 2055 { 2056 if (ioctl(dev, DIOCSETHOSTID, &hostid) == -1) { 2057 warnx("DIOCSETHOSTID"); 2058 return (1); 2059 } 2060 return (0); 2061 } 2062 2063 int 2064 pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly) 2065 { 2066 if (ioctl(dev, DIOCSETREASS, &reassembly) == -1) { 2067 warnx("DIOCSETREASS"); 2068 return (1); 2069 } 2070 return (0); 2071 } 2072 2073 int 2074 pfctl_load_syncookies(struct pfctl *pf, u_int8_t val) 2075 { 2076 if (ioctl(dev, DIOCSETSYNCOOKIES, &val) == -1) { 2077 warnx("DIOCSETSYNCOOKIES"); 2078 return (1); 2079 } 2080 return (0); 2081 } 2082 2083 int 2084 pfctl_set_debug(struct pfctl *pf, char *d) 2085 { 2086 u_int32_t level; 2087 int loglevel; 2088 2089 if ((loglevel = string_to_loglevel(d)) >= 0) 2090 level = loglevel; 2091 else { 2092 warnx("unknown debug level \"%s\"", d); 2093 return (-1); 2094 } 2095 pf->debug = level; 2096 pf->debug_set = 1; 2097 2098 if ((pf->opts & PF_OPT_NOACTION) == 0) 2099 if (ioctl(dev, DIOCSETDEBUG, &level) == -1) 2100 err(1, "DIOCSETDEBUG"); 2101 2102 if (pf->opts & PF_OPT_VERBOSE) 2103 printf("set debug %s\n", d); 2104 2105 return (0); 2106 } 2107 2108 int 2109 pfctl_load_debug(struct pfctl *pf, unsigned int level) 2110 { 2111 if (ioctl(pf->dev, DIOCSETDEBUG, &level) == -1) { 2112 warnx("DIOCSETDEBUG"); 2113 return (1); 2114 } 2115 return (0); 2116 } 2117 2118 int 2119 pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) 2120 { 2121 struct pfioc_iface pi; 2122 2123 bzero(&pi, sizeof(pi)); 2124 2125 pi.pfiio_flags = flags; 2126 2127 if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= 2128 sizeof(pi.pfiio_name)) 2129 errx(1, "pfctl_set_interface_flags: strlcpy"); 2130 2131 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2132 if (how == 0) { 2133 if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi) == -1) 2134 err(1, "DIOCCLRIFFLAG"); 2135 } else { 2136 if (ioctl(pf->dev, DIOCSETIFFLAG, &pi) == -1) 2137 err(1, "DIOCSETIFFLAG"); 2138 } 2139 } 2140 return (0); 2141 } 2142 2143 void 2144 pfctl_debug(int dev, u_int32_t level, int opts) 2145 { 2146 struct pfr_buffer t; 2147 2148 memset(&t, 0, sizeof(t)); 2149 t.pfrb_type = PFRB_TRANS; 2150 if (pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 2151 ioctl(dev, DIOCSETDEBUG, &level) == -1|| 2152 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 2153 err(1, "pfctl_debug ioctl"); 2154 2155 if ((opts & PF_OPT_QUIET) == 0) 2156 fprintf(stderr, "debug level set to '%s'\n", 2157 loglevel_to_string(level)); 2158 } 2159 2160 int 2161 pfctl_walk_show(int opts, struct pfioc_ruleset *pr, void *warg) 2162 { 2163 if (pr->path[0]) { 2164 if (pr->path[0] != '_' || (opts & PF_OPT_VERBOSE)) 2165 printf(" %s/%s\n", pr->path, pr->name); 2166 } else if (pr->name[0] != '_' || (opts & PF_OPT_VERBOSE)) 2167 printf(" %s\n", pr->name); 2168 2169 return (0); 2170 } 2171 2172 int 2173 pfctl_walk_get(int opts, struct pfioc_ruleset *pr, void *warg) 2174 { 2175 struct pfr_anchoritem *pfra; 2176 struct pfr_anchors *anchors; 2177 int e; 2178 2179 anchors = (struct pfr_anchors *) warg; 2180 2181 pfra = malloc(sizeof(*pfra)); 2182 if (pfra == NULL) 2183 err(1, "%s", __func__); 2184 2185 if (pr->path[0]) 2186 e = asprintf(&pfra->pfra_anchorname, "%s/%s", pr->path, 2187 pr->name); 2188 else 2189 e = asprintf(&pfra->pfra_anchorname, "%s", pr->name); 2190 2191 if (e == -1) 2192 err(1, "%s", __func__); 2193 2194 2195 SLIST_INSERT_HEAD(anchors, pfra, pfra_sle); 2196 2197 return (0); 2198 } 2199 2200 int 2201 pfctl_walk_anchors(int dev, int opts, const char *anchor, 2202 int(walkf)(int, struct pfioc_ruleset *, void *), void *warg) 2203 { 2204 struct pfioc_ruleset pr; 2205 u_int32_t mnr, nr; 2206 2207 memset(&pr, 0, sizeof(pr)); 2208 strlcpy(pr.path, anchor, sizeof(pr.path)); 2209 if (ioctl(dev, DIOCGETRULESETS, &pr) == -1) 2210 errx(1, "%s", pf_strerror(errno)); 2211 mnr = pr.nr; 2212 for (nr = 0; nr < mnr; ++nr) { 2213 char sub[PATH_MAX]; 2214 2215 pr.nr = nr; 2216 if (ioctl(dev, DIOCGETRULESET, &pr) == -1) 2217 errx(1, "%s", pf_strerror(errno)); 2218 if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) 2219 continue; 2220 sub[0] = '\0'; 2221 2222 if (walkf(opts, &pr, warg)) 2223 return (-1); 2224 2225 if (pr.path[0]) 2226 snprintf(sub, sizeof(sub), "%s/%s", 2227 pr.path, pr.name); 2228 else 2229 snprintf(sub, sizeof(sub), "%s", 2230 pr.name); 2231 if (pfctl_walk_anchors(dev, opts, sub, walkf, warg)) 2232 return (-1); 2233 } 2234 return (0); 2235 } 2236 2237 int 2238 pfctl_show_anchors(int dev, int opts, char *anchor) 2239 { 2240 return ( 2241 pfctl_walk_anchors(dev, opts, anchor, pfctl_walk_show, NULL)); 2242 } 2243 2244 struct pfr_anchors * 2245 pfctl_get_anchors(int dev, const char *anchor, int opts) 2246 { 2247 struct pfioc_ruleset pr; 2248 static struct pfr_anchors anchors; 2249 char anchorbuf[PATH_MAX]; 2250 char *n; 2251 2252 SLIST_INIT(&anchors); 2253 2254 memset(&pr, 0, sizeof(pr)); 2255 if (*anchor != '\0') { 2256 strlcpy(anchorbuf, anchor, sizeof(anchorbuf)); 2257 n = dirname(anchorbuf); 2258 if (n[0] != '.' && n[1] != '\0') 2259 strlcpy(pr.path, n, sizeof(pr.path)); 2260 strlcpy(anchorbuf, anchor, sizeof(anchorbuf)); 2261 n = basename(anchorbuf); 2262 if (n != NULL) 2263 strlcpy(pr.name, n, sizeof(pr.name)); 2264 } 2265 2266 /* insert a root anchor first. */ 2267 pfctl_walk_get(opts, &pr, &anchors); 2268 2269 if (pfctl_walk_anchors(dev, opts, anchor, pfctl_walk_get, &anchors)) 2270 errx(1, 2271 "%s failed to retrieve list of anchors, can't continue", 2272 __func__); 2273 2274 return (&anchors); 2275 } 2276 2277 int 2278 pfctl_call_cleartables(int dev, int opts, struct pfr_anchoritem *pfra) 2279 { 2280 /* 2281 * PF_OPT_QUIET makes pfctl_clear_tables() to stop printing number of 2282 * tables cleared for given anchor. 2283 */ 2284 opts |= PF_OPT_QUIET; 2285 return ((pfctl_clear_tables(pfra->pfra_anchorname, opts) == -1) ? 2286 1 : 0); 2287 } 2288 2289 int 2290 pfctl_call_clearrules(int dev, int opts, struct pfr_anchoritem *pfra) 2291 { 2292 /* 2293 * PF_OPT_QUIET makes pfctl_clear_rules() to stop printing a 'rules 2294 * cleared' message for every anchor it deletes. 2295 */ 2296 opts |= PF_OPT_QUIET; 2297 return (pfctl_clear_rules(dev, opts, pfra->pfra_anchorname)); 2298 } 2299 2300 int 2301 pfctl_call_clearanchors(int dev, int opts, struct pfr_anchoritem *pfra) 2302 { 2303 int rv = 0; 2304 2305 rv |= pfctl_call_cleartables(dev, opts, pfra); 2306 rv |= pfctl_call_clearrules(dev, opts, pfra); 2307 2308 return (rv); 2309 } 2310 2311 int 2312 pfctl_recurse(int dev, int opts, const char *anchorname, 2313 int(*walkf)(int, int, struct pfr_anchoritem *)) 2314 { 2315 int rv = 0; 2316 struct pfr_anchors *anchors; 2317 struct pfr_anchoritem *pfra, *pfra_save; 2318 2319 anchors = pfctl_get_anchors(dev, anchorname, opts); 2320 /* 2321 * While traversing the list, pfctl_clear_*() must always return 2322 * so that failures on one anchor do not prevent clearing others. 2323 */ 2324 opts |= PF_OPT_IGNFAIL; 2325 printf("Removing:\n"); 2326 SLIST_FOREACH_SAFE(pfra, anchors, pfra_sle, pfra_save) { 2327 printf(" %s\n", (*pfra->pfra_anchorname == '\0') ? 2328 "/" : pfra->pfra_anchorname); 2329 rv |= walkf(dev, opts, pfra); 2330 SLIST_REMOVE(anchors, pfra, pfr_anchoritem, pfra_sle); 2331 free(pfra->pfra_anchorname); 2332 free(pfra); 2333 } 2334 2335 return (rv); 2336 } 2337 2338 const char * 2339 pfctl_lookup_option(char *cmd, const char **list) 2340 { 2341 const char *item = NULL; 2342 2343 if (cmd != NULL && *cmd) 2344 for (; *list; list++) 2345 if (!strncmp(cmd, *list, strlen(cmd))) { 2346 if (item == NULL) 2347 item = *list; 2348 else 2349 errx(1, "%s is ambigious", cmd); 2350 } 2351 2352 return (item); 2353 } 2354 2355 2356 void 2357 pfctl_state_store(int dev, const char *file) 2358 { 2359 FILE *f; 2360 struct pfioc_states ps; 2361 char *inbuf = NULL, *newinbuf = NULL; 2362 size_t n, len = 0; 2363 2364 f = fopen(file, "w"); 2365 if (f == NULL) 2366 err(1, "open: %s", file); 2367 2368 memset(&ps, 0, sizeof(ps)); 2369 for (;;) { 2370 ps.ps_len = len; 2371 if (len) { 2372 newinbuf = realloc(inbuf, len); 2373 if (newinbuf == NULL) 2374 err(1, "realloc"); 2375 ps.ps_buf = inbuf = newinbuf; 2376 } 2377 if (ioctl(dev, DIOCGETSTATES, &ps) == -1) 2378 err(1, "DIOCGETSTATES"); 2379 2380 if (ps.ps_len + sizeof(struct pfioc_states) < len) 2381 break; 2382 if (len == 0 && ps.ps_len == 0) 2383 goto done; 2384 if (len == 0 && ps.ps_len != 0) 2385 len = ps.ps_len; 2386 if (ps.ps_len == 0) 2387 goto done; /* no states */ 2388 len *= 2; 2389 } 2390 2391 n = ps.ps_len / sizeof(struct pfsync_state); 2392 if (fwrite(inbuf, sizeof(struct pfsync_state), n, f) < n) 2393 err(1, "fwrite"); 2394 2395 done: 2396 free(inbuf); 2397 fclose(f); 2398 } 2399 2400 void 2401 pfctl_state_load(int dev, const char *file) 2402 { 2403 FILE *f; 2404 struct pfioc_state ps; 2405 2406 f = fopen(file, "r"); 2407 if (f == NULL) 2408 err(1, "open: %s", file); 2409 2410 while (fread(&ps.state, sizeof(ps.state), 1, f) == 1) { 2411 if (ioctl(dev, DIOCADDSTATE, &ps) == -1) { 2412 switch (errno) { 2413 case EEXIST: 2414 case EINVAL: 2415 break; 2416 default: 2417 err(1, "DIOCADDSTATE"); 2418 } 2419 } 2420 } 2421 2422 fclose(f); 2423 } 2424 2425 void 2426 pfctl_reset(int dev, int opts) 2427 { 2428 struct pfctl pf; 2429 struct pfr_buffer t; 2430 int i; 2431 2432 pf.dev = dev; 2433 pfctl_init_options(&pf); 2434 2435 /* Force reset upon pfctl_load_options() */ 2436 pf.debug_set = 1; 2437 pf.reass_set = 1; 2438 pf.syncookieswat_set = 1; 2439 pf.syncookies_set = 1; 2440 pf.ifname = strdup("none"); 2441 if (pf.ifname == NULL) 2442 err(1, "%s: strdup", __func__); 2443 pf.ifname_set = 1; 2444 2445 memset(&t, 0, sizeof(t)); 2446 t.pfrb_type = PFRB_TRANS; 2447 if (pfctl_trans(dev, &t, DIOCXBEGIN, 0)) 2448 err(1, "%s: DIOCXBEGIN", __func__); 2449 2450 for (i = 0; pf_limits[i].name; i++) 2451 pf.limit_set[pf_limits[i].index] = 1; 2452 2453 for (i = 0; pf_timeouts[i].name; i++) 2454 pf.timeout_set[pf_timeouts[i].timeout] = 1; 2455 2456 pfctl_load_options(&pf); 2457 2458 if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 2459 err(1, "%s: DIOCXCOMMIT", __func__); 2460 2461 pfctl_clear_interface_flags(dev, opts); 2462 } 2463 2464 #ifndef REGRESS_NOMAIN 2465 int 2466 main(int argc, char *argv[]) 2467 { 2468 int ch; 2469 int mode = O_RDONLY; 2470 int opts = 0; 2471 int optimize = PF_OPTIMIZE_BASIC; 2472 int level; 2473 int rdomain = 0; 2474 char anchorname[PATH_MAX]; 2475 int anchor_wildcard = 0; 2476 char *path; 2477 char *lfile = NULL, *sfile = NULL; 2478 const char *errstr; 2479 long shownr = -1; 2480 2481 if (argc < 2) 2482 usage(); 2483 2484 while ((ch = getopt(argc, argv, 2485 "a:dD:eqf:F:ghi:k:K:L:Nno:Pp:R:rS:s:t:T:vV:x:z")) != -1) { 2486 switch (ch) { 2487 case 'a': 2488 anchoropt = optarg; 2489 break; 2490 case 'd': 2491 opts |= PF_OPT_DISABLE; 2492 mode = O_RDWR; 2493 break; 2494 case 'D': 2495 if (pfctl_cmdline_symset(optarg) < 0) 2496 warnx("could not parse macro definition %s", 2497 optarg); 2498 break; 2499 case 'e': 2500 opts |= PF_OPT_ENABLE; 2501 mode = O_RDWR; 2502 break; 2503 case 'q': 2504 opts |= PF_OPT_QUIET; 2505 break; 2506 case 'F': 2507 clearopt = pfctl_lookup_option(optarg, clearopt_list); 2508 if (clearopt == NULL) { 2509 warnx("Unknown flush modifier '%s'", optarg); 2510 usage(); 2511 } 2512 mode = O_RDWR; 2513 break; 2514 case 'i': 2515 ifaceopt = optarg; 2516 break; 2517 case 'k': 2518 if (state_killers >= 2) { 2519 warnx("can only specify -k twice"); 2520 usage(); 2521 /* NOTREACHED */ 2522 } 2523 state_kill[state_killers++] = optarg; 2524 mode = O_RDWR; 2525 break; 2526 case 'K': 2527 if (src_node_killers >= 2) { 2528 warnx("can only specify -K twice"); 2529 usage(); 2530 /* NOTREACHED */ 2531 } 2532 src_node_kill[src_node_killers++] = optarg; 2533 mode = O_RDWR; 2534 break; 2535 case 'N': 2536 opts |= PF_OPT_NODNS; 2537 break; 2538 case 'n': 2539 opts |= PF_OPT_NOACTION; 2540 break; 2541 case 'r': 2542 opts |= PF_OPT_USEDNS; 2543 break; 2544 case 'R': 2545 shownr = strtonum(optarg, -1, LONG_MAX, &errstr); 2546 if (errstr) { 2547 warnx("invalid rule id: %s", errstr); 2548 usage(); 2549 } 2550 break; 2551 case 'f': 2552 rulesopt = optarg; 2553 mode = O_RDWR; 2554 break; 2555 case 'g': 2556 opts |= PF_OPT_DEBUG; 2557 break; 2558 case 'o': 2559 optiopt = pfctl_lookup_option(optarg, optiopt_list); 2560 if (optiopt == NULL) { 2561 warnx("Unknown optimization '%s'", optarg); 2562 usage(); 2563 } 2564 opts |= PF_OPT_OPTIMIZE; 2565 break; 2566 case 'P': 2567 opts |= PF_OPT_PORTNAMES; 2568 break; 2569 case 'p': 2570 pf_device = optarg; 2571 break; 2572 case 's': 2573 showopt = pfctl_lookup_option(optarg, showopt_list); 2574 if (showopt == NULL) { 2575 warnx("Unknown show modifier '%s'", optarg); 2576 usage(); 2577 } 2578 break; 2579 case 't': 2580 tableopt = optarg; 2581 break; 2582 case 'T': 2583 tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 2584 if (tblcmdopt == NULL) { 2585 warnx("Unknown table command '%s'", optarg); 2586 usage(); 2587 } 2588 break; 2589 case 'v': 2590 if (opts & PF_OPT_VERBOSE) 2591 opts |= PF_OPT_VERBOSE2; 2592 opts |= PF_OPT_VERBOSE; 2593 break; 2594 case 'V': 2595 rdomain = strtonum(optarg, 0, RT_TABLEID_MAX, &errstr); 2596 if (errstr) { 2597 warnx("Invalid rdomain: %s", errstr); 2598 usage(); 2599 } 2600 break; 2601 case 'x': 2602 debugopt = pfctl_lookup_option(optarg, debugopt_list); 2603 if (debugopt == NULL) { 2604 warnx("Unknown debug level '%s'", optarg); 2605 usage(); 2606 } 2607 mode = O_RDWR; 2608 break; 2609 case 'z': 2610 opts |= PF_OPT_CLRRULECTRS; 2611 mode = O_RDWR; 2612 break; 2613 case 'S': 2614 sfile = optarg; 2615 break; 2616 case 'L': 2617 mode = O_RDWR; 2618 lfile = optarg; 2619 break; 2620 case 'h': 2621 /* FALLTHROUGH */ 2622 default: 2623 usage(); 2624 /* NOTREACHED */ 2625 } 2626 } 2627 2628 if ((opts & PF_OPT_NODNS) && (opts & PF_OPT_USEDNS)) 2629 errx(1, "-N and -r are mutually exclusive"); 2630 2631 if ((tblcmdopt == NULL) ^ (tableopt == NULL)) 2632 usage(); 2633 2634 if (tblcmdopt != NULL) { 2635 argc -= optind; 2636 argv += optind; 2637 ch = *tblcmdopt; 2638 mode = strchr("st", ch) ? O_RDONLY : O_RDWR; 2639 } else if (argc != optind) { 2640 warnx("unknown command line argument: %s ...", argv[optind]); 2641 usage(); 2642 /* NOTREACHED */ 2643 } 2644 2645 memset(anchorname, 0, sizeof(anchorname)); 2646 if (anchoropt != NULL) { 2647 if (anchoropt[0] == '\0') 2648 errx(1, "anchor name must not be empty"); 2649 if (mode == O_RDONLY && showopt == NULL && tblcmdopt == NULL) { 2650 warnx("anchors apply to -f, -F, -s, and -T only"); 2651 usage(); 2652 } 2653 if (mode == O_RDWR && tblcmdopt == NULL && 2654 (anchoropt[0] == '_' || strstr(anchoropt, "/_") != NULL)) 2655 errx(1, "anchor names beginning with '_' cannot " 2656 "be modified from the command line"); 2657 int len = strlen(anchoropt); 2658 2659 if (anchoropt[len - 1] == '*') { 2660 if (len >= 2 && anchoropt[len - 2] == '/') { 2661 anchoropt[len - 2] = '\0'; 2662 anchor_wildcard = 1; 2663 } else 2664 anchoropt[len - 1] = '\0'; 2665 opts |= PF_OPT_RECURSE; 2666 } 2667 if (strlcpy(anchorname, anchoropt, 2668 sizeof(anchorname)) >= sizeof(anchorname)) 2669 errx(1, "anchor name '%s' too long", 2670 anchoropt); 2671 } 2672 2673 if ((opts & PF_OPT_NOACTION) == 0) { 2674 dev = open(pf_device, mode); 2675 if (dev == -1) 2676 err(1, "%s", pf_device); 2677 } else { 2678 dev = open(pf_device, O_RDONLY); 2679 if (dev >= 0) 2680 opts |= PF_OPT_DUMMYACTION; 2681 /* turn off options */ 2682 opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 2683 clearopt = showopt = debugopt = NULL; 2684 } 2685 2686 if (opts & PF_OPT_DISABLE) 2687 if (pfctl_disable(dev, opts)) 2688 exit_val = 1; 2689 2690 if ((path = calloc(1, PATH_MAX)) == NULL) 2691 errx(1, "%s: calloc", __func__); 2692 2693 if (showopt != NULL) { 2694 switch (*showopt) { 2695 case 'A': 2696 pfctl_show_anchors(dev, opts, anchorname); 2697 break; 2698 case 'r': 2699 pfctl_load_fingerprints(dev, opts); 2700 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 2701 anchorname, 0, anchor_wildcard, shownr); 2702 break; 2703 case 'l': 2704 pfctl_load_fingerprints(dev, opts); 2705 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 2706 anchorname, 0, anchor_wildcard, shownr); 2707 break; 2708 case 'q': 2709 pfctl_show_queues(dev, ifaceopt, opts, 2710 opts & PF_OPT_VERBOSE2); 2711 break; 2712 case 's': 2713 pfctl_show_states(dev, ifaceopt, opts, shownr); 2714 break; 2715 case 'S': 2716 pfctl_show_src_nodes(dev, opts); 2717 break; 2718 case 'i': 2719 pfctl_show_status(dev, opts); 2720 break; 2721 case 't': 2722 pfctl_show_timeouts(dev, opts); 2723 break; 2724 case 'm': 2725 pfctl_show_limits(dev, opts); 2726 break; 2727 case 'a': 2728 opts |= PF_OPT_SHOWALL; 2729 pfctl_load_fingerprints(dev, opts); 2730 2731 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 2732 anchorname, 0, 0, -1); 2733 pfctl_show_queues(dev, ifaceopt, opts, 2734 opts & PF_OPT_VERBOSE2); 2735 pfctl_show_states(dev, ifaceopt, opts, -1); 2736 pfctl_show_src_nodes(dev, opts); 2737 pfctl_show_status(dev, opts); 2738 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 2739 anchorname, 0, 0, -1); 2740 pfctl_show_timeouts(dev, opts); 2741 pfctl_show_limits(dev, opts); 2742 pfctl_show_tables(anchorname, opts); 2743 pfctl_show_fingerprints(opts); 2744 break; 2745 case 'T': 2746 pfctl_show_tables(anchorname, opts); 2747 break; 2748 case 'o': 2749 pfctl_load_fingerprints(dev, opts); 2750 pfctl_show_fingerprints(opts); 2751 break; 2752 case 'I': 2753 pfctl_show_ifaces(ifaceopt, opts); 2754 break; 2755 } 2756 } 2757 2758 if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) 2759 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 2760 anchorname, 0, 0, -1); 2761 2762 if (clearopt != NULL) { 2763 switch (*clearopt) { 2764 case 'r': 2765 if (opts & PF_OPT_RECURSE) 2766 pfctl_recurse(dev, opts, anchorname, 2767 pfctl_call_clearrules); 2768 else 2769 pfctl_clear_rules(dev, opts, anchorname); 2770 break; 2771 case 's': 2772 pfctl_clear_states(dev, ifaceopt, opts); 2773 break; 2774 case 'S': 2775 pfctl_clear_src_nodes(dev, opts); 2776 break; 2777 case 'i': 2778 pfctl_clear_stats(dev, ifaceopt, opts); 2779 break; 2780 case 'a': 2781 if (ifaceopt) { 2782 warnx("don't specify an interface with -Fall"); 2783 usage(); 2784 /* NOTREACHED */ 2785 } 2786 if (opts & PF_OPT_RECURSE) 2787 pfctl_recurse(dev, opts, anchorname, 2788 pfctl_call_clearanchors); 2789 else { 2790 pfctl_clear_tables(anchorname, opts); 2791 pfctl_clear_rules(dev, opts, anchorname); 2792 } 2793 2794 if (!*anchorname) { 2795 pfctl_clear_states(dev, ifaceopt, opts); 2796 pfctl_clear_src_nodes(dev, opts); 2797 pfctl_clear_stats(dev, ifaceopt, opts); 2798 pfctl_clear_fingerprints(dev, opts); 2799 pfctl_reset(dev, opts); 2800 } 2801 break; 2802 case 'o': 2803 pfctl_clear_fingerprints(dev, opts); 2804 break; 2805 case 'T': 2806 if ((opts & PF_OPT_RECURSE) == 0) 2807 pfctl_clear_tables(anchorname, opts); 2808 else 2809 pfctl_recurse(dev, opts, anchorname, 2810 pfctl_call_cleartables); 2811 break; 2812 case 'R': 2813 pfctl_reset(dev, opts); 2814 break; 2815 } 2816 } 2817 if (state_killers) { 2818 if (!strcmp(state_kill[0], "label")) 2819 pfctl_label_kill_states(dev, ifaceopt, opts, rdomain); 2820 else if (!strcmp(state_kill[0], "id")) 2821 pfctl_id_kill_states(dev, opts); 2822 else if (!strcmp(state_kill[0], "key")) 2823 pfctl_key_kill_states(dev, ifaceopt, opts, rdomain); 2824 else 2825 pfctl_net_kill_states(dev, ifaceopt, opts, rdomain); 2826 } 2827 2828 if (src_node_killers) 2829 pfctl_kill_src_nodes(dev, opts); 2830 2831 if (tblcmdopt != NULL) { 2832 exit_val = pfctl_table(argc, argv, tableopt, 2833 tblcmdopt, rulesopt, anchorname, opts); 2834 rulesopt = NULL; 2835 } 2836 if (optiopt != NULL) { 2837 switch (*optiopt) { 2838 case 'n': 2839 optimize = 0; 2840 break; 2841 case 'b': 2842 optimize |= PF_OPTIMIZE_BASIC; 2843 break; 2844 case 'o': 2845 case 'p': 2846 optimize |= PF_OPTIMIZE_PROFILE; 2847 break; 2848 } 2849 } 2850 2851 if (rulesopt != NULL && !anchorname[0]) { 2852 pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET); 2853 if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 2854 exit_val = 1; 2855 } 2856 2857 if (rulesopt != NULL) { 2858 if (pfctl_rules(dev, rulesopt, opts, optimize, 2859 anchorname, NULL)) 2860 exit_val = 1; 2861 } 2862 2863 if (opts & PF_OPT_ENABLE) 2864 if (pfctl_enable(dev, opts)) 2865 exit_val = 1; 2866 2867 if (debugopt != NULL) { 2868 if ((level = string_to_loglevel((char *)debugopt)) < 0) { 2869 switch (*debugopt) { 2870 case 'n': 2871 level = LOG_CRIT; 2872 break; 2873 case 'u': 2874 level = LOG_ERR; 2875 break; 2876 case 'm': 2877 level = LOG_NOTICE; 2878 break; 2879 case 'l': 2880 level = LOG_DEBUG; 2881 break; 2882 } 2883 } 2884 if (level >= 0) 2885 pfctl_debug(dev, level, opts); 2886 } 2887 2888 if (sfile != NULL) 2889 pfctl_state_store(dev, sfile); 2890 if (lfile != NULL) 2891 pfctl_state_load(dev, lfile); 2892 2893 exit(exit_val); 2894 } 2895 #endif /* REGRESS_NOMAIN */ 2896 2897 char * 2898 pf_strerror(int errnum) 2899 { 2900 switch (errnum) { 2901 case ESRCH: 2902 return "Table does not exist"; 2903 case EINVAL: 2904 case ENOENT: 2905 return "Anchor does not exist"; 2906 default: 2907 return strerror(errnum); 2908 } 2909 } 2910