1 /* $OpenBSD: pfctl.c,v 1.278 2008/08/31 20:18:17 jmc Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2001 Daniel Hartmeier 7 * Copyright (c) 2002,2003 Henning Brauer 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * - Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * - Redistributions in binary form must reproduce the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer in the documentation and/or other materials provided 19 * with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 * 34 */ 35 36 #include <sys/cdefs.h> 37 #define PFIOC_USE_LATEST 38 39 #include <sys/types.h> 40 #include <sys/ioctl.h> 41 #include <sys/socket.h> 42 #include <sys/stat.h> 43 #include <sys/endian.h> 44 45 #include <net/if.h> 46 #include <netinet/in.h> 47 #include <net/pfvar.h> 48 #include <arpa/inet.h> 49 #include <net/altq/altq.h> 50 51 #include <err.h> 52 #include <errno.h> 53 #include <fcntl.h> 54 #include <libpfctl.h> 55 #include <limits.h> 56 #include <netdb.h> 57 #include <stdint.h> 58 #include <stdio.h> 59 #include <stdlib.h> 60 #include <string.h> 61 #include <unistd.h> 62 #include <stdarg.h> 63 #include <stddef.h> 64 #include <libgen.h> 65 66 #include "pfctl_parser.h" 67 #include "pfctl.h" 68 69 struct pfctl_opt_id; 70 71 void usage(void); 72 int pfctl_enable(int, int); 73 int pfctl_disable(int, int); 74 void pfctl_clear_stats(struct pfctl_handle *, int); 75 void pfctl_get_skip_ifaces(void); 76 void pfctl_check_skip_ifaces(char *); 77 void pfctl_adjust_skip_ifaces(struct pfctl *); 78 void pfctl_clear_interface_flags(int, int); 79 void pfctl_flush_eth_rules(int, int, char *); 80 int pfctl_flush_rules(int, int, char *); 81 void pfctl_flush_nat(int, int, char *); 82 int pfctl_clear_altq(int, int); 83 void pfctl_clear_src_nodes(int, int); 84 void pfctl_clear_iface_states(int, const char *, int); 85 struct addrinfo * 86 pfctl_addrprefix(char *, struct pf_addr *, int); 87 void pfctl_kill_src_nodes(int, int); 88 void pfctl_net_kill_states(int, const char *, int); 89 void pfctl_gateway_kill_states(int, const char *, int); 90 void pfctl_label_kill_states(int, const char *, int); 91 void pfctl_id_kill_states(int, const char *, int); 92 void pfctl_key_kill_states(int, const char *, int); 93 void pfctl_kill_source(int, const char *, const char *, int); 94 int pfctl_parse_host(char *, struct pf_rule_addr *); 95 void pfctl_init_options(struct pfctl *); 96 int pfctl_load_options(struct pfctl *); 97 int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); 98 int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); 99 int pfctl_load_debug(struct pfctl *, unsigned int); 100 int pfctl_load_logif(struct pfctl *, char *); 101 int pfctl_load_hostid(struct pfctl *, u_int32_t); 102 int pfctl_load_reassembly(struct pfctl *, u_int32_t); 103 int pfctl_load_syncookies(struct pfctl *, u_int8_t); 104 int pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int, 105 const char *, int); 106 void pfctl_print_eth_rule_counters(struct pfctl_eth_rule *, int); 107 void pfctl_print_rule_counters(struct pfctl_rule *, int); 108 int pfctl_show_statelims(int, enum pfctl_show, int); 109 int pfctl_show_sourcelims(int, enum pfctl_show, int, const char *); 110 int pfctl_show_eth_rules(int, char *, int, enum pfctl_show, char *, int, int); 111 int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int); 112 int pfctl_show_nat(int, const char *, int, char *, int, int); 113 int pfctl_show_src_nodes(int, int); 114 int pfctl_show_states(int, const char *, int); 115 int pfctl_show_status(int, int); 116 int pfctl_show_running(int); 117 int pfctl_show_timeouts(int, int); 118 int pfctl_show_limits(int, int); 119 void pfctl_read_limits(struct pfctl_handle *); 120 void pfctl_restore_limits(void); 121 void pfctl_debug(int, u_int32_t, int); 122 int pfctl_test_altqsupport(int, int); 123 int pfctl_show_anchors(int, int, char *); 124 int pfctl_show_eth_anchors(int, int, char *); 125 int pfctl_ruleset_trans(struct pfctl *, char *, struct pfctl_anchor *, bool); 126 void pfctl_load_statelims(struct pfctl *); 127 void pfctl_load_statelim(struct pfctl *, struct pfctl_statelim *); 128 void pfctl_load_sourcelims(struct pfctl *); 129 void pfctl_load_sourcelim(struct pfctl *, struct pfctl_source_lim *); 130 int pfctl_eth_ruleset_trans(struct pfctl *, char *, 131 struct pfctl_eth_anchor *); 132 int pfctl_load_eth_ruleset(struct pfctl *, char *, 133 struct pfctl_eth_ruleset *, int); 134 int pfctl_load_eth_rule(struct pfctl *, char *, struct pfctl_eth_rule *, 135 int); 136 int pfctl_load_ruleset(struct pfctl *, char *, 137 struct pfctl_ruleset *, int, int); 138 int pfctl_load_rule(struct pfctl *, char *, struct pfctl_rule *, int); 139 const char *pfctl_lookup_option(char *, const char * const *); 140 int pfctl_lookup_id(const char *, const struct pfctl_opt_id *); 141 void pfctl_reset(int, int); 142 int pfctl_walk_show(int, struct pfioc_ruleset *, void *); 143 int pfctl_walk_get(int, struct pfioc_ruleset *, void *); 144 int pfctl_walk_anchors(int, int, const char *, 145 int(*)(int, struct pfioc_ruleset *, void *), void *); 146 struct pfr_anchors * 147 pfctl_get_anchors(int, const char *, int); 148 int pfctl_recurse(int, int, const char *, 149 int(*)(int, int, struct pfr_anchoritem *)); 150 int pfctl_call_clearrules(int, int, struct pfr_anchoritem *); 151 int pfctl_call_cleartables(int, int, struct pfr_anchoritem *); 152 int pfctl_call_clearanchors(int, int, struct pfr_anchoritem *); 153 int pfctl_call_showtables(int, int, struct pfr_anchoritem *); 154 155 RB_PROTOTYPE(pfctl_statelim_ids, pfctl_statelim, entry, 156 pfctl_statelim_id_cmp); 157 RB_PROTOTYPE(pfctl_statelim_nms, pfctl_statelim, entry, 158 pfctl_statelim_nm_cmp); 159 RB_PROTOTYPE(pfctl_sourcelim_ids, pfctl_sourcelim, entry, 160 pfctl_sourcelim_id_cmp); 161 RB_PROTOTYPE(pfctl_sourcelim_nms, pfctl_sourcelim, entry, 162 pfctl_sourcelim_nm_cmp); 163 164 enum showopt_id { 165 SHOWOPT_NONE = 0, 166 SHOWOPT_ETHER, 167 SHOWOPT_NAT, 168 SHOWOPT_QUEUE, 169 SHOWOPT_RULES, 170 SHOWOPT_ANCHORS, 171 SHOWOPT_SOURCES, 172 SHOWOPT_STATES, 173 SHOWOPT_INFO, 174 SHOWOPT_IFACES, 175 SHOWOPT_LABELS, 176 SHOWOPT_TIMEOUTS, 177 SHOWOPT_MEMORY, 178 SHOWOPT_TABLES, 179 SHOWOPT_OSFP, 180 SHOWOPT_RUNNING, 181 SHOWOPT_STATELIMS, 182 SHOWOPT_SOURCELIMS, 183 SHOWOPT_CREATORIDS, 184 SHOWOPT_ALL, 185 }; 186 187 static struct pfctl_anchor_global pf_anchors; 188 struct pfctl_anchor pf_main_anchor; 189 struct pfctl_eth_anchor pf_eth_main_anchor; 190 static struct pfr_buffer skip_b; 191 192 static const char *clearopt; 193 static char *rulesopt; 194 static int showopt; 195 static const char *debugopt; 196 static char *anchoropt; 197 static const char *optiopt = NULL; 198 static const char *pf_device = PF_DEVICE; 199 static char *ifaceopt; 200 static char *tableopt; 201 static const char *tblcmdopt; 202 static int src_node_killers; 203 static char *src_node_kill[2]; 204 static int state_killers; 205 static char *state_kill[2]; 206 int loadopt; 207 int altqsupport; 208 209 int dev = -1; 210 struct pfctl_handle *pfh = NULL; 211 static int first_title = 1; 212 static int labels = 0; 213 static int exit_val = 0; 214 215 #define INDENT(d, o) do { \ 216 if (o) { \ 217 int i; \ 218 for (i=0; i < d; i++) \ 219 printf(" "); \ 220 } \ 221 } while (0); \ 222 223 224 static const struct { 225 const char *name; 226 int index; 227 } pf_limits[] = { 228 { "states", PF_LIMIT_STATES }, 229 { "src-nodes", PF_LIMIT_SRC_NODES }, 230 { "frags", PF_LIMIT_FRAGS }, 231 { "table-entries", PF_LIMIT_TABLE_ENTRIES }, 232 { "anchors", PF_LIMIT_ANCHORS }, 233 { "eth-anchors", PF_LIMIT_ETH_ANCHORS }, 234 { NULL, 0 } 235 }; 236 237 static unsigned int limit_curr[PF_LIMIT_MAX]; 238 239 struct pf_hint { 240 const char *name; 241 int timeout; 242 }; 243 static const struct pf_hint pf_hint_normal[] = { 244 { "tcp.first", 2 * 60 }, 245 { "tcp.opening", 30 }, 246 { "tcp.established", 24 * 60 * 60 }, 247 { "tcp.closing", 15 * 60 }, 248 { "tcp.finwait", 45 }, 249 { "tcp.closed", 90 }, 250 { "tcp.tsdiff", 30 }, 251 { NULL, 0 } 252 }; 253 static const struct pf_hint pf_hint_satellite[] = { 254 { "tcp.first", 3 * 60 }, 255 { "tcp.opening", 30 + 5 }, 256 { "tcp.established", 24 * 60 * 60 }, 257 { "tcp.closing", 15 * 60 + 5 }, 258 { "tcp.finwait", 45 + 5 }, 259 { "tcp.closed", 90 + 5 }, 260 { "tcp.tsdiff", 60 }, 261 { NULL, 0 } 262 }; 263 static const struct pf_hint pf_hint_conservative[] = { 264 { "tcp.first", 60 * 60 }, 265 { "tcp.opening", 15 * 60 }, 266 { "tcp.established", 5 * 24 * 60 * 60 }, 267 { "tcp.closing", 60 * 60 }, 268 { "tcp.finwait", 10 * 60 }, 269 { "tcp.closed", 3 * 60 }, 270 { "tcp.tsdiff", 60 }, 271 { NULL, 0 } 272 }; 273 static const struct pf_hint pf_hint_aggressive[] = { 274 { "tcp.first", 30 }, 275 { "tcp.opening", 5 }, 276 { "tcp.established", 5 * 60 * 60 }, 277 { "tcp.closing", 60 }, 278 { "tcp.finwait", 30 }, 279 { "tcp.closed", 30 }, 280 { "tcp.tsdiff", 10 }, 281 { NULL, 0 } 282 }; 283 284 static const struct { 285 const char *name; 286 const struct pf_hint *hint; 287 } pf_hints[] = { 288 { "normal", pf_hint_normal }, 289 { "satellite", pf_hint_satellite }, 290 { "high-latency", pf_hint_satellite }, 291 { "conservative", pf_hint_conservative }, 292 { "aggressive", pf_hint_aggressive }, 293 { NULL, NULL } 294 }; 295 296 static const char * const clearopt_list[] = { 297 "nat", "queue", "rules", "Sources", 298 "states", "info", "Tables", "osfp", "all", 299 "ethernet", "Reset", NULL 300 }; 301 302 struct pfctl_opt_id { 303 const char *name; 304 int id; 305 }; 306 307 static const struct pfctl_opt_id showopt_list[] = { 308 { "ether", SHOWOPT_ETHER }, 309 { "nat", SHOWOPT_NAT }, 310 { "queue", SHOWOPT_QUEUE }, 311 { "rules", SHOWOPT_RULES }, 312 { "Anchors", SHOWOPT_ANCHORS }, 313 { "Sources", SHOWOPT_SOURCES }, 314 { "states", SHOWOPT_STATES }, 315 { "info", SHOWOPT_INFO }, 316 { "Interfaces", SHOWOPT_IFACES }, 317 { "labels", SHOWOPT_LABELS }, 318 { "timeouts", SHOWOPT_TIMEOUTS }, 319 { "memory", SHOWOPT_MEMORY }, 320 { "Tables", SHOWOPT_TABLES }, 321 { "osfp", SHOWOPT_OSFP }, 322 { "Running", SHOWOPT_RUNNING }, 323 { "LimiterStates", SHOWOPT_STATELIMS }, 324 { "LimiterSrcs", SHOWOPT_SOURCELIMS }, 325 { "creatorids", SHOWOPT_CREATORIDS }, 326 { "all", SHOWOPT_ALL }, 327 328 { NULL, SHOWOPT_NONE }, 329 }; 330 331 static const char * const tblcmdopt_list[] = { 332 "kill", "flush", "add", "delete", "load", "replace", "show", 333 "test", "zero", "expire", "reset", NULL 334 }; 335 336 static const char * const debugopt_list[] = { 337 "none", "urgent", "misc", "loud", NULL 338 }; 339 340 static const char * const optiopt_list[] = { 341 "none", "basic", "profile", NULL 342 }; 343 344 void 345 usage(void) 346 { 347 extern char *__progname; 348 349 fprintf(stderr, 350 "usage: %s [-AdeghMmNnOPqRSrvz] [-a anchor] [-D macro=value] [-F modifier]\n" 351 "\t[-f file] [-i interface] [-K host | network]\n" 352 "\t[-k host | network | gateway | label | id] [-o level] [-p device]\n" 353 "\t[-s modifier] [-t table -T command [address ...]] [-x level]\n", 354 __progname); 355 356 exit(1); 357 } 358 359 void 360 pfctl_err(int opts, int eval, const char *fmt, ...) 361 { 362 va_list ap; 363 364 va_start(ap, fmt); 365 366 if ((opts & PF_OPT_IGNFAIL) == 0) 367 verr(eval, fmt, ap); 368 else 369 vwarn(fmt, ap); 370 371 va_end(ap); 372 373 exit_val = eval; 374 } 375 376 void 377 pfctl_errx(int opts, int eval, const char *fmt, ...) 378 { 379 va_list ap; 380 381 va_start(ap, fmt); 382 383 if ((opts & PF_OPT_IGNFAIL) == 0) 384 verrx(eval, fmt, ap); 385 else 386 vwarnx(fmt, ap); 387 388 va_end(ap); 389 390 exit_val = eval; 391 } 392 393 /* 394 * Cache protocol number to name translations. 395 * 396 * Translation is performed a lot e.g., when dumping states and 397 * getprotobynumber is incredibly expensive. 398 * 399 * Note from the getprotobynumber(3) manpage: 400 * <quote> 401 * These functions use a thread-specific data space; if the data is needed 402 * for future use, it should be copied before any subsequent calls overwrite 403 * it. Only the Internet protocols are currently understood. 404 * </quote> 405 * 406 * Consequently we only cache the name and strdup it for safety. 407 * 408 * At the time of writing this comment the last entry in /etc/protocols is: 409 * divert 258 DIVERT # Divert pseudo-protocol [non IANA] 410 */ 411 const char * 412 pfctl_proto2name(int proto) 413 { 414 static const char *pfctl_proto_cache[259]; 415 struct protoent *p; 416 417 if (proto >= nitems(pfctl_proto_cache)) { 418 p = getprotobynumber(proto); 419 if (p == NULL) { 420 return (NULL); 421 } 422 return (p->p_name); 423 } 424 425 if (pfctl_proto_cache[proto] == NULL) { 426 p = getprotobynumber(proto); 427 if (p == NULL) { 428 return (NULL); 429 } 430 pfctl_proto_cache[proto] = strdup(p->p_name); 431 } 432 433 return (pfctl_proto_cache[proto]); 434 } 435 436 int 437 pfctl_enable(int dev, int opts) 438 { 439 int ret; 440 441 if ((ret = pfctl_startstop(pfh, 1)) != 0) { 442 if (ret == EEXIST) 443 errx(1, "pf already enabled"); 444 else if (ret == ESRCH) 445 errx(1, "pfil registration failed"); 446 else 447 errc(1, ret, "DIOCSTART"); 448 } 449 if ((opts & PF_OPT_QUIET) == 0) 450 fprintf(stderr, "pf enabled\n"); 451 452 if (altqsupport && ioctl(dev, DIOCSTARTALTQ)) 453 if (errno != EEXIST) 454 err(1, "DIOCSTARTALTQ"); 455 456 return (0); 457 } 458 459 int 460 pfctl_disable(int dev, int opts) 461 { 462 int ret; 463 464 if ((ret = pfctl_startstop(pfh, 0)) != 0) { 465 if (ret == ENOENT) 466 errx(1, "pf not enabled"); 467 else 468 errc(1, ret, "DIOCSTOP"); 469 } 470 if ((opts & PF_OPT_QUIET) == 0) 471 fprintf(stderr, "pf disabled\n"); 472 473 if (altqsupport && ioctl(dev, DIOCSTOPALTQ)) 474 if (errno != ENOENT) 475 err(1, "DIOCSTOPALTQ"); 476 477 return (0); 478 } 479 480 void 481 pfctl_clear_stats(struct pfctl_handle *h, int opts) 482 { 483 int ret; 484 if ((ret = pfctl_clear_status(h)) != 0) 485 pfctl_err(opts, 1, "DIOCCLRSTATUS"); 486 if ((opts & PF_OPT_QUIET) == 0) 487 fprintf(stderr, "pf: statistics cleared\n"); 488 } 489 490 void 491 pfctl_get_skip_ifaces(void) 492 { 493 bzero(&skip_b, sizeof(skip_b)); 494 skip_b.pfrb_type = PFRB_IFACES; 495 for (;;) { 496 pfr_buf_grow(&skip_b, skip_b.pfrb_size); 497 skip_b.pfrb_size = skip_b.pfrb_msize; 498 if (pfi_get_ifaces(NULL, skip_b.pfrb_caddr, &skip_b.pfrb_size)) 499 err(1, "pfi_get_ifaces"); 500 if (skip_b.pfrb_size <= skip_b.pfrb_msize) 501 break; 502 } 503 } 504 505 void 506 pfctl_check_skip_ifaces(char *ifname) 507 { 508 struct pfi_kif *p; 509 struct node_host *h = NULL, *n = NULL; 510 511 PFRB_FOREACH(p, &skip_b) { 512 if (!strcmp(ifname, p->pfik_name) && 513 (p->pfik_flags & PFI_IFLAG_SKIP)) 514 p->pfik_flags &= ~PFI_IFLAG_SKIP; 515 if (!strcmp(ifname, p->pfik_name) && p->pfik_group != NULL) { 516 if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL) 517 continue; 518 519 for (n = h; n != NULL; n = n->next) { 520 if (strncmp(p->pfik_name, ifname, IFNAMSIZ)) 521 continue; 522 523 p->pfik_flags &= ~PFI_IFLAG_SKIP; 524 } 525 } 526 } 527 } 528 529 void 530 pfctl_adjust_skip_ifaces(struct pfctl *pf) 531 { 532 struct pfi_kif *p, *pp; 533 struct node_host *h = NULL, *n = NULL; 534 535 PFRB_FOREACH(p, &skip_b) { 536 if (p->pfik_group == NULL || !(p->pfik_flags & PFI_IFLAG_SKIP)) 537 continue; 538 539 pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0); 540 if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL) 541 continue; 542 543 for (n = h; n != NULL; n = n->next) 544 PFRB_FOREACH(pp, &skip_b) { 545 if (strncmp(pp->pfik_name, n->ifname, IFNAMSIZ)) 546 continue; 547 548 if (!(pp->pfik_flags & PFI_IFLAG_SKIP)) 549 pfctl_set_interface_flags(pf, 550 pp->pfik_name, PFI_IFLAG_SKIP, 1); 551 if (pp->pfik_flags & PFI_IFLAG_SKIP) 552 pp->pfik_flags &= ~PFI_IFLAG_SKIP; 553 } 554 } 555 556 PFRB_FOREACH(p, &skip_b) { 557 if (! (p->pfik_flags & PFI_IFLAG_SKIP)) 558 continue; 559 560 pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0); 561 } 562 } 563 564 void 565 pfctl_clear_interface_flags(int dev, int opts) 566 { 567 struct pfioc_iface pi; 568 569 if ((opts & PF_OPT_NOACTION) == 0) { 570 bzero(&pi, sizeof(pi)); 571 pi.pfiio_flags = PFI_IFLAG_SKIP; 572 573 if (ioctl(dev, DIOCCLRIFFLAG, &pi)) 574 err(1, "DIOCCLRIFFLAG"); 575 if ((opts & PF_OPT_QUIET) == 0) 576 fprintf(stderr, "pf: interface flags reset\n"); 577 } 578 } 579 580 void 581 pfctl_flush_eth_rules(int dev, int opts, char *anchorname) 582 { 583 int ret; 584 585 ret = pfctl_clear_eth_rules(dev, anchorname); 586 if (ret != 0) 587 err(1, "pfctl_clear_eth_rules"); 588 589 if ((opts & PF_OPT_QUIET) == 0) 590 fprintf(stderr, "Ethernet rules cleared\n"); 591 } 592 593 int 594 pfctl_flush_rules(int dev, int opts, char *anchorname) 595 { 596 int ret; 597 598 ret = pfctl_clear_rules(dev, anchorname); 599 if (ret != 0) { 600 pfctl_err(opts, 1, "%s", __func__); 601 return (1); 602 } else if ((opts & PF_OPT_QUIET) == 0) 603 fprintf(stderr, "rules cleared\n"); 604 605 return (0); 606 } 607 608 void 609 pfctl_flush_nat(int dev, int opts, char *anchorname) 610 { 611 int ret; 612 613 ret = pfctl_clear_nat(dev, anchorname); 614 if (ret != 0) 615 err(1, "pfctl_clear_nat"); 616 if ((opts & PF_OPT_QUIET) == 0) 617 fprintf(stderr, "nat cleared\n"); 618 } 619 620 int 621 pfctl_clear_altq(int dev, int opts) 622 { 623 struct pfr_buffer t; 624 625 if (!altqsupport) 626 return (-1); 627 memset(&t, 0, sizeof(t)); 628 t.pfrb_type = PFRB_TRANS; 629 if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") || 630 pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 631 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 632 err(1, "pfctl_clear_altq"); 633 if ((opts & PF_OPT_QUIET) == 0) 634 fprintf(stderr, "altq cleared\n"); 635 return (0); 636 } 637 638 void 639 pfctl_clear_src_nodes(int dev, int opts) 640 { 641 if (ioctl(dev, DIOCCLRSRCNODES)) 642 pfctl_err(opts, 1, "DIOCCLRSRCNODES"); 643 if ((opts & PF_OPT_QUIET) == 0) 644 fprintf(stderr, "source tracking entries cleared\n"); 645 } 646 647 void 648 pfctl_clear_iface_states(int dev, const char *iface, int opts) 649 { 650 struct pfctl_kill kill; 651 unsigned int killed; 652 int ret; 653 654 memset(&kill, 0, sizeof(kill)); 655 if (iface != NULL && strlcpy(kill.ifname, iface, 656 sizeof(kill.ifname)) >= sizeof(kill.ifname)) 657 pfctl_errx(opts, 1, "invalid interface: %s", iface); 658 659 if (opts & PF_OPT_KILLMATCH) 660 kill.kill_match = true; 661 662 if ((ret = pfctl_clear_states_h(pfh, &kill, &killed)) != 0) 663 pfctl_err(opts, 1, "DIOCCLRSTATUS"); 664 if ((opts & PF_OPT_QUIET) == 0) 665 fprintf(stderr, "%d states cleared\n", killed); 666 } 667 668 struct addrinfo * 669 pfctl_addrprefix(char *addr, struct pf_addr *mask, int numeric) 670 { 671 char *p; 672 const char *errstr; 673 int prefix, ret_ga, q, r; 674 struct addrinfo hints, *res; 675 676 bzero(&hints, sizeof(hints)); 677 hints.ai_socktype = SOCK_DGRAM; /* dummy */ 678 if (numeric) 679 hints.ai_flags = AI_NUMERICHOST; 680 681 if ((p = strchr(addr, '/')) != NULL) { 682 *p++ = '\0'; 683 /* prefix only with numeric addresses */ 684 hints.ai_flags |= AI_NUMERICHOST; 685 } 686 687 if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) { 688 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 689 /* NOTREACHED */ 690 } 691 692 if (p == NULL) 693 return (res); 694 695 prefix = strtonum(p, 0, res->ai_family == AF_INET6 ? 128 : 32, &errstr); 696 if (errstr) 697 errx(1, "prefix is %s: %s", errstr, p); 698 699 q = prefix >> 3; 700 r = prefix & 7; 701 switch (res->ai_family) { 702 case AF_INET: 703 bzero(&mask->v4, sizeof(mask->v4)); 704 mask->v4.s_addr = htonl((u_int32_t) 705 (0xffffffffffULL << (32 - prefix))); 706 break; 707 case AF_INET6: 708 bzero(&mask->v6, sizeof(mask->v6)); 709 if (q > 0) 710 memset((void *)&mask->v6, 0xff, q); 711 if (r > 0) 712 *((u_char *)&mask->v6 + q) = 713 (0xff00 >> r) & 0xff; 714 break; 715 } 716 717 return (res); 718 } 719 720 void 721 pfctl_kill_src_nodes(int dev, int opts) 722 { 723 struct pfioc_src_node_kill psnk; 724 struct addrinfo *res[2], *resp[2]; 725 struct sockaddr last_src, last_dst; 726 int killed, sources, dests; 727 728 killed = sources = dests = 0; 729 730 memset(&psnk, 0, sizeof(psnk)); 731 memset(&psnk.psnk_src.addr.v.a.mask, 0xff, 732 sizeof(psnk.psnk_src.addr.v.a.mask)); 733 memset(&last_src, 0xff, sizeof(last_src)); 734 memset(&last_dst, 0xff, sizeof(last_dst)); 735 736 res[0] = pfctl_addrprefix(src_node_kill[0], 737 &psnk.psnk_src.addr.v.a.mask, (opts & PF_OPT_NODNS)); 738 739 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 740 if (resp[0]->ai_addr == NULL) 741 continue; 742 /* We get lots of duplicates. Catch the easy ones */ 743 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 744 continue; 745 last_src = *(struct sockaddr *)resp[0]->ai_addr; 746 747 psnk.psnk_af = resp[0]->ai_family; 748 sources++; 749 750 copy_satopfaddr(&psnk.psnk_src.addr.v.a.addr, resp[0]->ai_addr); 751 752 if (src_node_killers > 1) { 753 dests = 0; 754 memset(&psnk.psnk_dst.addr.v.a.mask, 0xff, 755 sizeof(psnk.psnk_dst.addr.v.a.mask)); 756 memset(&last_dst, 0xff, sizeof(last_dst)); 757 res[1] = pfctl_addrprefix(src_node_kill[1], 758 &psnk.psnk_dst.addr.v.a.mask, 759 (opts & PF_OPT_NODNS)); 760 for (resp[1] = res[1]; resp[1]; 761 resp[1] = resp[1]->ai_next) { 762 if (resp[1]->ai_addr == NULL) 763 continue; 764 if (psnk.psnk_af != resp[1]->ai_family) 765 continue; 766 767 if (memcmp(&last_dst, resp[1]->ai_addr, 768 sizeof(last_dst)) == 0) 769 continue; 770 last_dst = *(struct sockaddr *)resp[1]->ai_addr; 771 772 dests++; 773 774 copy_satopfaddr(&psnk.psnk_dst.addr.v.a.addr, 775 resp[1]->ai_addr); 776 if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 777 err(1, "DIOCKILLSRCNODES"); 778 killed += psnk.psnk_killed; 779 } 780 freeaddrinfo(res[1]); 781 } else { 782 if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 783 err(1, "DIOCKILLSRCNODES"); 784 killed += psnk.psnk_killed; 785 } 786 } 787 788 freeaddrinfo(res[0]); 789 790 if ((opts & PF_OPT_QUIET) == 0) 791 fprintf(stderr, "killed %d src nodes from %d sources and %d " 792 "destinations\n", killed, sources, dests); 793 } 794 795 void 796 pfctl_net_kill_states(int dev, const char *iface, int opts) 797 { 798 struct pfctl_kill kill; 799 struct addrinfo *res[2], *resp[2]; 800 struct sockaddr last_src, last_dst; 801 unsigned int newkilled; 802 int killed, sources, dests; 803 int ret; 804 805 killed = sources = dests = 0; 806 807 memset(&kill, 0, sizeof(kill)); 808 memset(&kill.src.addr.v.a.mask, 0xff, 809 sizeof(kill.src.addr.v.a.mask)); 810 memset(&last_src, 0xff, sizeof(last_src)); 811 memset(&last_dst, 0xff, sizeof(last_dst)); 812 if (iface != NULL && strlcpy(kill.ifname, iface, 813 sizeof(kill.ifname)) >= sizeof(kill.ifname)) 814 pfctl_errx(opts, 1, "invalid interface: %s", iface); 815 816 if (state_killers == 2 && (strcmp(state_kill[0], "nat") == 0)) { 817 kill.nat = true; 818 state_kill[0] = state_kill[1]; 819 state_killers = 1; 820 } 821 822 res[0] = pfctl_addrprefix(state_kill[0], 823 &kill.src.addr.v.a.mask, (opts & PF_OPT_NODNS)); 824 825 if (opts & PF_OPT_KILLMATCH) 826 kill.kill_match = true; 827 828 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 829 if (resp[0]->ai_addr == NULL) 830 continue; 831 /* We get lots of duplicates. Catch the easy ones */ 832 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 833 continue; 834 last_src = *(struct sockaddr *)resp[0]->ai_addr; 835 836 kill.af = resp[0]->ai_family; 837 sources++; 838 839 copy_satopfaddr(&kill.src.addr.v.a.addr, resp[0]->ai_addr); 840 841 if (state_killers > 1) { 842 dests = 0; 843 memset(&kill.dst.addr.v.a.mask, 0xff, 844 sizeof(kill.dst.addr.v.a.mask)); 845 memset(&last_dst, 0xff, sizeof(last_dst)); 846 res[1] = pfctl_addrprefix(state_kill[1], 847 &kill.dst.addr.v.a.mask, 848 (opts & PF_OPT_NODNS)); 849 for (resp[1] = res[1]; resp[1]; 850 resp[1] = resp[1]->ai_next) { 851 if (resp[1]->ai_addr == NULL) 852 continue; 853 if (kill.af != resp[1]->ai_family) 854 continue; 855 856 if (memcmp(&last_dst, resp[1]->ai_addr, 857 sizeof(last_dst)) == 0) 858 continue; 859 last_dst = *(struct sockaddr *)resp[1]->ai_addr; 860 861 dests++; 862 863 copy_satopfaddr(&kill.dst.addr.v.a.addr, 864 resp[1]->ai_addr); 865 866 if ((ret = pfctl_kill_states_h(pfh, &kill, &newkilled)) != 0) 867 pfctl_errx(opts, 1, "DIOCKILLSTATES"); 868 killed += newkilled; 869 } 870 freeaddrinfo(res[1]); 871 } else { 872 if ((ret = pfctl_kill_states_h(pfh, &kill, &newkilled)) != 0) 873 pfctl_errx(opts, 1, "DIOCKILLSTATES"); 874 killed += newkilled; 875 } 876 } 877 878 freeaddrinfo(res[0]); 879 880 if ((opts & PF_OPT_QUIET) == 0) 881 fprintf(stderr, "killed %d states from %d sources and %d " 882 "destinations\n", killed, sources, dests); 883 } 884 885 void 886 pfctl_gateway_kill_states(int dev, const char *iface, int opts) 887 { 888 struct pfctl_kill kill; 889 struct addrinfo *res, *resp; 890 struct sockaddr last_src; 891 unsigned int newkilled; 892 int killed = 0; 893 894 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 895 warnx("no gateway specified"); 896 usage(); 897 } 898 899 memset(&kill, 0, sizeof(kill)); 900 memset(&kill.rt_addr.addr.v.a.mask, 0xff, 901 sizeof(kill.rt_addr.addr.v.a.mask)); 902 memset(&last_src, 0xff, sizeof(last_src)); 903 if (iface != NULL && strlcpy(kill.ifname, iface, 904 sizeof(kill.ifname)) >= sizeof(kill.ifname)) 905 pfctl_errx(opts, 1, "invalid interface: %s", iface); 906 907 if (opts & PF_OPT_KILLMATCH) 908 kill.kill_match = true; 909 910 res = pfctl_addrprefix(state_kill[1], &kill.rt_addr.addr.v.a.mask, 911 (opts & PF_OPT_NODNS)); 912 913 for (resp = res; resp; resp = resp->ai_next) { 914 if (resp->ai_addr == NULL) 915 continue; 916 /* We get lots of duplicates. Catch the easy ones */ 917 if (memcmp(&last_src, resp->ai_addr, sizeof(last_src)) == 0) 918 continue; 919 last_src = *(struct sockaddr *)resp->ai_addr; 920 921 kill.af = resp->ai_family; 922 923 copy_satopfaddr(&kill.rt_addr.addr.v.a.addr, 924 resp->ai_addr); 925 if (pfctl_kill_states_h(pfh, &kill, &newkilled)) 926 pfctl_errx(opts, 1, "DIOCKILLSTATES"); 927 killed += newkilled; 928 } 929 930 freeaddrinfo(res); 931 932 if ((opts & PF_OPT_QUIET) == 0) 933 fprintf(stderr, "killed %d states\n", killed); 934 } 935 936 void 937 pfctl_label_kill_states(int dev, const char *iface, int opts) 938 { 939 struct pfctl_kill kill; 940 unsigned int killed; 941 int ret; 942 943 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 944 warnx("no label specified"); 945 usage(); 946 } 947 memset(&kill, 0, sizeof(kill)); 948 if (iface != NULL && strlcpy(kill.ifname, iface, 949 sizeof(kill.ifname)) >= sizeof(kill.ifname)) 950 pfctl_errx(opts, 1, "invalid interface: %s", iface); 951 952 if (opts & PF_OPT_KILLMATCH) 953 kill.kill_match = true; 954 955 if (strlcpy(kill.label, state_kill[1], sizeof(kill.label)) >= 956 sizeof(kill.label)) 957 errx(1, "label too long: %s", state_kill[1]); 958 959 if ((ret = pfctl_kill_states_h(pfh, &kill, &killed)) != 0) 960 pfctl_errx(opts, 1, "DIOCKILLSTATES"); 961 962 if ((opts & PF_OPT_QUIET) == 0) 963 fprintf(stderr, "killed %d states\n", killed); 964 } 965 966 void 967 pfctl_id_kill_states(int dev, const char *iface, int opts) 968 { 969 struct pfctl_kill kill; 970 unsigned int killed; 971 int ret; 972 973 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 974 warnx("no id specified"); 975 usage(); 976 } 977 978 memset(&kill, 0, sizeof(kill)); 979 980 if (opts & PF_OPT_KILLMATCH) 981 kill.kill_match = true; 982 983 if ((sscanf(state_kill[1], "%jx/%x", 984 &kill.cmp.id, &kill.cmp.creatorid)) == 2) { 985 } 986 else if ((sscanf(state_kill[1], "%jx", &kill.cmp.id)) == 1) { 987 kill.cmp.creatorid = 0; 988 } else { 989 warnx("wrong id format specified"); 990 usage(); 991 } 992 if (kill.cmp.id == 0) { 993 warnx("cannot kill id 0"); 994 usage(); 995 } 996 997 if ((ret = pfctl_kill_states_h(pfh, &kill, &killed)) != 0) 998 pfctl_errx(opts, 1, "DIOCKILLSTATES"); 999 1000 if ((opts & PF_OPT_QUIET) == 0) 1001 fprintf(stderr, "killed %d states\n", killed); 1002 } 1003 1004 void 1005 pfctl_key_kill_states(int dev, const char *iface, int opts) 1006 { 1007 struct pfctl_kill kill; 1008 char *s, *token, *tokens[4]; 1009 struct protoent *p; 1010 u_int i, sidx, didx; 1011 int ret, killed; 1012 1013 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 1014 warnx("no key specified"); 1015 usage(); 1016 } 1017 memset(&kill, 0, sizeof(kill)); 1018 1019 if (iface != NULL && 1020 strlcpy(kill.ifname, iface, sizeof(kill.ifname)) >= 1021 sizeof(kill.ifname)) 1022 pfctl_errx(opts, 1, "invalid interface: %s", iface); 1023 1024 s = strdup(state_kill[1]); 1025 if (!s) 1026 errx(1, "%s: strdup", __func__); 1027 i = 0; 1028 while ((token = strsep(&s, " \t")) != NULL) 1029 if (*token != '\0') { 1030 if (i < 4) 1031 tokens[i] = token; 1032 i++; 1033 } 1034 if (i != 4) 1035 errx(1, "%s: key must be " 1036 "\"protocol host1:port1 direction host2:port2\" format", 1037 __func__); 1038 1039 if ((p = getprotobyname(tokens[0])) == NULL) 1040 errx(1, "invalid protocol: %s", tokens[0]); 1041 kill.proto = p->p_proto; 1042 1043 if (strcmp(tokens[2], "->") == 0) { 1044 sidx = 1; 1045 didx = 3; 1046 } else if (strcmp(tokens[2], "<-") == 0) { 1047 sidx = 3; 1048 didx = 1; 1049 } else 1050 errx(1, "invalid direction: %s", tokens[2]); 1051 1052 if (pfctl_parse_host(tokens[sidx], &kill.src) == -1) 1053 errx(1, "invalid host: %s", tokens[sidx]); 1054 if (pfctl_parse_host(tokens[didx], &kill.dst) == -1) 1055 errx(1, "invalid host: %s", tokens[didx]); 1056 1057 if ((ret = pfctl_kill_states_h(pfh, &kill, &killed)) != 0) 1058 pfctl_errx(opts, 1, "DIOCKILLSTATES"); 1059 1060 if ((opts & PF_OPT_QUIET) == 0) 1061 fprintf(stderr, "killed %d states\n", killed); 1062 } 1063 1064 int 1065 pfctl_parse_host(char *str, struct pf_rule_addr *addr) 1066 { 1067 char *s = NULL, *sbs, *sbe; 1068 struct addrinfo hints, *ai; 1069 1070 s = strdup(str); 1071 if (!s) 1072 errx(1, "pfctl_parse_host: strdup"); 1073 1074 memset(&hints, 0, sizeof(hints)); 1075 hints.ai_socktype = SOCK_DGRAM; /* dummy */ 1076 hints.ai_flags = AI_NUMERICHOST; 1077 1078 if ((sbs = strchr(s, '[')) != NULL && (sbe = strrchr(s, ']')) != NULL) { 1079 hints.ai_family = AF_INET6; 1080 *(sbs++) = *sbe = '\0'; 1081 } else if ((sbs = strchr(s, ':')) != NULL) { 1082 hints.ai_family = AF_INET; 1083 *(sbs++) = '\0'; 1084 } else { 1085 /* Assume that no ':<number>' means port 0 */ 1086 } 1087 1088 if (getaddrinfo(s, sbs, &hints, &ai) != 0) 1089 goto error; 1090 1091 copy_satopfaddr(&addr->addr.v.a.addr, ai->ai_addr); 1092 addr->port[0] = ai->ai_family == AF_INET6 ? 1093 ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port : 1094 ((struct sockaddr_in *)ai->ai_addr)->sin_port; 1095 freeaddrinfo(ai); 1096 free(s); 1097 1098 memset(&addr->addr.v.a.mask, 0xff, sizeof(struct pf_addr)); 1099 addr->port_op = PF_OP_EQ; 1100 addr->addr.type = PF_ADDR_ADDRMASK; 1101 1102 return (0); 1103 1104 error: 1105 free(s); 1106 return (-1); 1107 } 1108 1109 int 1110 pfctl_get_pool(int dev, struct pfctl_pool *pool, u_int32_t nr, 1111 u_int32_t ticket, int r_action, const char *anchorname, int which) 1112 { 1113 struct pfioc_pooladdr pp; 1114 struct pfctl_pooladdr *pa; 1115 u_int32_t pnr, mpnr; 1116 int ret; 1117 1118 memset(&pp, 0, sizeof(pp)); 1119 if ((ret = pfctl_get_addrs(pfh, ticket, nr, r_action, anchorname, &mpnr, which)) != 0) { 1120 warnc(ret, "DIOCGETADDRS"); 1121 return (-1); 1122 } 1123 1124 TAILQ_INIT(&pool->list); 1125 for (pnr = 0; pnr < mpnr; ++pnr) { 1126 if ((ret = pfctl_get_addr(pfh, ticket, nr, r_action, anchorname, pnr, &pp, which)) != 0) { 1127 warnc(ret, "DIOCGETADDR"); 1128 return (-1); 1129 } 1130 pa = calloc(1, sizeof(struct pfctl_pooladdr)); 1131 if (pa == NULL) 1132 err(1, "calloc"); 1133 bcopy(&pp.addr, pa, sizeof(struct pfctl_pooladdr)); 1134 pa->af = pp.af; 1135 TAILQ_INSERT_TAIL(&pool->list, pa, entries); 1136 } 1137 1138 return (0); 1139 } 1140 1141 void 1142 pfctl_move_pool(struct pfctl_pool *src, struct pfctl_pool *dst) 1143 { 1144 struct pfctl_pooladdr *pa; 1145 1146 while ((pa = TAILQ_FIRST(&src->list)) != NULL) { 1147 TAILQ_REMOVE(&src->list, pa, entries); 1148 TAILQ_INSERT_TAIL(&dst->list, pa, entries); 1149 } 1150 } 1151 1152 void 1153 pfctl_clear_pool(struct pfctl_pool *pool) 1154 { 1155 struct pfctl_pooladdr *pa; 1156 1157 while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { 1158 TAILQ_REMOVE(&pool->list, pa, entries); 1159 free(pa); 1160 } 1161 } 1162 1163 void 1164 pfctl_print_eth_rule_counters(struct pfctl_eth_rule *rule, int opts) 1165 { 1166 if (opts & PF_OPT_VERBOSE) { 1167 printf(" [ Evaluations: %-8llu Packets: %-8llu " 1168 "Bytes: %-10llu]\n", 1169 (unsigned long long)rule->evaluations, 1170 (unsigned long long)(rule->packets[0] + 1171 rule->packets[1]), 1172 (unsigned long long)(rule->bytes[0] + 1173 rule->bytes[1])); 1174 } 1175 if (opts & PF_OPT_VERBOSE2) { 1176 char timestr[30]; 1177 1178 if (rule->last_active_timestamp != 0) { 1179 bcopy(ctime(&rule->last_active_timestamp), timestr, 1180 sizeof(timestr)); 1181 *strchr(timestr, '\n') = '\0'; 1182 } else { 1183 snprintf(timestr, sizeof(timestr), "N/A"); 1184 } 1185 printf(" [ Last Active Time: %s ]\n", timestr); 1186 } 1187 } 1188 1189 void 1190 pfctl_print_rule_counters(struct pfctl_rule *rule, int opts) 1191 { 1192 if (opts & PF_OPT_DEBUG) { 1193 const char *t[PF_SKIP_COUNT] = { "i", "d", "f", 1194 "p", "sa", "da", "sp", "dp" }; 1195 int i; 1196 1197 printf(" [ Skip steps: "); 1198 for (i = 0; i < PF_SKIP_COUNT; ++i) { 1199 if (rule->skip[i].nr == rule->nr + 1) 1200 continue; 1201 printf("%s=", t[i]); 1202 if (rule->skip[i].nr == -1) 1203 printf("end "); 1204 else 1205 printf("%u ", rule->skip[i].nr); 1206 } 1207 printf("]\n"); 1208 1209 printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n", 1210 rule->qname, rule->qid, rule->pqname, rule->pqid); 1211 if (rule->rule_flag & PFRULE_EXPIRED) 1212 printf(" [ Expired: %lld secs ago ]\n", 1213 (long long)(time(NULL) - rule->exptime)); 1214 } 1215 if (opts & PF_OPT_VERBOSE) { 1216 printf(" [ Evaluations: %-8llu Packets: %-8llu " 1217 "Bytes: %-10llu States: %-6ju]\n", 1218 (unsigned long long)rule->evaluations, 1219 (unsigned long long)(rule->packets[0] + 1220 rule->packets[1]), 1221 (unsigned long long)(rule->bytes[0] + 1222 rule->bytes[1]), (uintmax_t)rule->states_cur); 1223 printf(" [ Source Nodes: %-6ju " 1224 "Limit: %-6ju " 1225 "NAT/RDR: %-6ju " 1226 "Route: %-6ju " 1227 "]\n", 1228 (uintmax_t)rule->src_nodes, 1229 (uintmax_t)rule->src_nodes_type[PF_SN_LIMIT], 1230 (uintmax_t)rule->src_nodes_type[PF_SN_NAT], 1231 (uintmax_t)rule->src_nodes_type[PF_SN_ROUTE]); 1232 if (!(opts & PF_OPT_DEBUG)) 1233 printf(" [ Inserted: uid %u pid %u " 1234 "State Creations: %-6ju]\n", 1235 (unsigned)rule->cuid, (unsigned)rule->cpid, 1236 (uintmax_t)rule->states_tot); 1237 } 1238 if (opts & PF_OPT_VERBOSE2) { 1239 char timestr[30]; 1240 if (rule->last_active_timestamp != 0) { 1241 bcopy(ctime(&rule->last_active_timestamp), timestr, 1242 sizeof(timestr)); 1243 *strchr(timestr, '\n') = '\0'; 1244 } else { 1245 snprintf(timestr, sizeof(timestr), "N/A"); 1246 } 1247 printf(" [ Last Active Time: %s ]\n", timestr); 1248 } 1249 } 1250 1251 void 1252 pfctl_print_title(char *title) 1253 { 1254 if (!first_title) 1255 printf("\n"); 1256 first_title = 0; 1257 printf("%s\n", title); 1258 } 1259 1260 int 1261 pfctl_show_statelims(int dev, enum pfctl_show format, int opts) 1262 { 1263 struct pfctl_state_lim stlim; 1264 uint32_t id = PF_STATELIM_ID_MIN; 1265 int error; 1266 1267 if (opts & PF_OPT_SHOWALL) 1268 pfctl_print_title("STATE LIMITERS:"); 1269 1270 if (format == PFCTL_SHOW_LABELS) { 1271 printf("%3s %8s/%-8s %5s/%-5s %8s %8s %8s\n", "ID", "USE", 1272 "LIMIT", "RATE", "SECS", "ADMIT", "HARDLIM", "RATELIM"); 1273 } 1274 1275 for (;;) { 1276 memset(&stlim, 0, sizeof(stlim)); 1277 stlim.id = id; 1278 1279 error = pfctl_state_limiter_nget(pfh, &stlim); 1280 if (error != 0) { 1281 if (error == ENOENT) { 1282 /* we're done */ 1283 return (0); 1284 } 1285 warnc(error, "DIOCGETNSTATELIM %u", stlim.id); 1286 return (-1); 1287 } 1288 1289 switch (format) { 1290 case PFCTL_SHOW_RULES: 1291 print_statelim(&stlim); 1292 break; 1293 case PFCTL_SHOW_LABELS: 1294 printf("%3u %8u/%-8u ", stlim.id, stlim.inuse, 1295 stlim.limit); 1296 if (stlim.rate.limit != 0) { 1297 printf("%5u/%-5u ", stlim.rate.limit, 1298 stlim.rate.seconds); 1299 } else 1300 printf("%5s/%-5s ", "nil", "nil"); 1301 printf("%8ju %8ju %8ju\n", stlim.admitted, 1302 stlim.hardlimited, stlim.ratelimited); 1303 break; 1304 default: 1305 errx(1, "%s: unexpected format %d", __func__, format); 1306 /* NOTREACHED */ 1307 } 1308 1309 id = stlim.id + 1; 1310 } 1311 } 1312 1313 static inline int 1314 pf_addr_inc(struct pf_addr *addr) 1315 { 1316 int i; 1317 uint32_t val, inc; 1318 1319 for (i = 3; i >= 0; i--) { 1320 val = ntohl(addr->addr32[i]); 1321 inc = val + 1; 1322 addr->addr32[i] = htonl(inc); 1323 if (inc > val) 1324 return (0); 1325 } 1326 1327 return (1); 1328 } 1329 1330 static int 1331 pfctl_print_source(struct pfctl_source *e, void *arg) 1332 { 1333 print_addr_str(e->af, &e->addr); 1334 switch (e->af) { 1335 case AF_INET: 1336 printf("/%u ", e->inet_prefix); 1337 break; 1338 case AF_INET6: 1339 printf("/%u ", e->inet6_prefix); 1340 break; 1341 default: 1342 printf("/af? "); 1343 break; 1344 } 1345 printf("rdomain %u ", e->rdomain); 1346 1347 printf("inuse %u/%u ", e->inuse, e->limit); 1348 printf("admit %ju hardlim %ju ratelim %ju\n", 1349 e->admitted, e->hardlimited, e->ratelimited); 1350 1351 return (0); 1352 } 1353 1354 static int 1355 pfctl_show_sources(int dev, const struct pfctl_source_lim *srlim, 1356 enum pfctl_show format, int opts) 1357 { 1358 int error; 1359 1360 if (format != PFCTL_SHOW_LABELS) 1361 errx(1, "%s format is not PFCTL_SHOW_LABELS", __func__); 1362 1363 error = pfctl_source_get(pfh, srlim->id, pfctl_print_source, NULL); 1364 if (error != 0) 1365 warnc(error, "DIOCGETNSOURCE %u", srlim->id); 1366 return (error); 1367 } 1368 1369 int 1370 pfctl_show_sourcelims(int dev, enum pfctl_show format, int opts, 1371 const char *idopt) 1372 { 1373 struct pfctl_source_lim srlim; 1374 uint32_t id = PF_SOURCELIM_ID_MIN; 1375 int error; 1376 1377 if (idopt != NULL) { 1378 const char *errstr; 1379 1380 id = strtonum(idopt, PF_SOURCELIM_ID_MIN, PF_SOURCELIM_ID_MAX, 1381 &errstr); 1382 if (errstr != NULL) 1383 errx(1, "source limiter id: %s", errstr); 1384 } 1385 1386 if (opts & PF_OPT_SHOWALL) 1387 pfctl_print_title("SOURCE LIMITERS:"); 1388 1389 if (format == PFCTL_SHOW_LABELS) { 1390 printf("%3s %8s/%-8s %5s %5s/%-5s %8s %8s %8s %8s\n", "ID", 1391 "USE", "ADDRS", "LIMIT", "RATE", "SECS", "ADMIT", "ADDRLIM", 1392 "HARDLIM", "RATELIM"); 1393 } 1394 1395 for (;;) { 1396 memset(&srlim, 0, sizeof(srlim)); 1397 srlim.id = id; 1398 1399 if (idopt != NULL) { 1400 error = pfctl_source_limiter_get(pfh, &srlim); 1401 } else { 1402 error = pfctl_source_limiter_nget(pfh, &srlim); 1403 } 1404 1405 if (error != 0) { 1406 if (error == ESRCH) { 1407 /* we're done */ 1408 return (0); 1409 } 1410 warnc(error, "DIOCGETNSOURCELIM %u", srlim.id); 1411 return (-1); 1412 } 1413 1414 switch (format) { 1415 case PFCTL_SHOW_RULES: 1416 print_sourcelim(&srlim); 1417 break; 1418 1419 case PFCTL_SHOW_LABELS: 1420 printf("%3u %8u/%-8u %5u ", srlim.id, srlim.nentries, 1421 srlim.entries, srlim.limit); 1422 if (srlim.rate.limit != 0) { 1423 printf("%5u/%-5u ", srlim.rate.limit, 1424 srlim.rate.seconds); 1425 } else 1426 printf("%5s/%-5s ", "nil", "nil"); 1427 printf("%8ju %8ju %8ju %8ju\n", 1428 srlim.admitted, srlim.addrlimited, srlim.hardlimited, 1429 srlim.ratelimited); 1430 1431 if (opts & PF_OPT_VERBOSE) 1432 if (pfctl_show_sources(dev, &srlim, format, 1433 opts) != 0) 1434 return (-1); 1435 break; 1436 1437 default: 1438 errx(1, "%s: unexpected format %d", __func__, format); 1439 /* NOTREACHED */ 1440 } 1441 1442 id = srlim.id + 1; 1443 } 1444 1445 return (0); 1446 } 1447 1448 void 1449 pfctl_kill_source(int dev, const char *idopt, const char *source, int opts) 1450 { 1451 struct pfctl_source_clear clear = { 0 }; 1452 unsigned int id; 1453 const char *errstr; 1454 struct addrinfo hints, *res; 1455 int error; 1456 1457 if (idopt == NULL) 1458 errx(1, "source limiter id unspecified"); 1459 if (source == NULL) 1460 errx(1, "source limiter address unspecified"); 1461 1462 id = strtonum(idopt, PF_SOURCELIM_ID_MIN, PF_SOURCELIM_ID_MAX, &errstr); 1463 if (errstr != NULL) 1464 errx(1, "source limiter id: %s", errstr); 1465 1466 memset(&hints, 0, sizeof(hints)); 1467 hints.ai_socktype = SOCK_DGRAM; /* dummy */ 1468 hints.ai_flags = AI_NUMERICHOST; 1469 1470 error = getaddrinfo(source, NULL, &hints, &res); 1471 if (error != 0) 1472 errx(1, "source limiter address: %s", gai_strerror(error)); 1473 1474 clear.id = id; 1475 clear.af = res->ai_family; 1476 copy_satopfaddr(&clear.addr, res->ai_addr); 1477 1478 freeaddrinfo(res); 1479 1480 error = pfctl_source_clear(pfh, &clear); 1481 switch (error) { 1482 case 0: 1483 break; 1484 case ESRCH: 1485 errx(1, "source limiter %u not found", id); 1486 case ENOENT: 1487 errx(1, "source limiter %u: %s not found", id, source); 1488 default: 1489 err(1, "kill source limiter %u entry %s", id, source); 1490 } 1491 } 1492 1493 int 1494 pfctl_show_eth_rules(int dev, char *path, int opts, enum pfctl_show format, 1495 char *anchorname, int depth, int wildcard) 1496 { 1497 char anchor_call[MAXPATHLEN]; 1498 struct pfctl_eth_rules_info info; 1499 struct pfctl_eth_rule rule; 1500 int brace; 1501 int dotitle = opts & PF_OPT_SHOWALL; 1502 int len = strlen(path); 1503 int ret; 1504 char *npath, *p; 1505 1506 /* 1507 * Truncate a trailing / and * on an anchorname before searching for 1508 * the ruleset, this is syntactic sugar that doesn't actually make it 1509 * to the kernel. 1510 */ 1511 if ((p = strrchr(anchorname, '/')) != NULL && 1512 p[1] == '*' && p[2] == '\0') { 1513 p[0] = '\0'; 1514 } 1515 1516 if (anchorname[0] == '/') { 1517 if ((npath = calloc(1, MAXPATHLEN)) == NULL) 1518 errx(1, "calloc"); 1519 snprintf(npath, MAXPATHLEN, "%s", anchorname); 1520 } else { 1521 if (path[0]) 1522 snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 1523 else 1524 snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 1525 npath = path; 1526 } 1527 1528 /* 1529 * If this anchor was called with a wildcard path, go through 1530 * the rulesets in the anchor rather than the rules. 1531 */ 1532 if (wildcard && (opts & PF_OPT_RECURSE)) { 1533 struct pfctl_eth_rulesets_info ri; 1534 u_int32_t mnr, nr; 1535 1536 if ((ret = pfctl_get_eth_rulesets_info(dev, &ri, npath)) != 0) { 1537 if (ret == EINVAL) { 1538 fprintf(stderr, "Anchor '%s' " 1539 "not found.\n", anchorname); 1540 } else { 1541 warnc(ret, "DIOCGETETHRULESETS"); 1542 return (-1); 1543 } 1544 } 1545 mnr = ri.nr; 1546 1547 pfctl_print_eth_rule_counters(&rule, opts); 1548 for (nr = 0; nr < mnr; ++nr) { 1549 struct pfctl_eth_ruleset_info rs; 1550 1551 if ((ret = pfctl_get_eth_ruleset(dev, npath, nr, &rs)) != 0) 1552 errc(1, ret, "DIOCGETETHRULESET"); 1553 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1554 printf("anchor \"%s\" all {\n", rs.name); 1555 pfctl_show_eth_rules(dev, npath, opts, 1556 format, rs.name, depth + 1, 0); 1557 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1558 printf("}\n"); 1559 } 1560 path[len] = '\0'; 1561 return (0); 1562 } 1563 1564 if ((ret = pfctl_get_eth_rules_info(dev, &info, path)) != 0) { 1565 warnc(ret, "DIOCGETETHRULES"); 1566 return (-1); 1567 } 1568 for (int nr = 0; nr < info.nr; nr++) { 1569 brace = 0; 1570 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1571 if ((ret = pfctl_get_eth_rule(dev, nr, info.ticket, path, &rule, 1572 opts & PF_OPT_CLRRULECTRS, anchor_call)) != 0) { 1573 warnc(ret, "DIOCGETETHRULE"); 1574 return (-1); 1575 } 1576 if (anchor_call[0] && 1577 ((((p = strrchr(anchor_call, '_')) != NULL) && 1578 (p == anchor_call || 1579 *(--p) == '/')) || (opts & PF_OPT_RECURSE))) { 1580 brace++; 1581 int aclen = strlen(anchor_call); 1582 if (anchor_call[aclen - 1] == '*') 1583 anchor_call[aclen - 2] = '\0'; 1584 } 1585 p = &anchor_call[0]; 1586 if (dotitle) { 1587 pfctl_print_title("ETH RULES:"); 1588 dotitle = 0; 1589 } 1590 print_eth_rule(&rule, anchor_call, 1591 opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG)); 1592 if (brace) 1593 printf(" {\n"); 1594 else 1595 printf("\n"); 1596 pfctl_print_eth_rule_counters(&rule, opts); 1597 if (brace) { 1598 pfctl_show_eth_rules(dev, path, opts, format, 1599 p, depth + 1, rule.anchor_wildcard); 1600 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1601 printf("}\n"); 1602 } 1603 } 1604 1605 path[len] = '\0'; 1606 return (0); 1607 } 1608 1609 int 1610 pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, 1611 char *anchorname, int depth, int wildcard) 1612 { 1613 struct pfctl_rules_info ri; 1614 struct pfctl_rule rule; 1615 char anchor_call[MAXPATHLEN]; 1616 u_int32_t nr, header = 0; 1617 int numeric = opts & PF_OPT_NUMERIC; 1618 int len = strlen(path), ret = 0; 1619 char *npath, *p; 1620 1621 /* 1622 * Truncate a trailing / and * on an anchorname before searching for 1623 * the ruleset, this is syntactic sugar that doesn't actually make it 1624 * to the kernel. 1625 */ 1626 if ((p = strrchr(anchorname, '/')) != NULL && 1627 p[1] == '*' && p[2] == '\0') { 1628 p[0] = '\0'; 1629 } 1630 1631 if (anchorname[0] == '/') { 1632 if ((npath = calloc(1, MAXPATHLEN)) == NULL) 1633 errx(1, "calloc"); 1634 strlcpy(npath, anchorname, MAXPATHLEN); 1635 } else { 1636 if (path[0]) 1637 snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 1638 else 1639 snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 1640 npath = path; 1641 } 1642 1643 /* 1644 * If this anchor was called with a wildcard path, go through 1645 * the rulesets in the anchor rather than the rules. 1646 */ 1647 if (wildcard && (opts & PF_OPT_RECURSE)) { 1648 struct pfioc_ruleset prs; 1649 u_int32_t mnr, nr; 1650 1651 memset(&prs, 0, sizeof(prs)); 1652 if ((ret = pfctl_get_rulesets(pfh, npath, &mnr)) != 0) 1653 errx(1, "%s", pf_strerror(ret)); 1654 1655 for (nr = 0; nr < mnr; ++nr) { 1656 if ((ret = pfctl_get_ruleset(pfh, npath, nr, &prs)) != 0) 1657 errx(1, "%s", pf_strerror(ret)); 1658 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1659 printf("anchor \"%s\" all {\n", prs.name); 1660 pfctl_show_rules(dev, npath, opts, 1661 format, prs.name, depth + 1, 0); 1662 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1663 printf("}\n"); 1664 } 1665 path[len] = '\0'; 1666 return (0); 1667 } 1668 1669 if (opts & PF_OPT_SHOWALL) { 1670 ret = pfctl_get_rules_info_h(pfh, &ri, PF_PASS, path); 1671 if (ret != 0) { 1672 warnx("%s", pf_strerror(ret)); 1673 goto error; 1674 } 1675 header++; 1676 } 1677 ret = pfctl_get_rules_info_h(pfh, &ri, PF_SCRUB, path); 1678 if (ret != 0) { 1679 warnx("%s", pf_strerror(ret)); 1680 goto error; 1681 } 1682 if (opts & PF_OPT_SHOWALL) { 1683 if (format == PFCTL_SHOW_RULES && (ri.nr > 0 || header)) 1684 pfctl_print_title("FILTER RULES:"); 1685 else if (format == PFCTL_SHOW_LABELS && labels) 1686 pfctl_print_title("LABEL COUNTERS:"); 1687 } 1688 1689 for (nr = 0; nr < ri.nr; ++nr) { 1690 if ((ret = pfctl_get_clear_rule_h(pfh, nr, ri.ticket, path, PF_SCRUB, 1691 &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) != 0) { 1692 warnc(ret, "DIOCGETRULENV"); 1693 goto error; 1694 } 1695 1696 if (pfctl_get_pool(dev, &rule.rdr, 1697 nr, ri.ticket, PF_SCRUB, path, PF_RDR) != 0) 1698 goto error; 1699 1700 if (pfctl_get_pool(dev, &rule.nat, 1701 nr, ri.ticket, PF_SCRUB, path, PF_NAT) != 0) 1702 goto error; 1703 1704 if (pfctl_get_pool(dev, &rule.route, 1705 nr, ri.ticket, PF_SCRUB, path, PF_RT) != 0) 1706 goto error; 1707 1708 switch (format) { 1709 case PFCTL_SHOW_LABELS: 1710 break; 1711 case PFCTL_SHOW_RULES: 1712 if (rule.label[0][0] && (opts & PF_OPT_SHOWALL)) 1713 labels = 1; 1714 print_rule(&rule, anchor_call, opts, numeric); 1715 /* 1716 * Do not print newline, when we have not 1717 * printed expired rule. 1718 */ 1719 if (!(rule.rule_flag & PFRULE_EXPIRED) || 1720 (opts & (PF_OPT_VERBOSE2|PF_OPT_DEBUG))) 1721 printf("\n"); 1722 pfctl_print_rule_counters(&rule, opts); 1723 break; 1724 case PFCTL_SHOW_NOTHING: 1725 break; 1726 } 1727 pfctl_clear_pool(&rule.rdr); 1728 pfctl_clear_pool(&rule.nat); 1729 pfctl_clear_pool(&rule.route); 1730 } 1731 ret = pfctl_get_rules_info_h(pfh, &ri, PF_PASS, path); 1732 if (ret != 0) { 1733 warnc(ret, "DIOCGETRULES"); 1734 goto error; 1735 } 1736 for (nr = 0; nr < ri.nr; ++nr) { 1737 if ((ret = pfctl_get_clear_rule_h(pfh, nr, ri.ticket, path, PF_PASS, 1738 &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) != 0) { 1739 warnc(ret, "DIOCGETRULE"); 1740 goto error; 1741 } 1742 1743 if (pfctl_get_pool(dev, &rule.rdr, 1744 nr, ri.ticket, PF_PASS, path, PF_RDR) != 0) 1745 goto error; 1746 1747 if (pfctl_get_pool(dev, &rule.nat, 1748 nr, ri.ticket, PF_PASS, path, PF_NAT) != 0) 1749 goto error; 1750 1751 if (pfctl_get_pool(dev, &rule.route, 1752 nr, ri.ticket, PF_PASS, path, PF_RT) != 0) 1753 goto error; 1754 1755 switch (format) { 1756 case PFCTL_SHOW_LABELS: { 1757 bool show = false; 1758 int i = 0; 1759 1760 while (rule.label[i][0]) { 1761 printf("%s ", rule.label[i++]); 1762 show = true; 1763 } 1764 1765 if (show) { 1766 printf("%llu %llu %llu %llu" 1767 " %llu %llu %llu %ju\n", 1768 (unsigned long long)rule.evaluations, 1769 (unsigned long long)(rule.packets[0] + 1770 rule.packets[1]), 1771 (unsigned long long)(rule.bytes[0] + 1772 rule.bytes[1]), 1773 (unsigned long long)rule.packets[0], 1774 (unsigned long long)rule.bytes[0], 1775 (unsigned long long)rule.packets[1], 1776 (unsigned long long)rule.bytes[1], 1777 (uintmax_t)rule.states_tot); 1778 } 1779 1780 if (anchor_call[0] && 1781 (((p = strrchr(anchor_call, '/')) ? 1782 p[1] == '_' : anchor_call[0] == '_') || 1783 opts & PF_OPT_RECURSE)) { 1784 pfctl_show_rules(dev, npath, opts, format, 1785 anchor_call, depth, rule.anchor_wildcard); 1786 } 1787 break; 1788 } 1789 case PFCTL_SHOW_RULES: 1790 if (rule.label[0][0] && (opts & PF_OPT_SHOWALL)) 1791 labels = 1; 1792 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1793 print_rule(&rule, anchor_call, opts, numeric); 1794 1795 /* 1796 * If this is a 'unnamed' brace notation 1797 * anchor, OR the user has explicitly requested 1798 * recursion, print it recursively. 1799 */ 1800 if (anchor_call[0] && 1801 (((p = strrchr(anchor_call, '/')) ? 1802 p[1] == '_' : anchor_call[0] == '_') || 1803 opts & PF_OPT_RECURSE)) { 1804 printf(" {\n"); 1805 pfctl_print_rule_counters(&rule, opts); 1806 pfctl_show_rules(dev, npath, opts, format, 1807 anchor_call, depth + 1, 1808 rule.anchor_wildcard); 1809 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1810 printf("}\n"); 1811 } else { 1812 printf("\n"); 1813 pfctl_print_rule_counters(&rule, opts); 1814 } 1815 break; 1816 case PFCTL_SHOW_NOTHING: 1817 break; 1818 } 1819 pfctl_clear_pool(&rule.rdr); 1820 pfctl_clear_pool(&rule.nat); 1821 } 1822 1823 error: 1824 path[len] = '\0'; 1825 return (ret); 1826 } 1827 1828 int 1829 pfctl_show_nat(int dev, const char *path, int opts, char *anchorname, int depth, 1830 int wildcard) 1831 { 1832 struct pfctl_rules_info ri; 1833 struct pfctl_rule rule; 1834 char anchor_call[MAXPATHLEN]; 1835 u_int32_t nr; 1836 static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; 1837 int i, dotitle = opts & PF_OPT_SHOWALL; 1838 int ret; 1839 int len = strlen(path); 1840 char *npath, *p; 1841 1842 /* 1843 * Truncate a trailing / and * on an anchorname before searching for 1844 * the ruleset, this is syntactic sugar that doesn't actually make it 1845 * to the kernel. 1846 */ 1847 if ((p = strrchr(anchorname, '/')) != NULL && 1848 p[1] == '*' && p[2] == '\0') { 1849 p[0] = '\0'; 1850 } 1851 1852 if ((npath = calloc(1, MAXPATHLEN)) == NULL) 1853 errx(1, "calloc"); 1854 1855 if (anchorname[0] == '/') { 1856 snprintf(npath, MAXPATHLEN, "%s", anchorname); 1857 } else { 1858 snprintf(npath, MAXPATHLEN, "%s", path); 1859 if (npath[0]) 1860 snprintf(&npath[len], MAXPATHLEN - len, "/%s", anchorname); 1861 else 1862 snprintf(&npath[len], MAXPATHLEN - len, "%s", anchorname); 1863 } 1864 1865 /* 1866 * If this anchor was called with a wildcard path, go through 1867 * the rulesets in the anchor rather than the rules. 1868 */ 1869 if (wildcard && (opts & PF_OPT_RECURSE)) { 1870 struct pfioc_ruleset prs; 1871 u_int32_t mnr, nr; 1872 memset(&prs, 0, sizeof(prs)); 1873 if ((ret = pfctl_get_rulesets(pfh, npath, &mnr)) != 0) { 1874 if (ret == EINVAL) 1875 fprintf(stderr, "NAT anchor '%s' " 1876 "not found.\n", anchorname); 1877 else 1878 errx(1, "%s", pf_strerror(ret)); 1879 } 1880 1881 for (nr = 0; nr < mnr; ++nr) { 1882 if ((ret = pfctl_get_ruleset(pfh, npath, nr, &prs)) != 0) 1883 errx(1, "%s", pf_strerror(ret)); 1884 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1885 printf("nat-anchor \"%s\" all {\n", prs.name); 1886 pfctl_show_nat(dev, npath, opts, 1887 prs.name, depth + 1, 0); 1888 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1889 printf("}\n"); 1890 } 1891 npath[len] = '\0'; 1892 return (0); 1893 } 1894 1895 for (i = 0; i < 3; i++) { 1896 ret = pfctl_get_rules_info_h(pfh, &ri, nattype[i], npath); 1897 if (ret != 0) { 1898 warnc(ret, "DIOCGETRULES"); 1899 return (-1); 1900 } 1901 for (nr = 0; nr < ri.nr; ++nr) { 1902 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1903 1904 if ((ret = pfctl_get_rule_h(pfh, nr, ri.ticket, npath, 1905 nattype[i], &rule, anchor_call)) != 0) { 1906 warnc(ret, "DIOCGETRULE"); 1907 return (-1); 1908 } 1909 if (pfctl_get_pool(dev, &rule.rdr, nr, 1910 ri.ticket, nattype[i], npath, PF_RDR) != 0) 1911 return (-1); 1912 if (pfctl_get_pool(dev, &rule.nat, nr, 1913 ri.ticket, nattype[i], npath, PF_NAT) != 0) 1914 return (-1); 1915 if (pfctl_get_pool(dev, &rule.route, nr, 1916 ri.ticket, nattype[i], npath, PF_RT) != 0) 1917 return (-1); 1918 1919 if (dotitle) { 1920 pfctl_print_title("TRANSLATION RULES:"); 1921 dotitle = 0; 1922 } 1923 print_rule(&rule, anchor_call, 1924 opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC); 1925 if (anchor_call[0] && 1926 (((p = strrchr(anchor_call, '/')) ? 1927 p[1] == '_' : anchor_call[0] == '_') || 1928 opts & PF_OPT_RECURSE)) { 1929 printf(" {\n"); 1930 pfctl_print_rule_counters(&rule, opts); 1931 pfctl_show_nat(dev, npath, opts, anchor_call, 1932 depth + 1, rule.anchor_wildcard); 1933 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1934 printf("}\n"); 1935 } else { 1936 printf("\n"); 1937 pfctl_print_rule_counters(&rule, opts); 1938 } 1939 } 1940 } 1941 return (0); 1942 } 1943 1944 static int 1945 pfctl_print_src_node(struct pfctl_src_node *sn, void *arg) 1946 { 1947 int *opts = (int *)arg; 1948 1949 if (*opts & PF_OPT_SHOWALL) { 1950 pfctl_print_title("SOURCE TRACKING NODES:"); 1951 *opts &= ~PF_OPT_SHOWALL; 1952 } 1953 1954 print_src_node(sn, *opts); 1955 1956 return (0); 1957 } 1958 1959 int 1960 pfctl_show_src_nodes(int dev, int opts) 1961 { 1962 int error; 1963 1964 error = pfctl_get_srcnodes(pfh, pfctl_print_src_node, &opts); 1965 1966 return (error); 1967 } 1968 1969 struct pfctl_show_state_arg { 1970 int opts; 1971 int dotitle; 1972 const char *iface; 1973 }; 1974 1975 static int 1976 pfctl_show_state(struct pfctl_state *s, void *arg) 1977 { 1978 struct pfctl_show_state_arg *a = (struct pfctl_show_state_arg *)arg; 1979 1980 if (a->dotitle) { 1981 pfctl_print_title("STATES:"); 1982 a->dotitle = 0; 1983 } 1984 print_state(s, a->opts); 1985 1986 return (0); 1987 } 1988 1989 int 1990 pfctl_show_states(int dev, const char *iface, int opts) 1991 { 1992 struct pfctl_show_state_arg arg; 1993 struct pfctl_state_filter filter = {}; 1994 1995 if (iface != NULL) 1996 strlcpy(filter.ifname, iface, IFNAMSIZ); 1997 1998 arg.opts = opts; 1999 arg.dotitle = opts & PF_OPT_SHOWALL; 2000 arg.iface = iface; 2001 2002 if (pfctl_get_states_h(pfh, &filter, pfctl_show_state, &arg)) 2003 return (-1); 2004 2005 return (0); 2006 } 2007 2008 int 2009 pfctl_show_status(int dev, int opts) 2010 { 2011 struct pfctl_status *status; 2012 struct pfctl_syncookies cookies; 2013 int ret; 2014 2015 if ((status = pfctl_get_status_h(pfh)) == NULL) { 2016 warn("DIOCGETSTATUS"); 2017 return (-1); 2018 } 2019 if ((ret = pfctl_get_syncookies(dev, &cookies)) != 0) { 2020 pfctl_free_status(status); 2021 warnc(ret, "DIOCGETSYNCOOKIES"); 2022 return (-1); 2023 } 2024 if (opts & PF_OPT_SHOWALL) 2025 pfctl_print_title("INFO:"); 2026 print_status(status, &cookies, opts); 2027 pfctl_free_status(status); 2028 return (0); 2029 } 2030 2031 int 2032 pfctl_show_running(int dev) 2033 { 2034 struct pfctl_status *status; 2035 int running; 2036 2037 if ((status = pfctl_get_status_h(pfh)) == NULL) { 2038 warn("DIOCGETSTATUS"); 2039 return (-1); 2040 } 2041 2042 running = status->running; 2043 2044 print_running(status); 2045 pfctl_free_status(status); 2046 return (!running); 2047 } 2048 2049 int 2050 pfctl_show_timeouts(int dev, int opts) 2051 { 2052 uint32_t seconds; 2053 int i; 2054 int ret; 2055 2056 if (opts & PF_OPT_SHOWALL) 2057 pfctl_print_title("TIMEOUTS:"); 2058 for (i = 0; pf_timeouts[i].name; i++) { 2059 if ((ret = pfctl_get_timeout(pfh, pf_timeouts[i].timeout, &seconds)) != 0) 2060 errc(1, ret, "DIOCGETTIMEOUT"); 2061 printf("%-20s %10d", pf_timeouts[i].name, seconds); 2062 if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && 2063 pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) 2064 printf(" states"); 2065 else 2066 printf("s"); 2067 printf("\n"); 2068 } 2069 return (0); 2070 2071 } 2072 2073 int 2074 pfctl_show_limits(int dev, int opts) 2075 { 2076 unsigned int limit; 2077 int i; 2078 int ret; 2079 2080 if (opts & PF_OPT_SHOWALL) 2081 pfctl_print_title("LIMITS:"); 2082 for (i = 0; pf_limits[i].name; i++) { 2083 if ((ret = pfctl_get_limit(pfh, pf_limits[i].index, &limit)) != 0) 2084 errc(1, ret, "DIOCGETLIMIT"); 2085 printf("%-13s ", pf_limits[i].name); 2086 if (limit == UINT_MAX) 2087 printf("unlimited\n"); 2088 else 2089 printf("hard limit %8u\n", limit); 2090 } 2091 return (0); 2092 } 2093 2094 void 2095 pfctl_read_limits(struct pfctl_handle *h) 2096 { 2097 int i; 2098 2099 for (i = 0; pf_limits[i].name; i++) { 2100 if (pfctl_get_limit(h, i, &limit_curr[i])) 2101 err(1, "DIOCGETLIMIT"); 2102 } 2103 } 2104 2105 void 2106 pfctl_restore_limits(void) 2107 { 2108 int i; 2109 2110 if (pfh == NULL) 2111 return; 2112 2113 for (i = 0; pf_limits[i].name; i++) { 2114 if (pfctl_set_limit(pfh, i, limit_curr[i])) 2115 warn("DIOCSETLIMIT (%s)", pf_limits[i].name); 2116 } 2117 } 2118 2119 void 2120 pfctl_show_creators(int opts) 2121 { 2122 int ret; 2123 uint32_t creators[16]; 2124 size_t count = nitems(creators); 2125 2126 ret = pfctl_get_creatorids(pfh, creators, &count); 2127 if (ret != 0) 2128 errx(ret, "Failed to retrieve creators"); 2129 2130 printf("Creator IDs:\n"); 2131 for (size_t i = 0; i < count; i++) 2132 printf("%08x\n", creators[i]); 2133 } 2134 2135 /* callbacks for rule/nat/rdr/addr */ 2136 int 2137 pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, int which) 2138 { 2139 struct pfctl_pooladdr *pa; 2140 int ret; 2141 2142 TAILQ_FOREACH(pa, &p->list, entries) { 2143 memcpy(&pf->paddr.addr, pa, sizeof(struct pfctl_pooladdr)); 2144 pf->paddr.af = pa->af; 2145 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2146 if ((ret = pfctl_add_addr(pf->h, &pf->paddr, which)) != 0) 2147 errc(1, ret, "DIOCADDADDR"); 2148 } 2149 } 2150 return (0); 2151 } 2152 2153 void 2154 pfctl_init_rule(struct pfctl_rule *r) 2155 { 2156 memset(r, 0, sizeof(struct pfctl_rule)); 2157 TAILQ_INIT(&(r->rdr.list)); 2158 TAILQ_INIT(&(r->nat.list)); 2159 TAILQ_INIT(&(r->route.list)); 2160 } 2161 2162 void 2163 pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r) 2164 { 2165 u_int8_t rs_num; 2166 struct pfctl_rule *rule; 2167 struct pfctl_ruleset *rs; 2168 2169 rs_num = pf_get_ruleset_number(r->action); 2170 if (rs_num == PF_RULESET_MAX) 2171 errx(1, "Invalid rule type %d", r->action); 2172 2173 rs = &pf->anchor->ruleset; 2174 2175 if ((rule = calloc(1, sizeof(*rule))) == NULL) 2176 err(1, "calloc"); 2177 bcopy(r, rule, sizeof(*rule)); 2178 TAILQ_INIT(&rule->rdr.list); 2179 pfctl_move_pool(&r->rdr, &rule->rdr); 2180 TAILQ_INIT(&rule->nat.list); 2181 pfctl_move_pool(&r->nat, &rule->nat); 2182 TAILQ_INIT(&rule->route.list); 2183 pfctl_move_pool(&r->route, &rule->route); 2184 2185 TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries); 2186 } 2187 2188 int 2189 pfctl_append_eth_rule(struct pfctl *pf, struct pfctl_eth_rule *r, 2190 const char *anchor_call) 2191 { 2192 struct pfctl_eth_rule *rule; 2193 struct pfctl_eth_ruleset *rs; 2194 char *p; 2195 2196 rs = &pf->eanchor->ruleset; 2197 2198 if (anchor_call[0] && r->anchor == NULL) { 2199 /* 2200 * Don't make non-brace anchors part of the main anchor pool. 2201 */ 2202 if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 2203 err(1, "pfctl_append_rule: calloc"); 2204 2205 pf_init_eth_ruleset(&r->anchor->ruleset); 2206 r->anchor->ruleset.anchor = r->anchor; 2207 if (strlcpy(r->anchor->path, anchor_call, 2208 sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 2209 errx(1, "pfctl_append_rule: strlcpy"); 2210 if ((p = strrchr(anchor_call, '/')) != NULL) { 2211 if (!strlen(p)) 2212 err(1, "pfctl_append_eth_rule: bad anchor name %s", 2213 anchor_call); 2214 } else 2215 p = (char *)anchor_call; 2216 if (strlcpy(r->anchor->name, p, 2217 sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 2218 errx(1, "pfctl_append_eth_rule: strlcpy"); 2219 } 2220 2221 if ((rule = calloc(1, sizeof(*rule))) == NULL) 2222 err(1, "calloc"); 2223 bcopy(r, rule, sizeof(*rule)); 2224 2225 TAILQ_INSERT_TAIL(&rs->rules, rule, entries); 2226 return (0); 2227 } 2228 2229 int 2230 pfctl_eth_ruleset_trans(struct pfctl *pf, char *path, 2231 struct pfctl_eth_anchor *a) 2232 { 2233 int osize = pf->trans->pfrb_size; 2234 2235 if ((pf->loadopt & PFCTL_FLAG_ETH) != 0) { 2236 if (pfctl_add_trans(pf->trans, PF_RULESET_ETH, path)) 2237 return (1); 2238 } 2239 if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 2240 return (5); 2241 2242 return (0); 2243 } 2244 2245 int 2246 pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pfctl_anchor *a, bool do_eth) 2247 { 2248 int osize = pf->trans->pfrb_size; 2249 2250 if ((pf->loadopt & PFCTL_FLAG_ETH) != 0 && do_eth) { 2251 if (pfctl_add_trans(pf->trans, PF_RULESET_ETH, path)) 2252 return (1); 2253 } 2254 if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { 2255 if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || 2256 pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || 2257 pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) 2258 return (1); 2259 } 2260 if (a == pf->astack[0] && ((altqsupport && 2261 (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) { 2262 if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path)) 2263 return (2); 2264 } 2265 if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) { 2266 if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) || 2267 pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path)) 2268 return (3); 2269 } 2270 if (pf->loadopt & PFCTL_FLAG_TABLE) 2271 if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path)) 2272 return (4); 2273 if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 2274 return (5); 2275 2276 return (0); 2277 } 2278 2279 void 2280 pfctl_load_statelim(struct pfctl *pf, struct pfctl_statelim *stlim) 2281 { 2282 int error; 2283 2284 if (pf->opts & PF_OPT_VERBOSE) 2285 print_statelim(&stlim->ioc); 2286 2287 if (pf->opts & PF_OPT_NOACTION) 2288 return; 2289 2290 error = pfctl_state_limiter_add(pf->h, &stlim->ioc); 2291 if (error) { 2292 errc(1, error, "DIOCADDSTATELIM %s id %u", stlim->ioc.name, 2293 stlim->ioc.id); 2294 } 2295 } 2296 2297 void 2298 pfctl_load_statelims(struct pfctl *pf) 2299 { 2300 struct pfctl_statelim *stlim; 2301 u_int32_t ticket = 0; 2302 2303 if ((pf->opts & PF_OPT_NOACTION) == 0) 2304 ticket = pfctl_get_ticket(pf->trans, PF_RULESET_FILTER, ""); 2305 2306 RB_FOREACH(stlim, pfctl_statelim_ids, &pf->statelim_ids) 2307 { 2308 stlim->ioc.ticket = ticket; 2309 pfctl_load_statelim(pf, stlim); 2310 } 2311 2312 /* Don't free the statelims because we're about to exit anyway. */ 2313 } 2314 2315 void 2316 pfctl_load_sourcelim(struct pfctl *pf, struct pfctl_source_lim *srlim) 2317 { 2318 int error; 2319 2320 if (pf->opts & PF_OPT_VERBOSE) 2321 print_sourcelim(srlim); 2322 2323 if (pf->opts & PF_OPT_NOACTION) 2324 return; 2325 2326 error = pfctl_source_limiter_add(pf->h, srlim); 2327 if (error != 0) { 2328 errc(1, error, "DIOCADDSOURCELIM %s id %u", srlim->name, 2329 srlim->id); 2330 } 2331 } 2332 2333 void 2334 pfctl_load_sourcelims(struct pfctl *pf) 2335 { 2336 struct pfctl_sourcelim *srlim; 2337 uint32_t ticket = 0; 2338 2339 if ((pf->opts & PF_OPT_NOACTION) == 0) 2340 ticket = pfctl_get_ticket(pf->trans, PF_RULESET_FILTER, ""); 2341 2342 RB_FOREACH(srlim, pfctl_sourcelim_ids, &pf->sourcelim_ids) 2343 { 2344 srlim->ioc.ticket = ticket; 2345 pfctl_load_sourcelim(pf, &srlim->ioc); 2346 } 2347 2348 /* Don't free the sourcelims because we're about to exit anyway. */ 2349 } 2350 2351 int 2352 pfctl_load_eth_ruleset(struct pfctl *pf, char *path, 2353 struct pfctl_eth_ruleset *rs, int depth) 2354 { 2355 struct pfctl_eth_rule *r; 2356 int error, len = strlen(path); 2357 int brace = 0; 2358 2359 pf->eanchor = rs->anchor; 2360 if (path[0]) 2361 snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->eanchor->name); 2362 else 2363 snprintf(&path[len], MAXPATHLEN - len, "%s", pf->eanchor->name); 2364 2365 if (depth) { 2366 if (TAILQ_FIRST(&rs->rules) != NULL) { 2367 brace++; 2368 if (pf->opts & PF_OPT_VERBOSE) 2369 printf(" {\n"); 2370 if ((pf->opts & PF_OPT_NOACTION) == 0 && 2371 (error = pfctl_eth_ruleset_trans(pf, 2372 path, rs->anchor))) { 2373 printf("pfctl_load_eth_rulesets: " 2374 "pfctl_eth_ruleset_trans %d\n", error); 2375 goto error; 2376 } 2377 } else if (pf->opts & PF_OPT_VERBOSE) 2378 printf("\n"); 2379 } 2380 2381 while ((r = TAILQ_FIRST(&rs->rules)) != NULL) { 2382 TAILQ_REMOVE(&rs->rules, r, entries); 2383 2384 error = pfctl_load_eth_rule(pf, path, r, depth); 2385 if (error) 2386 return (error); 2387 2388 if (r->anchor) { 2389 if ((error = pfctl_load_eth_ruleset(pf, path, 2390 &r->anchor->ruleset, depth + 1))) 2391 return (error); 2392 } else if (pf->opts & PF_OPT_VERBOSE) 2393 printf("\n"); 2394 free(r); 2395 } 2396 if (brace && pf->opts & PF_OPT_VERBOSE) { 2397 INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 2398 printf("}\n"); 2399 } 2400 path[len] = '\0'; 2401 2402 return (0); 2403 error: 2404 path[len] = '\0'; 2405 return (error); 2406 } 2407 2408 int 2409 pfctl_load_eth_rule(struct pfctl *pf, char *path, struct pfctl_eth_rule *r, 2410 int depth) 2411 { 2412 char *name; 2413 char anchor[PF_ANCHOR_NAME_SIZE]; 2414 int len = strlen(path); 2415 int ret; 2416 2417 if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor)) 2418 errx(1, "pfctl_load_eth_rule: strlcpy"); 2419 2420 if (r->anchor) { 2421 if (r->anchor->match) { 2422 if (path[0]) 2423 snprintf(&path[len], MAXPATHLEN - len, 2424 "/%s", r->anchor->name); 2425 else 2426 snprintf(&path[len], MAXPATHLEN - len, 2427 "%s", r->anchor->name); 2428 name = r->anchor->name; 2429 } else 2430 name = r->anchor->path; 2431 } else 2432 name = ""; 2433 2434 if ((pf->opts & PF_OPT_NOACTION) == 0) 2435 if ((ret = pfctl_add_eth_rule(pf->dev, r, anchor, name, 2436 pf->eth_ticket)) != 0) 2437 errc(1, ret, "DIOCADDETHRULENV"); 2438 2439 if (pf->opts & PF_OPT_VERBOSE) { 2440 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 2441 print_eth_rule(r, r->anchor ? r->anchor->name : "", 2442 pf->opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG)); 2443 } 2444 2445 path[len] = '\0'; 2446 2447 return (0); 2448 } 2449 2450 static int 2451 pfctl_load_tables(struct pfctl *pf, char *path, struct pfctl_anchor *a, 2452 int rs_num) 2453 { 2454 struct pfr_ktable *kt, *ktw; 2455 struct pfr_uktable *ukt; 2456 char anchor_path[PF_ANCHOR_MAXPATH]; 2457 int e; 2458 2459 RB_FOREACH_SAFE(kt, pfr_ktablehead, &pfr_ktables, ktw) { 2460 if (strcmp(kt->pfrkt_anchor, a->path) != 0) 2461 continue; 2462 2463 if (path != NULL && *path) { 2464 strlcpy(anchor_path, kt->pfrkt_anchor, 2465 sizeof(anchor_path)); 2466 snprintf(kt->pfrkt_anchor, PF_ANCHOR_MAXPATH, "%s/%s", 2467 path, anchor_path); 2468 } 2469 ukt = (struct pfr_uktable *)kt; 2470 e = pfr_ina_define(&ukt->pfrukt_t, ukt->pfrukt_addrs.pfrb_caddr, 2471 ukt->pfrukt_addrs.pfrb_size, NULL, NULL, 2472 pf->anchor->ruleset.tticket, 2473 ukt->pfrukt_init_addr ? PFR_FLAG_ADDRSTOO : 0); 2474 if (e != 0) 2475 err(1, "%s pfr_ina_define() %s@%s", __func__, 2476 kt->pfrkt_name, kt->pfrkt_anchor); 2477 RB_REMOVE(pfr_ktablehead, &pfr_ktables, kt); 2478 pfr_buf_clear(&ukt->pfrukt_addrs); 2479 free(ukt); 2480 } 2481 2482 return (0); 2483 } 2484 2485 int 2486 pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs, 2487 int rs_num, int depth) 2488 { 2489 struct pfctl_rule *r; 2490 int error, len = strlen(path); 2491 int brace = 0; 2492 2493 pf->anchor = rs->anchor; 2494 2495 if (path[0]) 2496 snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name); 2497 else 2498 snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name); 2499 2500 if (depth) { 2501 if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) { 2502 brace++; 2503 if (pf->opts & PF_OPT_VERBOSE) 2504 printf(" {\n"); 2505 if ((pf->opts & PF_OPT_NOACTION) == 0 && 2506 (error = pfctl_ruleset_trans(pf, 2507 path, rs->anchor, false))) { 2508 printf("%s: " 2509 "pfctl_ruleset_trans %d\n", __func__, error); 2510 goto error; 2511 } 2512 } else if (pf->opts & PF_OPT_VERBOSE) 2513 printf("\n"); 2514 } 2515 2516 if (pf->optimize && rs_num == PF_RULESET_FILTER) 2517 pfctl_optimize_ruleset(pf, rs); 2518 2519 while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) { 2520 TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries); 2521 2522 for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) 2523 expand_label(r->label[i], PF_RULE_LABEL_SIZE, r); 2524 expand_label(r->tagname, PF_TAG_NAME_SIZE, r); 2525 expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r); 2526 2527 if ((error = pfctl_load_rule(pf, path, r, depth))) 2528 goto error; 2529 if (r->anchor) { 2530 if ((error = pfctl_load_ruleset(pf, path, 2531 &r->anchor->ruleset, rs_num, depth + 1))) 2532 goto error; 2533 if ((error = pfctl_load_tables(pf, path, r->anchor, rs_num))) 2534 goto error; 2535 } else if (pf->opts & PF_OPT_VERBOSE) 2536 printf("\n"); 2537 free(r); 2538 } 2539 if (brace && pf->opts & PF_OPT_VERBOSE) { 2540 INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 2541 printf("}\n"); 2542 } 2543 path[len] = '\0'; 2544 return (0); 2545 2546 error: 2547 path[len] = '\0'; 2548 return (error); 2549 2550 } 2551 2552 int 2553 pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth) 2554 { 2555 u_int8_t rs_num = pf_get_ruleset_number(r->action); 2556 char *name; 2557 uint32_t ticket; 2558 char anchor[PF_ANCHOR_NAME_SIZE]; 2559 int len = strlen(path); 2560 int error; 2561 bool was_present; 2562 2563 /* set up anchor before adding to path for anchor_call */ 2564 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2565 if (pf->trans == NULL) 2566 errx(1, "pfctl_load_rule: no transaction"); 2567 ticket = pfctl_get_ticket(pf->trans, rs_num, path); 2568 if (rs_num == PF_RULESET_FILTER) 2569 pf->anchor->ruleset.tticket = ticket; 2570 } 2571 if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor)) 2572 errx(1, "pfctl_load_rule: strlcpy"); 2573 2574 if (r->anchor) { 2575 if (r->anchor->match) { 2576 if (path[0]) 2577 snprintf(&path[len], MAXPATHLEN - len, 2578 "/%s", r->anchor->name); 2579 else 2580 snprintf(&path[len], MAXPATHLEN - len, 2581 "%s", r->anchor->name); 2582 name = r->anchor->name; 2583 } else 2584 name = r->anchor->path; 2585 } else 2586 name = ""; 2587 2588 was_present = false; 2589 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2590 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2591 if ((error = pfctl_begin_addrs(pf->h, 2592 &pf->paddr.ticket)) != 0) 2593 errc(1, error, "DIOCBEGINADDRS"); 2594 } 2595 2596 if (pfctl_add_pool(pf, &r->rdr, PF_RDR)) 2597 return (1); 2598 if (pfctl_add_pool(pf, &r->nat, PF_NAT)) 2599 return (1); 2600 if (pfctl_add_pool(pf, &r->route, PF_RT)) 2601 return (1); 2602 error = pfctl_add_rule_h(pf->h, r, anchor, name, ticket, 2603 pf->paddr.ticket); 2604 switch (error) { 2605 case 0: 2606 /* things worked, do nothing */ 2607 break; 2608 case EEXIST: 2609 /* an identical rule is already present */ 2610 was_present = true; 2611 break; 2612 default: 2613 errc(1, error, "DIOCADDRULE"); 2614 } 2615 } 2616 2617 if (pf->opts & PF_OPT_VERBOSE) { 2618 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 2619 print_rule(r, name, 2620 pf->opts & PF_OPT_VERBOSE2, 2621 pf->opts & PF_OPT_NUMERIC); 2622 if (was_present) 2623 printf(" -- rule was already present"); 2624 } 2625 path[len] = '\0'; 2626 pfctl_clear_pool(&r->rdr); 2627 pfctl_clear_pool(&r->nat); 2628 return (0); 2629 } 2630 2631 int 2632 pfctl_add_altq(struct pfctl *pf, struct pf_altq *a) 2633 { 2634 if (altqsupport && 2635 (loadopt & PFCTL_FLAG_ALTQ) != 0) { 2636 memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq)); 2637 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2638 if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) { 2639 if (errno == ENXIO) 2640 errx(1, "qtype not configured"); 2641 else if (errno == ENODEV) 2642 errx(1, "%s: driver does not support " 2643 "altq", a->ifname); 2644 else 2645 err(1, "DIOCADDALTQ"); 2646 } 2647 } 2648 pfaltq_store(&pf->paltq->altq); 2649 } 2650 return (0); 2651 } 2652 2653 int 2654 pfctl_rules(int dev, char *filename, int opts, int optimize, 2655 char *anchorname, struct pfr_buffer *trans) 2656 { 2657 #define ERR(...) do { warn(__VA_ARGS__); goto _error; } while(0) 2658 #define ERRX(...) do { warnx(__VA_ARGS__); goto _error; } while(0) 2659 2660 struct pfr_buffer *t, buf; 2661 struct pfioc_altq pa; 2662 struct pfctl pf; 2663 struct pfctl_ruleset *rs; 2664 struct pfctl_eth_ruleset *ethrs; 2665 struct pfr_table trs; 2666 char *path = NULL; 2667 int osize; 2668 2669 RB_INIT(&pf_anchors); 2670 memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); 2671 pf_init_ruleset(&pf_main_anchor.ruleset); 2672 memset(&pf, 0, sizeof(pf)); 2673 memset(&trs, 0, sizeof(trs)); 2674 pf_main_anchor.ruleset.anchor = &pf_main_anchor; 2675 2676 memset(&pf_eth_main_anchor, 0, sizeof(pf_eth_main_anchor)); 2677 pf_init_eth_ruleset(&pf_eth_main_anchor.ruleset); 2678 pf_eth_main_anchor.ruleset.anchor = &pf_eth_main_anchor; 2679 2680 if (trans == NULL) { 2681 bzero(&buf, sizeof(buf)); 2682 buf.pfrb_type = PFRB_TRANS; 2683 pf.trans = &buf; 2684 t = &buf; 2685 osize = 0; 2686 } else { 2687 t = trans; 2688 osize = t->pfrb_size; 2689 } 2690 2691 memset(&pa, 0, sizeof(pa)); 2692 pa.version = PFIOC_ALTQ_VERSION; 2693 memset(&pf, 0, sizeof(pf)); 2694 memset(&trs, 0, sizeof(trs)); 2695 if ((path = calloc(1, MAXPATHLEN)) == NULL) 2696 ERRX("%s: calloc", __func__); 2697 if (strlcpy(trs.pfrt_anchor, anchorname, 2698 sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) 2699 ERRX("%s: strlcpy", __func__); 2700 pf.dev = dev; 2701 pf.h = pfh; 2702 pf.opts = opts; 2703 pf.optimize = optimize; 2704 pf.loadopt = loadopt; 2705 2706 RB_INIT(&pf.statelim_ids); 2707 RB_INIT(&pf.statelim_nms); 2708 RB_INIT(&pf.sourcelim_ids); 2709 RB_INIT(&pf.sourcelim_nms); 2710 2711 /* non-brace anchor, create without resolving the path */ 2712 if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) 2713 ERRX("%s: calloc", __func__); 2714 rs = &pf.anchor->ruleset; 2715 pf_init_ruleset(rs); 2716 rs->anchor = pf.anchor; 2717 if (strlcpy(pf.anchor->path, anchorname, 2718 sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 2719 errx(1, "%s: strlcpy", __func__); 2720 if (strlcpy(pf.anchor->name, anchorname, 2721 sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 2722 errx(1, "%s: strlcpy", __func__); 2723 2724 2725 pf.astack[0] = pf.anchor; 2726 pf.asd = 0; 2727 if (anchorname[0]) 2728 pf.loadopt &= ~PFCTL_FLAG_ALTQ; 2729 pf.paltq = &pa; 2730 pf.trans = t; 2731 pfctl_init_options(&pf); 2732 2733 /* Set up ethernet anchor */ 2734 if ((pf.eanchor = calloc(1, sizeof(*pf.eanchor))) == NULL) 2735 ERRX("%s: calloc", __func__); 2736 2737 if (strlcpy(pf.eanchor->path, anchorname, 2738 sizeof(pf.eanchor->path)) >= sizeof(pf.eanchor->path)) 2739 errx(1, "%s: strlcpy", __func__); 2740 if (strlcpy(pf.eanchor->name, anchorname, 2741 sizeof(pf.eanchor->name)) >= sizeof(pf.eanchor->name)) 2742 errx(1, "%s: strlcpy", __func__); 2743 2744 ethrs = &pf.eanchor->ruleset; 2745 pf_init_eth_ruleset(ethrs); 2746 ethrs->anchor = pf.eanchor; 2747 pf.eastack[0] = pf.eanchor; 2748 2749 if ((opts & PF_OPT_NOACTION) == 0) { 2750 /* 2751 * XXX For the time being we need to open transactions for 2752 * the main ruleset before parsing, because tables are still 2753 * loaded at parse time. 2754 */ 2755 if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor, true)) 2756 ERRX("%s", __func__); 2757 if (pf.loadopt & PFCTL_FLAG_ETH) 2758 pf.eth_ticket = pfctl_get_ticket(t, PF_RULESET_ETH, anchorname); 2759 if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) 2760 pa.ticket = 2761 pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname); 2762 if (pf.loadopt & PFCTL_FLAG_TABLE) 2763 pf.astack[0]->ruleset.tticket = 2764 pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname); 2765 } 2766 2767 if (parse_config(filename, &pf) < 0) { 2768 if ((opts & PF_OPT_NOACTION) == 0) 2769 ERRX("Syntax error in config file: " 2770 "pf rules not loaded"); 2771 else 2772 goto _error; 2773 } 2774 if (loadopt & PFCTL_FLAG_OPTION) 2775 pfctl_adjust_skip_ifaces(&pf); 2776 2777 if (anchorname[0] == '\0' && pf.loadopt & PFCTL_FLAG_FILTER) { 2778 pfctl_load_statelims(&pf); 2779 pfctl_load_sourcelims(&pf); 2780 } 2781 2782 if ((pf.loadopt & PFCTL_FLAG_FILTER && 2783 (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) || 2784 (pf.loadopt & PFCTL_FLAG_ETH && 2785 (pfctl_load_eth_ruleset(&pf, path, ethrs, 0))) || 2786 (pf.loadopt & PFCTL_FLAG_NAT && 2787 (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) || 2788 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) || 2789 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) || 2790 (pf.loadopt & PFCTL_FLAG_FILTER && 2791 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) { 2792 if ((opts & PF_OPT_NOACTION) == 0) 2793 ERRX("Unable to load rules into kernel"); 2794 else 2795 goto _error; 2796 } 2797 2798 if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0)) 2799 if (check_commit_altq(dev, opts) != 0) 2800 ERRX("errors in altq config"); 2801 2802 if (trans == NULL) { 2803 /* process "load anchor" directives */ 2804 if (pfctl_load_anchors(dev, &pf) == -1) 2805 ERRX("load anchors"); 2806 2807 if ((opts & PF_OPT_NOACTION) == 0) { 2808 if (!anchorname[0] && pfctl_load_options(&pf)) 2809 goto _error; 2810 if (pfctl_trans(dev, t, DIOCXCOMMIT, osize)) 2811 ERR("DIOCXCOMMIT"); 2812 } 2813 } 2814 free(path); 2815 return (0); 2816 2817 _error: 2818 if (trans == NULL) { /* main ruleset */ 2819 if ((opts & PF_OPT_NOACTION) == 0) 2820 if (pfctl_trans(dev, t, DIOCXROLLBACK, osize)) 2821 err(1, "DIOCXROLLBACK"); 2822 exit(1); 2823 } else { /* sub ruleset */ 2824 free(path); 2825 return (-1); 2826 } 2827 2828 #undef ERR 2829 #undef ERRX 2830 } 2831 2832 FILE * 2833 pfctl_fopen(const char *name, const char *mode) 2834 { 2835 struct stat st; 2836 FILE *fp; 2837 2838 fp = fopen(name, mode); 2839 if (fp == NULL) 2840 return (NULL); 2841 if (fstat(fileno(fp), &st)) { 2842 fclose(fp); 2843 return (NULL); 2844 } 2845 if (S_ISDIR(st.st_mode)) { 2846 fclose(fp); 2847 errno = EISDIR; 2848 return (NULL); 2849 } 2850 return (fp); 2851 } 2852 2853 void 2854 pfctl_init_options(struct pfctl *pf) 2855 { 2856 2857 pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 2858 pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; 2859 pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 2860 pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; 2861 pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; 2862 pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; 2863 pf->timeout[PFTM_SCTP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 2864 pf->timeout[PFTM_SCTP_OPENING] = PFTM_TCP_OPENING_VAL; 2865 pf->timeout[PFTM_SCTP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 2866 pf->timeout[PFTM_SCTP_CLOSING] = PFTM_TCP_CLOSING_VAL; 2867 pf->timeout[PFTM_SCTP_CLOSED] = PFTM_TCP_CLOSED_VAL; 2868 pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; 2869 pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; 2870 pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; 2871 pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; 2872 pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; 2873 pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; 2874 pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; 2875 pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; 2876 pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; 2877 pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; 2878 pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; 2879 pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; 2880 pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; 2881 pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; 2882 2883 pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; 2884 pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT; 2885 2886 pf->limit[PF_LIMIT_SRC_NODES] = (limit_curr[PF_LIMIT_SRC_NODES] == 0) ? 2887 PFSNODE_HIWAT : limit_curr[PF_LIMIT_SRC_NODES]; 2888 pf->limit[PF_LIMIT_TABLE_ENTRIES] = 2889 (limit_curr[PF_LIMIT_TABLE_ENTRIES] == 0) ? 2890 PFR_KENTRY_HIWAT : limit_curr[PF_LIMIT_TABLE_ENTRIES]; 2891 pf->limit[PF_LIMIT_ANCHORS] = (limit_curr[PF_LIMIT_ANCHORS] == 0) ? 2892 PF_ANCHOR_HIWAT : limit_curr[PF_LIMIT_ANCHORS]; 2893 2894 pf->debug = PF_DEBUG_URGENT; 2895 pf->reassemble = 0; 2896 2897 pf->syncookies = false; 2898 pf->syncookieswat[0] = PF_SYNCOOKIES_LOWATPCT; 2899 pf->syncookieswat[1] = PF_SYNCOOKIES_HIWATPCT; 2900 } 2901 2902 int 2903 pfctl_load_options(struct pfctl *pf) 2904 { 2905 int i, error = 0; 2906 2907 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 2908 return (0); 2909 2910 /* load limits */ 2911 for (i = 0; i < PF_LIMIT_MAX; i++) { 2912 if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i]) 2913 continue; 2914 if (pfctl_load_limit(pf, i, pf->limit[i])) 2915 error = 1; 2916 } 2917 2918 /* 2919 * If we've set the states limit, but haven't explicitly set adaptive 2920 * timeouts, do it now with a start of 60% and end of 120%. 2921 */ 2922 if (pf->limit_set[PF_LIMIT_STATES] && 2923 !pf->timeout_set[PFTM_ADAPTIVE_START] && 2924 !pf->timeout_set[PFTM_ADAPTIVE_END]) { 2925 pf->timeout[PFTM_ADAPTIVE_START] = 2926 (pf->limit[PF_LIMIT_STATES] / 10) * 6; 2927 pf->timeout_set[PFTM_ADAPTIVE_START] = 1; 2928 pf->timeout[PFTM_ADAPTIVE_END] = 2929 (pf->limit[PF_LIMIT_STATES] / 10) * 12; 2930 pf->timeout_set[PFTM_ADAPTIVE_END] = 1; 2931 } 2932 2933 /* load timeouts */ 2934 for (i = 0; i < PFTM_MAX; i++) { 2935 if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i]) 2936 continue; 2937 if (pfctl_load_timeout(pf, i, pf->timeout[i])) 2938 error = 1; 2939 } 2940 2941 /* load debug */ 2942 if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set) 2943 if (pfctl_load_debug(pf, pf->debug)) 2944 error = 1; 2945 2946 /* load logif */ 2947 if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set) 2948 if (pfctl_load_logif(pf, pf->ifname)) 2949 error = 1; 2950 2951 /* load hostid */ 2952 if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set) 2953 if (pfctl_load_hostid(pf, pf->hostid)) 2954 error = 1; 2955 2956 /* load reassembly settings */ 2957 if (!(pf->opts & PF_OPT_MERGE) || pf->reass_set) 2958 if (pfctl_load_reassembly(pf, pf->reassemble)) 2959 error = 1; 2960 2961 /* load keepcounters */ 2962 if (pfctl_set_keepcounters(pf->dev, pf->keep_counters)) 2963 error = 1; 2964 2965 /* load syncookies settings */ 2966 if (pfctl_load_syncookies(pf, pf->syncookies)) 2967 error = 1; 2968 2969 return (error); 2970 } 2971 2972 int 2973 pfctl_apply_limit(struct pfctl *pf, const char *opt, unsigned int limit) 2974 { 2975 int i; 2976 2977 2978 for (i = 0; pf_limits[i].name; i++) { 2979 if (strcasecmp(opt, pf_limits[i].name) == 0) { 2980 pf->limit[pf_limits[i].index] = limit; 2981 pf->limit_set[pf_limits[i].index] = 1; 2982 break; 2983 } 2984 } 2985 if (pf_limits[i].name == NULL) { 2986 warnx("Bad pool name."); 2987 return (1); 2988 } 2989 2990 if (pf->opts & PF_OPT_VERBOSE) 2991 printf("set limit %s %d\n", opt, limit); 2992 2993 if ((pf->opts & PF_OPT_NOACTION) == 0) 2994 pfctl_load_options(pf); 2995 2996 return (0); 2997 } 2998 2999 int 3000 pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) 3001 { 3002 static int restore_limit_handler_armed = 0; 3003 3004 if (pfctl_set_limit(pf->h, index, limit)) { 3005 if (errno == EBUSY) 3006 warnx("Current pool size exceeds requested %s limit %u", 3007 pf_limits[index].name, limit); 3008 else 3009 warnx("Cannot set %s limit to %u", 3010 pf_limits[index].name, limit); 3011 return (1); 3012 } else if (restore_limit_handler_armed == 0) { 3013 atexit(pfctl_restore_limits); 3014 restore_limit_handler_armed = 1; 3015 } 3016 return (0); 3017 } 3018 3019 int 3020 pfctl_apply_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 3021 { 3022 int i; 3023 3024 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 3025 return (0); 3026 3027 for (i = 0; pf_timeouts[i].name; i++) { 3028 if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 3029 pf->timeout[pf_timeouts[i].timeout] = seconds; 3030 pf->timeout_set[pf_timeouts[i].timeout] = 1; 3031 break; 3032 } 3033 } 3034 3035 if (pf_timeouts[i].name == NULL) { 3036 warnx("Bad timeout name."); 3037 return (1); 3038 } 3039 3040 3041 if (pf->opts & PF_OPT_VERBOSE && ! quiet) 3042 printf("set timeout %s %d\n", opt, seconds); 3043 3044 return (0); 3045 } 3046 3047 int 3048 pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) 3049 { 3050 if (pfctl_set_timeout(pf->h, timeout, seconds)) { 3051 warnx("DIOCSETTIMEOUT"); 3052 return (1); 3053 } 3054 return (0); 3055 } 3056 3057 int 3058 pfctl_set_reassembly(struct pfctl *pf, int on, int nodf) 3059 { 3060 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 3061 return (0); 3062 3063 pf->reass_set = 1; 3064 if (on) { 3065 pf->reassemble = PF_REASS_ENABLED; 3066 if (nodf) 3067 pf->reassemble |= PF_REASS_NODF; 3068 } else { 3069 pf->reassemble = 0; 3070 } 3071 3072 if (pf->opts & PF_OPT_VERBOSE) 3073 printf("set reassemble %s %s\n", on ? "yes" : "no", 3074 nodf ? "no-df" : ""); 3075 3076 return (0); 3077 } 3078 3079 int 3080 pfctl_set_optimization(struct pfctl *pf, const char *opt) 3081 { 3082 const struct pf_hint *hint; 3083 int i, r; 3084 3085 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 3086 return (0); 3087 3088 for (i = 0; pf_hints[i].name; i++) 3089 if (strcasecmp(opt, pf_hints[i].name) == 0) 3090 break; 3091 3092 hint = pf_hints[i].hint; 3093 if (hint == NULL) { 3094 warnx("invalid state timeouts optimization"); 3095 return (1); 3096 } 3097 3098 for (i = 0; hint[i].name; i++) 3099 if ((r = pfctl_apply_timeout(pf, hint[i].name, 3100 hint[i].timeout, 1))) 3101 return (r); 3102 3103 if (pf->opts & PF_OPT_VERBOSE) 3104 printf("set optimization %s\n", opt); 3105 3106 return (0); 3107 } 3108 3109 int 3110 pfctl_set_logif(struct pfctl *pf, char *ifname) 3111 { 3112 3113 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 3114 return (0); 3115 3116 if (!strcmp(ifname, "none")) { 3117 free(pf->ifname); 3118 pf->ifname = NULL; 3119 } else { 3120 pf->ifname = strdup(ifname); 3121 if (!pf->ifname) 3122 errx(1, "pfctl_set_logif: strdup"); 3123 } 3124 pf->ifname_set = 1; 3125 3126 if (pf->opts & PF_OPT_VERBOSE) 3127 printf("set loginterface %s\n", ifname); 3128 3129 return (0); 3130 } 3131 3132 int 3133 pfctl_load_logif(struct pfctl *pf, char *ifname) 3134 { 3135 if (ifname != NULL && strlen(ifname) >= IFNAMSIZ) { 3136 warnx("pfctl_load_logif: strlcpy"); 3137 return (1); 3138 } 3139 return (pfctl_set_statusif(pfh, ifname ? ifname : "")); 3140 } 3141 3142 void 3143 pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 3144 { 3145 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 3146 return; 3147 3148 HTONL(hostid); 3149 3150 pf->hostid = hostid; 3151 pf->hostid_set = 1; 3152 3153 if (pf->opts & PF_OPT_VERBOSE) 3154 printf("set hostid 0x%08x\n", ntohl(hostid)); 3155 } 3156 3157 int 3158 pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) 3159 { 3160 if (ioctl(dev, DIOCSETHOSTID, &hostid)) { 3161 warnx("DIOCSETHOSTID"); 3162 return (1); 3163 } 3164 return (0); 3165 } 3166 3167 int 3168 pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly) 3169 { 3170 if (ioctl(dev, DIOCSETREASS, &reassembly)) { 3171 warnx("DIOCSETREASS"); 3172 return (1); 3173 } 3174 return (0); 3175 } 3176 3177 int 3178 pfctl_load_syncookies(struct pfctl *pf, u_int8_t val) 3179 { 3180 struct pfctl_syncookies cookies; 3181 3182 bzero(&cookies, sizeof(cookies)); 3183 3184 cookies.mode = val; 3185 cookies.lowwater = pf->syncookieswat[0]; 3186 cookies.highwater = pf->syncookieswat[1]; 3187 3188 if (pfctl_set_syncookies(dev, &cookies)) { 3189 warnx("DIOCSETSYNCOOKIES"); 3190 return (1); 3191 } 3192 return (0); 3193 } 3194 3195 int 3196 pfctl_cfg_syncookies(struct pfctl *pf, uint8_t val, struct pfctl_watermarks *w) 3197 { 3198 if (val != PF_SYNCOOKIES_ADAPTIVE && w != NULL) { 3199 warnx("syncookies start/end only apply to adaptive"); 3200 return (1); 3201 } 3202 if (val == PF_SYNCOOKIES_ADAPTIVE && w != NULL) { 3203 if (!w->hi) 3204 w->hi = PF_SYNCOOKIES_HIWATPCT; 3205 if (!w->lo) 3206 w->lo = w->hi / 2; 3207 if (w->lo >= w->hi) { 3208 warnx("start must be higher than end"); 3209 return (1); 3210 } 3211 pf->syncookieswat[0] = w->lo; 3212 pf->syncookieswat[1] = w->hi; 3213 pf->syncookieswat_set = 1; 3214 } 3215 3216 if (pf->opts & PF_OPT_VERBOSE) { 3217 if (val == PF_SYNCOOKIES_NEVER) 3218 printf("set syncookies never\n"); 3219 else if (val == PF_SYNCOOKIES_ALWAYS) 3220 printf("set syncookies always\n"); 3221 else if (val == PF_SYNCOOKIES_ADAPTIVE) { 3222 if (pf->syncookieswat_set) 3223 printf("set syncookies adaptive (start %u%%, " 3224 "end %u%%)\n", pf->syncookieswat[1], 3225 pf->syncookieswat[0]); 3226 else 3227 printf("set syncookies adaptive\n"); 3228 } else { /* cannot happen */ 3229 warnx("king bula ate all syncookies"); 3230 return (1); 3231 } 3232 } 3233 3234 pf->syncookies = val; 3235 return (0); 3236 } 3237 3238 int 3239 pfctl_do_set_debug(struct pfctl *pf, char *d) 3240 { 3241 u_int32_t level; 3242 int ret; 3243 3244 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 3245 return (0); 3246 3247 if (!strcmp(d, "none")) 3248 pf->debug = PF_DEBUG_NONE; 3249 else if (!strcmp(d, "urgent")) 3250 pf->debug = PF_DEBUG_URGENT; 3251 else if (!strcmp(d, "misc")) 3252 pf->debug = PF_DEBUG_MISC; 3253 else if (!strcmp(d, "loud")) 3254 pf->debug = PF_DEBUG_NOISY; 3255 else { 3256 warnx("unknown debug level \"%s\"", d); 3257 return (-1); 3258 } 3259 3260 pf->debug_set = 1; 3261 level = pf->debug; 3262 3263 if ((pf->opts & PF_OPT_NOACTION) == 0) 3264 if ((ret = pfctl_set_debug(pfh, level)) != 0) 3265 errc(1, ret, "DIOCSETDEBUG"); 3266 3267 if (pf->opts & PF_OPT_VERBOSE) 3268 printf("set debug %s\n", d); 3269 3270 return (0); 3271 } 3272 3273 int 3274 pfctl_load_debug(struct pfctl *pf, unsigned int level) 3275 { 3276 if (pfctl_set_debug(pf->h, level)) { 3277 warnx("DIOCSETDEBUG"); 3278 return (1); 3279 } 3280 return (0); 3281 } 3282 3283 int 3284 pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) 3285 { 3286 struct pfioc_iface pi; 3287 struct node_host *h = NULL, *n = NULL; 3288 3289 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 3290 return (0); 3291 3292 bzero(&pi, sizeof(pi)); 3293 3294 pi.pfiio_flags = flags; 3295 3296 /* Make sure our cache matches the kernel. If we set or clear the flag 3297 * for a group this applies to all members. */ 3298 h = ifa_grouplookup(ifname, 0); 3299 for (n = h; n != NULL; n = n->next) 3300 pfctl_set_interface_flags(pf, n->ifname, flags, how); 3301 3302 if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= 3303 sizeof(pi.pfiio_name)) 3304 errx(1, "pfctl_set_interface_flags: strlcpy"); 3305 3306 if ((pf->opts & PF_OPT_NOACTION) == 0) { 3307 if (how == 0) { 3308 if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi)) 3309 pfctl_err(pf->opts, 1, "DIOCCLRIFFLAG"); 3310 } else { 3311 if (ioctl(pf->dev, DIOCSETIFFLAG, &pi)) 3312 err(1, "DIOCSETIFFLAG"); 3313 pfctl_check_skip_ifaces(ifname); 3314 } 3315 } 3316 return (0); 3317 } 3318 3319 void 3320 pfctl_debug(int dev, u_int32_t level, int opts) 3321 { 3322 int ret; 3323 3324 if ((ret = pfctl_set_debug(pfh, level)) != 0) 3325 errc(1, ret, "DIOCSETDEBUG"); 3326 if ((opts & PF_OPT_QUIET) == 0) { 3327 fprintf(stderr, "debug level set to '"); 3328 switch (level) { 3329 case PF_DEBUG_NONE: 3330 fprintf(stderr, "none"); 3331 break; 3332 case PF_DEBUG_URGENT: 3333 fprintf(stderr, "urgent"); 3334 break; 3335 case PF_DEBUG_MISC: 3336 fprintf(stderr, "misc"); 3337 break; 3338 case PF_DEBUG_NOISY: 3339 fprintf(stderr, "loud"); 3340 break; 3341 default: 3342 fprintf(stderr, "<invalid>"); 3343 break; 3344 } 3345 fprintf(stderr, "'\n"); 3346 } 3347 } 3348 3349 int 3350 pfctl_test_altqsupport(int dev, int opts) 3351 { 3352 struct pfioc_altq pa; 3353 3354 pa.version = PFIOC_ALTQ_VERSION; 3355 if (ioctl(dev, DIOCGETALTQS, &pa)) { 3356 if (errno == ENODEV) { 3357 if (opts & PF_OPT_VERBOSE) 3358 fprintf(stderr, "No ALTQ support in kernel\n" 3359 "ALTQ related functions disabled\n"); 3360 return (0); 3361 } else 3362 err(1, "DIOCGETALTQS"); 3363 } 3364 return (1); 3365 } 3366 3367 int 3368 pfctl_walk_show(int opts, struct pfioc_ruleset *pr, void *warg) 3369 { 3370 if (pr->path[0]) { 3371 if (pr->path[0] != '_' || (opts & PF_OPT_VERBOSE)) 3372 printf(" %s/%s\n", pr->path, pr->name); 3373 } else if (pr->name[0] != '_' || (opts & PF_OPT_VERBOSE)) 3374 printf(" %s\n", pr->name); 3375 3376 return (0); 3377 } 3378 3379 int 3380 pfctl_walk_get(int opts, struct pfioc_ruleset *pr, void *warg) 3381 { 3382 struct pfr_anchoritem *pfra; 3383 struct pfr_anchors *anchors; 3384 int e; 3385 3386 anchors = (struct pfr_anchors *)warg; 3387 3388 pfra = malloc(sizeof(*pfra)); 3389 if (pfra == NULL) 3390 err(1, "%s", __func__); 3391 3392 if (pr->path[0]) 3393 e = asprintf(&pfra->pfra_anchorname, "%s/%s", pr->path, 3394 pr->name); 3395 else 3396 e = asprintf(&pfra->pfra_anchorname, "%s", pr->name); 3397 3398 if (e == -1) 3399 err(1, "%s", __func__); 3400 3401 SLIST_INSERT_HEAD(anchors, pfra, pfra_sle); 3402 3403 return (0); 3404 } 3405 3406 int 3407 pfctl_walk_anchors(int dev, int opts, const char *anchor, 3408 int(walkf)(int, struct pfioc_ruleset *, void *), void *warg) 3409 { 3410 struct pfioc_ruleset pr; 3411 u_int32_t mnr, nr; 3412 int ret; 3413 3414 memset(&pr, 0, sizeof(pr)); 3415 if ((ret = pfctl_get_rulesets(pfh, anchor, &mnr)) != 0) 3416 errx(1, "%s", pf_strerror(ret)); 3417 for (nr = 0; nr < mnr; ++nr) { 3418 char sub[MAXPATHLEN]; 3419 3420 if ((ret = pfctl_get_ruleset(pfh, anchor, nr, &pr)) != 0) 3421 errc(1, ret, "DIOCGETRULESET"); 3422 if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) 3423 continue; 3424 sub[0] = '\0'; 3425 if (walkf(opts, &pr, warg)) 3426 return (-1); 3427 3428 if (pr.path[0]) 3429 snprintf(sub, sizeof(sub), "%s/%s", pr.path, pr.name); 3430 else 3431 snprintf(sub, sizeof(sub), "%s", pr.name); 3432 if (pfctl_walk_anchors(dev, opts, sub, walkf, warg)) 3433 return (-1); 3434 } 3435 return (0); 3436 } 3437 3438 int 3439 pfctl_show_anchors(int dev, int opts, char *anchor) 3440 { 3441 return ( 3442 pfctl_walk_anchors(dev, opts, anchor, pfctl_walk_show, NULL)); 3443 } 3444 3445 struct pfr_anchors * 3446 pfctl_get_anchors(int dev, const char *anchor, int opts) 3447 { 3448 struct pfioc_ruleset pr; 3449 static struct pfr_anchors anchors; 3450 char anchorbuf[PATH_MAX]; 3451 char *n; 3452 3453 SLIST_INIT(&anchors); 3454 3455 memset(&pr, 0, sizeof(pr)); 3456 if (*anchor != '\0') { 3457 strlcpy(anchorbuf, anchor, sizeof(anchorbuf)); 3458 n = dirname(anchorbuf); 3459 if (n[0] != '.' && n[1] != '\0') 3460 strlcpy(pr.path, n, sizeof(pr.path)); 3461 strlcpy(anchorbuf, anchor, sizeof(anchorbuf)); 3462 n = basename(anchorbuf); 3463 if (n != NULL) 3464 strlcpy(pr.name, n, sizeof(pr.name)); 3465 } 3466 3467 /* insert a root anchor first. */ 3468 pfctl_walk_get(opts, &pr, &anchors); 3469 3470 if (pfctl_walk_anchors(dev, opts, anchor, pfctl_walk_get, &anchors)) 3471 errx(1, "%s failed to retrieve list of anchors, can't continue", 3472 __func__); 3473 3474 return (&anchors); 3475 } 3476 3477 int 3478 pfctl_call_cleartables(int dev, int opts, struct pfr_anchoritem *pfra) 3479 { 3480 /* 3481 * PF_OPT_QUIET makes pfctl_clear_tables() to stop printing number of 3482 * tables cleared for given anchor. 3483 */ 3484 opts |= PF_OPT_QUIET; 3485 return ((pfctl_do_clear_tables(pfra->pfra_anchorname, opts) == -1) ? 3486 1 : 0); 3487 } 3488 3489 int 3490 pfctl_call_clearrules(int dev, int opts, struct pfr_anchoritem *pfra) 3491 { 3492 /* 3493 * PF_OPT_QUIET makes pfctl_clear_rules() to stop printing a 'rules 3494 * cleared' message for every anchor it deletes. 3495 */ 3496 opts |= PF_OPT_QUIET; 3497 return (pfctl_flush_rules(dev, opts, pfra->pfra_anchorname)); 3498 } 3499 3500 int 3501 pfctl_call_clearanchors(int dev, int opts, struct pfr_anchoritem *pfra) 3502 { 3503 int rv = 0; 3504 3505 rv |= pfctl_call_cleartables(dev, opts, pfra); 3506 rv |= pfctl_call_clearrules(dev, opts, pfra); 3507 3508 return (rv); 3509 } 3510 3511 int 3512 pfctl_call_showtables(int dev, int opts, struct pfr_anchoritem *pfra) 3513 { 3514 pfctl_show_tables(pfra->pfra_anchorname, opts); 3515 return (0); 3516 } 3517 3518 int 3519 pfctl_recurse(int dev, int opts, const char *anchorname, 3520 int(*walkf)(int, int, struct pfr_anchoritem *)) 3521 { 3522 int rv = 0; 3523 struct pfr_anchors *anchors; 3524 struct pfr_anchoritem *pfra, *pfra_save; 3525 3526 anchors = pfctl_get_anchors(dev, anchorname, opts); 3527 /* 3528 * While traversing the list, pfctl_clear_*() must always return 3529 * so that failures on one anchor do not prevent clearing others. 3530 */ 3531 opts |= PF_OPT_IGNFAIL; 3532 if ((opts & PF_OPT_CALLSHOW) == 0) 3533 printf("Removing:\n"); 3534 SLIST_FOREACH_SAFE(pfra, anchors, pfra_sle, pfra_save) { 3535 if ((opts & PF_OPT_CALLSHOW) == 0) 3536 printf(" %s\n", 3537 (*pfra->pfra_anchorname == '\0') ? "/" : 3538 pfra->pfra_anchorname); 3539 rv |= walkf(dev, opts, pfra); 3540 SLIST_REMOVE(anchors, pfra, pfr_anchoritem, pfra_sle); 3541 free(pfra->pfra_anchorname); 3542 free(pfra); 3543 } 3544 3545 return (rv); 3546 } 3547 3548 int 3549 pfctl_show_eth_anchors(int dev, int opts, char *anchorname) 3550 { 3551 struct pfctl_eth_rulesets_info ri; 3552 struct pfctl_eth_ruleset_info rs; 3553 int ret; 3554 3555 if ((ret = pfctl_get_eth_rulesets_info(dev, &ri, anchorname)) != 0) { 3556 if (ret != ENOENT) 3557 errc(1, ret, "DIOCGETETHRULESETS"); 3558 return (-1); 3559 } 3560 3561 for (int nr = 0; nr < ri.nr; nr++) { 3562 char sub[MAXPATHLEN]; 3563 3564 if ((ret = pfctl_get_eth_ruleset(dev, anchorname, nr, &rs)) != 0) 3565 errc(1, ret, "DIOCGETETHRULESET"); 3566 3567 if (!strcmp(rs.name, PF_RESERVED_ANCHOR)) 3568 continue; 3569 sub[0] = 0; 3570 if (rs.path[0]) { 3571 strlcat(sub, rs.path, sizeof(sub)); 3572 strlcat(sub, "/", sizeof(sub)); 3573 } 3574 strlcat(sub, rs.name, sizeof(sub)); 3575 if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 3576 printf(" %s\n", sub); 3577 if ((opts & PF_OPT_VERBOSE) && pfctl_show_eth_anchors(dev, opts, sub)) 3578 return (-1); 3579 } 3580 return (0); 3581 } 3582 3583 const char * 3584 pfctl_lookup_option(char *cmd, const char * const *list) 3585 { 3586 if (cmd != NULL && *cmd) 3587 for (; *list; list++) 3588 if (!strncmp(cmd, *list, strlen(cmd))) 3589 return (*list); 3590 return (NULL); 3591 } 3592 3593 int 3594 pfctl_lookup_id(const char *cmd, const struct pfctl_opt_id *opt_ids) 3595 { 3596 const struct pfctl_opt_id *opt_id; 3597 int id = 0; 3598 size_t cmdlen = strlen(cmd); 3599 3600 for (opt_id = opt_ids; opt_id->id != 0; opt_id++) { 3601 if (strncmp(cmd, opt_id->name, cmdlen) == 0) { 3602 if (id != 0) 3603 errx(1, "%s is ambiguous", cmd); 3604 3605 id = opt_id->id; 3606 } 3607 } 3608 3609 return (id); 3610 } 3611 3612 void 3613 pfctl_reset(int dev, int opts) 3614 { 3615 struct pfctl pf; 3616 struct pfr_buffer t; 3617 int i; 3618 3619 memset(&pf, 0, sizeof(pf)); 3620 pf.dev = dev; 3621 pf.h = pfh; 3622 pfctl_init_options(&pf); 3623 3624 /* Force reset upon pfctl_load_options() */ 3625 pf.debug_set = 1; 3626 pf.reass_set = 1; 3627 pf.syncookieswat_set = 1; 3628 pf.ifname = strdup("none"); 3629 if (pf.ifname == NULL) 3630 err(1, "%s: strdup", __func__); 3631 pf.ifname_set = 1; 3632 3633 memset(&t, 0, sizeof(t)); 3634 t.pfrb_type = PFRB_TRANS; 3635 if (pfctl_trans(dev, &t, DIOCXBEGIN, 0)) 3636 err(1, "%s: DIOCXBEGIN", __func__); 3637 3638 for (i = 0; pf_limits[i].name; i++) 3639 pf.limit_set[pf_limits[i].index] = 1; 3640 3641 for (i = 0; pf_timeouts[i].name; i++) 3642 pf.timeout_set[pf_timeouts[i].timeout] = 1; 3643 3644 pfctl_load_options(&pf); 3645 3646 if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 3647 err(1, "%s: DIOCXCOMMIT", __func__); 3648 3649 pfctl_clear_interface_flags(dev, opts); 3650 } 3651 3652 int 3653 main(int argc, char *argv[]) 3654 { 3655 int ch; 3656 int mode = O_RDONLY; 3657 int opts = 0; 3658 int optimize = PF_OPTIMIZE_BASIC; 3659 char anchorname[MAXPATHLEN]; 3660 char *path; 3661 const char *idopt = NULL; 3662 3663 if (argc < 2) 3664 usage(); 3665 3666 while ((ch = getopt(argc, argv, 3667 "a:AdD:eqf:F:ghi:I:k:K:mMnNOo:Pp:rRs:St:T:vx:z")) != -1) { 3668 switch (ch) { 3669 case 'a': 3670 anchoropt = optarg; 3671 break; 3672 case 'd': 3673 opts |= PF_OPT_DISABLE; 3674 mode = O_RDWR; 3675 break; 3676 case 'D': 3677 if (pfctl_cmdline_symset(optarg) < 0) 3678 warnx("could not parse macro definition %s", 3679 optarg); 3680 break; 3681 case 'e': 3682 opts |= PF_OPT_ENABLE; 3683 mode = O_RDWR; 3684 break; 3685 case 'q': 3686 opts |= PF_OPT_QUIET; 3687 break; 3688 case 'F': 3689 clearopt = pfctl_lookup_option(optarg, clearopt_list); 3690 if (clearopt == NULL) { 3691 warnx("Unknown flush modifier '%s'", optarg); 3692 usage(); 3693 } 3694 mode = O_RDWR; 3695 break; 3696 case 'i': 3697 ifaceopt = optarg; 3698 break; 3699 case 'I': 3700 idopt = optarg; 3701 break; 3702 case 'k': 3703 if (state_killers >= 2) { 3704 warnx("can only specify -k twice"); 3705 usage(); 3706 /* NOTREACHED */ 3707 } 3708 state_kill[state_killers++] = optarg; 3709 mode = O_RDWR; 3710 break; 3711 case 'K': 3712 if (src_node_killers >= 2) { 3713 warnx("can only specify -K twice"); 3714 usage(); 3715 /* NOTREACHED */ 3716 } 3717 src_node_kill[src_node_killers++] = optarg; 3718 mode = O_RDWR; 3719 break; 3720 case 'm': 3721 opts |= PF_OPT_MERGE; 3722 break; 3723 case 'M': 3724 opts |= PF_OPT_KILLMATCH; 3725 break; 3726 case 'n': 3727 opts |= PF_OPT_NOACTION; 3728 break; 3729 case 'N': 3730 loadopt |= PFCTL_FLAG_NAT; 3731 break; 3732 case 'r': 3733 opts |= PF_OPT_USEDNS; 3734 break; 3735 case 'f': 3736 rulesopt = optarg; 3737 mode = O_RDWR; 3738 break; 3739 case 'g': 3740 opts |= PF_OPT_DEBUG; 3741 break; 3742 case 'A': 3743 loadopt |= PFCTL_FLAG_ALTQ; 3744 break; 3745 case 'R': 3746 loadopt |= PFCTL_FLAG_FILTER; 3747 break; 3748 case 'o': 3749 optiopt = pfctl_lookup_option(optarg, optiopt_list); 3750 if (optiopt == NULL) { 3751 warnx("Unknown optimization '%s'", optarg); 3752 usage(); 3753 } 3754 opts |= PF_OPT_OPTIMIZE; 3755 break; 3756 case 'O': 3757 loadopt |= PFCTL_FLAG_OPTION; 3758 break; 3759 case 'p': 3760 pf_device = optarg; 3761 break; 3762 case 'P': 3763 opts |= PF_OPT_NUMERIC; 3764 break; 3765 case 's': 3766 showopt = pfctl_lookup_id(optarg, showopt_list); 3767 if (showopt == 0) { 3768 warnx("Unknown show modifier '%s'", optarg); 3769 usage(); 3770 } 3771 break; 3772 case 'S': 3773 opts |= PF_OPT_NODNS; 3774 break; 3775 case 't': 3776 tableopt = optarg; 3777 break; 3778 case 'T': 3779 tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 3780 if (tblcmdopt == NULL) { 3781 warnx("Unknown table command '%s'", optarg); 3782 usage(); 3783 } 3784 break; 3785 case 'v': 3786 if (opts & PF_OPT_VERBOSE) 3787 opts |= PF_OPT_VERBOSE2; 3788 opts |= PF_OPT_VERBOSE; 3789 break; 3790 case 'x': 3791 debugopt = pfctl_lookup_option(optarg, debugopt_list); 3792 if (debugopt == NULL) { 3793 warnx("Unknown debug level '%s'", optarg); 3794 usage(); 3795 } 3796 mode = O_RDWR; 3797 break; 3798 case 'z': 3799 opts |= PF_OPT_CLRRULECTRS; 3800 mode = O_RDWR; 3801 break; 3802 case 'h': 3803 /* FALLTHROUGH */ 3804 default: 3805 usage(); 3806 /* NOTREACHED */ 3807 } 3808 } 3809 3810 if ((opts & PF_OPT_NODNS) && (opts & PF_OPT_USEDNS)) 3811 errx(1, "-N and -r are mutually exclusive"); 3812 3813 if ((tblcmdopt == NULL) ^ (tableopt == NULL) && 3814 (tblcmdopt == NULL || *tblcmdopt != 'l')) 3815 usage(); 3816 3817 if (tblcmdopt != NULL) { 3818 argc -= optind; 3819 argv += optind; 3820 ch = *tblcmdopt; 3821 if (ch == 'l') { 3822 loadopt |= PFCTL_FLAG_TABLE; 3823 tblcmdopt = NULL; 3824 } else 3825 mode = strchr("st", ch) ? O_RDONLY : O_RDWR; 3826 } else if (argc != optind) { 3827 warnx("unknown command line argument: %s ...", argv[optind]); 3828 usage(); 3829 /* NOTREACHED */ 3830 } 3831 if (loadopt == 0) 3832 loadopt = ~0; 3833 3834 memset(anchorname, 0, sizeof(anchorname)); 3835 if (anchoropt != NULL) { 3836 int len = strlen(anchoropt); 3837 3838 if (anchoropt[0] == '\0') 3839 errx(1, "anchor name must not be empty"); 3840 if (mode == O_RDONLY && showopt == 0 && tblcmdopt == NULL) { 3841 warnx("anchors apply to -f, -F, -s, and -T only"); 3842 usage(); 3843 } 3844 if (mode == O_RDWR && tblcmdopt == NULL && 3845 (anchoropt[0] == '_' || strstr(anchoropt, "/_") != NULL)) 3846 errx(1, "anchor names beginning with '_' cannot " 3847 "be modified from the command line"); 3848 3849 if (len >= 1 && anchoropt[len - 1] == '*') { 3850 if (len >= 2 && anchoropt[len - 2] == '/') 3851 anchoropt[len - 2] = '\0'; 3852 else 3853 anchoropt[len - 1] = '\0'; 3854 opts |= PF_OPT_RECURSE; 3855 } 3856 if (strlcpy(anchorname, anchoropt, 3857 sizeof(anchorname)) >= sizeof(anchorname)) 3858 errx(1, "anchor name '%s' too long", 3859 anchoropt); 3860 loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE|PFCTL_FLAG_ETH; 3861 } 3862 3863 if ((opts & PF_OPT_NOACTION) == 0) { 3864 dev = open(pf_device, mode); 3865 if (dev == -1) 3866 err(1, "%s", pf_device); 3867 altqsupport = pfctl_test_altqsupport(dev, opts); 3868 } else { 3869 dev = open(pf_device, O_RDONLY); 3870 if (dev >= 0) 3871 opts |= PF_OPT_DUMMYACTION; 3872 /* turn off options */ 3873 opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 3874 clearopt = debugopt = NULL; 3875 showopt = 0; 3876 #if !defined(ENABLE_ALTQ) 3877 altqsupport = 0; 3878 #else 3879 altqsupport = 1; 3880 #endif 3881 } 3882 pfh = pfctl_open(pf_device); 3883 if (pfh == NULL) 3884 err(1, "Failed to open netlink"); 3885 3886 if ((opts & PF_OPT_NOACTION) == 0) { 3887 pfctl_read_limits(pfh); 3888 } 3889 3890 if (opts & PF_OPT_DISABLE) 3891 if (pfctl_disable(dev, opts)) 3892 exit_val = 1; 3893 3894 if ((path = calloc(1, MAXPATHLEN)) == NULL) 3895 errx(1, "%s: calloc", __func__); 3896 3897 switch (showopt) { 3898 case SHOWOPT_NONE: 3899 break; 3900 case SHOWOPT_ANCHORS: 3901 pfctl_show_anchors(dev, opts, anchorname); 3902 if (opts & PF_OPT_VERBOSE2) 3903 printf("Ethernet:\n"); 3904 pfctl_show_eth_anchors(dev, opts, anchorname); 3905 break; 3906 case SHOWOPT_RULES: 3907 pfctl_load_fingerprints(dev, opts); 3908 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, anchorname, 3909 0, 0); 3910 break; 3911 case SHOWOPT_LABELS: 3912 pfctl_load_fingerprints(dev, opts); 3913 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, anchorname, 3914 0, 0); 3915 break; 3916 case SHOWOPT_NAT: 3917 pfctl_load_fingerprints(dev, opts); 3918 pfctl_show_nat(dev, path, opts, anchorname, 0, 0); 3919 break; 3920 case SHOWOPT_QUEUE: 3921 pfctl_show_altq(dev, ifaceopt, opts, opts & PF_OPT_VERBOSE2); 3922 break; 3923 case SHOWOPT_STATES: 3924 pfctl_show_states(dev, ifaceopt, opts); 3925 break; 3926 case SHOWOPT_SOURCES: 3927 pfctl_show_src_nodes(dev, opts); 3928 break; 3929 case SHOWOPT_INFO: 3930 pfctl_show_status(dev, opts); 3931 break; 3932 case SHOWOPT_RUNNING: 3933 exit_val = pfctl_show_running(dev); 3934 break; 3935 case SHOWOPT_TIMEOUTS: 3936 pfctl_show_timeouts(dev, opts); 3937 break; 3938 case SHOWOPT_MEMORY: 3939 pfctl_show_limits(dev, opts); 3940 break; 3941 case SHOWOPT_ETHER: 3942 pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0, 0); 3943 break; 3944 case SHOWOPT_ALL: 3945 opts |= PF_OPT_SHOWALL; 3946 pfctl_load_fingerprints(dev, opts); 3947 3948 pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0, 0); 3949 3950 pfctl_show_nat(dev, path, opts, anchorname, 0, 0); 3951 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, anchorname, 3952 0, 0); 3953 pfctl_show_altq(dev, ifaceopt, opts, 0); 3954 pfctl_show_states(dev, ifaceopt, opts); 3955 pfctl_show_src_nodes(dev, opts); 3956 pfctl_show_status(dev, opts); 3957 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, anchorname, 3958 0, 0); 3959 pfctl_show_timeouts(dev, opts); 3960 pfctl_show_limits(dev, opts); 3961 pfctl_show_statelims(dev, PFCTL_SHOW_LABELS, opts); 3962 pfctl_show_sourcelims(dev, PFCTL_SHOW_LABELS, opts, idopt); 3963 pfctl_show_tables(anchorname, opts); 3964 pfctl_show_fingerprints(opts); 3965 break; 3966 case SHOWOPT_TABLES: 3967 if (opts & PF_OPT_RECURSE) { 3968 opts |= PF_OPT_CALLSHOW; 3969 pfctl_recurse(dev, opts, anchorname, 3970 pfctl_call_showtables); 3971 } else 3972 pfctl_show_tables(anchorname, opts); 3973 break; 3974 case SHOWOPT_OSFP: 3975 pfctl_load_fingerprints(dev, opts); 3976 pfctl_show_fingerprints(opts); 3977 break; 3978 case SHOWOPT_IFACES: 3979 pfctl_show_ifaces(ifaceopt, opts); 3980 break; 3981 case SHOWOPT_CREATORIDS: 3982 pfctl_show_creators(opts); 3983 break; 3984 case SHOWOPT_STATELIMS: 3985 pfctl_show_statelims(dev, PFCTL_SHOW_LABELS, opts); 3986 break; 3987 case SHOWOPT_SOURCELIMS: 3988 pfctl_show_sourcelims(dev, PFCTL_SHOW_LABELS, opts, idopt); 3989 break; 3990 } 3991 3992 if ((opts & PF_OPT_CLRRULECTRS) && showopt == 0) { 3993 pfctl_show_eth_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 3994 anchorname, 0, 0); 3995 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 3996 anchorname, 0, 0); 3997 } 3998 3999 if (clearopt != NULL) { 4000 int mnr; 4001 4002 /* Check if anchor exists. */ 4003 if ((pfctl_get_rulesets(pfh, anchorname, &mnr)) == ENOENT) 4004 errx(1, "No such anchor %s", anchorname); 4005 4006 switch (*clearopt) { 4007 case 'e': 4008 pfctl_flush_eth_rules(dev, opts, anchorname); 4009 break; 4010 case 'r': 4011 if (opts & PF_OPT_RECURSE) 4012 pfctl_recurse(dev, opts, anchorname, 4013 pfctl_call_clearrules); 4014 else 4015 pfctl_flush_rules(dev, opts, anchorname); 4016 break; 4017 case 'n': 4018 pfctl_flush_nat(dev, opts, anchorname); 4019 break; 4020 case 'q': 4021 pfctl_clear_altq(dev, opts); 4022 break; 4023 case 's': 4024 pfctl_clear_iface_states(dev, ifaceopt, opts); 4025 break; 4026 case 'S': 4027 pfctl_clear_src_nodes(dev, opts); 4028 break; 4029 case 'i': 4030 pfctl_clear_stats(pfh, opts); 4031 break; 4032 case 'a': 4033 if (ifaceopt) { 4034 warnx("don't specify an interface with -Fall"); 4035 usage(); 4036 /* NOTREACHED */ 4037 } 4038 pfctl_flush_eth_rules(dev, opts, anchorname); 4039 pfctl_flush_rules(dev, opts, anchorname); 4040 pfctl_flush_nat(dev, opts, anchorname); 4041 if (opts & PF_OPT_RECURSE) 4042 pfctl_recurse(dev, opts, anchorname, 4043 pfctl_call_clearanchors); 4044 else { 4045 pfctl_do_clear_tables(anchorname, opts); 4046 pfctl_flush_rules(dev, opts, anchorname); 4047 } 4048 if (!*anchorname) { 4049 pfctl_clear_altq(dev, opts); 4050 pfctl_clear_iface_states(dev, ifaceopt, opts); 4051 pfctl_clear_src_nodes(dev, opts); 4052 pfctl_clear_stats(pfh, opts); 4053 pfctl_clear_fingerprints(dev, opts); 4054 pfctl_reset(dev, opts); 4055 } 4056 break; 4057 case 'o': 4058 pfctl_clear_fingerprints(dev, opts); 4059 break; 4060 case 'T': 4061 if ((opts & PF_OPT_RECURSE) == 0) 4062 pfctl_do_clear_tables(anchorname, opts); 4063 else 4064 pfctl_recurse(dev, opts, anchorname, 4065 pfctl_call_cleartables); 4066 break; 4067 case 'R': 4068 pfctl_reset(dev, opts); 4069 break; 4070 } 4071 } 4072 if (state_killers) { 4073 if (!strcmp(state_kill[0], "label")) 4074 pfctl_label_kill_states(dev, ifaceopt, opts); 4075 else if (!strcmp(state_kill[0], "id")) 4076 pfctl_id_kill_states(dev, ifaceopt, opts); 4077 else if (!strcmp(state_kill[0], "gateway")) 4078 pfctl_gateway_kill_states(dev, ifaceopt, opts); 4079 else if (!strcmp(state_kill[0], "key")) 4080 pfctl_key_kill_states(dev, ifaceopt, opts); 4081 else if (!strcmp(state_kill[0], "source")) 4082 pfctl_kill_source(dev, idopt, state_kill[1], opts); 4083 else 4084 pfctl_net_kill_states(dev, ifaceopt, opts); 4085 } 4086 4087 if (src_node_killers) 4088 pfctl_kill_src_nodes(dev, opts); 4089 4090 if (tblcmdopt != NULL) { 4091 exit_val = pfctl_table(argc, argv, tableopt, 4092 tblcmdopt, rulesopt, anchorname, opts); 4093 rulesopt = NULL; 4094 } 4095 if (optiopt != NULL) { 4096 switch (*optiopt) { 4097 case 'n': 4098 optimize = 0; 4099 break; 4100 case 'b': 4101 optimize |= PF_OPTIMIZE_BASIC; 4102 break; 4103 case 'o': 4104 case 'p': 4105 optimize |= PF_OPTIMIZE_PROFILE; 4106 break; 4107 } 4108 } 4109 4110 if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) && 4111 !anchorname[0] && !(opts & PF_OPT_NOACTION)) 4112 pfctl_get_skip_ifaces(); 4113 4114 if (rulesopt != NULL && !(opts & PF_OPT_MERGE) && 4115 !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION)) 4116 if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 4117 exit_val = 1; 4118 4119 if (rulesopt != NULL) { 4120 if (pfctl_rules(dev, rulesopt, opts, optimize, 4121 anchorname, NULL)) 4122 exit_val = 1; 4123 } 4124 4125 if (opts & PF_OPT_ENABLE) 4126 if (pfctl_enable(dev, opts)) 4127 exit_val = 1; 4128 4129 if (debugopt != NULL) { 4130 switch (*debugopt) { 4131 case 'n': 4132 pfctl_debug(dev, PF_DEBUG_NONE, opts); 4133 break; 4134 case 'u': 4135 pfctl_debug(dev, PF_DEBUG_URGENT, opts); 4136 break; 4137 case 'm': 4138 pfctl_debug(dev, PF_DEBUG_MISC, opts); 4139 break; 4140 case 'l': 4141 pfctl_debug(dev, PF_DEBUG_NOISY, opts); 4142 break; 4143 } 4144 } 4145 4146 /* 4147 * prevent pfctl_restore_limits() exit handler from restoring 4148 * pf(4) options settings on successful exit. 4149 */ 4150 if (exit_val == 0) { 4151 close(dev); 4152 dev = -1; 4153 pfctl_close(pfh); 4154 pfh = NULL; 4155 } 4156 4157 return (exit_val); 4158 } 4159 4160 char * 4161 pf_strerror(int errnum) 4162 { 4163 switch (errnum) { 4164 case ESRCH: 4165 return "Table does not exist."; 4166 case EINVAL: 4167 case ENOENT: 4168 return "Anchor does not exist."; 4169 default: 4170 return strerror(errnum); 4171 } 4172 } 4173 4174 static inline int 4175 pfctl_statelim_id_cmp(const struct pfctl_statelim *a, 4176 const struct pfctl_statelim *b) 4177 { 4178 uint32_t ida = a->ioc.id; 4179 uint32_t idb = b->ioc.id; 4180 4181 if (ida > idb) 4182 return (1); 4183 if (ida < idb) 4184 return (-1); 4185 4186 return (0); 4187 } 4188 4189 RB_GENERATE(pfctl_statelim_ids, pfctl_statelim, entry, pfctl_statelim_id_cmp); 4190 4191 static inline int 4192 pfctl_statelim_nm_cmp(const struct pfctl_statelim *a, 4193 const struct pfctl_statelim *b) 4194 { 4195 return (strcmp(a->ioc.name, b->ioc.name)); 4196 } 4197 4198 RB_GENERATE(pfctl_statelim_nms, pfctl_statelim, entry, pfctl_statelim_nm_cmp); 4199 4200 int 4201 pfctl_add_statelim(struct pfctl *pf, struct pfctl_statelim *stlim) 4202 { 4203 struct pfctl_statelim *ostlim; 4204 4205 ostlim = RB_INSERT(pfctl_statelim_ids, &pf->statelim_ids, stlim); 4206 if (ostlim != NULL) 4207 return (-1); 4208 4209 ostlim = RB_INSERT(pfctl_statelim_nms, &pf->statelim_nms, stlim); 4210 if (ostlim != NULL) { 4211 RB_REMOVE(pfctl_statelim_ids, &pf->statelim_ids, stlim); 4212 return (-1); 4213 } 4214 4215 return (0); 4216 } 4217 4218 struct pfctl_statelim * 4219 pfctl_get_statelim_id(struct pfctl *pf, uint32_t id) 4220 { 4221 struct pfctl_statelim key; 4222 4223 key.ioc.id = id; 4224 4225 return (RB_FIND(pfctl_statelim_nms, &pf->statelim_nms, &key)); 4226 } 4227 4228 struct pfctl_statelim * 4229 pfctl_get_statelim_nm(struct pfctl *pf, const char *name) 4230 { 4231 struct pfctl_statelim key; 4232 4233 if (strlcpy(key.ioc.name, name, sizeof(key.ioc.name)) >= 4234 sizeof(key.ioc.name)) 4235 return (NULL); 4236 4237 return (RB_FIND(pfctl_statelim_nms, &pf->statelim_nms, &key)); 4238 } 4239 4240 static inline int 4241 pfctl_sourcelim_id_cmp(const struct pfctl_sourcelim *a, 4242 const struct pfctl_sourcelim *b) 4243 { 4244 uint32_t ida = a->ioc.id; 4245 uint32_t idb = b->ioc.id; 4246 4247 if (ida > idb) 4248 return (1); 4249 if (ida < idb) 4250 return (-1); 4251 4252 return (0); 4253 } 4254 4255 RB_GENERATE(pfctl_sourcelim_ids, pfctl_sourcelim, entry, 4256 pfctl_sourcelim_id_cmp); 4257 4258 static inline int 4259 pfctl_sourcelim_nm_cmp(const struct pfctl_sourcelim *a, 4260 const struct pfctl_sourcelim *b) 4261 { 4262 return (strcmp(a->ioc.name, b->ioc.name)); 4263 } 4264 4265 RB_GENERATE(pfctl_sourcelim_nms, pfctl_sourcelim, entry, 4266 pfctl_sourcelim_nm_cmp); 4267 4268 int 4269 pfctl_add_sourcelim(struct pfctl *pf, struct pfctl_sourcelim *srlim) 4270 { 4271 struct pfctl_sourcelim *osrlim; 4272 4273 osrlim = RB_INSERT(pfctl_sourcelim_ids, &pf->sourcelim_ids, srlim); 4274 if (osrlim != NULL) 4275 return (-1); 4276 4277 osrlim = RB_INSERT(pfctl_sourcelim_nms, &pf->sourcelim_nms, srlim); 4278 if (osrlim != NULL) { 4279 RB_REMOVE(pfctl_sourcelim_ids, &pf->sourcelim_ids, srlim); 4280 return (-1); 4281 } 4282 4283 return (0); 4284 } 4285 4286 struct pfctl_sourcelim * 4287 pfctl_get_sourcelim_id(struct pfctl *pf, uint32_t id) 4288 { 4289 struct pfctl_sourcelim key; 4290 4291 key.ioc.id = id; 4292 4293 return (RB_FIND(pfctl_sourcelim_nms, &pf->sourcelim_nms, &key)); 4294 } 4295 4296 struct pfctl_sourcelim * 4297 pfctl_get_sourcelim_nm(struct pfctl *pf, const char *name) 4298 { 4299 struct pfctl_sourcelim key; 4300 4301 if (strlcpy(key.ioc.name, name, sizeof(key.ioc.name)) >= 4302 sizeof(key.ioc.name)) 4303 return (NULL); 4304 4305 return (RB_FIND(pfctl_sourcelim_nms, &pf->sourcelim_nms, &key)); 4306 } 4307