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