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