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 __FBSDID("$FreeBSD$"); 38 39 #define PFIOC_USE_LATEST 40 41 #include <sys/types.h> 42 #include <sys/ioctl.h> 43 #include <sys/nv.h> 44 #include <sys/socket.h> 45 #include <sys/stat.h> 46 #include <sys/endian.h> 47 48 #include <net/if.h> 49 #include <netinet/in.h> 50 #include <net/pfvar.h> 51 #include <arpa/inet.h> 52 #include <net/altq/altq.h> 53 #include <sys/sysctl.h> 54 55 #include <err.h> 56 #include <errno.h> 57 #include <fcntl.h> 58 #include <libpfctl.h> 59 #include <limits.h> 60 #include <netdb.h> 61 #include <stdint.h> 62 #include <stdio.h> 63 #include <stdlib.h> 64 #include <string.h> 65 #include <unistd.h> 66 67 #include "pfctl_parser.h" 68 #include "pfctl.h" 69 70 void usage(void); 71 int pfctl_enable(int, int); 72 int pfctl_disable(int, int); 73 int pfctl_clear_stats(int, int); 74 int pfctl_get_skip_ifaces(void); 75 int pfctl_check_skip_ifaces(char *); 76 int pfctl_adjust_skip_ifaces(struct pfctl *); 77 int pfctl_clear_interface_flags(int, int); 78 int pfctl_clear_rules(int, int, char *); 79 int pfctl_clear_nat(int, int, char *); 80 int pfctl_clear_altq(int, int); 81 int pfctl_clear_src_nodes(int, int); 82 int pfctl_clear_states(int, const char *, int); 83 void pfctl_addrprefix(char *, struct pf_addr *); 84 int pfctl_kill_src_nodes(int, const char *, int); 85 int pfctl_net_kill_states(int, const char *, int); 86 int pfctl_label_kill_states(int, const char *, int); 87 int pfctl_id_kill_states(int, const char *, int); 88 void pfctl_init_options(struct pfctl *); 89 int pfctl_load_options(struct pfctl *); 90 int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); 91 int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); 92 int pfctl_load_debug(struct pfctl *, unsigned int); 93 int pfctl_load_logif(struct pfctl *, char *); 94 int pfctl_load_hostid(struct pfctl *, u_int32_t); 95 int pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int, 96 char *); 97 void pfctl_print_rule_counters(struct pfctl_rule *, int); 98 int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int); 99 int pfctl_show_nat(int, int, char *); 100 int pfctl_show_src_nodes(int, int); 101 int pfctl_show_states(int, const char *, int); 102 int pfctl_show_status(int, int); 103 int pfctl_show_running(int); 104 int pfctl_show_timeouts(int, int); 105 int pfctl_show_limits(int, int); 106 void pfctl_debug(int, u_int32_t, int); 107 int pfctl_test_altqsupport(int, int); 108 int pfctl_show_anchors(int, int, char *); 109 int pfctl_ruleset_trans(struct pfctl *, char *, struct pfctl_anchor *); 110 int pfctl_load_ruleset(struct pfctl *, char *, 111 struct pfctl_ruleset *, int, int); 112 int pfctl_load_rule(struct pfctl *, char *, struct pfctl_rule *, int); 113 const char *pfctl_lookup_option(char *, const char * const *); 114 115 static struct pfctl_anchor_global pf_anchors; 116 static struct pfctl_anchor pf_main_anchor; 117 static struct pfr_buffer skip_b; 118 119 static const char *clearopt; 120 static char *rulesopt; 121 static const char *showopt; 122 static const char *debugopt; 123 static char *anchoropt; 124 static const char *optiopt = NULL; 125 static const char *pf_device = "/dev/pf"; 126 static char *ifaceopt; 127 static char *tableopt; 128 static const char *tblcmdopt; 129 static int src_node_killers; 130 static char *src_node_kill[2]; 131 static int state_killers; 132 static char *state_kill[2]; 133 int loadopt; 134 int altqsupport; 135 136 int dev = -1; 137 static int first_title = 1; 138 static int labels = 0; 139 140 #define INDENT(d, o) do { \ 141 if (o) { \ 142 int i; \ 143 for (i=0; i < d; i++) \ 144 printf(" "); \ 145 } \ 146 } while (0); \ 147 148 149 static const struct { 150 const char *name; 151 int index; 152 } pf_limits[] = { 153 { "states", PF_LIMIT_STATES }, 154 { "src-nodes", PF_LIMIT_SRC_NODES }, 155 { "frags", PF_LIMIT_FRAGS }, 156 { "table-entries", PF_LIMIT_TABLE_ENTRIES }, 157 { NULL, 0 } 158 }; 159 160 struct pf_hint { 161 const char *name; 162 int timeout; 163 }; 164 static const struct pf_hint pf_hint_normal[] = { 165 { "tcp.first", 2 * 60 }, 166 { "tcp.opening", 30 }, 167 { "tcp.established", 24 * 60 * 60 }, 168 { "tcp.closing", 15 * 60 }, 169 { "tcp.finwait", 45 }, 170 { "tcp.closed", 90 }, 171 { "tcp.tsdiff", 30 }, 172 { NULL, 0 } 173 }; 174 static const struct pf_hint pf_hint_satellite[] = { 175 { "tcp.first", 3 * 60 }, 176 { "tcp.opening", 30 + 5 }, 177 { "tcp.established", 24 * 60 * 60 }, 178 { "tcp.closing", 15 * 60 + 5 }, 179 { "tcp.finwait", 45 + 5 }, 180 { "tcp.closed", 90 + 5 }, 181 { "tcp.tsdiff", 60 }, 182 { NULL, 0 } 183 }; 184 static const struct pf_hint pf_hint_conservative[] = { 185 { "tcp.first", 60 * 60 }, 186 { "tcp.opening", 15 * 60 }, 187 { "tcp.established", 5 * 24 * 60 * 60 }, 188 { "tcp.closing", 60 * 60 }, 189 { "tcp.finwait", 10 * 60 }, 190 { "tcp.closed", 3 * 60 }, 191 { "tcp.tsdiff", 60 }, 192 { NULL, 0 } 193 }; 194 static const struct pf_hint pf_hint_aggressive[] = { 195 { "tcp.first", 30 }, 196 { "tcp.opening", 5 }, 197 { "tcp.established", 5 * 60 * 60 }, 198 { "tcp.closing", 60 }, 199 { "tcp.finwait", 30 }, 200 { "tcp.closed", 30 }, 201 { "tcp.tsdiff", 10 }, 202 { NULL, 0 } 203 }; 204 205 static const struct { 206 const char *name; 207 const struct pf_hint *hint; 208 } pf_hints[] = { 209 { "normal", pf_hint_normal }, 210 { "satellite", pf_hint_satellite }, 211 { "high-latency", pf_hint_satellite }, 212 { "conservative", pf_hint_conservative }, 213 { "aggressive", pf_hint_aggressive }, 214 { NULL, NULL } 215 }; 216 217 static const char * const clearopt_list[] = { 218 "nat", "queue", "rules", "Sources", 219 "states", "info", "Tables", "osfp", "all", NULL 220 }; 221 222 static const char * const showopt_list[] = { 223 "nat", "queue", "rules", "Anchors", "Sources", "states", "info", 224 "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp", 225 "Running", "all", NULL 226 }; 227 228 static const char * const tblcmdopt_list[] = { 229 "kill", "flush", "add", "delete", "load", "replace", "show", 230 "test", "zero", "expire", NULL 231 }; 232 233 static const char * const debugopt_list[] = { 234 "none", "urgent", "misc", "loud", NULL 235 }; 236 237 static const char * const optiopt_list[] = { 238 "none", "basic", "profile", NULL 239 }; 240 241 void 242 usage(void) 243 { 244 extern char *__progname; 245 246 fprintf(stderr, 247 "usage: %s [-AdeghmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n" 248 "\t[-f file] [-i interface] [-K host | network]\n" 249 "\t[-k host | network | label | id] [-o level] [-p device]\n" 250 "\t[-s modifier] [-t table -T command [address ...]] [-x level]\n", 251 __progname); 252 253 exit(1); 254 } 255 256 int 257 pfctl_enable(int dev, int opts) 258 { 259 if (ioctl(dev, DIOCSTART)) { 260 if (errno == EEXIST) 261 errx(1, "pf already enabled"); 262 else if (errno == ESRCH) 263 errx(1, "pfil registeration failed"); 264 else 265 err(1, "DIOCSTART"); 266 } 267 if ((opts & PF_OPT_QUIET) == 0) 268 fprintf(stderr, "pf enabled\n"); 269 270 if (altqsupport && ioctl(dev, DIOCSTARTALTQ)) 271 if (errno != EEXIST) 272 err(1, "DIOCSTARTALTQ"); 273 274 return (0); 275 } 276 277 int 278 pfctl_disable(int dev, int opts) 279 { 280 if (ioctl(dev, DIOCSTOP)) { 281 if (errno == ENOENT) 282 errx(1, "pf not enabled"); 283 else 284 err(1, "DIOCSTOP"); 285 } 286 if ((opts & PF_OPT_QUIET) == 0) 287 fprintf(stderr, "pf disabled\n"); 288 289 if (altqsupport && ioctl(dev, DIOCSTOPALTQ)) 290 if (errno != ENOENT) 291 err(1, "DIOCSTOPALTQ"); 292 293 return (0); 294 } 295 296 int 297 pfctl_clear_stats(int dev, int opts) 298 { 299 if (ioctl(dev, DIOCCLRSTATUS)) 300 err(1, "DIOCCLRSTATUS"); 301 if ((opts & PF_OPT_QUIET) == 0) 302 fprintf(stderr, "pf: statistics cleared\n"); 303 return (0); 304 } 305 306 int 307 pfctl_get_skip_ifaces(void) 308 { 309 bzero(&skip_b, sizeof(skip_b)); 310 skip_b.pfrb_type = PFRB_IFACES; 311 for (;;) { 312 pfr_buf_grow(&skip_b, skip_b.pfrb_size); 313 skip_b.pfrb_size = skip_b.pfrb_msize; 314 if (pfi_get_ifaces(NULL, skip_b.pfrb_caddr, &skip_b.pfrb_size)) 315 err(1, "pfi_get_ifaces"); 316 if (skip_b.pfrb_size <= skip_b.pfrb_msize) 317 break; 318 } 319 return (0); 320 } 321 322 int 323 pfctl_check_skip_ifaces(char *ifname) 324 { 325 struct pfi_kif *p; 326 struct node_host *h = NULL, *n = NULL; 327 328 PFRB_FOREACH(p, &skip_b) { 329 if (!strcmp(ifname, p->pfik_name) && 330 (p->pfik_flags & PFI_IFLAG_SKIP)) 331 p->pfik_flags &= ~PFI_IFLAG_SKIP; 332 if (!strcmp(ifname, p->pfik_name) && p->pfik_group != NULL) { 333 if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL) 334 continue; 335 336 for (n = h; n != NULL; n = n->next) { 337 if (p->pfik_ifp == NULL) 338 continue; 339 if (strncmp(p->pfik_name, ifname, IFNAMSIZ)) 340 continue; 341 342 p->pfik_flags &= ~PFI_IFLAG_SKIP; 343 } 344 } 345 } 346 return (0); 347 } 348 349 int 350 pfctl_adjust_skip_ifaces(struct pfctl *pf) 351 { 352 struct pfi_kif *p, *pp; 353 struct node_host *h = NULL, *n = NULL; 354 355 PFRB_FOREACH(p, &skip_b) { 356 if (p->pfik_group == NULL || !(p->pfik_flags & PFI_IFLAG_SKIP)) 357 continue; 358 359 pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0); 360 if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL) 361 continue; 362 363 for (n = h; n != NULL; n = n->next) 364 PFRB_FOREACH(pp, &skip_b) { 365 if (pp->pfik_ifp == NULL) 366 continue; 367 368 if (strncmp(pp->pfik_name, n->ifname, IFNAMSIZ)) 369 continue; 370 371 if (!(pp->pfik_flags & PFI_IFLAG_SKIP)) 372 pfctl_set_interface_flags(pf, 373 pp->pfik_name, PFI_IFLAG_SKIP, 1); 374 if (pp->pfik_flags & PFI_IFLAG_SKIP) 375 pp->pfik_flags &= ~PFI_IFLAG_SKIP; 376 } 377 } 378 379 PFRB_FOREACH(p, &skip_b) { 380 if (p->pfik_ifp == NULL || ! (p->pfik_flags & PFI_IFLAG_SKIP)) 381 continue; 382 383 pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0); 384 } 385 386 return (0); 387 } 388 389 int 390 pfctl_clear_interface_flags(int dev, int opts) 391 { 392 struct pfioc_iface pi; 393 394 if ((opts & PF_OPT_NOACTION) == 0) { 395 bzero(&pi, sizeof(pi)); 396 pi.pfiio_flags = PFI_IFLAG_SKIP; 397 398 if (ioctl(dev, DIOCCLRIFFLAG, &pi)) 399 err(1, "DIOCCLRIFFLAG"); 400 if ((opts & PF_OPT_QUIET) == 0) 401 fprintf(stderr, "pf: interface flags reset\n"); 402 } 403 return (0); 404 } 405 406 int 407 pfctl_clear_rules(int dev, int opts, char *anchorname) 408 { 409 struct pfr_buffer t; 410 411 memset(&t, 0, sizeof(t)); 412 t.pfrb_type = PFRB_TRANS; 413 if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname) || 414 pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) || 415 pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 416 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 417 err(1, "pfctl_clear_rules"); 418 if ((opts & PF_OPT_QUIET) == 0) 419 fprintf(stderr, "rules cleared\n"); 420 return (0); 421 } 422 423 int 424 pfctl_clear_nat(int dev, int opts, char *anchorname) 425 { 426 struct pfr_buffer t; 427 428 memset(&t, 0, sizeof(t)); 429 t.pfrb_type = PFRB_TRANS; 430 if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname) || 431 pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname) || 432 pfctl_add_trans(&t, PF_RULESET_RDR, anchorname) || 433 pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 434 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 435 err(1, "pfctl_clear_nat"); 436 if ((opts & PF_OPT_QUIET) == 0) 437 fprintf(stderr, "nat cleared\n"); 438 return (0); 439 } 440 441 int 442 pfctl_clear_altq(int dev, int opts) 443 { 444 struct pfr_buffer t; 445 446 if (!altqsupport) 447 return (-1); 448 memset(&t, 0, sizeof(t)); 449 t.pfrb_type = PFRB_TRANS; 450 if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") || 451 pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 452 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 453 err(1, "pfctl_clear_altq"); 454 if ((opts & PF_OPT_QUIET) == 0) 455 fprintf(stderr, "altq cleared\n"); 456 return (0); 457 } 458 459 int 460 pfctl_clear_src_nodes(int dev, int opts) 461 { 462 if (ioctl(dev, DIOCCLRSRCNODES)) 463 err(1, "DIOCCLRSRCNODES"); 464 if ((opts & PF_OPT_QUIET) == 0) 465 fprintf(stderr, "source tracking entries cleared\n"); 466 return (0); 467 } 468 469 int 470 pfctl_clear_states(int dev, const char *iface, int opts) 471 { 472 struct pfioc_state_kill psk; 473 474 memset(&psk, 0, sizeof(psk)); 475 if (iface != NULL && strlcpy(psk.psk_ifname, iface, 476 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 477 errx(1, "invalid interface: %s", iface); 478 479 if (ioctl(dev, DIOCCLRSTATES, &psk)) 480 err(1, "DIOCCLRSTATES"); 481 if ((opts & PF_OPT_QUIET) == 0) 482 fprintf(stderr, "%d states cleared\n", psk.psk_killed); 483 return (0); 484 } 485 486 void 487 pfctl_addrprefix(char *addr, struct pf_addr *mask) 488 { 489 char *p; 490 const char *errstr; 491 int prefix, ret_ga, q, r; 492 struct addrinfo hints, *res; 493 494 if ((p = strchr(addr, '/')) == NULL) 495 return; 496 497 *p++ = '\0'; 498 prefix = strtonum(p, 0, 128, &errstr); 499 if (errstr) 500 errx(1, "prefix is %s: %s", errstr, p); 501 502 bzero(&hints, sizeof(hints)); 503 /* prefix only with numeric addresses */ 504 hints.ai_flags |= AI_NUMERICHOST; 505 506 if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) { 507 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 508 /* NOTREACHED */ 509 } 510 511 if (res->ai_family == AF_INET && prefix > 32) 512 errx(1, "prefix too long for AF_INET"); 513 else if (res->ai_family == AF_INET6 && prefix > 128) 514 errx(1, "prefix too long for AF_INET6"); 515 516 q = prefix >> 3; 517 r = prefix & 7; 518 switch (res->ai_family) { 519 case AF_INET: 520 bzero(&mask->v4, sizeof(mask->v4)); 521 mask->v4.s_addr = htonl((u_int32_t) 522 (0xffffffffffULL << (32 - prefix))); 523 break; 524 case AF_INET6: 525 bzero(&mask->v6, sizeof(mask->v6)); 526 if (q > 0) 527 memset((void *)&mask->v6, 0xff, q); 528 if (r > 0) 529 *((u_char *)&mask->v6 + q) = 530 (0xff00 >> r) & 0xff; 531 break; 532 } 533 freeaddrinfo(res); 534 } 535 536 int 537 pfctl_kill_src_nodes(int dev, const char *iface, int opts) 538 { 539 struct pfioc_src_node_kill psnk; 540 struct addrinfo *res[2], *resp[2]; 541 struct sockaddr last_src, last_dst; 542 int killed, sources, dests; 543 int ret_ga; 544 545 killed = sources = dests = 0; 546 547 memset(&psnk, 0, sizeof(psnk)); 548 memset(&psnk.psnk_src.addr.v.a.mask, 0xff, 549 sizeof(psnk.psnk_src.addr.v.a.mask)); 550 memset(&last_src, 0xff, sizeof(last_src)); 551 memset(&last_dst, 0xff, sizeof(last_dst)); 552 553 pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask); 554 555 if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) { 556 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 557 /* NOTREACHED */ 558 } 559 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 560 if (resp[0]->ai_addr == NULL) 561 continue; 562 /* We get lots of duplicates. Catch the easy ones */ 563 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 564 continue; 565 last_src = *(struct sockaddr *)resp[0]->ai_addr; 566 567 psnk.psnk_af = resp[0]->ai_family; 568 sources++; 569 570 if (psnk.psnk_af == AF_INET) 571 psnk.psnk_src.addr.v.a.addr.v4 = 572 ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 573 else if (psnk.psnk_af == AF_INET6) 574 psnk.psnk_src.addr.v.a.addr.v6 = 575 ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 576 sin6_addr; 577 else 578 errx(1, "Unknown address family %d", psnk.psnk_af); 579 580 if (src_node_killers > 1) { 581 dests = 0; 582 memset(&psnk.psnk_dst.addr.v.a.mask, 0xff, 583 sizeof(psnk.psnk_dst.addr.v.a.mask)); 584 memset(&last_dst, 0xff, sizeof(last_dst)); 585 pfctl_addrprefix(src_node_kill[1], 586 &psnk.psnk_dst.addr.v.a.mask); 587 if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL, 588 &res[1]))) { 589 errx(1, "getaddrinfo: %s", 590 gai_strerror(ret_ga)); 591 /* NOTREACHED */ 592 } 593 for (resp[1] = res[1]; resp[1]; 594 resp[1] = resp[1]->ai_next) { 595 if (resp[1]->ai_addr == NULL) 596 continue; 597 if (psnk.psnk_af != resp[1]->ai_family) 598 continue; 599 600 if (memcmp(&last_dst, resp[1]->ai_addr, 601 sizeof(last_dst)) == 0) 602 continue; 603 last_dst = *(struct sockaddr *)resp[1]->ai_addr; 604 605 dests++; 606 607 if (psnk.psnk_af == AF_INET) 608 psnk.psnk_dst.addr.v.a.addr.v4 = 609 ((struct sockaddr_in *)resp[1]-> 610 ai_addr)->sin_addr; 611 else if (psnk.psnk_af == AF_INET6) 612 psnk.psnk_dst.addr.v.a.addr.v6 = 613 ((struct sockaddr_in6 *)resp[1]-> 614 ai_addr)->sin6_addr; 615 else 616 errx(1, "Unknown address family %d", 617 psnk.psnk_af); 618 619 if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 620 err(1, "DIOCKILLSRCNODES"); 621 killed += psnk.psnk_killed; 622 } 623 freeaddrinfo(res[1]); 624 } else { 625 if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 626 err(1, "DIOCKILLSRCNODES"); 627 killed += psnk.psnk_killed; 628 } 629 } 630 631 freeaddrinfo(res[0]); 632 633 if ((opts & PF_OPT_QUIET) == 0) 634 fprintf(stderr, "killed %d src nodes from %d sources and %d " 635 "destinations\n", killed, sources, dests); 636 return (0); 637 } 638 639 int 640 pfctl_net_kill_states(int dev, const char *iface, int opts) 641 { 642 struct pfioc_state_kill psk; 643 struct addrinfo *res[2], *resp[2]; 644 struct sockaddr last_src, last_dst; 645 int killed, sources, dests; 646 int ret_ga; 647 648 killed = sources = dests = 0; 649 650 memset(&psk, 0, sizeof(psk)); 651 memset(&psk.psk_src.addr.v.a.mask, 0xff, 652 sizeof(psk.psk_src.addr.v.a.mask)); 653 memset(&last_src, 0xff, sizeof(last_src)); 654 memset(&last_dst, 0xff, sizeof(last_dst)); 655 if (iface != NULL && strlcpy(psk.psk_ifname, iface, 656 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 657 errx(1, "invalid interface: %s", iface); 658 659 pfctl_addrprefix(state_kill[0], &psk.psk_src.addr.v.a.mask); 660 661 if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) { 662 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 663 /* NOTREACHED */ 664 } 665 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 666 if (resp[0]->ai_addr == NULL) 667 continue; 668 /* We get lots of duplicates. Catch the easy ones */ 669 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 670 continue; 671 last_src = *(struct sockaddr *)resp[0]->ai_addr; 672 673 psk.psk_af = resp[0]->ai_family; 674 sources++; 675 676 if (psk.psk_af == AF_INET) 677 psk.psk_src.addr.v.a.addr.v4 = 678 ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 679 else if (psk.psk_af == AF_INET6) 680 psk.psk_src.addr.v.a.addr.v6 = 681 ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 682 sin6_addr; 683 else 684 errx(1, "Unknown address family %d", psk.psk_af); 685 686 if (state_killers > 1) { 687 dests = 0; 688 memset(&psk.psk_dst.addr.v.a.mask, 0xff, 689 sizeof(psk.psk_dst.addr.v.a.mask)); 690 memset(&last_dst, 0xff, sizeof(last_dst)); 691 pfctl_addrprefix(state_kill[1], 692 &psk.psk_dst.addr.v.a.mask); 693 if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, 694 &res[1]))) { 695 errx(1, "getaddrinfo: %s", 696 gai_strerror(ret_ga)); 697 /* NOTREACHED */ 698 } 699 for (resp[1] = res[1]; resp[1]; 700 resp[1] = resp[1]->ai_next) { 701 if (resp[1]->ai_addr == NULL) 702 continue; 703 if (psk.psk_af != resp[1]->ai_family) 704 continue; 705 706 if (memcmp(&last_dst, resp[1]->ai_addr, 707 sizeof(last_dst)) == 0) 708 continue; 709 last_dst = *(struct sockaddr *)resp[1]->ai_addr; 710 711 dests++; 712 713 if (psk.psk_af == AF_INET) 714 psk.psk_dst.addr.v.a.addr.v4 = 715 ((struct sockaddr_in *)resp[1]-> 716 ai_addr)->sin_addr; 717 else if (psk.psk_af == AF_INET6) 718 psk.psk_dst.addr.v.a.addr.v6 = 719 ((struct sockaddr_in6 *)resp[1]-> 720 ai_addr)->sin6_addr; 721 else 722 errx(1, "Unknown address family %d", 723 psk.psk_af); 724 725 if (ioctl(dev, DIOCKILLSTATES, &psk)) 726 err(1, "DIOCKILLSTATES"); 727 killed += psk.psk_killed; 728 } 729 freeaddrinfo(res[1]); 730 } else { 731 if (ioctl(dev, DIOCKILLSTATES, &psk)) 732 err(1, "DIOCKILLSTATES"); 733 killed += psk.psk_killed; 734 } 735 } 736 737 freeaddrinfo(res[0]); 738 739 if ((opts & PF_OPT_QUIET) == 0) 740 fprintf(stderr, "killed %d states from %d sources and %d " 741 "destinations\n", killed, sources, dests); 742 return (0); 743 } 744 745 int 746 pfctl_label_kill_states(int dev, const char *iface, int opts) 747 { 748 struct pfioc_state_kill psk; 749 750 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 751 warnx("no label specified"); 752 usage(); 753 } 754 memset(&psk, 0, sizeof(psk)); 755 if (iface != NULL && strlcpy(psk.psk_ifname, iface, 756 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 757 errx(1, "invalid interface: %s", iface); 758 759 if (strlcpy(psk.psk_label, state_kill[1], sizeof(psk.psk_label)) >= 760 sizeof(psk.psk_label)) 761 errx(1, "label too long: %s", state_kill[1]); 762 763 if (ioctl(dev, DIOCKILLSTATES, &psk)) 764 err(1, "DIOCKILLSTATES"); 765 766 if ((opts & PF_OPT_QUIET) == 0) 767 fprintf(stderr, "killed %d states\n", psk.psk_killed); 768 769 return (0); 770 } 771 772 int 773 pfctl_id_kill_states(int dev, const char *iface, int opts) 774 { 775 struct pfioc_state_kill psk; 776 777 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 778 warnx("no id specified"); 779 usage(); 780 } 781 782 memset(&psk, 0, sizeof(psk)); 783 if ((sscanf(state_kill[1], "%jx/%x", 784 &psk.psk_pfcmp.id, &psk.psk_pfcmp.creatorid)) == 2) 785 HTONL(psk.psk_pfcmp.creatorid); 786 else if ((sscanf(state_kill[1], "%jx", &psk.psk_pfcmp.id)) == 1) { 787 psk.psk_pfcmp.creatorid = 0; 788 } else { 789 warnx("wrong id format specified"); 790 usage(); 791 } 792 if (psk.psk_pfcmp.id == 0) { 793 warnx("cannot kill id 0"); 794 usage(); 795 } 796 797 psk.psk_pfcmp.id = htobe64(psk.psk_pfcmp.id); 798 if (ioctl(dev, DIOCKILLSTATES, &psk)) 799 err(1, "DIOCKILLSTATES"); 800 801 if ((opts & PF_OPT_QUIET) == 0) 802 fprintf(stderr, "killed %d states\n", psk.psk_killed); 803 804 return (0); 805 } 806 807 int 808 pfctl_get_pool(int dev, struct pfctl_pool *pool, u_int32_t nr, 809 u_int32_t ticket, int r_action, char *anchorname) 810 { 811 struct pfioc_pooladdr pp; 812 struct pf_pooladdr *pa; 813 u_int32_t pnr, mpnr; 814 815 memset(&pp, 0, sizeof(pp)); 816 memcpy(pp.anchor, anchorname, sizeof(pp.anchor)); 817 pp.r_action = r_action; 818 pp.r_num = nr; 819 pp.ticket = ticket; 820 if (ioctl(dev, DIOCGETADDRS, &pp)) { 821 warn("DIOCGETADDRS"); 822 return (-1); 823 } 824 mpnr = pp.nr; 825 TAILQ_INIT(&pool->list); 826 for (pnr = 0; pnr < mpnr; ++pnr) { 827 pp.nr = pnr; 828 if (ioctl(dev, DIOCGETADDR, &pp)) { 829 warn("DIOCGETADDR"); 830 return (-1); 831 } 832 pa = calloc(1, sizeof(struct pf_pooladdr)); 833 if (pa == NULL) 834 err(1, "calloc"); 835 bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr)); 836 TAILQ_INSERT_TAIL(&pool->list, pa, entries); 837 } 838 839 return (0); 840 } 841 842 void 843 pfctl_move_pool(struct pfctl_pool *src, struct pfctl_pool *dst) 844 { 845 struct pf_pooladdr *pa; 846 847 while ((pa = TAILQ_FIRST(&src->list)) != NULL) { 848 TAILQ_REMOVE(&src->list, pa, entries); 849 TAILQ_INSERT_TAIL(&dst->list, pa, entries); 850 } 851 } 852 853 void 854 pfctl_clear_pool(struct pfctl_pool *pool) 855 { 856 struct pf_pooladdr *pa; 857 858 while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { 859 TAILQ_REMOVE(&pool->list, pa, entries); 860 free(pa); 861 } 862 } 863 864 void 865 pfctl_print_rule_counters(struct pfctl_rule *rule, int opts) 866 { 867 if (opts & PF_OPT_DEBUG) { 868 const char *t[PF_SKIP_COUNT] = { "i", "d", "f", 869 "p", "sa", "sp", "da", "dp" }; 870 int i; 871 872 printf(" [ Skip steps: "); 873 for (i = 0; i < PF_SKIP_COUNT; ++i) { 874 if (rule->skip[i].nr == rule->nr + 1) 875 continue; 876 printf("%s=", t[i]); 877 if (rule->skip[i].nr == -1) 878 printf("end "); 879 else 880 printf("%u ", rule->skip[i].nr); 881 } 882 printf("]\n"); 883 884 printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n", 885 rule->qname, rule->qid, rule->pqname, rule->pqid); 886 } 887 if (opts & PF_OPT_VERBOSE) { 888 printf(" [ Evaluations: %-8llu Packets: %-8llu " 889 "Bytes: %-10llu States: %-6ju]\n", 890 (unsigned long long)rule->evaluations, 891 (unsigned long long)(rule->packets[0] + 892 rule->packets[1]), 893 (unsigned long long)(rule->bytes[0] + 894 rule->bytes[1]), (uintmax_t)rule->states_cur); 895 if (!(opts & PF_OPT_DEBUG)) 896 printf(" [ Inserted: uid %u pid %u " 897 "State Creations: %-6ju]\n", 898 (unsigned)rule->cuid, (unsigned)rule->cpid, 899 (uintmax_t)rule->states_tot); 900 } 901 } 902 903 void 904 pfctl_print_title(char *title) 905 { 906 if (!first_title) 907 printf("\n"); 908 first_title = 0; 909 printf("%s\n", title); 910 } 911 912 int 913 pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, 914 char *anchorname, int depth) 915 { 916 struct pfioc_rule pr; 917 struct pfctl_rule rule; 918 u_int32_t nr, mnr, header = 0; 919 int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); 920 int numeric = opts & PF_OPT_NUMERIC; 921 int len = strlen(path); 922 int brace; 923 char *p; 924 925 if (path[0]) 926 snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 927 else 928 snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 929 930 memset(&pr, 0, sizeof(pr)); 931 memcpy(pr.anchor, path, sizeof(pr.anchor)); 932 if (opts & PF_OPT_SHOWALL) { 933 pr.rule.action = PF_PASS; 934 if (ioctl(dev, DIOCGETRULES, &pr)) { 935 warn("DIOCGETRULES"); 936 goto error; 937 } 938 header++; 939 } 940 pr.rule.action = PF_SCRUB; 941 if (ioctl(dev, DIOCGETRULES, &pr)) { 942 warn("DIOCGETRULES"); 943 goto error; 944 } 945 if (opts & PF_OPT_SHOWALL) { 946 if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header)) 947 pfctl_print_title("FILTER RULES:"); 948 else if (format == PFCTL_SHOW_LABELS && labels) 949 pfctl_print_title("LABEL COUNTERS:"); 950 } 951 mnr = pr.nr; 952 953 for (nr = 0; nr < mnr; ++nr) { 954 pr.nr = nr; 955 if (pfctl_get_clear_rule(dev, nr, pr.ticket, path, PF_SCRUB, 956 &rule, pr.anchor_call, opts & PF_OPT_CLRRULECTRS)) { 957 warn("DIOCGETRULENV"); 958 goto error; 959 } 960 961 if (pfctl_get_pool(dev, &rule.rpool, 962 nr, pr.ticket, PF_SCRUB, path) != 0) 963 goto error; 964 965 switch (format) { 966 case PFCTL_SHOW_LABELS: 967 break; 968 case PFCTL_SHOW_RULES: 969 if (rule.label[0] && (opts & PF_OPT_SHOWALL)) 970 labels = 1; 971 print_rule(&rule, pr.anchor_call, rule_numbers, numeric); 972 printf("\n"); 973 pfctl_print_rule_counters(&rule, opts); 974 break; 975 case PFCTL_SHOW_NOTHING: 976 break; 977 } 978 pfctl_clear_pool(&rule.rpool); 979 } 980 pr.rule.action = PF_PASS; 981 if (ioctl(dev, DIOCGETRULES, &pr)) { 982 warn("DIOCGETRULES"); 983 goto error; 984 } 985 mnr = pr.nr; 986 for (nr = 0; nr < mnr; ++nr) { 987 pr.nr = nr; 988 if (pfctl_get_clear_rule(dev, nr, pr.ticket, path, PF_PASS, 989 &rule, pr.anchor_call, opts & PF_OPT_CLRRULECTRS)) { 990 warn("DIOCGETRULE"); 991 goto error; 992 } 993 994 if (pfctl_get_pool(dev, &rule.rpool, 995 nr, pr.ticket, PF_PASS, path) != 0) 996 goto error; 997 998 switch (format) { 999 case PFCTL_SHOW_LABELS: { 1000 bool show = false; 1001 int i = 0; 1002 1003 while (rule.label[i][0]) { 1004 printf("%s ", rule.label[i++]); 1005 show = true; 1006 } 1007 1008 if (show) { 1009 printf("%llu %llu %llu %llu" 1010 " %llu %llu %llu %ju\n", 1011 (unsigned long long)rule.evaluations, 1012 (unsigned long long)(rule.packets[0] + 1013 rule.packets[1]), 1014 (unsigned long long)(rule.bytes[0] + 1015 rule.bytes[1]), 1016 (unsigned long long)rule.packets[0], 1017 (unsigned long long)rule.bytes[0], 1018 (unsigned long long)rule.packets[1], 1019 (unsigned long long)rule.bytes[1], 1020 (uintmax_t)rule.states_tot); 1021 } 1022 break; 1023 } 1024 case PFCTL_SHOW_RULES: 1025 brace = 0; 1026 if (rule.label[0] && (opts & PF_OPT_SHOWALL)) 1027 labels = 1; 1028 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1029 if (pr.anchor_call[0] && 1030 ((((p = strrchr(pr.anchor_call, '_')) != NULL) && 1031 ((void *)p == (void *)pr.anchor_call || 1032 *(--p) == '/')) || (opts & PF_OPT_RECURSE))) { 1033 brace++; 1034 if ((p = strrchr(pr.anchor_call, '/')) != 1035 NULL) 1036 p++; 1037 else 1038 p = &pr.anchor_call[0]; 1039 } else 1040 p = &pr.anchor_call[0]; 1041 1042 print_rule(&rule, p, rule_numbers, numeric); 1043 if (brace) 1044 printf(" {\n"); 1045 else 1046 printf("\n"); 1047 pfctl_print_rule_counters(&rule, opts); 1048 if (brace) { 1049 pfctl_show_rules(dev, path, opts, format, 1050 p, depth + 1); 1051 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1052 printf("}\n"); 1053 } 1054 break; 1055 case PFCTL_SHOW_NOTHING: 1056 break; 1057 } 1058 pfctl_clear_pool(&rule.rpool); 1059 } 1060 path[len] = '\0'; 1061 return (0); 1062 1063 error: 1064 path[len] = '\0'; 1065 return (-1); 1066 } 1067 1068 int 1069 pfctl_show_nat(int dev, int opts, char *anchorname) 1070 { 1071 struct pfioc_rule pr; 1072 struct pfctl_rule rule; 1073 u_int32_t mnr, nr; 1074 static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; 1075 int i, dotitle = opts & PF_OPT_SHOWALL; 1076 1077 memset(&pr, 0, sizeof(pr)); 1078 memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 1079 for (i = 0; i < 3; i++) { 1080 pr.rule.action = nattype[i]; 1081 if (ioctl(dev, DIOCGETRULES, &pr)) { 1082 warn("DIOCGETRULES"); 1083 return (-1); 1084 } 1085 mnr = pr.nr; 1086 for (nr = 0; nr < mnr; ++nr) { 1087 pr.nr = nr; 1088 if (pfctl_get_rule(dev, nr, pr.ticket, anchorname, 1089 nattype[i], &rule, pr.anchor_call)) { 1090 warn("DIOCGETRULE"); 1091 return (-1); 1092 } 1093 if (pfctl_get_pool(dev, &rule.rpool, nr, 1094 pr.ticket, nattype[i], anchorname) != 0) 1095 return (-1); 1096 if (dotitle) { 1097 pfctl_print_title("TRANSLATION RULES:"); 1098 dotitle = 0; 1099 } 1100 print_rule(&rule, pr.anchor_call, 1101 opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC); 1102 printf("\n"); 1103 pfctl_print_rule_counters(&rule, opts); 1104 pfctl_clear_pool(&rule.rpool); 1105 } 1106 } 1107 return (0); 1108 } 1109 1110 int 1111 pfctl_show_src_nodes(int dev, int opts) 1112 { 1113 struct pfioc_src_nodes psn; 1114 struct pf_src_node *p; 1115 char *inbuf = NULL, *newinbuf = NULL; 1116 unsigned int len = 0; 1117 int i; 1118 1119 memset(&psn, 0, sizeof(psn)); 1120 for (;;) { 1121 psn.psn_len = len; 1122 if (len) { 1123 newinbuf = realloc(inbuf, len); 1124 if (newinbuf == NULL) 1125 err(1, "realloc"); 1126 psn.psn_buf = inbuf = newinbuf; 1127 } 1128 if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) { 1129 warn("DIOCGETSRCNODES"); 1130 free(inbuf); 1131 return (-1); 1132 } 1133 if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len) 1134 break; 1135 if (len == 0 && psn.psn_len == 0) 1136 goto done; 1137 if (len == 0 && psn.psn_len != 0) 1138 len = psn.psn_len; 1139 if (psn.psn_len == 0) 1140 goto done; /* no src_nodes */ 1141 len *= 2; 1142 } 1143 p = psn.psn_src_nodes; 1144 if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL)) 1145 pfctl_print_title("SOURCE TRACKING NODES:"); 1146 for (i = 0; i < psn.psn_len; i += sizeof(*p)) { 1147 print_src_node(p, opts); 1148 p++; 1149 } 1150 done: 1151 free(inbuf); 1152 return (0); 1153 } 1154 1155 int 1156 pfctl_show_states(int dev, const char *iface, int opts) 1157 { 1158 struct pfioc_states ps; 1159 struct pfsync_state *p; 1160 char *inbuf = NULL, *newinbuf = NULL; 1161 unsigned int len = 0; 1162 int i, dotitle = (opts & PF_OPT_SHOWALL); 1163 1164 memset(&ps, 0, sizeof(ps)); 1165 for (;;) { 1166 ps.ps_len = len; 1167 if (len) { 1168 newinbuf = realloc(inbuf, len); 1169 if (newinbuf == NULL) 1170 err(1, "realloc"); 1171 ps.ps_buf = inbuf = newinbuf; 1172 } 1173 if (ioctl(dev, DIOCGETSTATES, &ps) < 0) { 1174 warn("DIOCGETSTATES"); 1175 free(inbuf); 1176 return (-1); 1177 } 1178 if (ps.ps_len + sizeof(struct pfioc_states) < len) 1179 break; 1180 if (len == 0 && ps.ps_len == 0) 1181 goto done; 1182 if (len == 0 && ps.ps_len != 0) 1183 len = ps.ps_len; 1184 if (ps.ps_len == 0) 1185 goto done; /* no states */ 1186 len *= 2; 1187 } 1188 p = ps.ps_states; 1189 for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) { 1190 if (iface != NULL && strcmp(p->ifname, iface)) 1191 continue; 1192 if (dotitle) { 1193 pfctl_print_title("STATES:"); 1194 dotitle = 0; 1195 } 1196 print_state(p, opts); 1197 } 1198 done: 1199 free(inbuf); 1200 return (0); 1201 } 1202 1203 int 1204 pfctl_show_status(int dev, int opts) 1205 { 1206 struct pf_status status; 1207 1208 if (ioctl(dev, DIOCGETSTATUS, &status)) { 1209 warn("DIOCGETSTATUS"); 1210 return (-1); 1211 } 1212 if (opts & PF_OPT_SHOWALL) 1213 pfctl_print_title("INFO:"); 1214 print_status(&status, opts); 1215 return (0); 1216 } 1217 1218 int 1219 pfctl_show_running(int dev) 1220 { 1221 struct pf_status status; 1222 1223 if (ioctl(dev, DIOCGETSTATUS, &status)) { 1224 warn("DIOCGETSTATUS"); 1225 return (-1); 1226 } 1227 1228 print_running(&status); 1229 return (!status.running); 1230 } 1231 1232 int 1233 pfctl_show_timeouts(int dev, int opts) 1234 { 1235 struct pfioc_tm pt; 1236 int i; 1237 1238 if (opts & PF_OPT_SHOWALL) 1239 pfctl_print_title("TIMEOUTS:"); 1240 memset(&pt, 0, sizeof(pt)); 1241 for (i = 0; pf_timeouts[i].name; i++) { 1242 pt.timeout = pf_timeouts[i].timeout; 1243 if (ioctl(dev, DIOCGETTIMEOUT, &pt)) 1244 err(1, "DIOCGETTIMEOUT"); 1245 printf("%-20s %10d", pf_timeouts[i].name, pt.seconds); 1246 if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && 1247 pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) 1248 printf(" states"); 1249 else 1250 printf("s"); 1251 printf("\n"); 1252 } 1253 return (0); 1254 1255 } 1256 1257 int 1258 pfctl_show_limits(int dev, int opts) 1259 { 1260 struct pfioc_limit pl; 1261 int i; 1262 1263 if (opts & PF_OPT_SHOWALL) 1264 pfctl_print_title("LIMITS:"); 1265 memset(&pl, 0, sizeof(pl)); 1266 for (i = 0; pf_limits[i].name; i++) { 1267 pl.index = pf_limits[i].index; 1268 if (ioctl(dev, DIOCGETLIMIT, &pl)) 1269 err(1, "DIOCGETLIMIT"); 1270 printf("%-13s ", pf_limits[i].name); 1271 if (pl.limit == UINT_MAX) 1272 printf("unlimited\n"); 1273 else 1274 printf("hard limit %8u\n", pl.limit); 1275 } 1276 return (0); 1277 } 1278 1279 /* callbacks for rule/nat/rdr/addr */ 1280 int 1281 pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af) 1282 { 1283 struct pf_pooladdr *pa; 1284 1285 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1286 if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) 1287 err(1, "DIOCBEGINADDRS"); 1288 } 1289 1290 pf->paddr.af = af; 1291 TAILQ_FOREACH(pa, &p->list, entries) { 1292 memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr)); 1293 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1294 if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) 1295 err(1, "DIOCADDADDR"); 1296 } 1297 } 1298 return (0); 1299 } 1300 1301 int 1302 pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r, 1303 const char *anchor_call) 1304 { 1305 u_int8_t rs_num; 1306 struct pfctl_rule *rule; 1307 struct pfctl_ruleset *rs; 1308 char *p; 1309 1310 rs_num = pf_get_ruleset_number(r->action); 1311 if (rs_num == PF_RULESET_MAX) 1312 errx(1, "Invalid rule type %d", r->action); 1313 1314 rs = &pf->anchor->ruleset; 1315 1316 if (anchor_call[0] && r->anchor == NULL) { 1317 /* 1318 * Don't make non-brace anchors part of the main anchor pool. 1319 */ 1320 if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 1321 err(1, "pfctl_append_rule: calloc"); 1322 1323 pf_init_ruleset(&r->anchor->ruleset); 1324 r->anchor->ruleset.anchor = r->anchor; 1325 if (strlcpy(r->anchor->path, anchor_call, 1326 sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 1327 errx(1, "pfctl_append_rule: strlcpy"); 1328 if ((p = strrchr(anchor_call, '/')) != NULL) { 1329 if (!strlen(p)) 1330 err(1, "pfctl_append_rule: bad anchor name %s", 1331 anchor_call); 1332 } else 1333 p = (char *)anchor_call; 1334 if (strlcpy(r->anchor->name, p, 1335 sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 1336 errx(1, "pfctl_append_rule: strlcpy"); 1337 } 1338 1339 if ((rule = calloc(1, sizeof(*rule))) == NULL) 1340 err(1, "calloc"); 1341 bcopy(r, rule, sizeof(*rule)); 1342 TAILQ_INIT(&rule->rpool.list); 1343 pfctl_move_pool(&r->rpool, &rule->rpool); 1344 1345 TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries); 1346 return (0); 1347 } 1348 1349 int 1350 pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pfctl_anchor *a) 1351 { 1352 int osize = pf->trans->pfrb_size; 1353 1354 if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { 1355 if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || 1356 pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || 1357 pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) 1358 return (1); 1359 } 1360 if (a == pf->astack[0] && ((altqsupport && 1361 (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) { 1362 if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path)) 1363 return (2); 1364 } 1365 if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) { 1366 if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) || 1367 pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path)) 1368 return (3); 1369 } 1370 if (pf->loadopt & PFCTL_FLAG_TABLE) 1371 if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path)) 1372 return (4); 1373 if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1374 return (5); 1375 1376 return (0); 1377 } 1378 1379 int 1380 pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs, 1381 int rs_num, int depth) 1382 { 1383 struct pfctl_rule *r; 1384 int error, len = strlen(path); 1385 int brace = 0; 1386 1387 pf->anchor = rs->anchor; 1388 1389 if (path[0]) 1390 snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name); 1391 else 1392 snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name); 1393 1394 if (depth) { 1395 if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) { 1396 brace++; 1397 if (pf->opts & PF_OPT_VERBOSE) 1398 printf(" {\n"); 1399 if ((pf->opts & PF_OPT_NOACTION) == 0 && 1400 (error = pfctl_ruleset_trans(pf, 1401 path, rs->anchor))) { 1402 printf("pfctl_load_rulesets: " 1403 "pfctl_ruleset_trans %d\n", error); 1404 goto error; 1405 } 1406 } else if (pf->opts & PF_OPT_VERBOSE) 1407 printf("\n"); 1408 1409 } 1410 1411 if (pf->optimize && rs_num == PF_RULESET_FILTER) 1412 pfctl_optimize_ruleset(pf, rs); 1413 1414 while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) { 1415 TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries); 1416 if ((error = pfctl_load_rule(pf, path, r, depth))) 1417 goto error; 1418 if (r->anchor) { 1419 if ((error = pfctl_load_ruleset(pf, path, 1420 &r->anchor->ruleset, rs_num, depth + 1))) 1421 goto error; 1422 } else if (pf->opts & PF_OPT_VERBOSE) 1423 printf("\n"); 1424 free(r); 1425 } 1426 if (brace && pf->opts & PF_OPT_VERBOSE) { 1427 INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1428 printf("}\n"); 1429 } 1430 path[len] = '\0'; 1431 return (0); 1432 1433 error: 1434 path[len] = '\0'; 1435 return (error); 1436 1437 } 1438 1439 int 1440 pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth) 1441 { 1442 u_int8_t rs_num = pf_get_ruleset_number(r->action); 1443 char *name; 1444 u_int32_t ticket; 1445 char anchor[PF_ANCHOR_NAME_SIZE]; 1446 int len = strlen(path); 1447 1448 /* set up anchor before adding to path for anchor_call */ 1449 if ((pf->opts & PF_OPT_NOACTION) == 0) 1450 ticket = pfctl_get_ticket(pf->trans, rs_num, path); 1451 if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor)) 1452 errx(1, "pfctl_load_rule: strlcpy"); 1453 1454 if (r->anchor) { 1455 if (r->anchor->match) { 1456 if (path[0]) 1457 snprintf(&path[len], MAXPATHLEN - len, 1458 "/%s", r->anchor->name); 1459 else 1460 snprintf(&path[len], MAXPATHLEN - len, 1461 "%s", r->anchor->name); 1462 name = r->anchor->name; 1463 } else 1464 name = r->anchor->path; 1465 } else 1466 name = ""; 1467 1468 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1469 if (pfctl_add_pool(pf, &r->rpool, r->af)) 1470 return (1); 1471 if (pfctl_add_rule(pf->dev, r, anchor, name, ticket, 1472 pf->paddr.ticket)) 1473 err(1, "DIOCADDRULENV"); 1474 } 1475 1476 if (pf->opts & PF_OPT_VERBOSE) { 1477 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 1478 print_rule(r, r->anchor ? r->anchor->name : "", 1479 pf->opts & PF_OPT_VERBOSE2, 1480 pf->opts & PF_OPT_NUMERIC); 1481 } 1482 path[len] = '\0'; 1483 pfctl_clear_pool(&r->rpool); 1484 return (0); 1485 } 1486 1487 int 1488 pfctl_add_altq(struct pfctl *pf, struct pf_altq *a) 1489 { 1490 if (altqsupport && 1491 (loadopt & PFCTL_FLAG_ALTQ) != 0) { 1492 memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq)); 1493 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1494 if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) { 1495 if (errno == ENXIO) 1496 errx(1, "qtype not configured"); 1497 else if (errno == ENODEV) 1498 errx(1, "%s: driver does not support " 1499 "altq", a->ifname); 1500 else 1501 err(1, "DIOCADDALTQ"); 1502 } 1503 } 1504 pfaltq_store(&pf->paltq->altq); 1505 } 1506 return (0); 1507 } 1508 1509 int 1510 pfctl_rules(int dev, char *filename, int opts, int optimize, 1511 char *anchorname, struct pfr_buffer *trans) 1512 { 1513 #define ERR(x) do { warn(x); goto _error; } while(0) 1514 #define ERRX(x) do { warnx(x); goto _error; } while(0) 1515 1516 struct pfr_buffer *t, buf; 1517 struct pfioc_altq pa; 1518 struct pfctl pf; 1519 struct pfctl_ruleset *rs; 1520 struct pfr_table trs; 1521 char *path; 1522 int osize; 1523 1524 RB_INIT(&pf_anchors); 1525 memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); 1526 pf_init_ruleset(&pf_main_anchor.ruleset); 1527 pf_main_anchor.ruleset.anchor = &pf_main_anchor; 1528 if (trans == NULL) { 1529 bzero(&buf, sizeof(buf)); 1530 buf.pfrb_type = PFRB_TRANS; 1531 t = &buf; 1532 osize = 0; 1533 } else { 1534 t = trans; 1535 osize = t->pfrb_size; 1536 } 1537 1538 memset(&pa, 0, sizeof(pa)); 1539 pa.version = PFIOC_ALTQ_VERSION; 1540 memset(&pf, 0, sizeof(pf)); 1541 memset(&trs, 0, sizeof(trs)); 1542 if ((path = calloc(1, MAXPATHLEN)) == NULL) 1543 ERRX("pfctl_rules: calloc"); 1544 if (strlcpy(trs.pfrt_anchor, anchorname, 1545 sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) 1546 ERRX("pfctl_rules: strlcpy"); 1547 pf.dev = dev; 1548 pf.opts = opts; 1549 pf.optimize = optimize; 1550 pf.loadopt = loadopt; 1551 1552 /* non-brace anchor, create without resolving the path */ 1553 if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) 1554 ERRX("pfctl_rules: calloc"); 1555 rs = &pf.anchor->ruleset; 1556 pf_init_ruleset(rs); 1557 rs->anchor = pf.anchor; 1558 if (strlcpy(pf.anchor->path, anchorname, 1559 sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 1560 errx(1, "pfctl_add_rule: strlcpy"); 1561 if (strlcpy(pf.anchor->name, anchorname, 1562 sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 1563 errx(1, "pfctl_add_rule: strlcpy"); 1564 1565 1566 pf.astack[0] = pf.anchor; 1567 pf.asd = 0; 1568 if (anchorname[0]) 1569 pf.loadopt &= ~PFCTL_FLAG_ALTQ; 1570 pf.paltq = &pa; 1571 pf.trans = t; 1572 pfctl_init_options(&pf); 1573 1574 if ((opts & PF_OPT_NOACTION) == 0) { 1575 /* 1576 * XXX For the time being we need to open transactions for 1577 * the main ruleset before parsing, because tables are still 1578 * loaded at parse time. 1579 */ 1580 if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor)) 1581 ERRX("pfctl_rules"); 1582 if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) 1583 pa.ticket = 1584 pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname); 1585 if (pf.loadopt & PFCTL_FLAG_TABLE) 1586 pf.astack[0]->ruleset.tticket = 1587 pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname); 1588 } 1589 1590 if (parse_config(filename, &pf) < 0) { 1591 if ((opts & PF_OPT_NOACTION) == 0) 1592 ERRX("Syntax error in config file: " 1593 "pf rules not loaded"); 1594 else 1595 goto _error; 1596 } 1597 if (loadopt & PFCTL_FLAG_OPTION) 1598 pfctl_adjust_skip_ifaces(&pf); 1599 1600 if ((pf.loadopt & PFCTL_FLAG_FILTER && 1601 (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) || 1602 (pf.loadopt & PFCTL_FLAG_NAT && 1603 (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) || 1604 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) || 1605 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) || 1606 (pf.loadopt & PFCTL_FLAG_FILTER && 1607 pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) { 1608 if ((opts & PF_OPT_NOACTION) == 0) 1609 ERRX("Unable to load rules into kernel"); 1610 else 1611 goto _error; 1612 } 1613 1614 if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0)) 1615 if (check_commit_altq(dev, opts) != 0) 1616 ERRX("errors in altq config"); 1617 1618 /* process "load anchor" directives */ 1619 if (!anchorname[0]) 1620 if (pfctl_load_anchors(dev, &pf, t) == -1) 1621 ERRX("load anchors"); 1622 1623 if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) { 1624 if (!anchorname[0]) 1625 if (pfctl_load_options(&pf)) 1626 goto _error; 1627 if (pfctl_trans(dev, t, DIOCXCOMMIT, osize)) 1628 ERR("DIOCXCOMMIT"); 1629 } 1630 free(path); 1631 return (0); 1632 1633 _error: 1634 if (trans == NULL) { /* main ruleset */ 1635 if ((opts & PF_OPT_NOACTION) == 0) 1636 if (pfctl_trans(dev, t, DIOCXROLLBACK, osize)) 1637 err(1, "DIOCXROLLBACK"); 1638 exit(1); 1639 } else { /* sub ruleset */ 1640 free(path); 1641 return (-1); 1642 } 1643 1644 #undef ERR 1645 #undef ERRX 1646 } 1647 1648 FILE * 1649 pfctl_fopen(const char *name, const char *mode) 1650 { 1651 struct stat st; 1652 FILE *fp; 1653 1654 fp = fopen(name, mode); 1655 if (fp == NULL) 1656 return (NULL); 1657 if (fstat(fileno(fp), &st)) { 1658 fclose(fp); 1659 return (NULL); 1660 } 1661 if (S_ISDIR(st.st_mode)) { 1662 fclose(fp); 1663 errno = EISDIR; 1664 return (NULL); 1665 } 1666 return (fp); 1667 } 1668 1669 void 1670 pfctl_init_options(struct pfctl *pf) 1671 { 1672 1673 pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 1674 pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; 1675 pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 1676 pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; 1677 pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; 1678 pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; 1679 pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; 1680 pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; 1681 pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; 1682 pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; 1683 pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; 1684 pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; 1685 pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; 1686 pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; 1687 pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; 1688 pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; 1689 pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; 1690 pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; 1691 pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; 1692 pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; 1693 1694 pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; 1695 pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT; 1696 pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; 1697 pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; 1698 1699 pf->debug = PF_DEBUG_URGENT; 1700 } 1701 1702 int 1703 pfctl_load_options(struct pfctl *pf) 1704 { 1705 int i, error = 0; 1706 1707 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1708 return (0); 1709 1710 /* load limits */ 1711 for (i = 0; i < PF_LIMIT_MAX; i++) { 1712 if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i]) 1713 continue; 1714 if (pfctl_load_limit(pf, i, pf->limit[i])) 1715 error = 1; 1716 } 1717 1718 /* 1719 * If we've set the limit, but haven't explicitly set adaptive 1720 * timeouts, do it now with a start of 60% and end of 120%. 1721 */ 1722 if (pf->limit_set[PF_LIMIT_STATES] && 1723 !pf->timeout_set[PFTM_ADAPTIVE_START] && 1724 !pf->timeout_set[PFTM_ADAPTIVE_END]) { 1725 pf->timeout[PFTM_ADAPTIVE_START] = 1726 (pf->limit[PF_LIMIT_STATES] / 10) * 6; 1727 pf->timeout_set[PFTM_ADAPTIVE_START] = 1; 1728 pf->timeout[PFTM_ADAPTIVE_END] = 1729 (pf->limit[PF_LIMIT_STATES] / 10) * 12; 1730 pf->timeout_set[PFTM_ADAPTIVE_END] = 1; 1731 } 1732 1733 /* load timeouts */ 1734 for (i = 0; i < PFTM_MAX; i++) { 1735 if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i]) 1736 continue; 1737 if (pfctl_load_timeout(pf, i, pf->timeout[i])) 1738 error = 1; 1739 } 1740 1741 /* load debug */ 1742 if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set) 1743 if (pfctl_load_debug(pf, pf->debug)) 1744 error = 1; 1745 1746 /* load logif */ 1747 if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set) 1748 if (pfctl_load_logif(pf, pf->ifname)) 1749 error = 1; 1750 1751 /* load hostid */ 1752 if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set) 1753 if (pfctl_load_hostid(pf, pf->hostid)) 1754 error = 1; 1755 1756 /* load keepcounters */ 1757 if (pfctl_set_keepcounters(pf->dev, pf->keep_counters)) 1758 error = 1; 1759 1760 return (error); 1761 } 1762 1763 int 1764 pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) 1765 { 1766 int i; 1767 1768 1769 for (i = 0; pf_limits[i].name; i++) { 1770 if (strcasecmp(opt, pf_limits[i].name) == 0) { 1771 pf->limit[pf_limits[i].index] = limit; 1772 pf->limit_set[pf_limits[i].index] = 1; 1773 break; 1774 } 1775 } 1776 if (pf_limits[i].name == NULL) { 1777 warnx("Bad pool name."); 1778 return (1); 1779 } 1780 1781 if (pf->opts & PF_OPT_VERBOSE) 1782 printf("set limit %s %d\n", opt, limit); 1783 1784 return (0); 1785 } 1786 1787 int 1788 pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) 1789 { 1790 struct pfioc_limit pl; 1791 1792 memset(&pl, 0, sizeof(pl)); 1793 pl.index = index; 1794 pl.limit = limit; 1795 if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) { 1796 if (errno == EBUSY) 1797 warnx("Current pool size exceeds requested hard limit"); 1798 else 1799 warnx("DIOCSETLIMIT"); 1800 return (1); 1801 } 1802 return (0); 1803 } 1804 1805 int 1806 pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 1807 { 1808 int i; 1809 1810 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1811 return (0); 1812 1813 for (i = 0; pf_timeouts[i].name; i++) { 1814 if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 1815 pf->timeout[pf_timeouts[i].timeout] = seconds; 1816 pf->timeout_set[pf_timeouts[i].timeout] = 1; 1817 break; 1818 } 1819 } 1820 1821 if (pf_timeouts[i].name == NULL) { 1822 warnx("Bad timeout name."); 1823 return (1); 1824 } 1825 1826 1827 if (pf->opts & PF_OPT_VERBOSE && ! quiet) 1828 printf("set timeout %s %d\n", opt, seconds); 1829 1830 return (0); 1831 } 1832 1833 int 1834 pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) 1835 { 1836 struct pfioc_tm pt; 1837 1838 memset(&pt, 0, sizeof(pt)); 1839 pt.timeout = timeout; 1840 pt.seconds = seconds; 1841 if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) { 1842 warnx("DIOCSETTIMEOUT"); 1843 return (1); 1844 } 1845 return (0); 1846 } 1847 1848 int 1849 pfctl_set_optimization(struct pfctl *pf, const char *opt) 1850 { 1851 const struct pf_hint *hint; 1852 int i, r; 1853 1854 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1855 return (0); 1856 1857 for (i = 0; pf_hints[i].name; i++) 1858 if (strcasecmp(opt, pf_hints[i].name) == 0) 1859 break; 1860 1861 hint = pf_hints[i].hint; 1862 if (hint == NULL) { 1863 warnx("invalid state timeouts optimization"); 1864 return (1); 1865 } 1866 1867 for (i = 0; hint[i].name; i++) 1868 if ((r = pfctl_set_timeout(pf, hint[i].name, 1869 hint[i].timeout, 1))) 1870 return (r); 1871 1872 if (pf->opts & PF_OPT_VERBOSE) 1873 printf("set optimization %s\n", opt); 1874 1875 return (0); 1876 } 1877 1878 int 1879 pfctl_set_logif(struct pfctl *pf, char *ifname) 1880 { 1881 1882 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1883 return (0); 1884 1885 if (!strcmp(ifname, "none")) { 1886 free(pf->ifname); 1887 pf->ifname = NULL; 1888 } else { 1889 pf->ifname = strdup(ifname); 1890 if (!pf->ifname) 1891 errx(1, "pfctl_set_logif: strdup"); 1892 } 1893 pf->ifname_set = 1; 1894 1895 if (pf->opts & PF_OPT_VERBOSE) 1896 printf("set loginterface %s\n", ifname); 1897 1898 return (0); 1899 } 1900 1901 int 1902 pfctl_load_logif(struct pfctl *pf, char *ifname) 1903 { 1904 struct pfioc_if pi; 1905 1906 memset(&pi, 0, sizeof(pi)); 1907 if (ifname && strlcpy(pi.ifname, ifname, 1908 sizeof(pi.ifname)) >= sizeof(pi.ifname)) { 1909 warnx("pfctl_load_logif: strlcpy"); 1910 return (1); 1911 } 1912 if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) { 1913 warnx("DIOCSETSTATUSIF"); 1914 return (1); 1915 } 1916 return (0); 1917 } 1918 1919 int 1920 pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 1921 { 1922 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1923 return (0); 1924 1925 HTONL(hostid); 1926 1927 pf->hostid = hostid; 1928 pf->hostid_set = 1; 1929 1930 if (pf->opts & PF_OPT_VERBOSE) 1931 printf("set hostid 0x%08x\n", ntohl(hostid)); 1932 1933 return (0); 1934 } 1935 1936 int 1937 pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) 1938 { 1939 if (ioctl(dev, DIOCSETHOSTID, &hostid)) { 1940 warnx("DIOCSETHOSTID"); 1941 return (1); 1942 } 1943 return (0); 1944 } 1945 1946 int 1947 pfctl_set_debug(struct pfctl *pf, char *d) 1948 { 1949 u_int32_t level; 1950 1951 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1952 return (0); 1953 1954 if (!strcmp(d, "none")) 1955 pf->debug = PF_DEBUG_NONE; 1956 else if (!strcmp(d, "urgent")) 1957 pf->debug = PF_DEBUG_URGENT; 1958 else if (!strcmp(d, "misc")) 1959 pf->debug = PF_DEBUG_MISC; 1960 else if (!strcmp(d, "loud")) 1961 pf->debug = PF_DEBUG_NOISY; 1962 else { 1963 warnx("unknown debug level \"%s\"", d); 1964 return (-1); 1965 } 1966 1967 pf->debug_set = 1; 1968 level = pf->debug; 1969 1970 if ((pf->opts & PF_OPT_NOACTION) == 0) 1971 if (ioctl(dev, DIOCSETDEBUG, &level)) 1972 err(1, "DIOCSETDEBUG"); 1973 1974 if (pf->opts & PF_OPT_VERBOSE) 1975 printf("set debug %s\n", d); 1976 1977 return (0); 1978 } 1979 1980 int 1981 pfctl_load_debug(struct pfctl *pf, unsigned int level) 1982 { 1983 if (ioctl(pf->dev, DIOCSETDEBUG, &level)) { 1984 warnx("DIOCSETDEBUG"); 1985 return (1); 1986 } 1987 return (0); 1988 } 1989 1990 int 1991 pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) 1992 { 1993 struct pfioc_iface pi; 1994 struct node_host *h = NULL, *n = NULL; 1995 1996 if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1997 return (0); 1998 1999 bzero(&pi, sizeof(pi)); 2000 2001 pi.pfiio_flags = flags; 2002 2003 /* Make sure our cache matches the kernel. If we set or clear the flag 2004 * for a group this applies to all members. */ 2005 h = ifa_grouplookup(ifname, 0); 2006 for (n = h; n != NULL; n = n->next) 2007 pfctl_set_interface_flags(pf, n->ifname, flags, how); 2008 2009 if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= 2010 sizeof(pi.pfiio_name)) 2011 errx(1, "pfctl_set_interface_flags: strlcpy"); 2012 2013 if ((pf->opts & PF_OPT_NOACTION) == 0) { 2014 if (how == 0) { 2015 if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi)) 2016 err(1, "DIOCCLRIFFLAG"); 2017 } else { 2018 if (ioctl(pf->dev, DIOCSETIFFLAG, &pi)) 2019 err(1, "DIOCSETIFFLAG"); 2020 pfctl_check_skip_ifaces(ifname); 2021 } 2022 } 2023 return (0); 2024 } 2025 2026 void 2027 pfctl_debug(int dev, u_int32_t level, int opts) 2028 { 2029 if (ioctl(dev, DIOCSETDEBUG, &level)) 2030 err(1, "DIOCSETDEBUG"); 2031 if ((opts & PF_OPT_QUIET) == 0) { 2032 fprintf(stderr, "debug level set to '"); 2033 switch (level) { 2034 case PF_DEBUG_NONE: 2035 fprintf(stderr, "none"); 2036 break; 2037 case PF_DEBUG_URGENT: 2038 fprintf(stderr, "urgent"); 2039 break; 2040 case PF_DEBUG_MISC: 2041 fprintf(stderr, "misc"); 2042 break; 2043 case PF_DEBUG_NOISY: 2044 fprintf(stderr, "loud"); 2045 break; 2046 default: 2047 fprintf(stderr, "<invalid>"); 2048 break; 2049 } 2050 fprintf(stderr, "'\n"); 2051 } 2052 } 2053 2054 int 2055 pfctl_test_altqsupport(int dev, int opts) 2056 { 2057 struct pfioc_altq pa; 2058 2059 pa.version = PFIOC_ALTQ_VERSION; 2060 if (ioctl(dev, DIOCGETALTQS, &pa)) { 2061 if (errno == ENODEV) { 2062 if (opts & PF_OPT_VERBOSE) 2063 fprintf(stderr, "No ALTQ support in kernel\n" 2064 "ALTQ related functions disabled\n"); 2065 return (0); 2066 } else 2067 err(1, "DIOCGETALTQS"); 2068 } 2069 return (1); 2070 } 2071 2072 int 2073 pfctl_show_anchors(int dev, int opts, char *anchorname) 2074 { 2075 struct pfioc_ruleset pr; 2076 u_int32_t mnr, nr; 2077 2078 memset(&pr, 0, sizeof(pr)); 2079 memcpy(pr.path, anchorname, sizeof(pr.path)); 2080 if (ioctl(dev, DIOCGETRULESETS, &pr)) { 2081 if (errno == EINVAL) 2082 fprintf(stderr, "Anchor '%s' not found.\n", 2083 anchorname); 2084 else 2085 err(1, "DIOCGETRULESETS"); 2086 return (-1); 2087 } 2088 mnr = pr.nr; 2089 for (nr = 0; nr < mnr; ++nr) { 2090 char sub[MAXPATHLEN]; 2091 2092 pr.nr = nr; 2093 if (ioctl(dev, DIOCGETRULESET, &pr)) 2094 err(1, "DIOCGETRULESET"); 2095 if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) 2096 continue; 2097 sub[0] = 0; 2098 if (pr.path[0]) { 2099 strlcat(sub, pr.path, sizeof(sub)); 2100 strlcat(sub, "/", sizeof(sub)); 2101 } 2102 strlcat(sub, pr.name, sizeof(sub)); 2103 if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 2104 printf(" %s\n", sub); 2105 if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub)) 2106 return (-1); 2107 } 2108 return (0); 2109 } 2110 2111 const char * 2112 pfctl_lookup_option(char *cmd, const char * const *list) 2113 { 2114 if (cmd != NULL && *cmd) 2115 for (; *list; list++) 2116 if (!strncmp(cmd, *list, strlen(cmd))) 2117 return (*list); 2118 return (NULL); 2119 } 2120 2121 int 2122 main(int argc, char *argv[]) 2123 { 2124 int error = 0; 2125 int ch; 2126 int mode = O_RDONLY; 2127 int opts = 0; 2128 int optimize = PF_OPTIMIZE_BASIC; 2129 char anchorname[MAXPATHLEN]; 2130 char *path; 2131 2132 if (argc < 2) 2133 usage(); 2134 2135 while ((ch = getopt(argc, argv, 2136 "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:z")) != -1) { 2137 switch (ch) { 2138 case 'a': 2139 anchoropt = optarg; 2140 break; 2141 case 'd': 2142 opts |= PF_OPT_DISABLE; 2143 mode = O_RDWR; 2144 break; 2145 case 'D': 2146 if (pfctl_cmdline_symset(optarg) < 0) 2147 warnx("could not parse macro definition %s", 2148 optarg); 2149 break; 2150 case 'e': 2151 opts |= PF_OPT_ENABLE; 2152 mode = O_RDWR; 2153 break; 2154 case 'q': 2155 opts |= PF_OPT_QUIET; 2156 break; 2157 case 'F': 2158 clearopt = pfctl_lookup_option(optarg, clearopt_list); 2159 if (clearopt == NULL) { 2160 warnx("Unknown flush modifier '%s'", optarg); 2161 usage(); 2162 } 2163 mode = O_RDWR; 2164 break; 2165 case 'i': 2166 ifaceopt = optarg; 2167 break; 2168 case 'k': 2169 if (state_killers >= 2) { 2170 warnx("can only specify -k twice"); 2171 usage(); 2172 /* NOTREACHED */ 2173 } 2174 state_kill[state_killers++] = optarg; 2175 mode = O_RDWR; 2176 break; 2177 case 'K': 2178 if (src_node_killers >= 2) { 2179 warnx("can only specify -K twice"); 2180 usage(); 2181 /* NOTREACHED */ 2182 } 2183 src_node_kill[src_node_killers++] = optarg; 2184 mode = O_RDWR; 2185 break; 2186 case 'm': 2187 opts |= PF_OPT_MERGE; 2188 break; 2189 case 'n': 2190 opts |= PF_OPT_NOACTION; 2191 break; 2192 case 'N': 2193 loadopt |= PFCTL_FLAG_NAT; 2194 break; 2195 case 'r': 2196 opts |= PF_OPT_USEDNS; 2197 break; 2198 case 'f': 2199 rulesopt = optarg; 2200 mode = O_RDWR; 2201 break; 2202 case 'g': 2203 opts |= PF_OPT_DEBUG; 2204 break; 2205 case 'A': 2206 loadopt |= PFCTL_FLAG_ALTQ; 2207 break; 2208 case 'R': 2209 loadopt |= PFCTL_FLAG_FILTER; 2210 break; 2211 case 'o': 2212 optiopt = pfctl_lookup_option(optarg, optiopt_list); 2213 if (optiopt == NULL) { 2214 warnx("Unknown optimization '%s'", optarg); 2215 usage(); 2216 } 2217 opts |= PF_OPT_OPTIMIZE; 2218 break; 2219 case 'O': 2220 loadopt |= PFCTL_FLAG_OPTION; 2221 break; 2222 case 'p': 2223 pf_device = optarg; 2224 break; 2225 case 'P': 2226 opts |= PF_OPT_NUMERIC; 2227 break; 2228 case 's': 2229 showopt = pfctl_lookup_option(optarg, showopt_list); 2230 if (showopt == NULL) { 2231 warnx("Unknown show modifier '%s'", optarg); 2232 usage(); 2233 } 2234 break; 2235 case 't': 2236 tableopt = optarg; 2237 break; 2238 case 'T': 2239 tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 2240 if (tblcmdopt == NULL) { 2241 warnx("Unknown table command '%s'", optarg); 2242 usage(); 2243 } 2244 break; 2245 case 'v': 2246 if (opts & PF_OPT_VERBOSE) 2247 opts |= PF_OPT_VERBOSE2; 2248 opts |= PF_OPT_VERBOSE; 2249 break; 2250 case 'x': 2251 debugopt = pfctl_lookup_option(optarg, debugopt_list); 2252 if (debugopt == NULL) { 2253 warnx("Unknown debug level '%s'", optarg); 2254 usage(); 2255 } 2256 mode = O_RDWR; 2257 break; 2258 case 'z': 2259 opts |= PF_OPT_CLRRULECTRS; 2260 mode = O_RDWR; 2261 break; 2262 case 'h': 2263 /* FALLTHROUGH */ 2264 default: 2265 usage(); 2266 /* NOTREACHED */ 2267 } 2268 } 2269 2270 if (tblcmdopt != NULL) { 2271 argc -= optind; 2272 argv += optind; 2273 ch = *tblcmdopt; 2274 if (ch == 'l') { 2275 loadopt |= PFCTL_FLAG_TABLE; 2276 tblcmdopt = NULL; 2277 } else 2278 mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY; 2279 } else if (argc != optind) { 2280 warnx("unknown command line argument: %s ...", argv[optind]); 2281 usage(); 2282 /* NOTREACHED */ 2283 } 2284 if (loadopt == 0) 2285 loadopt = ~0; 2286 2287 if ((path = calloc(1, MAXPATHLEN)) == NULL) 2288 errx(1, "pfctl: calloc"); 2289 memset(anchorname, 0, sizeof(anchorname)); 2290 if (anchoropt != NULL) { 2291 int len = strlen(anchoropt); 2292 2293 if (anchoropt[len - 1] == '*') { 2294 if (len >= 2 && anchoropt[len - 2] == '/') 2295 anchoropt[len - 2] = '\0'; 2296 else 2297 anchoropt[len - 1] = '\0'; 2298 opts |= PF_OPT_RECURSE; 2299 } 2300 if (strlcpy(anchorname, anchoropt, 2301 sizeof(anchorname)) >= sizeof(anchorname)) 2302 errx(1, "anchor name '%s' too long", 2303 anchoropt); 2304 loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE; 2305 } 2306 2307 if ((opts & PF_OPT_NOACTION) == 0) { 2308 dev = open(pf_device, mode); 2309 if (dev == -1) 2310 err(1, "%s", pf_device); 2311 altqsupport = pfctl_test_altqsupport(dev, opts); 2312 } else { 2313 dev = open(pf_device, O_RDONLY); 2314 if (dev >= 0) 2315 opts |= PF_OPT_DUMMYACTION; 2316 /* turn off options */ 2317 opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 2318 clearopt = showopt = debugopt = NULL; 2319 #if !defined(ENABLE_ALTQ) 2320 altqsupport = 0; 2321 #else 2322 altqsupport = 1; 2323 #endif 2324 } 2325 2326 if (opts & PF_OPT_DISABLE) 2327 if (pfctl_disable(dev, opts)) 2328 error = 1; 2329 2330 if (showopt != NULL) { 2331 switch (*showopt) { 2332 case 'A': 2333 pfctl_show_anchors(dev, opts, anchorname); 2334 break; 2335 case 'r': 2336 pfctl_load_fingerprints(dev, opts); 2337 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 2338 anchorname, 0); 2339 break; 2340 case 'l': 2341 pfctl_load_fingerprints(dev, opts); 2342 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 2343 anchorname, 0); 2344 break; 2345 case 'n': 2346 pfctl_load_fingerprints(dev, opts); 2347 pfctl_show_nat(dev, opts, anchorname); 2348 break; 2349 case 'q': 2350 pfctl_show_altq(dev, ifaceopt, opts, 2351 opts & PF_OPT_VERBOSE2); 2352 break; 2353 case 's': 2354 pfctl_show_states(dev, ifaceopt, opts); 2355 break; 2356 case 'S': 2357 pfctl_show_src_nodes(dev, opts); 2358 break; 2359 case 'i': 2360 pfctl_show_status(dev, opts); 2361 break; 2362 case 'R': 2363 error = pfctl_show_running(dev); 2364 break; 2365 case 't': 2366 pfctl_show_timeouts(dev, opts); 2367 break; 2368 case 'm': 2369 pfctl_show_limits(dev, opts); 2370 break; 2371 case 'a': 2372 opts |= PF_OPT_SHOWALL; 2373 pfctl_load_fingerprints(dev, opts); 2374 2375 pfctl_show_nat(dev, opts, anchorname); 2376 pfctl_show_rules(dev, path, opts, 0, anchorname, 0); 2377 pfctl_show_altq(dev, ifaceopt, opts, 0); 2378 pfctl_show_states(dev, ifaceopt, opts); 2379 pfctl_show_src_nodes(dev, opts); 2380 pfctl_show_status(dev, opts); 2381 pfctl_show_rules(dev, path, opts, 1, anchorname, 0); 2382 pfctl_show_timeouts(dev, opts); 2383 pfctl_show_limits(dev, opts); 2384 pfctl_show_tables(anchorname, opts); 2385 pfctl_show_fingerprints(opts); 2386 break; 2387 case 'T': 2388 pfctl_show_tables(anchorname, opts); 2389 break; 2390 case 'o': 2391 pfctl_load_fingerprints(dev, opts); 2392 pfctl_show_fingerprints(opts); 2393 break; 2394 case 'I': 2395 pfctl_show_ifaces(ifaceopt, opts); 2396 break; 2397 } 2398 } 2399 2400 if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) 2401 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 2402 anchorname, 0); 2403 2404 if (clearopt != NULL) { 2405 if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 2406 errx(1, "anchor names beginning with '_' cannot " 2407 "be modified from the command line"); 2408 2409 switch (*clearopt) { 2410 case 'r': 2411 pfctl_clear_rules(dev, opts, anchorname); 2412 break; 2413 case 'n': 2414 pfctl_clear_nat(dev, opts, anchorname); 2415 break; 2416 case 'q': 2417 pfctl_clear_altq(dev, opts); 2418 break; 2419 case 's': 2420 pfctl_clear_states(dev, ifaceopt, opts); 2421 break; 2422 case 'S': 2423 pfctl_clear_src_nodes(dev, opts); 2424 break; 2425 case 'i': 2426 pfctl_clear_stats(dev, opts); 2427 break; 2428 case 'a': 2429 pfctl_clear_rules(dev, opts, anchorname); 2430 pfctl_clear_nat(dev, opts, anchorname); 2431 pfctl_clear_tables(anchorname, opts); 2432 if (!*anchorname) { 2433 pfctl_clear_altq(dev, opts); 2434 pfctl_clear_states(dev, ifaceopt, opts); 2435 pfctl_clear_src_nodes(dev, opts); 2436 pfctl_clear_stats(dev, opts); 2437 pfctl_clear_fingerprints(dev, opts); 2438 pfctl_clear_interface_flags(dev, opts); 2439 } 2440 break; 2441 case 'o': 2442 pfctl_clear_fingerprints(dev, opts); 2443 break; 2444 case 'T': 2445 pfctl_clear_tables(anchorname, opts); 2446 break; 2447 } 2448 } 2449 if (state_killers) { 2450 if (!strcmp(state_kill[0], "label")) 2451 pfctl_label_kill_states(dev, ifaceopt, opts); 2452 else if (!strcmp(state_kill[0], "id")) 2453 pfctl_id_kill_states(dev, ifaceopt, opts); 2454 else 2455 pfctl_net_kill_states(dev, ifaceopt, opts); 2456 } 2457 2458 if (src_node_killers) 2459 pfctl_kill_src_nodes(dev, ifaceopt, opts); 2460 2461 if (tblcmdopt != NULL) { 2462 error = pfctl_command_tables(argc, argv, tableopt, 2463 tblcmdopt, rulesopt, anchorname, opts); 2464 rulesopt = NULL; 2465 } 2466 if (optiopt != NULL) { 2467 switch (*optiopt) { 2468 case 'n': 2469 optimize = 0; 2470 break; 2471 case 'b': 2472 optimize |= PF_OPTIMIZE_BASIC; 2473 break; 2474 case 'o': 2475 case 'p': 2476 optimize |= PF_OPTIMIZE_PROFILE; 2477 break; 2478 } 2479 } 2480 2481 if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) && 2482 !anchorname[0] && !(opts & PF_OPT_NOACTION)) 2483 if (pfctl_get_skip_ifaces()) 2484 error = 1; 2485 2486 if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) && 2487 !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION)) 2488 if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 2489 error = 1; 2490 2491 if (rulesopt != NULL) { 2492 if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 2493 errx(1, "anchor names beginning with '_' cannot " 2494 "be modified from the command line"); 2495 if (pfctl_rules(dev, rulesopt, opts, optimize, 2496 anchorname, NULL)) 2497 error = 1; 2498 else if (!(opts & PF_OPT_NOACTION) && 2499 (loadopt & PFCTL_FLAG_TABLE)) 2500 warn_namespace_collision(NULL); 2501 } 2502 2503 if (opts & PF_OPT_ENABLE) 2504 if (pfctl_enable(dev, opts)) 2505 error = 1; 2506 2507 if (debugopt != NULL) { 2508 switch (*debugopt) { 2509 case 'n': 2510 pfctl_debug(dev, PF_DEBUG_NONE, opts); 2511 break; 2512 case 'u': 2513 pfctl_debug(dev, PF_DEBUG_URGENT, opts); 2514 break; 2515 case 'm': 2516 pfctl_debug(dev, PF_DEBUG_MISC, opts); 2517 break; 2518 case 'l': 2519 pfctl_debug(dev, PF_DEBUG_NOISY, opts); 2520 break; 2521 } 2522 } 2523 2524 exit(error); 2525 } 2526