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