1 /* $OpenBSD: pfctl.c,v 1.391 2023/04/28 14:08:38 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 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 ((rule->rule_flag & PFRULE_EXPIRED) && 787 !(opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG))) 788 return; 789 790 if (opts & PF_OPT_DEBUG) { 791 const char *t[PF_SKIP_COUNT] = { "i", "d", "r", "f", 792 "p", "sa", "da", "sp", "dp" }; 793 int i; 794 795 printf(" [ Skip steps: "); 796 for (i = 0; i < PF_SKIP_COUNT; ++i) { 797 if (rule->skip[i].nr == rule->nr + 1) 798 continue; 799 printf("%s=", t[i]); 800 if (rule->skip[i].nr == -1) 801 printf("end "); 802 else 803 printf("%u ", rule->skip[i].nr); 804 } 805 printf("]\n"); 806 807 printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n", 808 rule->qname, rule->qid, rule->pqname, rule->pqid); 809 } 810 if (opts & PF_OPT_VERBOSE) { 811 printf(" [ Evaluations: %-8llu Packets: %-8llu " 812 "Bytes: %-10llu States: %-6u]\n", 813 (unsigned long long)rule->evaluations, 814 (unsigned long long)(rule->packets[0] + 815 rule->packets[1]), 816 (unsigned long long)(rule->bytes[0] + 817 rule->bytes[1]), rule->states_cur); 818 if (!(opts & PF_OPT_DEBUG)) 819 printf(" [ Inserted: uid %lu pid %lu " 820 "State Creations: %-6u]\n", 821 (unsigned long)rule->cuid, (unsigned long)rule->cpid, 822 rule->states_tot); 823 } 824 } 825 826 void 827 pfctl_print_title(char *title) 828 { 829 if (!first_title) 830 printf("\n"); 831 first_title = 0; 832 printf("%s\n", title); 833 } 834 835 int 836 pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, 837 char *anchorname, int depth, int wildcard, long shownr) 838 { 839 struct pfioc_rule pr; 840 u_int32_t header = 0; 841 int len = strlen(path), ret = 0; 842 char *npath, *p; 843 844 if (depth > PF_ANCHOR_STACK_MAX) { 845 warnx("%s: max stack depth exceeded for %s", __func__, path); 846 return (-1); 847 } 848 849 /* 850 * Truncate a trailing / and * on an anchorname before searching for 851 * the ruleset, this is syntactic sugar that doesn't actually make it 852 * to the kernel. 853 */ 854 if ((p = strrchr(anchorname, '/')) != NULL && 855 p[1] == '*' && p[2] == '\0') { 856 p[0] = '\0'; 857 } 858 859 memset(&pr, 0, sizeof(pr)); 860 if (anchorname[0] == '/') { 861 if ((npath = calloc(1, PATH_MAX)) == NULL) 862 err(1, "calloc"); 863 strlcpy(npath, anchorname, PATH_MAX); 864 } else { 865 if (path[0]) 866 snprintf(&path[len], PATH_MAX - len, "/%s", anchorname); 867 else 868 snprintf(&path[len], PATH_MAX - len, "%s", anchorname); 869 npath = path; 870 } 871 872 memcpy(pr.anchor, npath, sizeof(pr.anchor)); 873 if (opts & PF_OPT_SHOWALL) { 874 pr.rule.action = PF_PASS; 875 if (ioctl(dev, DIOCGETRULES, &pr) == -1) { 876 warnx("%s", pf_strerror(errno)); 877 ret = -1; 878 goto error; 879 } 880 header++; 881 if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header)) 882 pfctl_print_title("FILTER RULES:"); 883 else if (format == PFCTL_SHOW_LABELS && labels) 884 pfctl_print_title("LABEL COUNTERS:"); 885 } 886 if (opts & PF_OPT_CLRRULECTRS) 887 pr.action = PF_GET_CLR_CNTR; 888 889 pr.rule.action = PF_PASS; 890 if (ioctl(dev, DIOCGETRULES, &pr) == -1) { 891 warnx("%s", pf_strerror(errno)); 892 ret = -1; 893 goto error; 894 } 895 896 while (ioctl(dev, DIOCGETRULE, &pr) != -1) { 897 if (shownr != -1 && shownr != pr.nr) 898 continue; 899 900 /* anchor is the same for all rules in it */ 901 if (pr.rule.anchor_wildcard == 0) 902 wildcard = 0; 903 904 switch (format) { 905 case PFCTL_SHOW_LABELS: 906 if (pr.rule.label[0]) { 907 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 908 printf("%s %llu %llu %llu %llu" 909 " %llu %llu %llu %llu\n", 910 pr.rule.label, 911 (unsigned long long)pr.rule.evaluations, 912 (unsigned long long)(pr.rule.packets[0] + 913 pr.rule.packets[1]), 914 (unsigned long long)(pr.rule.bytes[0] + 915 pr.rule.bytes[1]), 916 (unsigned long long)pr.rule.packets[0], 917 (unsigned long long)pr.rule.bytes[0], 918 (unsigned long long)pr.rule.packets[1], 919 (unsigned long long)pr.rule.bytes[1], 920 (unsigned long long)pr.rule.states_tot); 921 } 922 break; 923 case PFCTL_SHOW_RULES: 924 if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) 925 labels = 1; 926 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 927 print_rule(&pr.rule, pr.anchor_call, opts); 928 929 /* 930 * If this is an 'unnamed' brace notation anchor OR 931 * the user has explicitly requested recursion, 932 * print it recursively. 933 */ 934 if (pr.anchor_call[0] && 935 (((p = strrchr(pr.anchor_call, '/')) ? 936 p[1] == '_' : pr.anchor_call[0] == '_') || 937 opts & PF_OPT_RECURSE)) { 938 printf(" {\n"); 939 pfctl_print_rule_counters(&pr.rule, opts); 940 pfctl_show_rules(dev, npath, opts, format, 941 pr.anchor_call, depth + 1, 942 pr.rule.anchor_wildcard, -1); 943 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 944 printf("}\n"); 945 } else { 946 if ((pr.rule.rule_flag & PFRULE_EXPIRED) && 947 !(opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG))) 948 break; 949 printf("\n"); 950 pfctl_print_rule_counters(&pr.rule, opts); 951 } 952 break; 953 case PFCTL_SHOW_NOTHING: 954 break; 955 } 956 errno = 0; 957 } 958 959 if (errno != 0 && errno != ENOENT) { 960 warn("DIOCGETRULE"); 961 ret = -1; 962 goto error; 963 } 964 965 /* 966 * If this anchor was called with a wildcard path, go through 967 * the rulesets in the anchor rather than the rules. 968 */ 969 if (wildcard && (opts & PF_OPT_RECURSE)) { 970 struct pfioc_ruleset prs; 971 u_int32_t mnr, nr; 972 973 memset(&prs, 0, sizeof(prs)); 974 memcpy(prs.path, npath, sizeof(prs.path)); 975 if (ioctl(dev, DIOCGETRULESETS, &prs) == -1) 976 errx(1, "%s", pf_strerror(errno)); 977 mnr = prs.nr; 978 979 for (nr = 0; nr < mnr; ++nr) { 980 prs.nr = nr; 981 if (ioctl(dev, DIOCGETRULESET, &prs) == -1) 982 errx(1, "%s", pf_strerror(errno)); 983 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 984 printf("anchor \"%s\" all {\n", prs.name); 985 pfctl_show_rules(dev, npath, opts, 986 format, prs.name, depth + 1, 0, shownr); 987 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 988 printf("}\n"); 989 } 990 path[len] = '\0'; 991 return (0); 992 } 993 994 error: 995 if (path != npath) 996 free(npath); 997 path[len] = '\0'; 998 return (ret); 999 } 1000 1001 int 1002 pfctl_show_src_nodes(int dev, int opts) 1003 { 1004 struct pfioc_src_nodes psn; 1005 struct pf_src_node *p; 1006 char *inbuf = NULL, *newinbuf = NULL; 1007 size_t i, len = 0; 1008 1009 memset(&psn, 0, sizeof(psn)); 1010 for (;;) { 1011 psn.psn_len = len; 1012 if (len) { 1013 newinbuf = realloc(inbuf, len); 1014 if (newinbuf == NULL) 1015 err(1, "realloc"); 1016 psn.psn_buf = inbuf = newinbuf; 1017 } 1018 if (ioctl(dev, DIOCGETSRCNODES, &psn) == -1) { 1019 warn("DIOCGETSRCNODES"); 1020 free(inbuf); 1021 return (-1); 1022 } 1023 if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len) 1024 break; 1025 if (len == 0 && psn.psn_len == 0) 1026 goto done; 1027 if (len == 0 && psn.psn_len != 0) 1028 len = psn.psn_len; 1029 if (psn.psn_len == 0) 1030 goto done; /* no src_nodes */ 1031 len *= 2; 1032 } 1033 p = psn.psn_src_nodes; 1034 if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL)) 1035 pfctl_print_title("SOURCE TRACKING NODES:"); 1036 for (i = 0; i < psn.psn_len; i += sizeof(*p)) { 1037 print_src_node(p, opts); 1038 p++; 1039 } 1040 done: 1041 free(inbuf); 1042 return (0); 1043 } 1044 1045 int 1046 pfctl_show_states(int dev, const char *iface, int opts, long shownr) 1047 { 1048 struct pfioc_states ps; 1049 struct pfsync_state *p; 1050 char *inbuf = NULL, *newinbuf = NULL; 1051 size_t i, len = 0; 1052 int dotitle = (opts & PF_OPT_SHOWALL); 1053 1054 memset(&ps, 0, sizeof(ps)); 1055 for (;;) { 1056 ps.ps_len = len; 1057 if (len) { 1058 newinbuf = realloc(inbuf, len); 1059 if (newinbuf == NULL) 1060 err(1, "realloc"); 1061 ps.ps_buf = inbuf = newinbuf; 1062 } 1063 if (ioctl(dev, DIOCGETSTATES, &ps) == -1) { 1064 warn("DIOCGETSTATES"); 1065 free(inbuf); 1066 return (-1); 1067 } 1068 if (ps.ps_len + sizeof(struct pfioc_states) < len) 1069 break; 1070 if (len == 0 && ps.ps_len == 0) 1071 goto done; 1072 if (len == 0 && ps.ps_len != 0) 1073 len = ps.ps_len; 1074 if (ps.ps_len == 0) 1075 goto done; /* no states */ 1076 len *= 2; 1077 } 1078 p = ps.ps_states; 1079 for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) { 1080 if (iface != NULL && strcmp(p->ifname, iface)) 1081 continue; 1082 if (dotitle) { 1083 pfctl_print_title("STATES:"); 1084 dotitle = 0; 1085 } 1086 if (shownr < 0 || ntohl(p->rule) == shownr) 1087 print_state(p, opts); 1088 } 1089 done: 1090 free(inbuf); 1091 return (0); 1092 } 1093 1094 int 1095 pfctl_show_status(int dev, int opts) 1096 { 1097 struct pf_status status; 1098 struct pfctl_watermarks wats; 1099 struct pfioc_synflwats iocwats; 1100 1101 if (ioctl(dev, DIOCGETSTATUS, &status) == -1) { 1102 warn("DIOCGETSTATUS"); 1103 return (-1); 1104 } 1105 if (ioctl(dev, DIOCGETSYNFLWATS, &iocwats) == -1) { 1106 warn("DIOCGETSYNFLWATS"); 1107 return (-1); 1108 } 1109 wats.hi = iocwats.hiwat; 1110 wats.lo = iocwats.lowat; 1111 if (opts & PF_OPT_SHOWALL) 1112 pfctl_print_title("INFO:"); 1113 print_status(&status, &wats, opts); 1114 return (0); 1115 } 1116 1117 int 1118 pfctl_show_timeouts(int dev, int opts) 1119 { 1120 struct pfioc_tm pt; 1121 int i; 1122 1123 if (opts & PF_OPT_SHOWALL) 1124 pfctl_print_title("TIMEOUTS:"); 1125 memset(&pt, 0, sizeof(pt)); 1126 for (i = 0; pf_timeouts[i].name; i++) { 1127 pt.timeout = pf_timeouts[i].timeout; 1128 if (ioctl(dev, DIOCGETTIMEOUT, &pt) == -1) 1129 err(1, "DIOCGETTIMEOUT"); 1130 printf("%-20s %10d", pf_timeouts[i].name, pt.seconds); 1131 if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && 1132 pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) 1133 printf(" states"); 1134 else 1135 printf("s"); 1136 printf("\n"); 1137 } 1138 return (0); 1139 1140 } 1141 1142 int 1143 pfctl_show_limits(int dev, int opts) 1144 { 1145 struct pfioc_limit pl; 1146 int i; 1147 1148 if (opts & PF_OPT_SHOWALL) 1149 pfctl_print_title("LIMITS:"); 1150 memset(&pl, 0, sizeof(pl)); 1151 for (i = 0; pf_limits[i].name; i++) { 1152 pl.index = pf_limits[i].index; 1153 if (ioctl(dev, DIOCGETLIMIT, &pl) == -1) 1154 err(1, "DIOCGETLIMIT"); 1155 printf("%-13s ", pf_limits[i].name); 1156 if (pl.limit == UINT_MAX) 1157 printf("unlimited\n"); 1158 else 1159 printf("hard limit %8u\n", pl.limit); 1160 } 1161 return (0); 1162 } 1163 1164 /* callbacks for rule/nat/rdr/addr */ 1165 void 1166 pfctl_add_rule(struct pfctl *pf, struct pf_rule *r) 1167 { 1168 struct pf_rule *rule; 1169 struct pf_ruleset *rs; 1170 1171 rs = &pf->anchor->ruleset; 1172 1173 if ((rule = calloc(1, sizeof(*rule))) == NULL) 1174 err(1, "calloc"); 1175 bcopy(r, rule, sizeof(*rule)); 1176 1177 TAILQ_INSERT_TAIL(rs->rules.active.ptr, rule, entries); 1178 } 1179 1180 int 1181 pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a) 1182 { 1183 int osize = pf->trans->pfrb_size; 1184 1185 if (pfctl_add_trans(pf->trans, PF_TRANS_RULESET, path)) 1186 return (3); 1187 if (pfctl_add_trans(pf->trans, PF_TRANS_TABLE, path)) 1188 return (4); 1189 if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1190 return (5); 1191 1192 return (0); 1193 } 1194 1195 int 1196 pfctl_add_queue(struct pfctl *pf, struct pf_queuespec *q) 1197 { 1198 struct pfctl_qsitem *qi; 1199 1200 if (pf->anchor->name[0]) { 1201 printf("must not have queue definitions in an anchor\n"); 1202 return (1); 1203 } 1204 1205 if (q->parent[0] == '\0') { 1206 TAILQ_FOREACH(qi, &rootqs, entries) { 1207 if (strcmp(q->ifname, qi->qs.ifname)) 1208 continue; 1209 printf("A root queue is already defined on %s\n", 1210 qi->qs.ifname); 1211 return (1); 1212 } 1213 } 1214 1215 if ((qi = calloc(1, sizeof(*qi))) == NULL) 1216 err(1, "calloc"); 1217 bcopy(q, &qi->qs, sizeof(qi->qs)); 1218 TAILQ_INIT(&qi->children); 1219 1220 if (qi->qs.parent[0]) 1221 TAILQ_INSERT_TAIL(&qspecs, qi, entries); 1222 else 1223 TAILQ_INSERT_TAIL(&rootqs, qi, entries); 1224 1225 return (0); 1226 } 1227 1228 struct pfctl_qsitem * 1229 pfctl_find_queue(char *what, struct pf_qihead *where) 1230 { 1231 struct pfctl_qsitem *q; 1232 1233 TAILQ_FOREACH(q, where, entries) 1234 if (strcmp(q->qs.qname, what) == 0) 1235 return (q); 1236 1237 return (NULL); 1238 } 1239 1240 u_int 1241 pfctl_find_childqs(struct pfctl_qsitem *qi) 1242 { 1243 struct pfctl_qsitem *n, *p, *q; 1244 u_int flags = qi->qs.flags; 1245 1246 TAILQ_FOREACH(p, &qspecs, entries) { 1247 if (strcmp(p->qs.parent, qi->qs.qname)) 1248 continue; 1249 if (p->qs.ifname[0] && strcmp(p->qs.ifname, qi->qs.ifname)) 1250 continue; 1251 if (++p->matches > 10000) 1252 errx(1, "pfctl_find_childqs: excessive matches, loop?"); 1253 1254 if ((q = pfctl_find_queue(p->qs.qname, &qi->children)) == NULL) { 1255 /* insert */ 1256 if ((n = calloc(1, sizeof(*n))) == NULL) 1257 err(1, "calloc"); 1258 TAILQ_INIT(&n->children); 1259 bcopy(&p->qs, &n->qs, sizeof(n->qs)); 1260 TAILQ_INSERT_TAIL(&qi->children, n, entries); 1261 } else { 1262 if ((q->qs.ifname[0] && p->qs.ifname[0])) 1263 errx(1, "queue %s on %s respecified", 1264 q->qs.qname, q->qs.ifname); 1265 if (!q->qs.ifname[0] && !p->qs.ifname[0]) 1266 errx(1, "queue %s respecified", 1267 q->qs.qname); 1268 /* ifbound beats floating */ 1269 if (!q->qs.ifname[0]) 1270 bcopy(&p->qs, &q->qs, sizeof(q->qs)); 1271 } 1272 } 1273 1274 TAILQ_FOREACH(p, &qi->children, entries) 1275 flags |= pfctl_find_childqs(p); 1276 1277 if (!TAILQ_EMPTY(&qi->children)) { 1278 if (qi->qs.flags & PFQS_DEFAULT) 1279 errx(1, "default queue %s is not a leaf queue", 1280 qi->qs.qname); 1281 if (qi->qs.flags & PFQS_FLOWQUEUE) 1282 errx(1, "flow queue %s is not a leaf queue", 1283 qi->qs.qname); 1284 } 1285 1286 return (flags); 1287 } 1288 1289 void 1290 pfctl_load_queue(struct pfctl *pf, u_int32_t ticket, struct pfctl_qsitem *qi) 1291 { 1292 struct pfioc_queue q; 1293 struct pfctl_qsitem *p; 1294 1295 q.ticket = ticket; 1296 bcopy(&qi->qs, &q.queue, sizeof(q.queue)); 1297 if ((pf->opts & PF_OPT_NOACTION) == 0) 1298 if (ioctl(pf->dev, DIOCADDQUEUE, &q) == -1) 1299 err(1, "DIOCADDQUEUE"); 1300 if (pf->opts & PF_OPT_VERBOSE) 1301 print_queuespec(&qi->qs); 1302 1303 TAILQ_FOREACH(p, &qi->children, entries) { 1304 strlcpy(p->qs.ifname, qi->qs.ifname, IFNAMSIZ); 1305 pfctl_load_queue(pf, ticket, p); 1306 } 1307 } 1308 1309 int 1310 pfctl_load_queues(struct pfctl *pf) 1311 { 1312 struct pfctl_qsitem *qi, *tempqi; 1313 struct pf_queue_scspec *rtsc, *lssc, *ulsc; 1314 u_int32_t ticket; 1315 1316 TAILQ_FOREACH(qi, &qspecs, entries) { 1317 if (qi->matches == 0) 1318 errx(1, "queue %s: parent %s not found", qi->qs.qname, 1319 qi->qs.parent); 1320 1321 rtsc = &qi->qs.realtime; 1322 lssc = &qi->qs.linkshare; 1323 ulsc = &qi->qs.upperlimit; 1324 1325 if (rtsc->m1.percent || rtsc->m2.percent || 1326 lssc->m1.percent || lssc->m2.percent || 1327 ulsc->m1.percent || ulsc->m2.percent) 1328 errx(1, "only absolute bandwidth specs for now"); 1329 1330 /* Link sharing policy must be specified for child classes */ 1331 if (qi->qs.parent[0] != '\0' && 1332 lssc->m1.absolute == 0 && lssc->m2.absolute == 0) 1333 errx(1, "queue %s: no bandwidth was specified", 1334 qi->qs.qname); 1335 } 1336 1337 if ((pf->opts & PF_OPT_NOACTION) == 0) 1338 ticket = pfctl_get_ticket(pf->trans, PF_TRANS_RULESET, ""); 1339 1340 TAILQ_FOREACH_SAFE(qi, &rootqs, entries, tempqi) { 1341 TAILQ_REMOVE(&rootqs, qi, entries); 1342 pfctl_load_queue(pf, ticket, qi); 1343 TAILQ_INSERT_HEAD(&rootqs, qi, entries); 1344 } 1345 1346 return (0); 1347 } 1348 1349 void 1350 pfctl_clear_queues(struct pf_qihead *head) 1351 { 1352 struct pfctl_qsitem *qi; 1353 1354 while ((qi = TAILQ_FIRST(head)) != NULL) { 1355 TAILQ_REMOVE(head, qi, entries); 1356 pfctl_clear_queues(&qi->children); 1357 free(qi); 1358 } 1359 } 1360 1361 u_int 1362 pfctl_leafqueue_check(char *qname) 1363 { 1364 struct pfctl_qsitem *qi; 1365 if (qname == NULL || qname[0] == 0) 1366 return (0); 1367 1368 TAILQ_FOREACH(qi, &rootqs, entries) { 1369 if (strcmp(qname, qi->qs.qname)) 1370 continue; 1371 if (!TAILQ_EMPTY(&qi->children)) { 1372 printf("queue %s: packets must be assigned to leaf " 1373 "queues only\n", qname); 1374 return (1); 1375 } 1376 } 1377 TAILQ_FOREACH(qi, &qspecs, entries) { 1378 if (strcmp(qname, qi->qs.qname)) 1379 continue; 1380 if (!TAILQ_EMPTY(&qi->children)) { 1381 printf("queue %s: packets must be assigned to leaf " 1382 "queues only\n", qname); 1383 return (1); 1384 } 1385 } 1386 return (0); 1387 } 1388 1389 u_int 1390 pfctl_check_qassignments(struct pf_ruleset *rs) 1391 { 1392 struct pf_rule *r; 1393 struct pfctl_qsitem *qi; 1394 u_int flags, errs = 0; 1395 1396 /* main ruleset: need find_childqs to populate qi->children */ 1397 if (rs->anchor->path[0] == 0) { 1398 TAILQ_FOREACH(qi, &rootqs, entries) { 1399 flags = pfctl_find_childqs(qi); 1400 if (!(qi->qs.flags & PFQS_ROOTCLASS) && 1401 !TAILQ_EMPTY(&qi->children)) { 1402 if (qi->qs.flags & PFQS_FLOWQUEUE) 1403 errx(1, "root queue %s doesn't " 1404 "support hierarchy", 1405 qi->qs.qname); 1406 else 1407 errx(1, "no bandwidth was specified " 1408 "for root queue %s", qi->qs.qname); 1409 } 1410 if ((qi->qs.flags & PFQS_ROOTCLASS) && 1411 !(flags & PFQS_DEFAULT)) 1412 errx(1, "no default queue specified"); 1413 } 1414 } 1415 1416 TAILQ_FOREACH(r, rs->rules.active.ptr, entries) { 1417 if (r->anchor) 1418 errs += pfctl_check_qassignments(&r->anchor->ruleset); 1419 if (pfctl_leafqueue_check(r->qname) || 1420 pfctl_leafqueue_check(r->pqname)) 1421 errs++; 1422 } 1423 return (errs); 1424 } 1425 1426 int 1427 pfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs, 1428 int depth) 1429 { 1430 struct pf_rule *r; 1431 int error, len = strlen(path); 1432 int brace = 0; 1433 unsigned int rno = 0; 1434 1435 pf->anchor = rs->anchor; 1436 1437 if (path[0]) 1438 snprintf(&path[len], PATH_MAX - len, "/%s", pf->anchor->name); 1439 else 1440 snprintf(&path[len], PATH_MAX - len, "%s", pf->anchor->path); 1441 1442 if (depth) { 1443 if (TAILQ_FIRST(rs->rules.active.ptr) != NULL) { 1444 brace++; 1445 if (pf->opts & PF_OPT_VERBOSE) 1446 printf(" {\n"); 1447 if ((pf->opts & PF_OPT_NOACTION) == 0 && 1448 (error = pfctl_ruleset_trans(pf, 1449 path, rs->anchor))) { 1450 printf("pfctl_load_ruleset: " 1451 "pfctl_ruleset_trans %d\n", error); 1452 goto error; 1453 } 1454 } else if (pf->opts & PF_OPT_VERBOSE) 1455 printf("\n"); 1456 } 1457 1458 if (pf->optimize) 1459 pfctl_optimize_ruleset(pf, rs); 1460 1461 while ((r = TAILQ_FIRST(rs->rules.active.ptr)) != NULL) { 1462 TAILQ_REMOVE(rs->rules.active.ptr, r, entries); 1463 pfctl_expand_label_nr(r, rno); 1464 rno++; 1465 if ((error = pfctl_load_rule(pf, path, r, depth))) 1466 goto error; 1467 if (r->anchor) { 1468 if ((error = pfctl_load_ruleset(pf, path, 1469 &r->anchor->ruleset, depth + 1))) 1470 goto error; 1471 } else if (pf->opts & PF_OPT_VERBOSE) 1472 printf("\n"); 1473 free(r); 1474 } 1475 if (brace && pf->opts & PF_OPT_VERBOSE) { 1476 INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1477 printf("}\n"); 1478 } 1479 path[len] = '\0'; 1480 return (0); 1481 1482 error: 1483 path[len] = '\0'; 1484 return (error); 1485 1486 } 1487 1488 int 1489 pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) 1490 { 1491 char *name; 1492 struct pfioc_rule pr; 1493 int len = strlen(path); 1494 1495 bzero(&pr, sizeof(pr)); 1496 /* set up anchor before adding to path for anchor_call */ 1497 if ((pf->opts & PF_OPT_NOACTION) == 0) 1498 pr.ticket = pfctl_get_ticket(pf->trans, PF_TRANS_RULESET, path); 1499 if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >= sizeof(pr.anchor)) 1500 errx(1, "pfctl_load_rule: strlcpy"); 1501 1502 if (r->anchor) { 1503 if (r->anchor->match) { 1504 if (path[0]) 1505 snprintf(&path[len], PATH_MAX - len, 1506 "/%s", r->anchor->name); 1507 else 1508 snprintf(&path[len], PATH_MAX - len, 1509 "%s", r->anchor->name); 1510 name = r->anchor->name; 1511 } else 1512 name = r->anchor->path; 1513 } else 1514 name = ""; 1515 1516 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1517 memcpy(&pr.rule, r, sizeof(pr.rule)); 1518 if (r->anchor && strlcpy(pr.anchor_call, name, 1519 sizeof(pr.anchor_call)) >= sizeof(pr.anchor_call)) 1520 errx(1, "pfctl_load_rule: strlcpy"); 1521 if (ioctl(pf->dev, DIOCADDRULE, &pr) == -1) 1522 err(1, "DIOCADDRULE"); 1523 } 1524 1525 if (pf->opts & PF_OPT_VERBOSE) { 1526 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 1527 print_rule(r, name, pf->opts); 1528 } 1529 path[len] = '\0'; 1530 return (0); 1531 } 1532 1533 int 1534 pfctl_rules(int dev, char *filename, int opts, int optimize, 1535 char *anchorname, struct pfr_buffer *trans) 1536 { 1537 #define ERR(x) do { warn(x); goto _error; } while(0) 1538 #define ERRX(x) do { warnx(x); goto _error; } while(0) 1539 1540 struct pfr_buffer *t, buf; 1541 struct pfctl pf; 1542 struct pf_ruleset *rs; 1543 struct pfr_table trs; 1544 char *path = NULL; 1545 int osize; 1546 char *p; 1547 1548 RB_INIT(&pf_anchors); 1549 memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); 1550 pf_init_ruleset(&pf_main_anchor.ruleset); 1551 if (trans == NULL) { 1552 bzero(&buf, sizeof(buf)); 1553 buf.pfrb_type = PFRB_TRANS; 1554 t = &buf; 1555 osize = 0; 1556 } else { 1557 t = trans; 1558 osize = t->pfrb_size; 1559 } 1560 1561 memset(&pf, 0, sizeof(pf)); 1562 memset(&trs, 0, sizeof(trs)); 1563 if ((path = calloc(1, PATH_MAX)) == NULL) 1564 ERRX("pfctl_rules: calloc"); 1565 if (strlcpy(trs.pfrt_anchor, anchorname, 1566 sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) 1567 ERRX("pfctl_rules: strlcpy"); 1568 pf.dev = dev; 1569 pf.opts = opts; 1570 pf.optimize = optimize; 1571 1572 /* non-brace anchor, create without resolving the path */ 1573 if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) 1574 ERRX("pfctl_rules: calloc"); 1575 rs = &pf.anchor->ruleset; 1576 pf_init_ruleset(rs); 1577 rs->anchor = pf.anchor; 1578 if (strlcpy(pf.anchor->path, anchorname, 1579 sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 1580 errx(1, "%s: strlcpy", __func__); 1581 1582 if ((p = strrchr(anchorname, '/')) != NULL) { 1583 if (strlen(p) == 1) 1584 errx(1, "%s: bad anchor name %s", __func__, anchorname); 1585 } else 1586 p = anchorname; 1587 1588 if (strlcpy(pf.anchor->name, p, 1589 sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 1590 errx(1, "%s: strlcpy", __func__); 1591 1592 pf.astack[0] = pf.anchor; 1593 pf.asd = 0; 1594 pf.trans = t; 1595 pfctl_init_options(&pf); 1596 1597 if ((opts & PF_OPT_NOACTION) == 0) { 1598 /* 1599 * XXX For the time being we need to open transactions for 1600 * the main ruleset before parsing, because tables are still 1601 * loaded at parse time. 1602 */ 1603 if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor)) 1604 ERRX("pfctl_rules"); 1605 pf.astack[0]->ruleset.tticket = 1606 pfctl_get_ticket(t, PF_TRANS_TABLE, anchorname); 1607 } 1608 1609 if (parse_config(filename, &pf) < 0) { 1610 if ((opts & PF_OPT_NOACTION) == 0) 1611 ERRX("Syntax error in config file: " 1612 "pf rules not loaded"); 1613 else 1614 goto _error; 1615 } 1616 1617 if (!anchorname[0] && (pfctl_check_qassignments(&pf.anchor->ruleset) || 1618 pfctl_load_queues(&pf))) { 1619 if ((opts & PF_OPT_NOACTION) == 0) 1620 ERRX("Unable to load queues into kernel"); 1621 else 1622 goto _error; 1623 } 1624 1625 if (pfctl_load_ruleset(&pf, path, rs, 0)) { 1626 if ((opts & PF_OPT_NOACTION) == 0) 1627 ERRX("Unable to load rules into kernel"); 1628 else 1629 goto _error; 1630 } 1631 1632 free(path); 1633 path = NULL; 1634 1635 if (trans == NULL) { 1636 /* 1637 * process "load anchor" directives that might have used queues 1638 */ 1639 if (pfctl_load_anchors(dev, &pf, t) == -1) 1640 ERRX("load anchors"); 1641 pfctl_clear_queues(&qspecs); 1642 pfctl_clear_queues(&rootqs); 1643 1644 if ((opts & PF_OPT_NOACTION) == 0) { 1645 if (!anchorname[0] && pfctl_load_options(&pf)) 1646 goto _error; 1647 if (pfctl_trans(dev, t, DIOCXCOMMIT, osize)) 1648 ERR("DIOCXCOMMIT"); 1649 } 1650 } 1651 return (0); 1652 1653 _error: 1654 if (trans == NULL) { /* main ruleset */ 1655 if ((opts & PF_OPT_NOACTION) == 0) 1656 if (pfctl_trans(dev, t, DIOCXROLLBACK, osize)) 1657 err(1, "DIOCXROLLBACK"); 1658 exit(1); 1659 } else { /* sub ruleset */ 1660 free(path); 1661 return (-1); 1662 } 1663 1664 #undef ERR 1665 #undef ERRX 1666 } 1667 1668 FILE * 1669 pfctl_fopen(const char *name, const char *mode) 1670 { 1671 struct stat st; 1672 FILE *fp; 1673 1674 fp = fopen(name, mode); 1675 if (fp == NULL) 1676 return (NULL); 1677 if (fstat(fileno(fp), &st) == -1) { 1678 fclose(fp); 1679 return (NULL); 1680 } 1681 if (S_ISDIR(st.st_mode)) { 1682 fclose(fp); 1683 errno = EISDIR; 1684 return (NULL); 1685 } 1686 return (fp); 1687 } 1688 1689 void 1690 pfctl_init_options(struct pfctl *pf) 1691 { 1692 int64_t mem; 1693 int mib[2], mcl; 1694 size_t size; 1695 1696 pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 1697 pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; 1698 pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 1699 pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; 1700 pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; 1701 pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; 1702 pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; 1703 pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; 1704 pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; 1705 pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; 1706 pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; 1707 pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; 1708 pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; 1709 pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; 1710 pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; 1711 pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; 1712 pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; 1713 pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; 1714 pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; 1715 pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; 1716 1717 pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; 1718 1719 pf->syncookieswat[0] = PF_SYNCOOKIES_LOWATPCT; 1720 pf->syncookieswat[1] = PF_SYNCOOKIES_HIWATPCT; 1721 1722 mib[0] = CTL_KERN; 1723 mib[1] = KERN_MAXCLUSTERS; 1724 size = sizeof(mcl); 1725 if (sysctl(mib, 2, &mcl, &size, NULL, 0) == -1) 1726 err(1, "sysctl"); 1727 pf->limit[PF_LIMIT_FRAGS] = mcl / 4; 1728 1729 pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; 1730 pf->limit[PF_LIMIT_TABLES] = PFR_KTABLE_HIWAT; 1731 pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; 1732 pf->limit[PF_LIMIT_PKTDELAY_PKTS] = PF_PKTDELAY_MAXPKTS; 1733 pf->limit[PF_LIMIT_ANCHORS] = PF_ANCHOR_HIWAT; 1734 1735 mib[0] = CTL_HW; 1736 mib[1] = HW_PHYSMEM64; 1737 size = sizeof(mem); 1738 if (sysctl(mib, 2, &mem, &size, NULL, 0) == -1) 1739 err(1, "sysctl"); 1740 if (mem <= 100*1024*1024) 1741 pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT_SMALL; 1742 1743 pf->debug = LOG_ERR; 1744 pf->debug_set = 0; 1745 pf->reassemble = PF_REASS_ENABLED; 1746 } 1747 1748 int 1749 pfctl_load_options(struct pfctl *pf) 1750 { 1751 int i, error = 0; 1752 1753 /* load limits */ 1754 for (i = 0; i < PF_LIMIT_MAX; i++) 1755 if (pfctl_load_limit(pf, i, pf->limit[i])) 1756 error = 1; 1757 1758 /* 1759 * If we've set the states limit, but haven't explicitly set adaptive 1760 * timeouts, do it now with a start of 60% and end of 120%. 1761 */ 1762 if (pf->limit_set[PF_LIMIT_STATES] && 1763 !pf->timeout_set[PFTM_ADAPTIVE_START] && 1764 !pf->timeout_set[PFTM_ADAPTIVE_END]) { 1765 pf->timeout[PFTM_ADAPTIVE_START] = 1766 (pf->limit[PF_LIMIT_STATES] / 10) * 6; 1767 pf->timeout_set[PFTM_ADAPTIVE_START] = 1; 1768 pf->timeout[PFTM_ADAPTIVE_END] = 1769 (pf->limit[PF_LIMIT_STATES] / 10) * 12; 1770 pf->timeout_set[PFTM_ADAPTIVE_END] = 1; 1771 } 1772 1773 /* load timeouts */ 1774 for (i = 0; i < PFTM_MAX; i++) 1775 if (pfctl_load_timeout(pf, i, pf->timeout[i])) 1776 error = 1; 1777 1778 /* load debug */ 1779 if (pf->debug_set && pfctl_load_debug(pf, pf->debug)) 1780 error = 1; 1781 1782 /* load logif */ 1783 if (pf->ifname_set && pfctl_load_logif(pf, pf->ifname)) 1784 error = 1; 1785 1786 /* load hostid */ 1787 if (pf->hostid_set && pfctl_load_hostid(pf, pf->hostid)) 1788 error = 1; 1789 1790 /* load reassembly settings */ 1791 if (pf->reass_set && pfctl_load_reassembly(pf, pf->reassemble)) 1792 error = 1; 1793 1794 /* load syncookies settings */ 1795 if (pf->syncookies_set && pfctl_load_syncookies(pf, pf->syncookies)) 1796 error = 1; 1797 if (pf->syncookieswat_set) { 1798 struct pfioc_limit pl; 1799 unsigned curlim; 1800 1801 if (pf->limit_set[PF_LIMIT_STATES]) 1802 curlim = pf->limit[PF_LIMIT_STATES]; 1803 else { 1804 memset(&pl, 0, sizeof(pl)); 1805 pl.index = pf_limits[PF_LIMIT_STATES].index; 1806 if (ioctl(dev, DIOCGETLIMIT, &pl) == -1) 1807 err(1, "DIOCGETLIMIT"); 1808 curlim = pl.limit; 1809 } 1810 if (pfctl_set_synflwats(pf, curlim * pf->syncookieswat[0]/100, 1811 curlim * pf->syncookieswat[1]/100)) 1812 error = 1; 1813 } 1814 1815 return (error); 1816 } 1817 1818 int 1819 pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) 1820 { 1821 int i; 1822 1823 for (i = 0; pf_limits[i].name; i++) { 1824 if (strcasecmp(opt, pf_limits[i].name) == 0) { 1825 pf->limit[pf_limits[i].index] = limit; 1826 pf->limit_set[pf_limits[i].index] = 1; 1827 break; 1828 } 1829 } 1830 if (pf_limits[i].name == NULL) { 1831 warnx("Bad pool name."); 1832 return (1); 1833 } 1834 1835 if (pf->opts & PF_OPT_VERBOSE) 1836 printf("set limit %s %d\n", opt, limit); 1837 1838 return (0); 1839 } 1840 1841 int 1842 pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) 1843 { 1844 struct pfioc_limit pl; 1845 1846 memset(&pl, 0, sizeof(pl)); 1847 pl.index = index; 1848 pl.limit = limit; 1849 if (ioctl(pf->dev, DIOCSETLIMIT, &pl) == -1) { 1850 if (errno == EBUSY) 1851 warnx("Current pool size exceeds requested %s limit %u", 1852 pf_limits[index].name, limit); 1853 else 1854 warnx("Cannot set %s limit to %u", 1855 pf_limits[index].name, limit); 1856 return (1); 1857 } 1858 return (0); 1859 } 1860 1861 int 1862 pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 1863 { 1864 int i; 1865 1866 for (i = 0; pf_timeouts[i].name; i++) { 1867 if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 1868 pf->timeout[pf_timeouts[i].timeout] = seconds; 1869 pf->timeout_set[pf_timeouts[i].timeout] = 1; 1870 break; 1871 } 1872 } 1873 1874 if (pf_timeouts[i].name == NULL) { 1875 warnx("Bad timeout name."); 1876 return (1); 1877 } 1878 1879 1880 if (pf->opts & PF_OPT_VERBOSE && ! quiet) 1881 printf("set timeout %s %d\n", opt, seconds); 1882 1883 return (0); 1884 } 1885 1886 int 1887 pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) 1888 { 1889 struct pfioc_tm pt; 1890 1891 memset(&pt, 0, sizeof(pt)); 1892 pt.timeout = timeout; 1893 pt.seconds = seconds; 1894 if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt) == -1) { 1895 warnx("DIOCSETTIMEOUT"); 1896 return (1); 1897 } 1898 return (0); 1899 } 1900 1901 int 1902 pfctl_set_synflwats(struct pfctl *pf, u_int32_t lowat, u_int32_t hiwat) 1903 { 1904 struct pfioc_synflwats ps; 1905 1906 memset(&ps, 0, sizeof(ps)); 1907 ps.hiwat = hiwat; 1908 ps.lowat = lowat; 1909 1910 if (ioctl(pf->dev, DIOCSETSYNFLWATS, &ps) == -1) { 1911 warnx("Cannot set synflood detection watermarks"); 1912 return (1); 1913 } 1914 return (0); 1915 } 1916 1917 int 1918 pfctl_set_reassembly(struct pfctl *pf, int on, int nodf) 1919 { 1920 pf->reass_set = 1; 1921 if (on) { 1922 pf->reassemble = PF_REASS_ENABLED; 1923 if (nodf) 1924 pf->reassemble |= PF_REASS_NODF; 1925 } else { 1926 pf->reassemble = 0; 1927 } 1928 1929 if (pf->opts & PF_OPT_VERBOSE) 1930 printf("set reassemble %s %s\n", on ? "yes" : "no", 1931 nodf ? "no-df" : ""); 1932 1933 return (0); 1934 } 1935 1936 int 1937 pfctl_set_syncookies(struct pfctl *pf, u_int8_t val, struct pfctl_watermarks *w) 1938 { 1939 if (val != PF_SYNCOOKIES_ADAPTIVE && w != NULL) { 1940 warnx("syncookies start/end only apply to adaptive"); 1941 return (1); 1942 } 1943 if (val == PF_SYNCOOKIES_ADAPTIVE && w != NULL) { 1944 if (!w->hi) 1945 w->hi = PF_SYNCOOKIES_HIWATPCT; 1946 if (!w->lo) 1947 w->lo = w->hi / 2; 1948 if (w->lo >= w->hi) { 1949 warnx("start must be higher than end"); 1950 return (1); 1951 } 1952 pf->syncookieswat[0] = w->lo; 1953 pf->syncookieswat[1] = w->hi; 1954 pf->syncookieswat_set = 1; 1955 } 1956 1957 if (pf->opts & PF_OPT_VERBOSE) { 1958 if (val == PF_SYNCOOKIES_NEVER) 1959 printf("set syncookies never\n"); 1960 else if (val == PF_SYNCOOKIES_ALWAYS) 1961 printf("set syncookies always\n"); 1962 else if (val == PF_SYNCOOKIES_ADAPTIVE) { 1963 if (pf->syncookieswat_set) 1964 printf("set syncookies adaptive (start %u%%, " 1965 "end %u%%)\n", pf->syncookieswat[1], 1966 pf->syncookieswat[0]); 1967 else 1968 printf("set syncookies adaptive\n"); 1969 } else { /* cannot happen */ 1970 warnx("king bula ate all syncookies"); 1971 return (1); 1972 } 1973 } 1974 1975 pf->syncookies_set = 1; 1976 pf->syncookies = val; 1977 return (0); 1978 } 1979 1980 int 1981 pfctl_set_optimization(struct pfctl *pf, const char *opt) 1982 { 1983 const struct pf_hint *hint; 1984 int i, r; 1985 1986 for (i = 0; pf_hints[i].name; i++) 1987 if (strcasecmp(opt, pf_hints[i].name) == 0) 1988 break; 1989 1990 hint = pf_hints[i].hint; 1991 if (hint == NULL) { 1992 warnx("invalid state timeouts optimization"); 1993 return (1); 1994 } 1995 1996 for (i = 0; hint[i].name; i++) 1997 if ((r = pfctl_set_timeout(pf, hint[i].name, 1998 hint[i].timeout, 1))) 1999 return (r); 2000 2001 if (pf->opts & PF_OPT_VERBOSE) 2002 printf("set optimization %s\n", opt); 2003 2004 return (0); 2005 } 2006 2007 int 2008 pfctl_set_logif(struct pfctl *pf, char *ifname) 2009 { 2010 if (!strcmp(ifname, "none")) { 2011 free(pf->ifname); 2012 pf->ifname = NULL; 2013 } else { 2014 pf->ifname = strdup(ifname); 2015 if (!pf->ifname) 2016 errx(1, "pfctl_set_logif: strdup"); 2017 } 2018 pf->ifname_set = 1; 2019 2020 if (pf->opts & PF_OPT_VERBOSE) 2021 printf("set loginterface %s\n", ifname); 2022 2023 return (0); 2024 } 2025 2026 int 2027 pfctl_load_logif(struct pfctl *pf, char *ifname) 2028 { 2029 struct pfioc_iface pi; 2030 2031 memset(&pi, 0, sizeof(pi)); 2032 if (ifname && strlcpy(pi.pfiio_name, ifname, 2033 sizeof(pi.pfiio_name)) >= sizeof(pi.pfiio_name)) { 2034 warnx("pfctl_load_logif: strlcpy"); 2035 return (1); 2036 } 2037 if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi) == -1) { 2038 warnx("DIOCSETSTATUSIF"); 2039 return (1); 2040 } 2041 return (0); 2042 } 2043 2044 void 2045 pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 2046 { 2047 HTONL(hostid); 2048 2049 pf->hostid = hostid; 2050 pf->hostid_set = 1; 2051 2052 if (pf->opts & PF_OPT_VERBOSE) 2053 printf("set hostid 0x%08x\n", ntohl(hostid)); 2054 } 2055 2056 int 2057 pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) 2058 { 2059 if (ioctl(dev, DIOCSETHOSTID, &hostid) == -1) { 2060 warnx("DIOCSETHOSTID"); 2061 return (1); 2062 } 2063 return (0); 2064 } 2065 2066 int 2067 pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly) 2068 { 2069 if (ioctl(dev, DIOCSETREASS, &reassembly) == -1) { 2070 warnx("DIOCSETREASS"); 2071 return (1); 2072 } 2073 return (0); 2074 } 2075 2076 int 2077 pfctl_load_syncookies(struct pfctl *pf, u_int8_t val) 2078 { 2079 if (ioctl(dev, DIOCSETSYNCOOKIES, &val) == -1) { 2080 warnx("DIOCSETSYNCOOKIES"); 2081 return (1); 2082 } 2083 return (0); 2084 } 2085 2086 int 2087 pfctl_set_debug(struct pfctl *pf, char *d) 2088 { 2089 u_int32_t level; 2090 int loglevel; 2091 2092 if ((loglevel = string_to_loglevel(d)) >= 0) 2093 level = loglevel; 2094 else { 2095 warnx("unknown debug level \"%s\"", d); 2096 return (-1); 2097 } 2098 pf->debug = level; 2099 pf->debug_set = 1; 2100 2101 if ((pf->opts & PF_OPT_NOACTION) == 0) 2102 if (ioctl(dev, DIOCSETDEBUG, &level) == -1) 2103 err(1, "DIOCSETDEBUG"); 2104 2105 if (pf->opts & PF_OPT_VERBOSE) 2106 printf("set debug %s\n", d); 2107 2108 return (0); 2109 } 2110 2111 int 2112 pfctl_load_debug(struct pfctl *pf, unsigned int level) 2113 { 2114 if (ioctl(pf->dev, DIOCSETDEBUG, &level) == -1) { 2115 warnx("DIOCSETDEBUG"); 2116 return (1); 2117 } 2118 return (0); 2119 } 2120 2121 int 2122 pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) 2123 { 2124 struct pfioc_iface pi; 2125 2126 bzero(&pi, sizeof(pi)); 2127 2128 pi.pfiio_flags = flags; 2129 2130 if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= 2131 sizeof(pi.pfiio_name)) 2132 errx(1, "pfctl_set_interface_flags: strlcpy"); 2133 2134 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2135 if (how == 0) { 2136 if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi) == -1) 2137 err(1, "DIOCCLRIFFLAG"); 2138 } else { 2139 if (ioctl(pf->dev, DIOCSETIFFLAG, &pi) == -1) 2140 err(1, "DIOCSETIFFLAG"); 2141 } 2142 } 2143 return (0); 2144 } 2145 2146 void 2147 pfctl_debug(int dev, u_int32_t level, int opts) 2148 { 2149 struct pfr_buffer t; 2150 2151 memset(&t, 0, sizeof(t)); 2152 t.pfrb_type = PFRB_TRANS; 2153 if (pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 2154 ioctl(dev, DIOCSETDEBUG, &level) == -1|| 2155 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 2156 err(1, "pfctl_debug ioctl"); 2157 2158 if ((opts & PF_OPT_QUIET) == 0) 2159 fprintf(stderr, "debug level set to '%s'\n", 2160 loglevel_to_string(level)); 2161 } 2162 2163 int 2164 pfctl_walk_show(int opts, struct pfioc_ruleset *pr, void *warg) 2165 { 2166 if (pr->path[0]) { 2167 if (pr->path[0] != '_' || (opts & PF_OPT_VERBOSE)) 2168 printf(" %s/%s\n", pr->path, pr->name); 2169 } else if (pr->name[0] != '_' || (opts & PF_OPT_VERBOSE)) 2170 printf(" %s\n", pr->name); 2171 2172 return (0); 2173 } 2174 2175 int 2176 pfctl_walk_get(int opts, struct pfioc_ruleset *pr, void *warg) 2177 { 2178 struct pfr_anchoritem *pfra; 2179 struct pfr_anchors *anchors; 2180 int e; 2181 2182 anchors = (struct pfr_anchors *) warg; 2183 2184 pfra = malloc(sizeof(*pfra)); 2185 if (pfra == NULL) 2186 err(1, "%s", __func__); 2187 2188 if (pr->path[0]) 2189 e = asprintf(&pfra->pfra_anchorname, "%s/%s", pr->path, 2190 pr->name); 2191 else 2192 e = asprintf(&pfra->pfra_anchorname, "%s", pr->name); 2193 2194 if (e == -1) 2195 err(1, "%s", __func__); 2196 2197 2198 SLIST_INSERT_HEAD(anchors, pfra, pfra_sle); 2199 2200 return (0); 2201 } 2202 2203 int 2204 pfctl_walk_anchors(int dev, int opts, const char *anchor, 2205 int(walkf)(int, struct pfioc_ruleset *, void *), void *warg) 2206 { 2207 struct pfioc_ruleset pr; 2208 u_int32_t mnr, nr; 2209 2210 memset(&pr, 0, sizeof(pr)); 2211 strlcpy(pr.path, anchor, sizeof(pr.path)); 2212 if (ioctl(dev, DIOCGETRULESETS, &pr) == -1) 2213 errx(1, "%s", pf_strerror(errno)); 2214 mnr = pr.nr; 2215 for (nr = 0; nr < mnr; ++nr) { 2216 char sub[PATH_MAX]; 2217 2218 pr.nr = nr; 2219 if (ioctl(dev, DIOCGETRULESET, &pr) == -1) 2220 errx(1, "%s", pf_strerror(errno)); 2221 if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) 2222 continue; 2223 sub[0] = '\0'; 2224 2225 if (walkf(opts, &pr, warg)) 2226 return (-1); 2227 2228 if (pr.path[0]) 2229 snprintf(sub, sizeof(sub), "%s/%s", 2230 pr.path, pr.name); 2231 else 2232 snprintf(sub, sizeof(sub), "%s", 2233 pr.name); 2234 if (pfctl_walk_anchors(dev, opts, sub, walkf, warg)) 2235 return (-1); 2236 } 2237 return (0); 2238 } 2239 2240 int 2241 pfctl_show_anchors(int dev, int opts, char *anchor) 2242 { 2243 return ( 2244 pfctl_walk_anchors(dev, opts, anchor, pfctl_walk_show, NULL)); 2245 } 2246 2247 struct pfr_anchors * 2248 pfctl_get_anchors(int dev, const char *anchor, int opts) 2249 { 2250 struct pfioc_ruleset pr; 2251 static struct pfr_anchors anchors; 2252 char anchorbuf[PATH_MAX]; 2253 char *n; 2254 2255 SLIST_INIT(&anchors); 2256 2257 memset(&pr, 0, sizeof(pr)); 2258 if (*anchor != '\0') { 2259 strlcpy(anchorbuf, anchor, sizeof(anchorbuf)); 2260 n = dirname(anchorbuf); 2261 if (n[0] != '.' && n[1] != '\0') 2262 strlcpy(pr.path, n, sizeof(pr.path)); 2263 strlcpy(anchorbuf, anchor, sizeof(anchorbuf)); 2264 n = basename(anchorbuf); 2265 if (n != NULL) 2266 strlcpy(pr.name, n, sizeof(pr.name)); 2267 } 2268 2269 /* insert a root anchor first. */ 2270 pfctl_walk_get(opts, &pr, &anchors); 2271 2272 if (pfctl_walk_anchors(dev, opts, anchor, pfctl_walk_get, &anchors)) 2273 errx(1, 2274 "%s failed to retrieve list of anchors, can't continue", 2275 __func__); 2276 2277 return (&anchors); 2278 } 2279 2280 int 2281 pfctl_call_cleartables(int dev, int opts, struct pfr_anchoritem *pfra) 2282 { 2283 /* 2284 * PF_OPT_QUIET makes pfctl_clear_tables() to stop printing number of 2285 * tables cleared for given anchor. 2286 */ 2287 opts |= PF_OPT_QUIET; 2288 return ((pfctl_clear_tables(pfra->pfra_anchorname, opts) == -1) ? 2289 1 : 0); 2290 } 2291 2292 int 2293 pfctl_call_clearrules(int dev, int opts, struct pfr_anchoritem *pfra) 2294 { 2295 /* 2296 * PF_OPT_QUIET makes pfctl_clear_rules() to stop printing a 'rules 2297 * cleared' message for every anchor it deletes. 2298 */ 2299 opts |= PF_OPT_QUIET; 2300 return (pfctl_clear_rules(dev, opts, pfra->pfra_anchorname)); 2301 } 2302 2303 int 2304 pfctl_call_clearanchors(int dev, int opts, struct pfr_anchoritem *pfra) 2305 { 2306 int rv = 0; 2307 2308 rv |= pfctl_call_cleartables(dev, opts, pfra); 2309 rv |= pfctl_call_clearrules(dev, opts, pfra); 2310 2311 return (rv); 2312 } 2313 2314 int 2315 pfctl_recurse(int dev, int opts, const char *anchorname, 2316 int(*walkf)(int, int, struct pfr_anchoritem *)) 2317 { 2318 int rv = 0; 2319 struct pfr_anchors *anchors; 2320 struct pfr_anchoritem *pfra, *pfra_save; 2321 2322 anchors = pfctl_get_anchors(dev, anchorname, opts); 2323 /* 2324 * While traversing the list, pfctl_clear_*() must always return 2325 * so that failures on one anchor do not prevent clearing others. 2326 */ 2327 opts |= PF_OPT_IGNFAIL; 2328 printf("Removing:\n"); 2329 SLIST_FOREACH_SAFE(pfra, anchors, pfra_sle, pfra_save) { 2330 printf(" %s\n", (*pfra->pfra_anchorname == '\0') ? 2331 "/" : pfra->pfra_anchorname); 2332 rv |= walkf(dev, opts, pfra); 2333 SLIST_REMOVE(anchors, pfra, pfr_anchoritem, pfra_sle); 2334 free(pfra->pfra_anchorname); 2335 free(pfra); 2336 } 2337 2338 return (rv); 2339 } 2340 2341 const char * 2342 pfctl_lookup_option(char *cmd, const char **list) 2343 { 2344 const char *item = NULL; 2345 2346 if (cmd != NULL && *cmd) 2347 for (; *list; list++) 2348 if (!strncmp(cmd, *list, strlen(cmd))) { 2349 if (item == NULL) 2350 item = *list; 2351 else 2352 errx(1, "%s is ambigious", cmd); 2353 } 2354 2355 return (item); 2356 } 2357 2358 2359 void 2360 pfctl_state_store(int dev, const char *file) 2361 { 2362 FILE *f; 2363 struct pfioc_states ps; 2364 char *inbuf = NULL, *newinbuf = NULL; 2365 size_t n, len = 0; 2366 2367 f = fopen(file, "w"); 2368 if (f == NULL) 2369 err(1, "open: %s", file); 2370 2371 memset(&ps, 0, sizeof(ps)); 2372 for (;;) { 2373 ps.ps_len = len; 2374 if (len) { 2375 newinbuf = realloc(inbuf, len); 2376 if (newinbuf == NULL) 2377 err(1, "realloc"); 2378 ps.ps_buf = inbuf = newinbuf; 2379 } 2380 if (ioctl(dev, DIOCGETSTATES, &ps) == -1) 2381 err(1, "DIOCGETSTATES"); 2382 2383 if (ps.ps_len + sizeof(struct pfioc_states) < len) 2384 break; 2385 if (len == 0 && ps.ps_len == 0) 2386 goto done; 2387 if (len == 0 && ps.ps_len != 0) 2388 len = ps.ps_len; 2389 if (ps.ps_len == 0) 2390 goto done; /* no states */ 2391 len *= 2; 2392 } 2393 2394 n = ps.ps_len / sizeof(struct pfsync_state); 2395 if (fwrite(inbuf, sizeof(struct pfsync_state), n, f) < n) 2396 err(1, "fwrite"); 2397 2398 done: 2399 free(inbuf); 2400 fclose(f); 2401 } 2402 2403 void 2404 pfctl_state_load(int dev, const char *file) 2405 { 2406 FILE *f; 2407 struct pfioc_state ps; 2408 2409 f = fopen(file, "r"); 2410 if (f == NULL) 2411 err(1, "open: %s", file); 2412 2413 while (fread(&ps.state, sizeof(ps.state), 1, f) == 1) { 2414 if (ioctl(dev, DIOCADDSTATE, &ps) == -1) { 2415 switch (errno) { 2416 case EEXIST: 2417 case EINVAL: 2418 break; 2419 default: 2420 err(1, "DIOCADDSTATE"); 2421 } 2422 } 2423 } 2424 2425 fclose(f); 2426 } 2427 2428 void 2429 pfctl_reset(int dev, int opts) 2430 { 2431 struct pfctl pf; 2432 struct pfr_buffer t; 2433 int i; 2434 2435 memset(&pf, 0, sizeof(pf)); 2436 pf.dev = dev; 2437 pfctl_init_options(&pf); 2438 2439 /* Force reset upon pfctl_load_options() */ 2440 pf.debug_set = 1; 2441 pf.reass_set = 1; 2442 pf.syncookieswat_set = 1; 2443 pf.syncookies_set = 1; 2444 pf.ifname = strdup("none"); 2445 if (pf.ifname == NULL) 2446 err(1, "%s: strdup", __func__); 2447 pf.ifname_set = 1; 2448 2449 memset(&t, 0, sizeof(t)); 2450 t.pfrb_type = PFRB_TRANS; 2451 if (pfctl_trans(dev, &t, DIOCXBEGIN, 0)) 2452 err(1, "%s: DIOCXBEGIN", __func__); 2453 2454 for (i = 0; pf_limits[i].name; i++) 2455 pf.limit_set[pf_limits[i].index] = 1; 2456 2457 for (i = 0; pf_timeouts[i].name; i++) 2458 pf.timeout_set[pf_timeouts[i].timeout] = 1; 2459 2460 pfctl_load_options(&pf); 2461 2462 if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 2463 err(1, "%s: DIOCXCOMMIT", __func__); 2464 2465 pfctl_clear_interface_flags(dev, opts); 2466 } 2467 2468 #ifndef REGRESS_NOMAIN 2469 int 2470 main(int argc, char *argv[]) 2471 { 2472 int ch; 2473 int mode = O_RDONLY; 2474 int opts = 0; 2475 int optimize = PF_OPTIMIZE_BASIC; 2476 int level; 2477 int rdomain = 0; 2478 char anchorname[PATH_MAX]; 2479 int anchor_wildcard = 0; 2480 char *path; 2481 char *lfile = NULL, *sfile = NULL; 2482 const char *errstr; 2483 long shownr = -1; 2484 2485 if (argc < 2) 2486 usage(); 2487 2488 while ((ch = getopt(argc, argv, 2489 "a:dD:eqf:F:ghi:k:K:L:Nno:Pp:R:rS:s:t:T:vV:x:z")) != -1) { 2490 switch (ch) { 2491 case 'a': 2492 anchoropt = optarg; 2493 break; 2494 case 'd': 2495 opts |= PF_OPT_DISABLE; 2496 mode = O_RDWR; 2497 break; 2498 case 'D': 2499 if (pfctl_cmdline_symset(optarg) < 0) 2500 warnx("could not parse macro definition %s", 2501 optarg); 2502 break; 2503 case 'e': 2504 opts |= PF_OPT_ENABLE; 2505 mode = O_RDWR; 2506 break; 2507 case 'q': 2508 opts |= PF_OPT_QUIET; 2509 break; 2510 case 'F': 2511 clearopt = pfctl_lookup_option(optarg, clearopt_list); 2512 if (clearopt == NULL) { 2513 warnx("Unknown flush modifier '%s'", optarg); 2514 usage(); 2515 } 2516 mode = O_RDWR; 2517 break; 2518 case 'i': 2519 ifaceopt = optarg; 2520 break; 2521 case 'k': 2522 if (state_killers >= 2) { 2523 warnx("can only specify -k twice"); 2524 usage(); 2525 /* NOTREACHED */ 2526 } 2527 state_kill[state_killers++] = optarg; 2528 mode = O_RDWR; 2529 break; 2530 case 'K': 2531 if (src_node_killers >= 2) { 2532 warnx("can only specify -K twice"); 2533 usage(); 2534 /* NOTREACHED */ 2535 } 2536 src_node_kill[src_node_killers++] = optarg; 2537 mode = O_RDWR; 2538 break; 2539 case 'N': 2540 opts |= PF_OPT_NODNS; 2541 break; 2542 case 'n': 2543 opts |= PF_OPT_NOACTION; 2544 break; 2545 case 'r': 2546 opts |= PF_OPT_USEDNS; 2547 break; 2548 case 'R': 2549 shownr = strtonum(optarg, -1, LONG_MAX, &errstr); 2550 if (errstr) { 2551 warnx("invalid rule id: %s", errstr); 2552 usage(); 2553 } 2554 break; 2555 case 'f': 2556 rulesopt = optarg; 2557 mode = O_RDWR; 2558 break; 2559 case 'g': 2560 opts |= PF_OPT_DEBUG; 2561 break; 2562 case 'o': 2563 optiopt = pfctl_lookup_option(optarg, optiopt_list); 2564 if (optiopt == NULL) { 2565 warnx("Unknown optimization '%s'", optarg); 2566 usage(); 2567 } 2568 opts |= PF_OPT_OPTIMIZE; 2569 break; 2570 case 'P': 2571 opts |= PF_OPT_PORTNAMES; 2572 break; 2573 case 'p': 2574 pf_device = optarg; 2575 break; 2576 case 's': 2577 showopt = pfctl_lookup_option(optarg, showopt_list); 2578 if (showopt == NULL) { 2579 warnx("Unknown show modifier '%s'", optarg); 2580 usage(); 2581 } 2582 break; 2583 case 't': 2584 tableopt = optarg; 2585 break; 2586 case 'T': 2587 tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 2588 if (tblcmdopt == NULL) { 2589 warnx("Unknown table command '%s'", optarg); 2590 usage(); 2591 } 2592 break; 2593 case 'v': 2594 if (opts & PF_OPT_VERBOSE) 2595 opts |= PF_OPT_VERBOSE2; 2596 opts |= PF_OPT_VERBOSE; 2597 break; 2598 case 'V': 2599 rdomain = strtonum(optarg, 0, RT_TABLEID_MAX, &errstr); 2600 if (errstr) { 2601 warnx("Invalid rdomain: %s", errstr); 2602 usage(); 2603 } 2604 break; 2605 case 'x': 2606 debugopt = pfctl_lookup_option(optarg, debugopt_list); 2607 if (debugopt == NULL) { 2608 warnx("Unknown debug level '%s'", optarg); 2609 usage(); 2610 } 2611 mode = O_RDWR; 2612 break; 2613 case 'z': 2614 opts |= PF_OPT_CLRRULECTRS; 2615 mode = O_RDWR; 2616 break; 2617 case 'S': 2618 sfile = optarg; 2619 break; 2620 case 'L': 2621 mode = O_RDWR; 2622 lfile = optarg; 2623 break; 2624 case 'h': 2625 /* FALLTHROUGH */ 2626 default: 2627 usage(); 2628 /* NOTREACHED */ 2629 } 2630 } 2631 2632 if ((opts & PF_OPT_NODNS) && (opts & PF_OPT_USEDNS)) 2633 errx(1, "-N and -r are mutually exclusive"); 2634 2635 if ((tblcmdopt == NULL) ^ (tableopt == NULL)) 2636 usage(); 2637 2638 if (tblcmdopt != NULL) { 2639 argc -= optind; 2640 argv += optind; 2641 ch = *tblcmdopt; 2642 mode = strchr("st", ch) ? O_RDONLY : O_RDWR; 2643 } else if (argc != optind) { 2644 warnx("unknown command line argument: %s ...", argv[optind]); 2645 usage(); 2646 /* NOTREACHED */ 2647 } 2648 2649 memset(anchorname, 0, sizeof(anchorname)); 2650 if (anchoropt != NULL) { 2651 if (anchoropt[0] == '\0') 2652 errx(1, "anchor name must not be empty"); 2653 if (mode == O_RDONLY && showopt == NULL && tblcmdopt == NULL) { 2654 warnx("anchors apply to -f, -F, -s, and -T only"); 2655 usage(); 2656 } 2657 if (mode == O_RDWR && tblcmdopt == NULL && 2658 (anchoropt[0] == '_' || strstr(anchoropt, "/_") != NULL)) 2659 errx(1, "anchor names beginning with '_' cannot " 2660 "be modified from the command line"); 2661 int len = strlen(anchoropt); 2662 2663 if (anchoropt[len - 1] == '*') { 2664 if (len >= 2 && anchoropt[len - 2] == '/') { 2665 anchoropt[len - 2] = '\0'; 2666 anchor_wildcard = 1; 2667 } else 2668 anchoropt[len - 1] = '\0'; 2669 opts |= PF_OPT_RECURSE; 2670 } 2671 if (strlcpy(anchorname, anchoropt, 2672 sizeof(anchorname)) >= sizeof(anchorname)) 2673 errx(1, "anchor name '%s' too long", 2674 anchoropt); 2675 } 2676 2677 if ((opts & PF_OPT_NOACTION) == 0) { 2678 dev = open(pf_device, mode); 2679 if (dev == -1) 2680 err(1, "%s", pf_device); 2681 } else { 2682 dev = open(pf_device, O_RDONLY); 2683 if (dev >= 0) 2684 opts |= PF_OPT_DUMMYACTION; 2685 /* turn off options */ 2686 opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 2687 clearopt = showopt = debugopt = NULL; 2688 } 2689 2690 if (opts & PF_OPT_DISABLE) 2691 if (pfctl_disable(dev, opts)) 2692 exit_val = 1; 2693 2694 if ((path = calloc(1, PATH_MAX)) == NULL) 2695 errx(1, "%s: calloc", __func__); 2696 2697 if (showopt != NULL) { 2698 switch (*showopt) { 2699 case 'A': 2700 pfctl_show_anchors(dev, opts, anchorname); 2701 break; 2702 case 'r': 2703 pfctl_load_fingerprints(dev, opts); 2704 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 2705 anchorname, 0, anchor_wildcard, shownr); 2706 break; 2707 case 'l': 2708 pfctl_load_fingerprints(dev, opts); 2709 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 2710 anchorname, 0, anchor_wildcard, shownr); 2711 break; 2712 case 'q': 2713 pfctl_show_queues(dev, ifaceopt, opts, 2714 opts & PF_OPT_VERBOSE2); 2715 break; 2716 case 's': 2717 pfctl_show_states(dev, ifaceopt, opts, shownr); 2718 break; 2719 case 'S': 2720 pfctl_show_src_nodes(dev, opts); 2721 break; 2722 case 'i': 2723 pfctl_show_status(dev, opts); 2724 break; 2725 case 't': 2726 pfctl_show_timeouts(dev, opts); 2727 break; 2728 case 'm': 2729 pfctl_show_limits(dev, opts); 2730 break; 2731 case 'a': 2732 opts |= PF_OPT_SHOWALL; 2733 pfctl_load_fingerprints(dev, opts); 2734 2735 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 2736 anchorname, 0, 0, -1); 2737 pfctl_show_queues(dev, ifaceopt, opts, 2738 opts & PF_OPT_VERBOSE2); 2739 pfctl_show_states(dev, ifaceopt, opts, -1); 2740 pfctl_show_src_nodes(dev, opts); 2741 pfctl_show_status(dev, opts); 2742 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 2743 anchorname, 0, 0, -1); 2744 pfctl_show_timeouts(dev, opts); 2745 pfctl_show_limits(dev, opts); 2746 pfctl_show_tables(anchorname, opts); 2747 pfctl_show_fingerprints(opts); 2748 break; 2749 case 'T': 2750 pfctl_show_tables(anchorname, opts); 2751 break; 2752 case 'o': 2753 pfctl_load_fingerprints(dev, opts); 2754 pfctl_show_fingerprints(opts); 2755 break; 2756 case 'I': 2757 pfctl_show_ifaces(ifaceopt, opts); 2758 break; 2759 } 2760 } 2761 2762 if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) 2763 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 2764 anchorname, 0, 0, -1); 2765 2766 if (clearopt != NULL) { 2767 switch (*clearopt) { 2768 case 'r': 2769 if (opts & PF_OPT_RECURSE) 2770 pfctl_recurse(dev, opts, anchorname, 2771 pfctl_call_clearrules); 2772 else 2773 pfctl_clear_rules(dev, opts, anchorname); 2774 break; 2775 case 's': 2776 pfctl_clear_states(dev, ifaceopt, opts); 2777 break; 2778 case 'S': 2779 pfctl_clear_src_nodes(dev, opts); 2780 break; 2781 case 'i': 2782 pfctl_clear_stats(dev, ifaceopt, opts); 2783 break; 2784 case 'a': 2785 if (ifaceopt) { 2786 warnx("don't specify an interface with -Fall"); 2787 usage(); 2788 /* NOTREACHED */ 2789 } 2790 if (opts & PF_OPT_RECURSE) 2791 pfctl_recurse(dev, opts, anchorname, 2792 pfctl_call_clearanchors); 2793 else { 2794 pfctl_clear_tables(anchorname, opts); 2795 pfctl_clear_rules(dev, opts, anchorname); 2796 } 2797 2798 if (!*anchorname) { 2799 pfctl_clear_states(dev, ifaceopt, opts); 2800 pfctl_clear_src_nodes(dev, opts); 2801 pfctl_clear_stats(dev, ifaceopt, opts); 2802 pfctl_clear_fingerprints(dev, opts); 2803 pfctl_reset(dev, opts); 2804 } 2805 break; 2806 case 'o': 2807 pfctl_clear_fingerprints(dev, opts); 2808 break; 2809 case 'T': 2810 if ((opts & PF_OPT_RECURSE) == 0) 2811 pfctl_clear_tables(anchorname, opts); 2812 else 2813 pfctl_recurse(dev, opts, anchorname, 2814 pfctl_call_cleartables); 2815 break; 2816 case 'R': 2817 pfctl_reset(dev, opts); 2818 break; 2819 } 2820 } 2821 if (state_killers) { 2822 if (!strcmp(state_kill[0], "label")) 2823 pfctl_label_kill_states(dev, ifaceopt, opts, rdomain); 2824 else if (!strcmp(state_kill[0], "id")) 2825 pfctl_id_kill_states(dev, opts); 2826 else if (!strcmp(state_kill[0], "key")) 2827 pfctl_key_kill_states(dev, ifaceopt, opts, rdomain); 2828 else 2829 pfctl_net_kill_states(dev, ifaceopt, opts, rdomain); 2830 } 2831 2832 if (src_node_killers) 2833 pfctl_kill_src_nodes(dev, opts); 2834 2835 if (tblcmdopt != NULL) { 2836 exit_val = pfctl_table(argc, argv, tableopt, 2837 tblcmdopt, rulesopt, anchorname, opts); 2838 rulesopt = NULL; 2839 } 2840 if (optiopt != NULL) { 2841 switch (*optiopt) { 2842 case 'n': 2843 optimize = 0; 2844 break; 2845 case 'b': 2846 optimize |= PF_OPTIMIZE_BASIC; 2847 break; 2848 case 'o': 2849 case 'p': 2850 optimize |= PF_OPTIMIZE_PROFILE; 2851 break; 2852 } 2853 } 2854 2855 if (rulesopt != NULL && !anchorname[0]) { 2856 pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET); 2857 if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 2858 exit_val = 1; 2859 } 2860 2861 if (rulesopt != NULL) { 2862 if (pfctl_rules(dev, rulesopt, opts, optimize, 2863 anchorname, NULL)) 2864 exit_val = 1; 2865 } 2866 2867 if (opts & PF_OPT_ENABLE) 2868 if (pfctl_enable(dev, opts)) 2869 exit_val = 1; 2870 2871 if (debugopt != NULL) { 2872 if ((level = string_to_loglevel((char *)debugopt)) < 0) { 2873 switch (*debugopt) { 2874 case 'n': 2875 level = LOG_CRIT; 2876 break; 2877 case 'u': 2878 level = LOG_ERR; 2879 break; 2880 case 'm': 2881 level = LOG_NOTICE; 2882 break; 2883 case 'l': 2884 level = LOG_DEBUG; 2885 break; 2886 } 2887 } 2888 if (level >= 0) 2889 pfctl_debug(dev, level, opts); 2890 } 2891 2892 if (sfile != NULL) 2893 pfctl_state_store(dev, sfile); 2894 if (lfile != NULL) 2895 pfctl_state_load(dev, lfile); 2896 2897 exit(exit_val); 2898 } 2899 #endif /* REGRESS_NOMAIN */ 2900 2901 char * 2902 pf_strerror(int errnum) 2903 { 2904 switch (errnum) { 2905 case ESRCH: 2906 return "Table does not exist"; 2907 case EINVAL: 2908 case ENOENT: 2909 return "Anchor does not exist"; 2910 default: 2911 return strerror(errnum); 2912 } 2913 } 2914