pfctl.c revision 171172
1171172Smlaier/* $OpenBSD: pfctl.c,v 1.262 2007/03/01 17:20:53 deraadt Exp $ */ 2126353Smlaier 3126353Smlaier/* 4126353Smlaier * Copyright (c) 2001 Daniel Hartmeier 5130617Smlaier * Copyright (c) 2002,2003 Henning Brauer 6126353Smlaier * All rights reserved. 7126353Smlaier * 8126353Smlaier * Redistribution and use in source and binary forms, with or without 9126353Smlaier * modification, are permitted provided that the following conditions 10126353Smlaier * are met: 11126353Smlaier * 12126353Smlaier * - Redistributions of source code must retain the above copyright 13126353Smlaier * notice, this list of conditions and the following disclaimer. 14126353Smlaier * - Redistributions in binary form must reproduce the above 15126353Smlaier * copyright notice, this list of conditions and the following 16126353Smlaier * disclaimer in the documentation and/or other materials provided 17126353Smlaier * with the distribution. 18126353Smlaier * 19126353Smlaier * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20126353Smlaier * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21126353Smlaier * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22126353Smlaier * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23126353Smlaier * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24126353Smlaier * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25126353Smlaier * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26126353Smlaier * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27126353Smlaier * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28126353Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 29126353Smlaier * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30126353Smlaier * POSSIBILITY OF SUCH DAMAGE. 31126353Smlaier * 32126353Smlaier */ 33126353Smlaier 34127082Sobrien#include <sys/cdefs.h> 35127082Sobrien__FBSDID("$FreeBSD: head/contrib/pf/pfctl/pfctl.c 171172 2007-07-03 12:30:03Z mlaier $"); 36127082Sobrien 37126353Smlaier#include <sys/types.h> 38126353Smlaier#include <sys/ioctl.h> 39126353Smlaier#include <sys/socket.h> 40145840Smlaier#include <sys/stat.h> 41126353Smlaier 42126353Smlaier#include <net/if.h> 43126353Smlaier#include <netinet/in.h> 44126353Smlaier#include <net/pfvar.h> 45126353Smlaier#include <arpa/inet.h> 46126353Smlaier#include <altq/altq.h> 47171172Smlaier#include <sys/sysctl.h> 48126353Smlaier 49126353Smlaier#include <err.h> 50126353Smlaier#include <errno.h> 51126353Smlaier#include <fcntl.h> 52126353Smlaier#include <limits.h> 53126353Smlaier#include <netdb.h> 54126353Smlaier#include <stdio.h> 55126353Smlaier#include <stdlib.h> 56126353Smlaier#include <string.h> 57126353Smlaier#include <unistd.h> 58126353Smlaier 59126353Smlaier#include "pfctl_parser.h" 60126353Smlaier#include "pfctl.h" 61126353Smlaier 62130617Smlaier#ifdef __FreeBSD__ 63130617Smlaier#define HTONL(x) (x) = htonl((__uint32_t)(x)) 64130617Smlaier#endif 65130617Smlaier 66126353Smlaiervoid usage(void); 67126353Smlaierint pfctl_enable(int, int); 68126353Smlaierint pfctl_disable(int, int); 69126353Smlaierint pfctl_clear_stats(int, int); 70145840Smlaierint pfctl_clear_interface_flags(int, int); 71145840Smlaierint pfctl_clear_rules(int, int, char *); 72145840Smlaierint pfctl_clear_nat(int, int, char *); 73126353Smlaierint pfctl_clear_altq(int, int); 74130617Smlaierint pfctl_clear_src_nodes(int, int); 75130617Smlaierint pfctl_clear_states(int, const char *, int); 76171172Smlaiervoid pfctl_addrprefix(char *, struct pf_addr *); 77171172Smlaierint pfctl_kill_src_nodes(int, const char *, int); 78130617Smlaierint pfctl_kill_states(int, const char *, int); 79145840Smlaiervoid pfctl_init_options(struct pfctl *); 80145840Smlaierint pfctl_load_options(struct pfctl *); 81145840Smlaierint pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); 82145840Smlaierint pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); 83145840Smlaierint pfctl_load_debug(struct pfctl *, unsigned int); 84145840Smlaierint pfctl_load_logif(struct pfctl *, char *); 85145840Smlaierint pfctl_load_hostid(struct pfctl *, unsigned int); 86126353Smlaierint pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int, 87145840Smlaier char *); 88126353Smlaiervoid pfctl_print_rule_counters(struct pf_rule *, int); 89171172Smlaierint pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int); 90145840Smlaierint pfctl_show_nat(int, int, char *); 91130617Smlaierint pfctl_show_src_nodes(int, int); 92130617Smlaierint pfctl_show_states(int, const char *, int); 93130617Smlaierint pfctl_show_status(int, int); 94130617Smlaierint pfctl_show_timeouts(int, int); 95130617Smlaierint pfctl_show_limits(int, int); 96145840Smlaiervoid pfctl_debug(int, u_int32_t, int); 97126353Smlaierint pfctl_test_altqsupport(int, int); 98126353Smlaierint pfctl_show_anchors(int, int, char *); 99171172Smlaierint pfctl_ruleset_trans(struct pfctl *, char *, struct pf_anchor *); 100171172Smlaierint pfctl_load_ruleset(struct pfctl *, char *, 101171172Smlaier struct pf_ruleset *, int, int); 102171172Smlaierint pfctl_load_rule(struct pfctl *, char *, struct pf_rule *, int); 103126353Smlaierconst char *pfctl_lookup_option(char *, const char **); 104126353Smlaier 105171172Smlaierstruct pf_anchor_global pf_anchors; 106171172Smlaierstruct pf_anchor pf_main_anchor; 107171172Smlaier 108126353Smlaierconst char *clearopt; 109126353Smlaierchar *rulesopt; 110126353Smlaierconst char *showopt; 111126353Smlaierconst char *debugopt; 112126353Smlaierchar *anchoropt; 113171172Smlaierconst char *optiopt = NULL; 114130617Smlaierchar *pf_device = "/dev/pf"; 115130617Smlaierchar *ifaceopt; 116126353Smlaierchar *tableopt; 117126353Smlaierconst char *tblcmdopt; 118171172Smlaierint src_node_killers; 119171172Smlaierchar *src_node_kill[2]; 120126353Smlaierint state_killers; 121126353Smlaierchar *state_kill[2]; 122126353Smlaierint loadopt; 123126353Smlaierint altqsupport; 124126353Smlaier 125126353Smlaierint dev = -1; 126130617Smlaierint first_title = 1; 127130617Smlaierint labels = 0; 128126353Smlaier 129126353Smlaierconst char *infile; 130126353Smlaier 131171172Smlaier#define INDENT(d, o) do { \ 132171172Smlaier if (o) { \ 133171172Smlaier int i; \ 134171172Smlaier for (i=0; i < d; i++) \ 135171172Smlaier printf(" "); \ 136171172Smlaier } \ 137171172Smlaier } while (0); \ 138171172Smlaier 139171172Smlaier 140126353Smlaierstatic const struct { 141126353Smlaier const char *name; 142126353Smlaier int index; 143126353Smlaier} pf_limits[] = { 144171172Smlaier { "states", PF_LIMIT_STATES }, 145171172Smlaier { "src-nodes", PF_LIMIT_SRC_NODES }, 146171172Smlaier { "frags", PF_LIMIT_FRAGS }, 147171172Smlaier { "tables", PF_LIMIT_TABLES }, 148171172Smlaier { "table-entries", PF_LIMIT_TABLE_ENTRIES }, 149171172Smlaier { NULL, 0 } 150126353Smlaier}; 151126353Smlaier 152126353Smlaierstruct pf_hint { 153126353Smlaier const char *name; 154126353Smlaier int timeout; 155126353Smlaier}; 156126353Smlaierstatic const struct pf_hint pf_hint_normal[] = { 157126353Smlaier { "tcp.first", 2 * 60 }, 158126353Smlaier { "tcp.opening", 30 }, 159126353Smlaier { "tcp.established", 24 * 60 * 60 }, 160126353Smlaier { "tcp.closing", 15 * 60 }, 161126353Smlaier { "tcp.finwait", 45 }, 162126353Smlaier { "tcp.closed", 90 }, 163145840Smlaier { "tcp.tsdiff", 30 }, 164126353Smlaier { NULL, 0 } 165126353Smlaier}; 166126353Smlaierstatic const struct pf_hint pf_hint_satellite[] = { 167126353Smlaier { "tcp.first", 3 * 60 }, 168126353Smlaier { "tcp.opening", 30 + 5 }, 169126353Smlaier { "tcp.established", 24 * 60 * 60 }, 170126353Smlaier { "tcp.closing", 15 * 60 + 5 }, 171126353Smlaier { "tcp.finwait", 45 + 5 }, 172126353Smlaier { "tcp.closed", 90 + 5 }, 173145840Smlaier { "tcp.tsdiff", 60 }, 174126353Smlaier { NULL, 0 } 175126353Smlaier}; 176126353Smlaierstatic const struct pf_hint pf_hint_conservative[] = { 177126353Smlaier { "tcp.first", 60 * 60 }, 178126353Smlaier { "tcp.opening", 15 * 60 }, 179126353Smlaier { "tcp.established", 5 * 24 * 60 * 60 }, 180126353Smlaier { "tcp.closing", 60 * 60 }, 181126353Smlaier { "tcp.finwait", 10 * 60 }, 182126353Smlaier { "tcp.closed", 3 * 60 }, 183145840Smlaier { "tcp.tsdiff", 60 }, 184126353Smlaier { NULL, 0 } 185126353Smlaier}; 186126353Smlaierstatic const struct pf_hint pf_hint_aggressive[] = { 187126353Smlaier { "tcp.first", 30 }, 188126353Smlaier { "tcp.opening", 5 }, 189126353Smlaier { "tcp.established", 5 * 60 * 60 }, 190126353Smlaier { "tcp.closing", 60 }, 191126353Smlaier { "tcp.finwait", 30 }, 192126353Smlaier { "tcp.closed", 30 }, 193145840Smlaier { "tcp.tsdiff", 10 }, 194126353Smlaier { NULL, 0 } 195126353Smlaier}; 196126353Smlaier 197126353Smlaierstatic const struct { 198126353Smlaier const char *name; 199126353Smlaier const struct pf_hint *hint; 200126353Smlaier} pf_hints[] = { 201126353Smlaier { "normal", pf_hint_normal }, 202126353Smlaier { "satellite", pf_hint_satellite }, 203126353Smlaier { "high-latency", pf_hint_satellite }, 204126353Smlaier { "conservative", pf_hint_conservative }, 205126353Smlaier { "aggressive", pf_hint_aggressive }, 206126353Smlaier { NULL, NULL } 207126353Smlaier}; 208126353Smlaier 209126353Smlaierstatic const char *clearopt_list[] = { 210130617Smlaier "nat", "queue", "rules", "Sources", 211130617Smlaier "state", "info", "Tables", "osfp", "all", NULL 212126353Smlaier}; 213126353Smlaier 214126353Smlaierstatic const char *showopt_list[] = { 215130617Smlaier "nat", "queue", "rules", "Anchors", "Sources", "state", "info", 216130617Smlaier "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp", 217130617Smlaier "all", NULL 218126353Smlaier}; 219126353Smlaier 220126353Smlaierstatic const char *tblcmdopt_list[] = { 221126353Smlaier "kill", "flush", "add", "delete", "load", "replace", "show", 222171172Smlaier "test", "zero", "expire", NULL 223126353Smlaier}; 224126353Smlaier 225126353Smlaierstatic const char *debugopt_list[] = { 226126353Smlaier "none", "urgent", "misc", "loud", NULL 227126353Smlaier}; 228126353Smlaier 229171172Smlaierstatic const char *optiopt_list[] = { 230171172Smlaier "o", "none", "basic", "profile", NULL 231171172Smlaier}; 232126353Smlaier 233126353Smlaiervoid 234126353Smlaierusage(void) 235126353Smlaier{ 236126353Smlaier extern char *__progname; 237126353Smlaier 238171172Smlaier fprintf(stderr, "usage: %s [-AdeghmNnOqRrvz] ", __progname); 239145840Smlaier fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n"); 240171172Smlaier fprintf(stderr, "\t[-f file] [-i interface] [-K host | network] "); 241171172Smlaier fprintf(stderr, "[-k host | network ]\n"); 242171172Smlaier fprintf(stderr, "\t[-o [level]] [-p device] [-s modifier ]\n"); 243171172Smlaier fprintf(stderr, "\t[-t table -T command [address ...]] [-x level]\n"); 244126353Smlaier exit(1); 245126353Smlaier} 246126353Smlaier 247126353Smlaierint 248126353Smlaierpfctl_enable(int dev, int opts) 249126353Smlaier{ 250126353Smlaier if (ioctl(dev, DIOCSTART)) { 251126353Smlaier if (errno == EEXIST) 252126353Smlaier errx(1, "pf already enabled"); 253127024Smlaier#ifdef __FreeBSD__ 254126355Smlaier else if (errno == ESRCH) 255126355Smlaier errx(1, "pfil registeration failed"); 256126355Smlaier#endif 257126353Smlaier else 258126353Smlaier err(1, "DIOCSTART"); 259126353Smlaier } 260126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 261126353Smlaier fprintf(stderr, "pf enabled\n"); 262126353Smlaier 263126353Smlaier if (altqsupport && ioctl(dev, DIOCSTARTALTQ)) 264126353Smlaier if (errno != EEXIST) 265126353Smlaier err(1, "DIOCSTARTALTQ"); 266126353Smlaier 267126353Smlaier return (0); 268126353Smlaier} 269126353Smlaier 270126353Smlaierint 271126353Smlaierpfctl_disable(int dev, int opts) 272126353Smlaier{ 273126353Smlaier if (ioctl(dev, DIOCSTOP)) { 274126353Smlaier if (errno == ENOENT) 275126353Smlaier errx(1, "pf not enabled"); 276126353Smlaier else 277126353Smlaier err(1, "DIOCSTOP"); 278126353Smlaier } 279126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 280126353Smlaier fprintf(stderr, "pf disabled\n"); 281126353Smlaier 282126353Smlaier if (altqsupport && ioctl(dev, DIOCSTOPALTQ)) 283126353Smlaier if (errno != ENOENT) 284126353Smlaier err(1, "DIOCSTOPALTQ"); 285126353Smlaier 286126353Smlaier return (0); 287126353Smlaier} 288126353Smlaier 289126353Smlaierint 290126353Smlaierpfctl_clear_stats(int dev, int opts) 291126353Smlaier{ 292126353Smlaier if (ioctl(dev, DIOCCLRSTATUS)) 293126353Smlaier err(1, "DIOCCLRSTATUS"); 294126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 295126353Smlaier fprintf(stderr, "pf: statistics cleared\n"); 296126353Smlaier return (0); 297126353Smlaier} 298126353Smlaier 299126353Smlaierint 300145840Smlaierpfctl_clear_interface_flags(int dev, int opts) 301126353Smlaier{ 302145840Smlaier struct pfioc_iface pi; 303126353Smlaier 304145840Smlaier if ((opts & PF_OPT_NOACTION) == 0) { 305145840Smlaier bzero(&pi, sizeof(pi)); 306171172Smlaier pi.pfiio_flags = PFI_IFLAG_SKIP; 307126353Smlaier 308145840Smlaier if (ioctl(dev, DIOCCLRIFFLAG, &pi)) 309145840Smlaier err(1, "DIOCCLRIFFLAG"); 310126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 311145840Smlaier fprintf(stderr, "pf: interface flags reset\n"); 312126353Smlaier } 313145840Smlaier return (0); 314145840Smlaier} 315145840Smlaier 316145840Smlaierint 317145840Smlaierpfctl_clear_rules(int dev, int opts, char *anchorname) 318145840Smlaier{ 319145840Smlaier struct pfr_buffer t; 320145840Smlaier 321130617Smlaier memset(&t, 0, sizeof(t)); 322130617Smlaier t.pfrb_type = PFRB_TRANS; 323145840Smlaier if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname) || 324145840Smlaier pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) || 325130617Smlaier pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 326130617Smlaier pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 327130617Smlaier err(1, "pfctl_clear_rules"); 328126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 329126353Smlaier fprintf(stderr, "rules cleared\n"); 330126353Smlaier return (0); 331126353Smlaier} 332126353Smlaier 333126353Smlaierint 334145840Smlaierpfctl_clear_nat(int dev, int opts, char *anchorname) 335126353Smlaier{ 336130617Smlaier struct pfr_buffer t; 337126353Smlaier 338130617Smlaier memset(&t, 0, sizeof(t)); 339130617Smlaier t.pfrb_type = PFRB_TRANS; 340145840Smlaier if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname) || 341145840Smlaier pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname) || 342145840Smlaier pfctl_add_trans(&t, PF_RULESET_RDR, anchorname) || 343130617Smlaier pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 344130617Smlaier pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 345130617Smlaier err(1, "pfctl_clear_nat"); 346126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 347126353Smlaier fprintf(stderr, "nat cleared\n"); 348126353Smlaier return (0); 349126353Smlaier} 350126353Smlaier 351126353Smlaierint 352126353Smlaierpfctl_clear_altq(int dev, int opts) 353126353Smlaier{ 354130617Smlaier struct pfr_buffer t; 355126353Smlaier 356126353Smlaier if (!altqsupport) 357126353Smlaier return (-1); 358130617Smlaier memset(&t, 0, sizeof(t)); 359130617Smlaier t.pfrb_type = PFRB_TRANS; 360145840Smlaier if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") || 361130617Smlaier pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 362130617Smlaier pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 363130617Smlaier err(1, "pfctl_clear_altq"); 364126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 365126353Smlaier fprintf(stderr, "altq cleared\n"); 366126353Smlaier return (0); 367126353Smlaier} 368126353Smlaier 369126353Smlaierint 370130617Smlaierpfctl_clear_src_nodes(int dev, int opts) 371126353Smlaier{ 372130617Smlaier if (ioctl(dev, DIOCCLRSRCNODES)) 373130617Smlaier err(1, "DIOCCLRSRCNODES"); 374130617Smlaier if ((opts & PF_OPT_QUIET) == 0) 375130617Smlaier fprintf(stderr, "source tracking entries cleared\n"); 376130617Smlaier return (0); 377130617Smlaier} 378130617Smlaier 379130617Smlaierint 380130617Smlaierpfctl_clear_states(int dev, const char *iface, int opts) 381130617Smlaier{ 382130617Smlaier struct pfioc_state_kill psk; 383130617Smlaier 384130617Smlaier memset(&psk, 0, sizeof(psk)); 385130617Smlaier if (iface != NULL && strlcpy(psk.psk_ifname, iface, 386130617Smlaier sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 387130617Smlaier errx(1, "invalid interface: %s", iface); 388130617Smlaier 389130617Smlaier if (ioctl(dev, DIOCCLRSTATES, &psk)) 390126353Smlaier err(1, "DIOCCLRSTATES"); 391126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 392130617Smlaier fprintf(stderr, "%d states cleared\n", psk.psk_af); 393126353Smlaier return (0); 394126353Smlaier} 395126353Smlaier 396171172Smlaiervoid 397171172Smlaierpfctl_addrprefix(char *addr, struct pf_addr *mask) 398171172Smlaier{ 399171172Smlaier char *p; 400171172Smlaier const char *errstr; 401171172Smlaier int prefix, ret_ga, q, r; 402171172Smlaier struct addrinfo hints, *res; 403171172Smlaier 404171172Smlaier if ((p = strchr(addr, '/')) == NULL) 405171172Smlaier return; 406171172Smlaier 407171172Smlaier *p++ = '\0'; 408171172Smlaier prefix = strtonum(p, 0, 128, &errstr); 409171172Smlaier if (errstr) 410171172Smlaier errx(1, "prefix is %s: %s", errstr, p); 411171172Smlaier 412171172Smlaier bzero(&hints, sizeof(hints)); 413171172Smlaier /* prefix only with numeric addresses */ 414171172Smlaier hints.ai_flags |= AI_NUMERICHOST; 415171172Smlaier 416171172Smlaier if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) { 417171172Smlaier errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 418171172Smlaier /* NOTREACHED */ 419171172Smlaier } 420171172Smlaier 421171172Smlaier if (res->ai_family == AF_INET && prefix > 32) 422171172Smlaier errx(1, "prefix too long for AF_INET"); 423171172Smlaier else if (res->ai_family == AF_INET6 && prefix > 128) 424171172Smlaier errx(1, "prefix too long for AF_INET6"); 425171172Smlaier 426171172Smlaier q = prefix >> 3; 427171172Smlaier r = prefix & 7; 428171172Smlaier switch (res->ai_family) { 429171172Smlaier case AF_INET: 430171172Smlaier bzero(&mask->v4, sizeof(mask->v4)); 431171172Smlaier mask->v4.s_addr = htonl((u_int32_t) 432171172Smlaier (0xffffffffffULL << (32 - prefix))); 433171172Smlaier break; 434171172Smlaier case AF_INET6: 435171172Smlaier bzero(&mask->v6, sizeof(mask->v6)); 436171172Smlaier if (q > 0) 437171172Smlaier memset((void *)&mask->v6, 0xff, q); 438171172Smlaier if (r > 0) 439171172Smlaier *((u_char *)&mask->v6 + q) = 440171172Smlaier (0xff00 >> r) & 0xff; 441171172Smlaier break; 442171172Smlaier } 443171172Smlaier freeaddrinfo(res); 444171172Smlaier} 445171172Smlaier 446126353Smlaierint 447171172Smlaierpfctl_kill_src_nodes(int dev, const char *iface, int opts) 448171172Smlaier{ 449171172Smlaier struct pfioc_src_node_kill psnk; 450171172Smlaier struct addrinfo *res[2], *resp[2]; 451171172Smlaier struct sockaddr last_src, last_dst; 452171172Smlaier int killed, sources, dests; 453171172Smlaier int ret_ga; 454171172Smlaier 455171172Smlaier killed = sources = dests = 0; 456171172Smlaier 457171172Smlaier memset(&psnk, 0, sizeof(psnk)); 458171172Smlaier memset(&psnk.psnk_src.addr.v.a.mask, 0xff, 459171172Smlaier sizeof(psnk.psnk_src.addr.v.a.mask)); 460171172Smlaier memset(&last_src, 0xff, sizeof(last_src)); 461171172Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 462171172Smlaier 463171172Smlaier pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask); 464171172Smlaier 465171172Smlaier if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) { 466171172Smlaier errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 467171172Smlaier /* NOTREACHED */ 468171172Smlaier } 469171172Smlaier for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 470171172Smlaier if (resp[0]->ai_addr == NULL) 471171172Smlaier continue; 472171172Smlaier /* We get lots of duplicates. Catch the easy ones */ 473171172Smlaier if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 474171172Smlaier continue; 475171172Smlaier last_src = *(struct sockaddr *)resp[0]->ai_addr; 476171172Smlaier 477171172Smlaier psnk.psnk_af = resp[0]->ai_family; 478171172Smlaier sources++; 479171172Smlaier 480171172Smlaier if (psnk.psnk_af == AF_INET) 481171172Smlaier psnk.psnk_src.addr.v.a.addr.v4 = 482171172Smlaier ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 483171172Smlaier else if (psnk.psnk_af == AF_INET6) 484171172Smlaier psnk.psnk_src.addr.v.a.addr.v6 = 485171172Smlaier ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 486171172Smlaier sin6_addr; 487171172Smlaier else 488171172Smlaier errx(1, "Unknown address family %d", psnk.psnk_af); 489171172Smlaier 490171172Smlaier if (src_node_killers > 1) { 491171172Smlaier dests = 0; 492171172Smlaier memset(&psnk.psnk_dst.addr.v.a.mask, 0xff, 493171172Smlaier sizeof(psnk.psnk_dst.addr.v.a.mask)); 494171172Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 495171172Smlaier pfctl_addrprefix(src_node_kill[1], 496171172Smlaier &psnk.psnk_dst.addr.v.a.mask); 497171172Smlaier if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL, 498171172Smlaier &res[1]))) { 499171172Smlaier errx(1, "getaddrinfo: %s", 500171172Smlaier gai_strerror(ret_ga)); 501171172Smlaier /* NOTREACHED */ 502171172Smlaier } 503171172Smlaier for (resp[1] = res[1]; resp[1]; 504171172Smlaier resp[1] = resp[1]->ai_next) { 505171172Smlaier if (resp[1]->ai_addr == NULL) 506171172Smlaier continue; 507171172Smlaier if (psnk.psnk_af != resp[1]->ai_family) 508171172Smlaier continue; 509171172Smlaier 510171172Smlaier if (memcmp(&last_dst, resp[1]->ai_addr, 511171172Smlaier sizeof(last_dst)) == 0) 512171172Smlaier continue; 513171172Smlaier last_dst = *(struct sockaddr *)resp[1]->ai_addr; 514171172Smlaier 515171172Smlaier dests++; 516171172Smlaier 517171172Smlaier if (psnk.psnk_af == AF_INET) 518171172Smlaier psnk.psnk_dst.addr.v.a.addr.v4 = 519171172Smlaier ((struct sockaddr_in *)resp[1]-> 520171172Smlaier ai_addr)->sin_addr; 521171172Smlaier else if (psnk.psnk_af == AF_INET6) 522171172Smlaier psnk.psnk_dst.addr.v.a.addr.v6 = 523171172Smlaier ((struct sockaddr_in6 *)resp[1]-> 524171172Smlaier ai_addr)->sin6_addr; 525171172Smlaier else 526171172Smlaier errx(1, "Unknown address family %d", 527171172Smlaier psnk.psnk_af); 528171172Smlaier 529171172Smlaier if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 530171172Smlaier err(1, "DIOCKILLSRCNODES"); 531171172Smlaier killed += psnk.psnk_af; 532171172Smlaier /* fixup psnk.psnk_af */ 533171172Smlaier psnk.psnk_af = resp[1]->ai_family; 534171172Smlaier } 535171172Smlaier freeaddrinfo(res[1]); 536171172Smlaier } else { 537171172Smlaier if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 538171172Smlaier err(1, "DIOCKILLSRCNODES"); 539171172Smlaier killed += psnk.psnk_af; 540171172Smlaier /* fixup psnk.psnk_af */ 541171172Smlaier psnk.psnk_af = res[0]->ai_family; 542171172Smlaier } 543171172Smlaier } 544171172Smlaier 545171172Smlaier freeaddrinfo(res[0]); 546171172Smlaier 547171172Smlaier if ((opts & PF_OPT_QUIET) == 0) 548171172Smlaier fprintf(stderr, "killed %d src nodes from %d sources and %d " 549171172Smlaier "destinations\n", killed, sources, dests); 550171172Smlaier return (0); 551171172Smlaier} 552171172Smlaier 553171172Smlaierint 554130617Smlaierpfctl_kill_states(int dev, const char *iface, int opts) 555126353Smlaier{ 556126353Smlaier struct pfioc_state_kill psk; 557126353Smlaier struct addrinfo *res[2], *resp[2]; 558126353Smlaier struct sockaddr last_src, last_dst; 559126353Smlaier int killed, sources, dests; 560126353Smlaier int ret_ga; 561126353Smlaier 562126353Smlaier killed = sources = dests = 0; 563126353Smlaier 564126353Smlaier memset(&psk, 0, sizeof(psk)); 565126353Smlaier memset(&psk.psk_src.addr.v.a.mask, 0xff, 566126353Smlaier sizeof(psk.psk_src.addr.v.a.mask)); 567126353Smlaier memset(&last_src, 0xff, sizeof(last_src)); 568126353Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 569130617Smlaier if (iface != NULL && strlcpy(psk.psk_ifname, iface, 570130617Smlaier sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 571130617Smlaier errx(1, "invalid interface: %s", iface); 572126353Smlaier 573171172Smlaier pfctl_addrprefix(state_kill[0], &psk.psk_src.addr.v.a.mask); 574171172Smlaier 575126353Smlaier if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) { 576126353Smlaier errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 577126353Smlaier /* NOTREACHED */ 578126353Smlaier } 579126353Smlaier for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 580126353Smlaier if (resp[0]->ai_addr == NULL) 581126353Smlaier continue; 582126353Smlaier /* We get lots of duplicates. Catch the easy ones */ 583126353Smlaier if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 584126353Smlaier continue; 585126353Smlaier last_src = *(struct sockaddr *)resp[0]->ai_addr; 586126353Smlaier 587126353Smlaier psk.psk_af = resp[0]->ai_family; 588126353Smlaier sources++; 589126353Smlaier 590126353Smlaier if (psk.psk_af == AF_INET) 591126353Smlaier psk.psk_src.addr.v.a.addr.v4 = 592126353Smlaier ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 593126353Smlaier else if (psk.psk_af == AF_INET6) 594126353Smlaier psk.psk_src.addr.v.a.addr.v6 = 595126353Smlaier ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 596126353Smlaier sin6_addr; 597126353Smlaier else 598126353Smlaier errx(1, "Unknown address family %d", psk.psk_af); 599126353Smlaier 600126353Smlaier if (state_killers > 1) { 601126353Smlaier dests = 0; 602126353Smlaier memset(&psk.psk_dst.addr.v.a.mask, 0xff, 603126353Smlaier sizeof(psk.psk_dst.addr.v.a.mask)); 604126353Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 605171172Smlaier pfctl_addrprefix(state_kill[1], 606171172Smlaier &psk.psk_dst.addr.v.a.mask); 607126353Smlaier if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, 608126353Smlaier &res[1]))) { 609130617Smlaier errx(1, "getaddrinfo: %s", 610130617Smlaier gai_strerror(ret_ga)); 611126353Smlaier /* NOTREACHED */ 612126353Smlaier } 613126353Smlaier for (resp[1] = res[1]; resp[1]; 614126353Smlaier resp[1] = resp[1]->ai_next) { 615126353Smlaier if (resp[1]->ai_addr == NULL) 616126353Smlaier continue; 617126353Smlaier if (psk.psk_af != resp[1]->ai_family) 618126353Smlaier continue; 619126353Smlaier 620126353Smlaier if (memcmp(&last_dst, resp[1]->ai_addr, 621126353Smlaier sizeof(last_dst)) == 0) 622126353Smlaier continue; 623126353Smlaier last_dst = *(struct sockaddr *)resp[1]->ai_addr; 624126353Smlaier 625126353Smlaier dests++; 626126353Smlaier 627126353Smlaier if (psk.psk_af == AF_INET) 628126353Smlaier psk.psk_dst.addr.v.a.addr.v4 = 629126353Smlaier ((struct sockaddr_in *)resp[1]-> 630126353Smlaier ai_addr)->sin_addr; 631126353Smlaier else if (psk.psk_af == AF_INET6) 632126353Smlaier psk.psk_dst.addr.v.a.addr.v6 = 633126353Smlaier ((struct sockaddr_in6 *)resp[1]-> 634126353Smlaier ai_addr)->sin6_addr; 635126353Smlaier else 636126353Smlaier errx(1, "Unknown address family %d", 637126353Smlaier psk.psk_af); 638126353Smlaier 639126353Smlaier if (ioctl(dev, DIOCKILLSTATES, &psk)) 640126353Smlaier err(1, "DIOCKILLSTATES"); 641126353Smlaier killed += psk.psk_af; 642126353Smlaier /* fixup psk.psk_af */ 643126353Smlaier psk.psk_af = resp[1]->ai_family; 644126353Smlaier } 645126353Smlaier freeaddrinfo(res[1]); 646126353Smlaier } else { 647126353Smlaier if (ioctl(dev, DIOCKILLSTATES, &psk)) 648126353Smlaier err(1, "DIOCKILLSTATES"); 649126353Smlaier killed += psk.psk_af; 650126353Smlaier /* fixup psk.psk_af */ 651126353Smlaier psk.psk_af = res[0]->ai_family; 652126353Smlaier } 653126353Smlaier } 654126353Smlaier 655126353Smlaier freeaddrinfo(res[0]); 656126353Smlaier 657126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 658126353Smlaier fprintf(stderr, "killed %d states from %d sources and %d " 659126353Smlaier "destinations\n", killed, sources, dests); 660126353Smlaier return (0); 661126353Smlaier} 662126353Smlaier 663126353Smlaierint 664126353Smlaierpfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr, 665145840Smlaier u_int32_t ticket, int r_action, char *anchorname) 666126353Smlaier{ 667126353Smlaier struct pfioc_pooladdr pp; 668126353Smlaier struct pf_pooladdr *pa; 669126353Smlaier u_int32_t pnr, mpnr; 670126353Smlaier 671126353Smlaier memset(&pp, 0, sizeof(pp)); 672126353Smlaier memcpy(pp.anchor, anchorname, sizeof(pp.anchor)); 673126353Smlaier pp.r_action = r_action; 674126353Smlaier pp.r_num = nr; 675126353Smlaier pp.ticket = ticket; 676126353Smlaier if (ioctl(dev, DIOCGETADDRS, &pp)) { 677126353Smlaier warn("DIOCGETADDRS"); 678126353Smlaier return (-1); 679126353Smlaier } 680126353Smlaier mpnr = pp.nr; 681126353Smlaier TAILQ_INIT(&pool->list); 682126353Smlaier for (pnr = 0; pnr < mpnr; ++pnr) { 683126353Smlaier pp.nr = pnr; 684126353Smlaier if (ioctl(dev, DIOCGETADDR, &pp)) { 685126353Smlaier warn("DIOCGETADDR"); 686126353Smlaier return (-1); 687126353Smlaier } 688126353Smlaier pa = calloc(1, sizeof(struct pf_pooladdr)); 689126353Smlaier if (pa == NULL) 690126353Smlaier err(1, "calloc"); 691126353Smlaier bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr)); 692126353Smlaier TAILQ_INSERT_TAIL(&pool->list, pa, entries); 693126353Smlaier } 694126353Smlaier 695126353Smlaier return (0); 696126353Smlaier} 697126353Smlaier 698126353Smlaiervoid 699171172Smlaierpfctl_move_pool(struct pf_pool *src, struct pf_pool *dst) 700171172Smlaier{ 701171172Smlaier struct pf_pooladdr *pa; 702171172Smlaier 703171172Smlaier while ((pa = TAILQ_FIRST(&src->list)) != NULL) { 704171172Smlaier TAILQ_REMOVE(&src->list, pa, entries); 705171172Smlaier TAILQ_INSERT_TAIL(&dst->list, pa, entries); 706171172Smlaier } 707171172Smlaier} 708171172Smlaier 709171172Smlaiervoid 710126353Smlaierpfctl_clear_pool(struct pf_pool *pool) 711126353Smlaier{ 712126353Smlaier struct pf_pooladdr *pa; 713126353Smlaier 714126353Smlaier while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { 715126353Smlaier TAILQ_REMOVE(&pool->list, pa, entries); 716126353Smlaier free(pa); 717126353Smlaier } 718126353Smlaier} 719126353Smlaier 720126353Smlaiervoid 721126353Smlaierpfctl_print_rule_counters(struct pf_rule *rule, int opts) 722126353Smlaier{ 723126353Smlaier if (opts & PF_OPT_DEBUG) { 724126353Smlaier const char *t[PF_SKIP_COUNT] = { "i", "d", "f", 725126353Smlaier "p", "sa", "sp", "da", "dp" }; 726126353Smlaier int i; 727126353Smlaier 728126353Smlaier printf(" [ Skip steps: "); 729126353Smlaier for (i = 0; i < PF_SKIP_COUNT; ++i) { 730126353Smlaier if (rule->skip[i].nr == rule->nr + 1) 731126353Smlaier continue; 732126353Smlaier printf("%s=", t[i]); 733126353Smlaier if (rule->skip[i].nr == -1) 734126353Smlaier printf("end "); 735126353Smlaier else 736126353Smlaier printf("%u ", rule->skip[i].nr); 737126353Smlaier } 738126353Smlaier printf("]\n"); 739126353Smlaier 740126353Smlaier printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n", 741126353Smlaier rule->qname, rule->qid, rule->pqname, rule->pqid); 742126353Smlaier } 743171172Smlaier if (opts & PF_OPT_VERBOSE) { 744127024Smlaier printf(" [ Evaluations: %-8llu Packets: %-8llu " 745127024Smlaier "Bytes: %-10llu States: %-6u]\n", 746127024Smlaier (unsigned long long)rule->evaluations, 747171172Smlaier (unsigned long long)(rule->packets[0] + 748171172Smlaier rule->packets[1]), 749171172Smlaier (unsigned long long)(rule->bytes[0] + 750171172Smlaier rule->bytes[1]), rule->states); 751171172Smlaier if (!(opts & PF_OPT_DEBUG)) 752171172Smlaier printf(" [ Inserted: uid %u pid %u ]\n", 753171172Smlaier (unsigned)rule->cuid, (unsigned)rule->cpid); 754171172Smlaier } 755126353Smlaier} 756126353Smlaier 757130617Smlaiervoid 758130617Smlaierpfctl_print_title(char *title) 759130617Smlaier{ 760130617Smlaier if (!first_title) 761130617Smlaier printf("\n"); 762130617Smlaier first_title = 0; 763130617Smlaier printf("%s\n", title); 764130617Smlaier} 765130617Smlaier 766126353Smlaierint 767171172Smlaierpfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, 768171172Smlaier char *anchorname, int depth) 769126353Smlaier{ 770126353Smlaier struct pfioc_rule pr; 771130617Smlaier u_int32_t nr, mnr, header = 0; 772126353Smlaier int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); 773171172Smlaier int len = strlen(path); 774171172Smlaier int brace; 775171172Smlaier char *p; 776126353Smlaier 777171172Smlaier if (path[0]) 778171172Smlaier snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 779171172Smlaier else 780171172Smlaier snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 781171172Smlaier 782126353Smlaier memset(&pr, 0, sizeof(pr)); 783171172Smlaier memcpy(pr.anchor, path, sizeof(pr.anchor)); 784130617Smlaier if (opts & PF_OPT_SHOWALL) { 785130617Smlaier pr.rule.action = PF_PASS; 786130617Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 787130617Smlaier warn("DIOCGETRULES"); 788171172Smlaier goto error; 789130617Smlaier } 790130617Smlaier header++; 791130617Smlaier } 792126353Smlaier pr.rule.action = PF_SCRUB; 793126353Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 794126353Smlaier warn("DIOCGETRULES"); 795171172Smlaier goto error; 796126353Smlaier } 797130617Smlaier if (opts & PF_OPT_SHOWALL) { 798171172Smlaier if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header)) 799130617Smlaier pfctl_print_title("FILTER RULES:"); 800171172Smlaier else if (format == PFCTL_SHOW_LABELS && labels) 801130617Smlaier pfctl_print_title("LABEL COUNTERS:"); 802130617Smlaier } 803126353Smlaier mnr = pr.nr; 804171172Smlaier if (opts & PF_OPT_CLRRULECTRS) 805171172Smlaier pr.action = PF_GET_CLR_CNTR; 806171172Smlaier 807126353Smlaier for (nr = 0; nr < mnr; ++nr) { 808126353Smlaier pr.nr = nr; 809126353Smlaier if (ioctl(dev, DIOCGETRULE, &pr)) { 810126353Smlaier warn("DIOCGETRULE"); 811171172Smlaier goto error; 812126353Smlaier } 813126353Smlaier 814126353Smlaier if (pfctl_get_pool(dev, &pr.rule.rpool, 815171172Smlaier nr, pr.ticket, PF_SCRUB, path) != 0) 816171172Smlaier goto error; 817126353Smlaier 818126353Smlaier switch (format) { 819171172Smlaier case PFCTL_SHOW_LABELS: 820126353Smlaier if (pr.rule.label[0]) { 821126353Smlaier printf("%s ", pr.rule.label); 822171172Smlaier printf("%llu %llu %llu %llu %llu %llu %llu\n", 823127024Smlaier (unsigned long long)pr.rule.evaluations, 824171172Smlaier (unsigned long long)(pr.rule.packets[0] + 825171172Smlaier pr.rule.packets[1]), 826171172Smlaier (unsigned long long)(pr.rule.bytes[0] + 827171172Smlaier pr.rule.bytes[1]), 828171172Smlaier (unsigned long long)pr.rule.packets[0], 829171172Smlaier (unsigned long long)pr.rule.bytes[0], 830171172Smlaier (unsigned long long)pr.rule.packets[1], 831171172Smlaier (unsigned long long)pr.rule.bytes[1]); 832126353Smlaier } 833126353Smlaier break; 834171172Smlaier case PFCTL_SHOW_RULES: 835130617Smlaier if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) 836130617Smlaier labels = 1; 837145840Smlaier print_rule(&pr.rule, pr.anchor_call, rule_numbers); 838171172Smlaier printf("\n"); 839126353Smlaier pfctl_print_rule_counters(&pr.rule, opts); 840171172Smlaier break; 841171172Smlaier case PFCTL_SHOW_NOTHING: 842171172Smlaier break; 843126353Smlaier } 844126353Smlaier pfctl_clear_pool(&pr.rule.rpool); 845126353Smlaier } 846126353Smlaier pr.rule.action = PF_PASS; 847126353Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 848126353Smlaier warn("DIOCGETRULES"); 849171172Smlaier goto error; 850126353Smlaier } 851126353Smlaier mnr = pr.nr; 852126353Smlaier for (nr = 0; nr < mnr; ++nr) { 853126353Smlaier pr.nr = nr; 854126353Smlaier if (ioctl(dev, DIOCGETRULE, &pr)) { 855126353Smlaier warn("DIOCGETRULE"); 856171172Smlaier goto error; 857126353Smlaier } 858126353Smlaier 859126353Smlaier if (pfctl_get_pool(dev, &pr.rule.rpool, 860171172Smlaier nr, pr.ticket, PF_PASS, path) != 0) 861171172Smlaier goto error; 862126353Smlaier 863126353Smlaier switch (format) { 864171172Smlaier case PFCTL_SHOW_LABELS: 865126353Smlaier if (pr.rule.label[0]) { 866126353Smlaier printf("%s ", pr.rule.label); 867171172Smlaier printf("%llu %llu %llu %llu %llu %llu %llu\n", 868127024Smlaier (unsigned long long)pr.rule.evaluations, 869171172Smlaier (unsigned long long)(pr.rule.packets[0] + 870171172Smlaier pr.rule.packets[1]), 871171172Smlaier (unsigned long long)(pr.rule.bytes[0] + 872171172Smlaier pr.rule.bytes[1]), 873171172Smlaier (unsigned long long)pr.rule.packets[0], 874171172Smlaier (unsigned long long)pr.rule.bytes[0], 875171172Smlaier (unsigned long long)pr.rule.packets[1], 876171172Smlaier (unsigned long long)pr.rule.bytes[1]); 877126353Smlaier } 878126353Smlaier break; 879171172Smlaier case PFCTL_SHOW_RULES: 880171172Smlaier brace = 0; 881130617Smlaier if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) 882130617Smlaier labels = 1; 883171172Smlaier INDENT(depth, !(opts & PF_OPT_VERBOSE)); 884171172Smlaier if (pr.anchor_call[0] && 885171172Smlaier ((((p = strrchr(pr.anchor_call, '_')) != NULL) && 886171172Smlaier ((void *)p == (void *)pr.anchor_call || 887171172Smlaier *(--p) == '/')) || (opts & PF_OPT_RECURSE))) { 888171172Smlaier brace++; 889171172Smlaier if ((p = strrchr(pr.anchor_call, '/')) != 890171172Smlaier NULL) 891171172Smlaier p++; 892171172Smlaier else 893171172Smlaier p = &pr.anchor_call[0]; 894171172Smlaier } else 895171172Smlaier p = &pr.anchor_call[0]; 896171172Smlaier 897171172Smlaier print_rule(&pr.rule, p, rule_numbers); 898171172Smlaier if (brace) 899171172Smlaier printf(" {\n"); 900171172Smlaier else 901171172Smlaier printf("\n"); 902126353Smlaier pfctl_print_rule_counters(&pr.rule, opts); 903171172Smlaier if (brace) { 904171172Smlaier pfctl_show_rules(dev, path, opts, format, 905171172Smlaier p, depth + 1); 906171172Smlaier INDENT(depth, !(opts & PF_OPT_VERBOSE)); 907171172Smlaier printf("}\n"); 908171172Smlaier } 909171172Smlaier break; 910171172Smlaier case PFCTL_SHOW_NOTHING: 911171172Smlaier break; 912126353Smlaier } 913126353Smlaier pfctl_clear_pool(&pr.rule.rpool); 914126353Smlaier } 915171172Smlaier path[len] = '\0'; 916126353Smlaier return (0); 917171172Smlaier 918171172Smlaier error: 919171172Smlaier path[len] = '\0'; 920171172Smlaier return (-1); 921126353Smlaier} 922126353Smlaier 923126353Smlaierint 924145840Smlaierpfctl_show_nat(int dev, int opts, char *anchorname) 925126353Smlaier{ 926126353Smlaier struct pfioc_rule pr; 927126353Smlaier u_int32_t mnr, nr; 928126353Smlaier static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; 929130617Smlaier int i, dotitle = opts & PF_OPT_SHOWALL; 930126353Smlaier 931126353Smlaier memset(&pr, 0, sizeof(pr)); 932126353Smlaier memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 933126353Smlaier for (i = 0; i < 3; i++) { 934126353Smlaier pr.rule.action = nattype[i]; 935126353Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 936126353Smlaier warn("DIOCGETRULES"); 937126353Smlaier return (-1); 938126353Smlaier } 939126353Smlaier mnr = pr.nr; 940126353Smlaier for (nr = 0; nr < mnr; ++nr) { 941126353Smlaier pr.nr = nr; 942126353Smlaier if (ioctl(dev, DIOCGETRULE, &pr)) { 943126353Smlaier warn("DIOCGETRULE"); 944126353Smlaier return (-1); 945126353Smlaier } 946126353Smlaier if (pfctl_get_pool(dev, &pr.rule.rpool, nr, 947145840Smlaier pr.ticket, nattype[i], anchorname) != 0) 948126353Smlaier return (-1); 949130617Smlaier if (dotitle) { 950130617Smlaier pfctl_print_title("TRANSLATION RULES:"); 951130617Smlaier dotitle = 0; 952130617Smlaier } 953145840Smlaier print_rule(&pr.rule, pr.anchor_call, 954145840Smlaier opts & PF_OPT_VERBOSE2); 955171172Smlaier printf("\n"); 956126353Smlaier pfctl_print_rule_counters(&pr.rule, opts); 957126353Smlaier pfctl_clear_pool(&pr.rule.rpool); 958126353Smlaier } 959126353Smlaier } 960126353Smlaier return (0); 961126353Smlaier} 962126353Smlaier 963126353Smlaierint 964130617Smlaierpfctl_show_src_nodes(int dev, int opts) 965126353Smlaier{ 966130617Smlaier struct pfioc_src_nodes psn; 967130617Smlaier struct pf_src_node *p; 968130617Smlaier char *inbuf = NULL, *newinbuf = NULL; 969130617Smlaier unsigned len = 0; 970130617Smlaier int i; 971130617Smlaier 972130617Smlaier memset(&psn, 0, sizeof(psn)); 973130617Smlaier for (;;) { 974130617Smlaier psn.psn_len = len; 975130617Smlaier if (len) { 976130617Smlaier newinbuf = realloc(inbuf, len); 977130617Smlaier if (newinbuf == NULL) 978130617Smlaier err(1, "realloc"); 979130617Smlaier psn.psn_buf = inbuf = newinbuf; 980130617Smlaier } 981130617Smlaier if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) { 982130617Smlaier warn("DIOCGETSRCNODES"); 983171172Smlaier free(inbuf); 984130617Smlaier return (-1); 985130617Smlaier } 986130617Smlaier if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len) 987130617Smlaier break; 988130617Smlaier if (len == 0 && psn.psn_len == 0) 989171172Smlaier goto done; 990130617Smlaier if (len == 0 && psn.psn_len != 0) 991130617Smlaier len = psn.psn_len; 992130617Smlaier if (psn.psn_len == 0) 993171172Smlaier goto done; /* no src_nodes */ 994130617Smlaier len *= 2; 995130617Smlaier } 996130617Smlaier p = psn.psn_src_nodes; 997130617Smlaier if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL)) 998130617Smlaier pfctl_print_title("SOURCE TRACKING NODES:"); 999130617Smlaier for (i = 0; i < psn.psn_len; i += sizeof(*p)) { 1000130617Smlaier print_src_node(p, opts); 1001130617Smlaier p++; 1002130617Smlaier } 1003171172Smlaierdone: 1004171172Smlaier free(inbuf); 1005130617Smlaier return (0); 1006130617Smlaier} 1007130617Smlaier 1008130617Smlaierint 1009130617Smlaierpfctl_show_states(int dev, const char *iface, int opts) 1010130617Smlaier{ 1011126353Smlaier struct pfioc_states ps; 1012126353Smlaier struct pf_state *p; 1013130617Smlaier char *inbuf = NULL, *newinbuf = NULL; 1014126353Smlaier unsigned len = 0; 1015130617Smlaier int i, dotitle = (opts & PF_OPT_SHOWALL); 1016126353Smlaier 1017126353Smlaier memset(&ps, 0, sizeof(ps)); 1018126353Smlaier for (;;) { 1019126353Smlaier ps.ps_len = len; 1020126353Smlaier if (len) { 1021130617Smlaier newinbuf = realloc(inbuf, len); 1022130617Smlaier if (newinbuf == NULL) 1023126353Smlaier err(1, "realloc"); 1024130617Smlaier ps.ps_buf = inbuf = newinbuf; 1025126353Smlaier } 1026126353Smlaier if (ioctl(dev, DIOCGETSTATES, &ps) < 0) { 1027126353Smlaier warn("DIOCGETSTATES"); 1028171172Smlaier free(inbuf); 1029126353Smlaier return (-1); 1030126353Smlaier } 1031126353Smlaier if (ps.ps_len + sizeof(struct pfioc_states) < len) 1032126353Smlaier break; 1033126353Smlaier if (len == 0 && ps.ps_len == 0) 1034171172Smlaier goto done; 1035126353Smlaier if (len == 0 && ps.ps_len != 0) 1036126353Smlaier len = ps.ps_len; 1037126353Smlaier if (ps.ps_len == 0) 1038171172Smlaier goto done; /* no states */ 1039126353Smlaier len *= 2; 1040126353Smlaier } 1041126353Smlaier p = ps.ps_states; 1042130617Smlaier for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) { 1043130617Smlaier if (iface != NULL && strcmp(p->u.ifname, iface)) 1044130617Smlaier continue; 1045130617Smlaier if (dotitle) { 1046130617Smlaier pfctl_print_title("STATES:"); 1047130617Smlaier dotitle = 0; 1048130617Smlaier } 1049130617Smlaier print_state(p, opts); 1050126353Smlaier } 1051171172Smlaierdone: 1052171172Smlaier free(inbuf); 1053126353Smlaier return (0); 1054126353Smlaier} 1055126353Smlaier 1056126353Smlaierint 1057130617Smlaierpfctl_show_status(int dev, int opts) 1058126353Smlaier{ 1059126353Smlaier struct pf_status status; 1060126353Smlaier 1061126353Smlaier if (ioctl(dev, DIOCGETSTATUS, &status)) { 1062126353Smlaier warn("DIOCGETSTATUS"); 1063126353Smlaier return (-1); 1064126353Smlaier } 1065130617Smlaier if (opts & PF_OPT_SHOWALL) 1066130617Smlaier pfctl_print_title("INFO:"); 1067130617Smlaier print_status(&status, opts); 1068126353Smlaier return (0); 1069126353Smlaier} 1070126353Smlaier 1071126353Smlaierint 1072130617Smlaierpfctl_show_timeouts(int dev, int opts) 1073126353Smlaier{ 1074126353Smlaier struct pfioc_tm pt; 1075126353Smlaier int i; 1076126353Smlaier 1077130617Smlaier if (opts & PF_OPT_SHOWALL) 1078130617Smlaier pfctl_print_title("TIMEOUTS:"); 1079126353Smlaier memset(&pt, 0, sizeof(pt)); 1080126353Smlaier for (i = 0; pf_timeouts[i].name; i++) { 1081126353Smlaier pt.timeout = pf_timeouts[i].timeout; 1082126353Smlaier if (ioctl(dev, DIOCGETTIMEOUT, &pt)) 1083126353Smlaier err(1, "DIOCGETTIMEOUT"); 1084126353Smlaier printf("%-20s %10d", pf_timeouts[i].name, pt.seconds); 1085145840Smlaier if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && 1086145840Smlaier pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) 1087126353Smlaier printf(" states"); 1088126353Smlaier else 1089126353Smlaier printf("s"); 1090126353Smlaier printf("\n"); 1091126353Smlaier } 1092126353Smlaier return (0); 1093126353Smlaier 1094126353Smlaier} 1095126353Smlaier 1096126353Smlaierint 1097130617Smlaierpfctl_show_limits(int dev, int opts) 1098126353Smlaier{ 1099126353Smlaier struct pfioc_limit pl; 1100126353Smlaier int i; 1101126353Smlaier 1102130617Smlaier if (opts & PF_OPT_SHOWALL) 1103130617Smlaier pfctl_print_title("LIMITS:"); 1104126353Smlaier memset(&pl, 0, sizeof(pl)); 1105126353Smlaier for (i = 0; pf_limits[i].name; i++) { 1106130617Smlaier pl.index = pf_limits[i].index; 1107126353Smlaier if (ioctl(dev, DIOCGETLIMIT, &pl)) 1108126353Smlaier err(1, "DIOCGETLIMIT"); 1109171172Smlaier printf("%-13s ", pf_limits[i].name); 1110126353Smlaier if (pl.limit == UINT_MAX) 1111126353Smlaier printf("unlimited\n"); 1112126353Smlaier else 1113171172Smlaier printf("hard limit %8u\n", pl.limit); 1114126353Smlaier } 1115126353Smlaier return (0); 1116126353Smlaier} 1117126353Smlaier 1118126353Smlaier/* callbacks for rule/nat/rdr/addr */ 1119126353Smlaierint 1120126353Smlaierpfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af) 1121126353Smlaier{ 1122126353Smlaier struct pf_pooladdr *pa; 1123126353Smlaier 1124126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1125126353Smlaier if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) 1126126353Smlaier err(1, "DIOCBEGINADDRS"); 1127126353Smlaier } 1128126353Smlaier 1129126353Smlaier pf->paddr.af = af; 1130126353Smlaier TAILQ_FOREACH(pa, &p->list, entries) { 1131126353Smlaier memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr)); 1132126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1133126353Smlaier if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) 1134126353Smlaier err(1, "DIOCADDADDR"); 1135126353Smlaier } 1136126353Smlaier } 1137126353Smlaier return (0); 1138126353Smlaier} 1139126353Smlaier 1140126353Smlaierint 1141145840Smlaierpfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call) 1142126353Smlaier{ 1143130617Smlaier u_int8_t rs_num; 1144171172Smlaier struct pf_rule *rule; 1145171172Smlaier struct pf_ruleset *rs; 1146171172Smlaier char *p; 1147126353Smlaier 1148171172Smlaier rs_num = pf_get_ruleset_number(r->action); 1149171172Smlaier if (rs_num == PF_RULESET_MAX) 1150145840Smlaier errx(1, "Invalid rule type %d", r->action); 1151126353Smlaier 1152171172Smlaier rs = &pf->anchor->ruleset; 1153145840Smlaier 1154171172Smlaier if (anchor_call[0] && r->anchor == NULL) { 1155171172Smlaier /* 1156171172Smlaier * Don't make non-brace anchors part of the main anchor pool. 1157145840Smlaier */ 1158171172Smlaier if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 1159171172Smlaier err(1, "pfctl_add_rule: calloc"); 1160171172Smlaier 1161171172Smlaier pf_init_ruleset(&r->anchor->ruleset); 1162171172Smlaier r->anchor->ruleset.anchor = r->anchor; 1163171172Smlaier if (strlcpy(r->anchor->path, anchor_call, 1164171172Smlaier sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 1165171172Smlaier errx(1, "pfctl_add_rule: strlcpy"); 1166171172Smlaier if ((p = strrchr(anchor_call, '/')) != NULL) { 1167171172Smlaier if (!strlen(p)) 1168171172Smlaier err(1, "pfctl_add_rule: bad anchor name %s", 1169171172Smlaier anchor_call); 1170171172Smlaier } else 1171171172Smlaier p = (char *)anchor_call; 1172171172Smlaier if (strlcpy(r->anchor->name, p, 1173171172Smlaier sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 1174171172Smlaier errx(1, "pfctl_add_rule: strlcpy"); 1175171172Smlaier } 1176145840Smlaier 1177171172Smlaier if ((rule = calloc(1, sizeof(*rule))) == NULL) 1178171172Smlaier err(1, "calloc"); 1179171172Smlaier bcopy(r, rule, sizeof(*rule)); 1180171172Smlaier TAILQ_INIT(&rule->rpool.list); 1181171172Smlaier pfctl_move_pool(&r->rpool, &rule->rpool); 1182145840Smlaier 1183171172Smlaier TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries); 1184171172Smlaier return (0); 1185171172Smlaier} 1186171172Smlaier 1187171172Smlaierint 1188171172Smlaierpfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a) 1189171172Smlaier{ 1190171172Smlaier int osize = pf->trans->pfrb_size; 1191171172Smlaier 1192171172Smlaier if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { 1193171172Smlaier if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || 1194171172Smlaier pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || 1195171172Smlaier pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) 1196171172Smlaier return (1); 1197171172Smlaier } 1198171172Smlaier if (a == pf->astack[0] && ((altqsupport && 1199171172Smlaier (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) { 1200171172Smlaier if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path)) 1201171172Smlaier return (2); 1202171172Smlaier } 1203171172Smlaier if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) { 1204171172Smlaier if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) || 1205171172Smlaier pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path)) 1206171172Smlaier return (3); 1207171172Smlaier } 1208171172Smlaier if (pf->loadopt & PFCTL_FLAG_TABLE) 1209171172Smlaier if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path)) 1210171172Smlaier return (4); 1211171172Smlaier if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1212171172Smlaier return (5); 1213171172Smlaier 1214171172Smlaier return (0); 1215171172Smlaier} 1216171172Smlaier 1217171172Smlaierint 1218171172Smlaierpfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs, 1219171172Smlaier int rs_num, int depth) 1220171172Smlaier{ 1221171172Smlaier struct pf_rule *r; 1222171172Smlaier int error, len = strlen(path); 1223171172Smlaier int brace = 0; 1224171172Smlaier 1225171172Smlaier pf->anchor = rs->anchor; 1226171172Smlaier 1227171172Smlaier if (path[0]) 1228171172Smlaier snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name); 1229171172Smlaier else 1230171172Smlaier snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name); 1231171172Smlaier 1232171172Smlaier if (depth) { 1233171172Smlaier if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) { 1234171172Smlaier brace++; 1235171172Smlaier if (pf->opts & PF_OPT_VERBOSE) 1236171172Smlaier printf(" {\n"); 1237171172Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0 && 1238171172Smlaier (error = pfctl_ruleset_trans(pf, 1239171172Smlaier path, rs->anchor))) { 1240171172Smlaier printf("pfctl_load_rulesets: " 1241171172Smlaier "pfctl_ruleset_trans %d\n", error); 1242171172Smlaier goto error; 1243145840Smlaier } 1244171172Smlaier } else if (pf->opts & PF_OPT_VERBOSE) 1245171172Smlaier printf("\n"); 1246145840Smlaier 1247145840Smlaier } 1248145840Smlaier 1249171172Smlaier if (pf->optimize && rs_num == PF_RULESET_FILTER) 1250171172Smlaier pfctl_optimize_ruleset(pf, rs); 1251171172Smlaier 1252171172Smlaier while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) { 1253171172Smlaier TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries); 1254171172Smlaier if ((error = pfctl_load_rule(pf, path, r, depth))) 1255171172Smlaier goto error; 1256171172Smlaier if (r->anchor) { 1257171172Smlaier if ((error = pfctl_load_ruleset(pf, path, 1258171172Smlaier &r->anchor->ruleset, rs_num, depth + 1))) 1259171172Smlaier goto error; 1260171172Smlaier } else if (pf->opts & PF_OPT_VERBOSE) 1261171172Smlaier printf("\n"); 1262171172Smlaier free(r); 1263171172Smlaier } 1264171172Smlaier if (brace && pf->opts & PF_OPT_VERBOSE) { 1265171172Smlaier INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1266171172Smlaier printf("}\n"); 1267171172Smlaier } 1268171172Smlaier path[len] = '\0'; 1269171172Smlaier return (0); 1270171172Smlaier 1271171172Smlaier error: 1272171172Smlaier path[len] = '\0'; 1273171172Smlaier return (error); 1274171172Smlaier 1275171172Smlaier} 1276171172Smlaier 1277171172Smlaierint 1278171172Smlaierpfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) 1279171172Smlaier{ 1280171172Smlaier u_int8_t rs_num = pf_get_ruleset_number(r->action); 1281171172Smlaier char *name; 1282171172Smlaier struct pfioc_rule pr; 1283171172Smlaier int len = strlen(path); 1284171172Smlaier 1285171172Smlaier bzero(&pr, sizeof(pr)); 1286171172Smlaier /* set up anchor before adding to path for anchor_call */ 1287171172Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) 1288171172Smlaier pr.ticket = pfctl_get_ticket(pf->trans, rs_num, path); 1289171172Smlaier if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >= sizeof(pr.anchor)) 1290171172Smlaier errx(1, "pfctl_load_rule: strlcpy"); 1291171172Smlaier 1292171172Smlaier if (r->anchor) { 1293171172Smlaier if (r->anchor->match) { 1294171172Smlaier if (path[0]) 1295171172Smlaier snprintf(&path[len], MAXPATHLEN - len, 1296171172Smlaier "/%s", r->anchor->name); 1297171172Smlaier else 1298171172Smlaier snprintf(&path[len], MAXPATHLEN - len, 1299171172Smlaier "%s", r->anchor->name); 1300171172Smlaier name = path; 1301171172Smlaier } else 1302171172Smlaier name = r->anchor->path; 1303171172Smlaier } else 1304171172Smlaier name = ""; 1305171172Smlaier 1306126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1307126353Smlaier if (pfctl_add_pool(pf, &r->rpool, r->af)) 1308126353Smlaier return (1); 1309130617Smlaier pr.pool_ticket = pf->paddr.ticket; 1310130617Smlaier memcpy(&pr.rule, r, sizeof(pr.rule)); 1311171172Smlaier if (r->anchor && strlcpy(pr.anchor_call, name, 1312171172Smlaier sizeof(pr.anchor_call)) >= sizeof(pr.anchor_call)) 1313171172Smlaier errx(1, "pfctl_load_rule: strlcpy"); 1314130617Smlaier if (ioctl(pf->dev, DIOCADDRULE, &pr)) 1315126353Smlaier err(1, "DIOCADDRULE"); 1316126353Smlaier } 1317171172Smlaier 1318171172Smlaier if (pf->opts & PF_OPT_VERBOSE) { 1319171172Smlaier INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 1320171172Smlaier print_rule(r, r->anchor ? r->anchor->name : "", 1321171172Smlaier pf->opts & PF_OPT_VERBOSE2); 1322171172Smlaier } 1323171172Smlaier path[len] = '\0'; 1324126353Smlaier pfctl_clear_pool(&r->rpool); 1325126353Smlaier return (0); 1326126353Smlaier} 1327126353Smlaier 1328126353Smlaierint 1329126353Smlaierpfctl_add_altq(struct pfctl *pf, struct pf_altq *a) 1330126353Smlaier{ 1331126353Smlaier if (altqsupport && 1332126353Smlaier (loadopt & PFCTL_FLAG_ALTQ) != 0) { 1333126353Smlaier memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq)); 1334126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1335126353Smlaier if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) { 1336126353Smlaier if (errno == ENXIO) 1337126353Smlaier errx(1, "qtype not configured"); 1338126353Smlaier else if (errno == ENODEV) 1339126353Smlaier errx(1, "%s: driver does not support " 1340126353Smlaier "altq", a->ifname); 1341126353Smlaier else 1342126353Smlaier err(1, "DIOCADDALTQ"); 1343126353Smlaier } 1344126353Smlaier } 1345126353Smlaier pfaltq_store(&pf->paltq->altq); 1346126353Smlaier } 1347126353Smlaier return (0); 1348126353Smlaier} 1349126353Smlaier 1350126353Smlaierint 1351171172Smlaierpfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize, 1352171172Smlaier char *anchorname, struct pfr_buffer *trans) 1353126353Smlaier{ 1354126353Smlaier#define ERR(x) do { warn(x); goto _error; } while(0) 1355126353Smlaier#define ERRX(x) do { warnx(x); goto _error; } while(0) 1356126353Smlaier 1357130617Smlaier struct pfr_buffer *t, buf; 1358130617Smlaier struct pfioc_altq pa; 1359130617Smlaier struct pfctl pf; 1360171172Smlaier struct pf_ruleset *rs; 1361130617Smlaier struct pfr_table trs; 1362171172Smlaier char *path; 1363130617Smlaier int osize; 1364126353Smlaier 1365171172Smlaier RB_INIT(&pf_anchors); 1366171172Smlaier memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); 1367171172Smlaier pf_init_ruleset(&pf_main_anchor.ruleset); 1368171172Smlaier pf_main_anchor.ruleset.anchor = &pf_main_anchor; 1369130617Smlaier if (trans == NULL) { 1370171172Smlaier bzero(&buf, sizeof(buf)); 1371171172Smlaier buf.pfrb_type = PFRB_TRANS; 1372171172Smlaier t = &buf; 1373171172Smlaier osize = 0; 1374130617Smlaier } else { 1375171172Smlaier t = trans; 1376171172Smlaier osize = t->pfrb_size; 1377130617Smlaier } 1378130617Smlaier 1379126353Smlaier memset(&pa, 0, sizeof(pa)); 1380126353Smlaier memset(&pf, 0, sizeof(pf)); 1381126353Smlaier memset(&trs, 0, sizeof(trs)); 1382171172Smlaier if ((path = calloc(1, MAXPATHLEN)) == NULL) 1383171172Smlaier ERRX("pfctl_rules: calloc"); 1384126353Smlaier if (strlcpy(trs.pfrt_anchor, anchorname, 1385145840Smlaier sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) 1386126353Smlaier ERRX("pfctl_rules: strlcpy"); 1387171172Smlaier infile = filename; 1388126353Smlaier pf.dev = dev; 1389126353Smlaier pf.opts = opts; 1390171172Smlaier pf.optimize = optimize; 1391126353Smlaier pf.loadopt = loadopt; 1392171172Smlaier 1393171172Smlaier /* non-brace anchor, create without resolving the path */ 1394171172Smlaier if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) 1395171172Smlaier ERRX("pfctl_rules: calloc"); 1396171172Smlaier rs = &pf.anchor->ruleset; 1397171172Smlaier pf_init_ruleset(rs); 1398171172Smlaier rs->anchor = pf.anchor; 1399171172Smlaier if (strlcpy(pf.anchor->path, anchorname, 1400171172Smlaier sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 1401171172Smlaier errx(1, "pfctl_add_rule: strlcpy"); 1402171172Smlaier if (strlcpy(pf.anchor->name, anchorname, 1403171172Smlaier sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 1404171172Smlaier errx(1, "pfctl_add_rule: strlcpy"); 1405171172Smlaier 1406171172Smlaier 1407171172Smlaier pf.astack[0] = pf.anchor; 1408171172Smlaier pf.asd = 0; 1409130617Smlaier if (anchorname[0]) 1410130617Smlaier pf.loadopt &= ~PFCTL_FLAG_ALTQ; 1411126353Smlaier pf.paltq = &pa; 1412130617Smlaier pf.trans = t; 1413145840Smlaier pfctl_init_options(&pf); 1414130617Smlaier 1415130617Smlaier if ((opts & PF_OPT_NOACTION) == 0) { 1416171172Smlaier /* 1417171172Smlaier * XXX For the time being we need to open transactions for 1418171172Smlaier * the main ruleset before parsing, because tables are still 1419171172Smlaier * loaded at parse time. 1420171172Smlaier */ 1421171172Smlaier if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor)) 1422171172Smlaier ERRX("pfctl_rules"); 1423130617Smlaier if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) 1424171172Smlaier pa.ticket = 1425171172Smlaier pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname); 1426130617Smlaier if (pf.loadopt & PFCTL_FLAG_TABLE) 1427171172Smlaier pf.astack[0]->ruleset.tticket = 1428171172Smlaier pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname); 1429130617Smlaier } 1430171172Smlaier 1431126353Smlaier if (parse_rules(fin, &pf) < 0) { 1432126353Smlaier if ((opts & PF_OPT_NOACTION) == 0) 1433126353Smlaier ERRX("Syntax error in config file: " 1434126353Smlaier "pf rules not loaded"); 1435126353Smlaier else 1436126353Smlaier goto _error; 1437126353Smlaier } 1438171172Smlaier 1439171172Smlaier if ((pf.loadopt & PFCTL_FLAG_FILTER && 1440171172Smlaier (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) || 1441171172Smlaier (pf.loadopt & PFCTL_FLAG_NAT && 1442171172Smlaier (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) || 1443171172Smlaier pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) || 1444171172Smlaier pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) || 1445171172Smlaier (pf.loadopt & PFCTL_FLAG_FILTER && 1446171172Smlaier pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) { 1447171172Smlaier if ((opts & PF_OPT_NOACTION) == 0) 1448171172Smlaier ERRX("Unable to load rules into kernel"); 1449171172Smlaier else 1450171172Smlaier goto _error; 1451145840Smlaier } 1452145840Smlaier 1453130617Smlaier if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0)) 1454126353Smlaier if (check_commit_altq(dev, opts) != 0) 1455126353Smlaier ERRX("errors in altq config"); 1456145840Smlaier 1457145840Smlaier if (fin != stdin) { 1458126353Smlaier fclose(fin); 1459145840Smlaier fin = NULL; 1460145840Smlaier } 1461126353Smlaier 1462126353Smlaier /* process "load anchor" directives */ 1463145840Smlaier if (!anchorname[0]) 1464171172Smlaier if (pfctl_load_anchors(dev, &pf, t) == -1) 1465126353Smlaier ERRX("load anchors"); 1466126353Smlaier 1467145840Smlaier if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) { 1468145840Smlaier if (!anchorname[0]) 1469145840Smlaier if (pfctl_load_options(&pf)) 1470145840Smlaier goto _error; 1471171172Smlaier if (pfctl_trans(dev, t, DIOCXCOMMIT, osize)) 1472130617Smlaier ERR("DIOCXCOMMIT"); 1473145840Smlaier } 1474126353Smlaier return (0); 1475126353Smlaier 1476126353Smlaier_error: 1477130617Smlaier if (trans == NULL) { /* main ruleset */ 1478130617Smlaier if ((opts & PF_OPT_NOACTION) == 0) 1479171172Smlaier if (pfctl_trans(dev, t, DIOCXROLLBACK, osize)) 1480130617Smlaier err(1, "DIOCXROLLBACK"); 1481130617Smlaier exit(1); 1482145840Smlaier } else { /* sub ruleset */ 1483145840Smlaier if (fin != NULL && fin != stdin) 1484145840Smlaier fclose(fin); 1485130617Smlaier return (-1); 1486145840Smlaier } 1487126353Smlaier 1488126353Smlaier#undef ERR 1489126353Smlaier#undef ERRX 1490126353Smlaier} 1491126353Smlaier 1492145840SmlaierFILE * 1493145840Smlaierpfctl_fopen(const char *name, const char *mode) 1494145840Smlaier{ 1495145840Smlaier struct stat st; 1496145840Smlaier FILE *fp; 1497145840Smlaier 1498145840Smlaier fp = fopen(name, mode); 1499145840Smlaier if (fp == NULL) 1500145840Smlaier return (NULL); 1501145840Smlaier if (fstat(fileno(fp), &st)) { 1502145840Smlaier fclose(fp); 1503145840Smlaier return (NULL); 1504145840Smlaier } 1505145840Smlaier if (S_ISDIR(st.st_mode)) { 1506145840Smlaier fclose(fp); 1507145840Smlaier errno = EISDIR; 1508145840Smlaier return (NULL); 1509145840Smlaier } 1510145840Smlaier return (fp); 1511145840Smlaier} 1512145840Smlaier 1513145840Smlaiervoid 1514145840Smlaierpfctl_init_options(struct pfctl *pf) 1515145840Smlaier{ 1516171172Smlaier int mib[2], mem; 1517171172Smlaier size_t size; 1518171172Smlaier 1519145840Smlaier pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 1520145840Smlaier pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; 1521145840Smlaier pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 1522145840Smlaier pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; 1523145840Smlaier pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; 1524145840Smlaier pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; 1525145840Smlaier pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; 1526145840Smlaier pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; 1527145840Smlaier pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; 1528145840Smlaier pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; 1529145840Smlaier pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; 1530145840Smlaier pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; 1531145840Smlaier pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; 1532145840Smlaier pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; 1533145840Smlaier pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; 1534145840Smlaier pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; 1535145840Smlaier pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; 1536145840Smlaier pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; 1537171172Smlaier pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; 1538171172Smlaier pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; 1539145840Smlaier 1540171172Smlaier pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; 1541171172Smlaier pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT; 1542171172Smlaier pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; 1543171172Smlaier pf->limit[PF_LIMIT_TABLES] = PFR_KTABLE_HIWAT; 1544171172Smlaier pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; 1545145840Smlaier 1546171172Smlaier mib[0] = CTL_HW; 1547171172Smlaier mib[1] = HW_PHYSMEM; 1548171172Smlaier size = sizeof(mem); 1549171172Smlaier (void) sysctl(mib, 2, &mem, &size, NULL, 0); 1550171172Smlaier if (mem <= 100*1024*1024) 1551171172Smlaier pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT_SMALL; 1552171172Smlaier 1553145840Smlaier pf->debug = PF_DEBUG_URGENT; 1554145840Smlaier} 1555145840Smlaier 1556126353Smlaierint 1557145840Smlaierpfctl_load_options(struct pfctl *pf) 1558126353Smlaier{ 1559145840Smlaier int i, error = 0; 1560126353Smlaier 1561126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1562126353Smlaier return (0); 1563126353Smlaier 1564145840Smlaier /* load limits */ 1565145840Smlaier for (i = 0; i < PF_LIMIT_MAX; i++) { 1566145840Smlaier if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i]) 1567145840Smlaier continue; 1568145840Smlaier if (pfctl_load_limit(pf, i, pf->limit[i])) 1569145840Smlaier error = 1; 1570145840Smlaier } 1571145840Smlaier 1572171172Smlaier /* 1573171172Smlaier * If we've set the limit, but havn't explicitly set adaptive 1574171172Smlaier * timeouts, do it now with a start of 60% and end of 120%. 1575171172Smlaier */ 1576171172Smlaier if (pf->limit_set[PF_LIMIT_STATES] && 1577171172Smlaier !pf->timeout_set[PFTM_ADAPTIVE_START] && 1578171172Smlaier !pf->timeout_set[PFTM_ADAPTIVE_END]) { 1579171172Smlaier pf->timeout[PFTM_ADAPTIVE_START] = 1580171172Smlaier (pf->limit[PF_LIMIT_STATES] / 10) * 6; 1581171172Smlaier pf->timeout_set[PFTM_ADAPTIVE_START] = 1; 1582171172Smlaier pf->timeout[PFTM_ADAPTIVE_END] = 1583171172Smlaier (pf->limit[PF_LIMIT_STATES] / 10) * 12; 1584171172Smlaier pf->timeout_set[PFTM_ADAPTIVE_END] = 1; 1585171172Smlaier } 1586171172Smlaier 1587145840Smlaier /* load timeouts */ 1588145840Smlaier for (i = 0; i < PFTM_MAX; i++) { 1589145840Smlaier if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i]) 1590145840Smlaier continue; 1591145840Smlaier if (pfctl_load_timeout(pf, i, pf->timeout[i])) 1592145840Smlaier error = 1; 1593145840Smlaier } 1594145840Smlaier 1595145840Smlaier /* load debug */ 1596145840Smlaier if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set) 1597145840Smlaier if (pfctl_load_debug(pf, pf->debug)) 1598145840Smlaier error = 1; 1599145840Smlaier 1600145840Smlaier /* load logif */ 1601145840Smlaier if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set) 1602145840Smlaier if (pfctl_load_logif(pf, pf->ifname)) 1603145840Smlaier error = 1; 1604145840Smlaier 1605145840Smlaier /* load hostid */ 1606145840Smlaier if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set) 1607145840Smlaier if (pfctl_load_hostid(pf, pf->hostid)) 1608145840Smlaier error = 1; 1609145840Smlaier 1610145840Smlaier return (error); 1611145840Smlaier} 1612145840Smlaier 1613145840Smlaierint 1614145840Smlaierpfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) 1615145840Smlaier{ 1616145840Smlaier int i; 1617145840Smlaier 1618145840Smlaier 1619126353Smlaier for (i = 0; pf_limits[i].name; i++) { 1620126353Smlaier if (strcasecmp(opt, pf_limits[i].name) == 0) { 1621145840Smlaier pf->limit[pf_limits[i].index] = limit; 1622145840Smlaier pf->limit_set[pf_limits[i].index] = 1; 1623126353Smlaier break; 1624126353Smlaier } 1625126353Smlaier } 1626126353Smlaier if (pf_limits[i].name == NULL) { 1627126353Smlaier warnx("Bad pool name."); 1628126353Smlaier return (1); 1629126353Smlaier } 1630126353Smlaier 1631126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 1632126353Smlaier printf("set limit %s %d\n", opt, limit); 1633126353Smlaier 1634126353Smlaier return (0); 1635126353Smlaier} 1636126353Smlaier 1637126353Smlaierint 1638145840Smlaierpfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) 1639145840Smlaier{ 1640145840Smlaier struct pfioc_limit pl; 1641145840Smlaier 1642145840Smlaier memset(&pl, 0, sizeof(pl)); 1643145840Smlaier pl.index = index; 1644145840Smlaier pl.limit = limit; 1645145840Smlaier if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) { 1646145840Smlaier if (errno == EBUSY) 1647145840Smlaier warnx("Current pool size exceeds requested hard limit"); 1648145840Smlaier else 1649145840Smlaier warnx("DIOCSETLIMIT"); 1650145840Smlaier return (1); 1651145840Smlaier } 1652145840Smlaier return (0); 1653145840Smlaier} 1654145840Smlaier 1655145840Smlaierint 1656126353Smlaierpfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 1657126353Smlaier{ 1658126353Smlaier int i; 1659126353Smlaier 1660126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1661126353Smlaier return (0); 1662126353Smlaier 1663126353Smlaier for (i = 0; pf_timeouts[i].name; i++) { 1664126353Smlaier if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 1665145840Smlaier pf->timeout[pf_timeouts[i].timeout] = seconds; 1666145840Smlaier pf->timeout_set[pf_timeouts[i].timeout] = 1; 1667126353Smlaier break; 1668126353Smlaier } 1669126353Smlaier } 1670126353Smlaier 1671126353Smlaier if (pf_timeouts[i].name == NULL) { 1672126353Smlaier warnx("Bad timeout name."); 1673126353Smlaier return (1); 1674126353Smlaier } 1675126353Smlaier 1676126353Smlaier 1677126353Smlaier if (pf->opts & PF_OPT_VERBOSE && ! quiet) 1678126353Smlaier printf("set timeout %s %d\n", opt, seconds); 1679126353Smlaier 1680126353Smlaier return (0); 1681126353Smlaier} 1682126353Smlaier 1683126353Smlaierint 1684145840Smlaierpfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) 1685145840Smlaier{ 1686145840Smlaier struct pfioc_tm pt; 1687145840Smlaier 1688145840Smlaier memset(&pt, 0, sizeof(pt)); 1689145840Smlaier pt.timeout = timeout; 1690145840Smlaier pt.seconds = seconds; 1691145840Smlaier if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) { 1692145840Smlaier warnx("DIOCSETTIMEOUT"); 1693145840Smlaier return (1); 1694145840Smlaier } 1695145840Smlaier return (0); 1696145840Smlaier} 1697145840Smlaier 1698145840Smlaierint 1699126353Smlaierpfctl_set_optimization(struct pfctl *pf, const char *opt) 1700126353Smlaier{ 1701126353Smlaier const struct pf_hint *hint; 1702126353Smlaier int i, r; 1703126353Smlaier 1704126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1705126353Smlaier return (0); 1706126353Smlaier 1707126353Smlaier for (i = 0; pf_hints[i].name; i++) 1708126353Smlaier if (strcasecmp(opt, pf_hints[i].name) == 0) 1709126353Smlaier break; 1710126353Smlaier 1711126353Smlaier hint = pf_hints[i].hint; 1712126353Smlaier if (hint == NULL) { 1713171172Smlaier warnx("invalid state timeouts optimization"); 1714126353Smlaier return (1); 1715126353Smlaier } 1716126353Smlaier 1717126353Smlaier for (i = 0; hint[i].name; i++) 1718126353Smlaier if ((r = pfctl_set_timeout(pf, hint[i].name, 1719126353Smlaier hint[i].timeout, 1))) 1720126353Smlaier return (r); 1721126353Smlaier 1722126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 1723126353Smlaier printf("set optimization %s\n", opt); 1724126353Smlaier 1725126353Smlaier return (0); 1726126353Smlaier} 1727126353Smlaier 1728126353Smlaierint 1729126353Smlaierpfctl_set_logif(struct pfctl *pf, char *ifname) 1730126353Smlaier{ 1731126353Smlaier 1732126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1733126353Smlaier return (0); 1734126353Smlaier 1735145840Smlaier if (!strcmp(ifname, "none")) { 1736145840Smlaier free(pf->ifname); 1737145840Smlaier pf->ifname = NULL; 1738145840Smlaier } else { 1739145840Smlaier pf->ifname = strdup(ifname); 1740145840Smlaier if (!pf->ifname) 1741145840Smlaier errx(1, "pfctl_set_logif: strdup"); 1742126353Smlaier } 1743145840Smlaier pf->ifname_set = 1; 1744126353Smlaier 1745126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 1746126353Smlaier printf("set loginterface %s\n", ifname); 1747126353Smlaier 1748126353Smlaier return (0); 1749126353Smlaier} 1750126353Smlaier 1751126353Smlaierint 1752145840Smlaierpfctl_load_logif(struct pfctl *pf, char *ifname) 1753145840Smlaier{ 1754145840Smlaier struct pfioc_if pi; 1755145840Smlaier 1756145840Smlaier memset(&pi, 0, sizeof(pi)); 1757145840Smlaier if (ifname && strlcpy(pi.ifname, ifname, 1758145840Smlaier sizeof(pi.ifname)) >= sizeof(pi.ifname)) { 1759171172Smlaier warnx("pfctl_load_logif: strlcpy"); 1760145840Smlaier return (1); 1761145840Smlaier } 1762145840Smlaier if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) { 1763145840Smlaier warnx("DIOCSETSTATUSIF"); 1764145840Smlaier return (1); 1765145840Smlaier } 1766145840Smlaier return (0); 1767145840Smlaier} 1768145840Smlaier 1769145840Smlaierint 1770130617Smlaierpfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 1771130617Smlaier{ 1772130617Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1773130617Smlaier return (0); 1774130617Smlaier 1775130617Smlaier HTONL(hostid); 1776130617Smlaier 1777145840Smlaier pf->hostid = hostid; 1778145840Smlaier pf->hostid_set = 1; 1779130617Smlaier 1780130617Smlaier if (pf->opts & PF_OPT_VERBOSE) 1781130617Smlaier printf("set hostid 0x%08x\n", ntohl(hostid)); 1782130617Smlaier 1783130617Smlaier return (0); 1784130617Smlaier} 1785130617Smlaier 1786130617Smlaierint 1787145840Smlaierpfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) 1788145840Smlaier{ 1789145840Smlaier if (ioctl(dev, DIOCSETHOSTID, &hostid)) { 1790145840Smlaier warnx("DIOCSETHOSTID"); 1791145840Smlaier return (1); 1792145840Smlaier } 1793145840Smlaier return (0); 1794145840Smlaier} 1795145840Smlaier 1796145840Smlaierint 1797130617Smlaierpfctl_set_debug(struct pfctl *pf, char *d) 1798130617Smlaier{ 1799130617Smlaier u_int32_t level; 1800130617Smlaier 1801130617Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1802130617Smlaier return (0); 1803130617Smlaier 1804130617Smlaier if (!strcmp(d, "none")) 1805145840Smlaier pf->debug = PF_DEBUG_NONE; 1806130617Smlaier else if (!strcmp(d, "urgent")) 1807145840Smlaier pf->debug = PF_DEBUG_URGENT; 1808130617Smlaier else if (!strcmp(d, "misc")) 1809145840Smlaier pf->debug = PF_DEBUG_MISC; 1810130617Smlaier else if (!strcmp(d, "loud")) 1811145840Smlaier pf->debug = PF_DEBUG_NOISY; 1812130617Smlaier else { 1813130617Smlaier warnx("unknown debug level \"%s\"", d); 1814130617Smlaier return (-1); 1815130617Smlaier } 1816130617Smlaier 1817145840Smlaier pf->debug_set = 1; 1818145840Smlaier 1819130617Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) 1820130617Smlaier if (ioctl(dev, DIOCSETDEBUG, &level)) 1821130617Smlaier err(1, "DIOCSETDEBUG"); 1822130617Smlaier 1823130617Smlaier if (pf->opts & PF_OPT_VERBOSE) 1824130617Smlaier printf("set debug %s\n", d); 1825130617Smlaier 1826130617Smlaier return (0); 1827130617Smlaier} 1828130617Smlaier 1829130617Smlaierint 1830145840Smlaierpfctl_load_debug(struct pfctl *pf, unsigned int level) 1831145840Smlaier{ 1832145840Smlaier if (ioctl(pf->dev, DIOCSETDEBUG, &level)) { 1833145840Smlaier warnx("DIOCSETDEBUG"); 1834145840Smlaier return (1); 1835145840Smlaier } 1836145840Smlaier return (0); 1837145840Smlaier} 1838145840Smlaier 1839145840Smlaierint 1840145840Smlaierpfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) 1841145840Smlaier{ 1842145840Smlaier struct pfioc_iface pi; 1843145840Smlaier 1844145840Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1845145840Smlaier return (0); 1846145840Smlaier 1847145840Smlaier bzero(&pi, sizeof(pi)); 1848145840Smlaier 1849145840Smlaier pi.pfiio_flags = flags; 1850145840Smlaier 1851145840Smlaier if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= 1852145840Smlaier sizeof(pi.pfiio_name)) 1853145840Smlaier errx(1, "pfctl_set_interface_flags: strlcpy"); 1854145840Smlaier 1855145840Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1856145840Smlaier if (how == 0) { 1857145840Smlaier if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi)) 1858145840Smlaier err(1, "DIOCCLRIFFLAG"); 1859145840Smlaier } else { 1860145840Smlaier if (ioctl(pf->dev, DIOCSETIFFLAG, &pi)) 1861145840Smlaier err(1, "DIOCSETIFFLAG"); 1862145840Smlaier } 1863145840Smlaier } 1864145840Smlaier return (0); 1865145840Smlaier} 1866145840Smlaier 1867145840Smlaiervoid 1868126353Smlaierpfctl_debug(int dev, u_int32_t level, int opts) 1869126353Smlaier{ 1870126353Smlaier if (ioctl(dev, DIOCSETDEBUG, &level)) 1871126353Smlaier err(1, "DIOCSETDEBUG"); 1872126353Smlaier if ((opts & PF_OPT_QUIET) == 0) { 1873126353Smlaier fprintf(stderr, "debug level set to '"); 1874126353Smlaier switch (level) { 1875126353Smlaier case PF_DEBUG_NONE: 1876126353Smlaier fprintf(stderr, "none"); 1877126353Smlaier break; 1878126353Smlaier case PF_DEBUG_URGENT: 1879126353Smlaier fprintf(stderr, "urgent"); 1880126353Smlaier break; 1881126353Smlaier case PF_DEBUG_MISC: 1882126353Smlaier fprintf(stderr, "misc"); 1883126353Smlaier break; 1884126353Smlaier case PF_DEBUG_NOISY: 1885126353Smlaier fprintf(stderr, "loud"); 1886126353Smlaier break; 1887126353Smlaier default: 1888126353Smlaier fprintf(stderr, "<invalid>"); 1889126353Smlaier break; 1890126353Smlaier } 1891126353Smlaier fprintf(stderr, "'\n"); 1892126353Smlaier } 1893126353Smlaier} 1894126353Smlaier 1895126353Smlaierint 1896126353Smlaierpfctl_test_altqsupport(int dev, int opts) 1897126353Smlaier{ 1898126355Smlaier#if defined(__FreeBSD__) && !defined(ENABLE_ALTQ) 1899126355Smlaier return (0); 1900126355Smlaier#else 1901126353Smlaier struct pfioc_altq pa; 1902126353Smlaier 1903126353Smlaier if (ioctl(dev, DIOCGETALTQS, &pa)) { 1904126353Smlaier if (errno == ENODEV) { 1905126353Smlaier if (!(opts & PF_OPT_QUIET)) 1906126353Smlaier fprintf(stderr, "No ALTQ support in kernel\n" 1907126353Smlaier "ALTQ related functions disabled\n"); 1908126353Smlaier return (0); 1909126353Smlaier } else 1910126353Smlaier err(1, "DIOCGETALTQS"); 1911126353Smlaier } 1912126353Smlaier return (1); 1913126355Smlaier#endif 1914126353Smlaier} 1915126353Smlaier 1916126353Smlaierint 1917126353Smlaierpfctl_show_anchors(int dev, int opts, char *anchorname) 1918126353Smlaier{ 1919145840Smlaier struct pfioc_ruleset pr; 1920145840Smlaier u_int32_t mnr, nr; 1921126353Smlaier 1922145840Smlaier memset(&pr, 0, sizeof(pr)); 1923145840Smlaier memcpy(pr.path, anchorname, sizeof(pr.path)); 1924145840Smlaier if (ioctl(dev, DIOCGETRULESETS, &pr)) { 1925145840Smlaier if (errno == EINVAL) 1926145840Smlaier fprintf(stderr, "Anchor '%s' not found.\n", 1927145840Smlaier anchorname); 1928145840Smlaier else 1929145840Smlaier err(1, "DIOCGETRULESETS"); 1930145840Smlaier return (-1); 1931145840Smlaier } 1932145840Smlaier mnr = pr.nr; 1933145840Smlaier for (nr = 0; nr < mnr; ++nr) { 1934145840Smlaier char sub[MAXPATHLEN]; 1935126353Smlaier 1936145840Smlaier pr.nr = nr; 1937145840Smlaier if (ioctl(dev, DIOCGETRULESET, &pr)) 1938145840Smlaier err(1, "DIOCGETRULESET"); 1939145840Smlaier if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) 1940145840Smlaier continue; 1941145840Smlaier sub[0] = 0; 1942145840Smlaier if (pr.path[0]) { 1943145840Smlaier strlcat(sub, pr.path, sizeof(sub)); 1944145840Smlaier strlcat(sub, "/", sizeof(sub)); 1945126353Smlaier } 1946145840Smlaier strlcat(sub, pr.name, sizeof(sub)); 1947171172Smlaier if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 1948171172Smlaier printf(" %s\n", sub); 1949171172Smlaier if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub)) 1950126353Smlaier return (-1); 1951126353Smlaier } 1952126353Smlaier return (0); 1953126353Smlaier} 1954126353Smlaier 1955126353Smlaierconst char * 1956126353Smlaierpfctl_lookup_option(char *cmd, const char **list) 1957126353Smlaier{ 1958126353Smlaier if (cmd != NULL && *cmd) 1959126353Smlaier for (; *list; list++) 1960126353Smlaier if (!strncmp(cmd, *list, strlen(cmd))) 1961126353Smlaier return (*list); 1962126353Smlaier return (NULL); 1963126353Smlaier} 1964126353Smlaier 1965126353Smlaierint 1966126353Smlaiermain(int argc, char *argv[]) 1967126353Smlaier{ 1968171172Smlaier int error = 0; 1969171172Smlaier int ch; 1970171172Smlaier int mode = O_RDONLY; 1971171172Smlaier int opts = 0; 1972171172Smlaier int optimize = 0; 1973171172Smlaier char anchorname[MAXPATHLEN]; 1974171172Smlaier char *path; 1975171172Smlaier FILE *fin = NULL; 1976126353Smlaier 1977126353Smlaier if (argc < 2) 1978126353Smlaier usage(); 1979126353Smlaier 1980130617Smlaier while ((ch = getopt(argc, argv, 1981171172Smlaier "a:AdD:eqf:F:ghi:k:K:mnNOo::p:rRs:t:T:vx:z")) != -1) { 1982126353Smlaier switch (ch) { 1983126353Smlaier case 'a': 1984126353Smlaier anchoropt = optarg; 1985126353Smlaier break; 1986126353Smlaier case 'd': 1987126353Smlaier opts |= PF_OPT_DISABLE; 1988126353Smlaier mode = O_RDWR; 1989126353Smlaier break; 1990126353Smlaier case 'D': 1991126353Smlaier if (pfctl_cmdline_symset(optarg) < 0) 1992126353Smlaier warnx("could not parse macro definition %s", 1993126353Smlaier optarg); 1994126353Smlaier break; 1995126353Smlaier case 'e': 1996126353Smlaier opts |= PF_OPT_ENABLE; 1997126353Smlaier mode = O_RDWR; 1998126353Smlaier break; 1999126353Smlaier case 'q': 2000126353Smlaier opts |= PF_OPT_QUIET; 2001126353Smlaier break; 2002126353Smlaier case 'F': 2003126353Smlaier clearopt = pfctl_lookup_option(optarg, clearopt_list); 2004126353Smlaier if (clearopt == NULL) { 2005126353Smlaier warnx("Unknown flush modifier '%s'", optarg); 2006126353Smlaier usage(); 2007126353Smlaier } 2008126353Smlaier mode = O_RDWR; 2009126353Smlaier break; 2010130617Smlaier case 'i': 2011130617Smlaier ifaceopt = optarg; 2012130617Smlaier break; 2013126353Smlaier case 'k': 2014126353Smlaier if (state_killers >= 2) { 2015126353Smlaier warnx("can only specify -k twice"); 2016126353Smlaier usage(); 2017126353Smlaier /* NOTREACHED */ 2018126353Smlaier } 2019126353Smlaier state_kill[state_killers++] = optarg; 2020126353Smlaier mode = O_RDWR; 2021126353Smlaier break; 2022171172Smlaier case 'K': 2023171172Smlaier if (src_node_killers >= 2) { 2024171172Smlaier warnx("can only specify -K twice"); 2025171172Smlaier usage(); 2026171172Smlaier /* NOTREACHED */ 2027171172Smlaier } 2028171172Smlaier src_node_kill[src_node_killers++] = optarg; 2029171172Smlaier mode = O_RDWR; 2030171172Smlaier break; 2031145840Smlaier case 'm': 2032145840Smlaier opts |= PF_OPT_MERGE; 2033145840Smlaier break; 2034126353Smlaier case 'n': 2035126353Smlaier opts |= PF_OPT_NOACTION; 2036126353Smlaier break; 2037126353Smlaier case 'N': 2038126353Smlaier loadopt |= PFCTL_FLAG_NAT; 2039126353Smlaier break; 2040126353Smlaier case 'r': 2041126353Smlaier opts |= PF_OPT_USEDNS; 2042126353Smlaier break; 2043126353Smlaier case 'f': 2044126353Smlaier rulesopt = optarg; 2045126353Smlaier mode = O_RDWR; 2046126353Smlaier break; 2047126353Smlaier case 'g': 2048126353Smlaier opts |= PF_OPT_DEBUG; 2049126353Smlaier break; 2050126353Smlaier case 'A': 2051126353Smlaier loadopt |= PFCTL_FLAG_ALTQ; 2052126353Smlaier break; 2053126353Smlaier case 'R': 2054126353Smlaier loadopt |= PFCTL_FLAG_FILTER; 2055126353Smlaier break; 2056145840Smlaier case 'o': 2057171172Smlaier if (optarg) { 2058171172Smlaier optiopt = pfctl_lookup_option(optarg, 2059171172Smlaier optiopt_list); 2060171172Smlaier if (optiopt == NULL) { 2061171172Smlaier warnx("Unknown optimization '%s'", 2062171172Smlaier optarg); 2063171172Smlaier usage(); 2064171172Smlaier } 2065171172Smlaier } 2066171172Smlaier if (opts & PF_OPT_OPTIMIZE) { 2067171172Smlaier if (optiopt != NULL) { 2068171172Smlaier warnx("Cannot specify -o multiple times" 2069171172Smlaier "with optimizer level"); 2070171172Smlaier usage(); 2071171172Smlaier } 2072171172Smlaier optimize |= PF_OPTIMIZE_PROFILE; 2073171172Smlaier } 2074171172Smlaier optimize |= PF_OPTIMIZE_BASIC; 2075171172Smlaier opts |= PF_OPT_OPTIMIZE; 2076145840Smlaier break; 2077126353Smlaier case 'O': 2078126353Smlaier loadopt |= PFCTL_FLAG_OPTION; 2079126353Smlaier break; 2080130617Smlaier case 'p': 2081130617Smlaier pf_device = optarg; 2082130617Smlaier break; 2083126353Smlaier case 's': 2084126353Smlaier showopt = pfctl_lookup_option(optarg, showopt_list); 2085126353Smlaier if (showopt == NULL) { 2086126353Smlaier warnx("Unknown show modifier '%s'", optarg); 2087126353Smlaier usage(); 2088126353Smlaier } 2089126353Smlaier break; 2090126353Smlaier case 't': 2091126353Smlaier tableopt = optarg; 2092126353Smlaier break; 2093126353Smlaier case 'T': 2094126353Smlaier tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 2095126353Smlaier if (tblcmdopt == NULL) { 2096126353Smlaier warnx("Unknown table command '%s'", optarg); 2097126353Smlaier usage(); 2098126353Smlaier } 2099126353Smlaier break; 2100126353Smlaier case 'v': 2101126353Smlaier if (opts & PF_OPT_VERBOSE) 2102126353Smlaier opts |= PF_OPT_VERBOSE2; 2103126353Smlaier opts |= PF_OPT_VERBOSE; 2104126353Smlaier break; 2105126353Smlaier case 'x': 2106126353Smlaier debugopt = pfctl_lookup_option(optarg, debugopt_list); 2107126353Smlaier if (debugopt == NULL) { 2108126353Smlaier warnx("Unknown debug level '%s'", optarg); 2109126353Smlaier usage(); 2110126353Smlaier } 2111126353Smlaier mode = O_RDWR; 2112126353Smlaier break; 2113126353Smlaier case 'z': 2114126353Smlaier opts |= PF_OPT_CLRRULECTRS; 2115126353Smlaier mode = O_RDWR; 2116126353Smlaier break; 2117126353Smlaier case 'h': 2118126353Smlaier /* FALLTHROUGH */ 2119126353Smlaier default: 2120126353Smlaier usage(); 2121126353Smlaier /* NOTREACHED */ 2122126353Smlaier } 2123126353Smlaier } 2124126353Smlaier 2125126353Smlaier if (tblcmdopt != NULL) { 2126126353Smlaier argc -= optind; 2127126353Smlaier argv += optind; 2128126353Smlaier ch = *tblcmdopt; 2129126353Smlaier if (ch == 'l') { 2130126353Smlaier loadopt |= PFCTL_FLAG_TABLE; 2131126353Smlaier tblcmdopt = NULL; 2132130617Smlaier } else 2133171172Smlaier mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY; 2134126353Smlaier } else if (argc != optind) { 2135126353Smlaier warnx("unknown command line argument: %s ...", argv[optind]); 2136126353Smlaier usage(); 2137126353Smlaier /* NOTREACHED */ 2138126353Smlaier } 2139126353Smlaier if (loadopt == 0) 2140126353Smlaier loadopt = ~0; 2141126353Smlaier 2142171172Smlaier if ((path = calloc(1, MAXPATHLEN)) == NULL) 2143171172Smlaier errx(1, "pfctl: calloc"); 2144126353Smlaier memset(anchorname, 0, sizeof(anchorname)); 2145126353Smlaier if (anchoropt != NULL) { 2146171172Smlaier int len = strlen(anchoropt); 2147171172Smlaier 2148171172Smlaier if (anchoropt[len - 1] == '*') { 2149171172Smlaier if (len >= 2 && anchoropt[len - 2] == '/') 2150171172Smlaier anchoropt[len - 2] = '\0'; 2151171172Smlaier else 2152171172Smlaier anchoropt[len - 1] = '\0'; 2153171172Smlaier opts |= PF_OPT_RECURSE; 2154171172Smlaier } 2155145840Smlaier if (strlcpy(anchorname, anchoropt, 2156145840Smlaier sizeof(anchorname)) >= sizeof(anchorname)) 2157145840Smlaier errx(1, "anchor name '%s' too long", 2158145840Smlaier anchoropt); 2159126353Smlaier loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE; 2160126353Smlaier } 2161126353Smlaier 2162126353Smlaier if ((opts & PF_OPT_NOACTION) == 0) { 2163130617Smlaier dev = open(pf_device, mode); 2164126353Smlaier if (dev == -1) 2165130617Smlaier err(1, "%s", pf_device); 2166126353Smlaier altqsupport = pfctl_test_altqsupport(dev, opts); 2167126353Smlaier } else { 2168130617Smlaier dev = open(pf_device, O_RDONLY); 2169130617Smlaier if (dev >= 0) 2170130617Smlaier opts |= PF_OPT_DUMMYACTION; 2171126353Smlaier /* turn off options */ 2172126353Smlaier opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 2173126353Smlaier clearopt = showopt = debugopt = NULL; 2174126355Smlaier#if defined(__FreeBSD__) && !defined(ENABLE_ALTQ) 2175126355Smlaier altqsupport = 0; 2176126355Smlaier#else 2177126353Smlaier altqsupport = 1; 2178126355Smlaier#endif 2179126353Smlaier } 2180126353Smlaier 2181126353Smlaier if (opts & PF_OPT_DISABLE) 2182126353Smlaier if (pfctl_disable(dev, opts)) 2183126353Smlaier error = 1; 2184126353Smlaier 2185126353Smlaier if (showopt != NULL) { 2186126353Smlaier switch (*showopt) { 2187126353Smlaier case 'A': 2188126353Smlaier pfctl_show_anchors(dev, opts, anchorname); 2189126353Smlaier break; 2190126353Smlaier case 'r': 2191126353Smlaier pfctl_load_fingerprints(dev, opts); 2192171172Smlaier pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 2193171172Smlaier anchorname, 0); 2194126353Smlaier break; 2195126353Smlaier case 'l': 2196126353Smlaier pfctl_load_fingerprints(dev, opts); 2197171172Smlaier pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 2198171172Smlaier anchorname, 0); 2199126353Smlaier break; 2200126353Smlaier case 'n': 2201126353Smlaier pfctl_load_fingerprints(dev, opts); 2202145840Smlaier pfctl_show_nat(dev, opts, anchorname); 2203126353Smlaier break; 2204126353Smlaier case 'q': 2205130617Smlaier pfctl_show_altq(dev, ifaceopt, opts, 2206130617Smlaier opts & PF_OPT_VERBOSE2); 2207126353Smlaier break; 2208126353Smlaier case 's': 2209130617Smlaier pfctl_show_states(dev, ifaceopt, opts); 2210126353Smlaier break; 2211130617Smlaier case 'S': 2212130617Smlaier pfctl_show_src_nodes(dev, opts); 2213130617Smlaier break; 2214126353Smlaier case 'i': 2215130617Smlaier pfctl_show_status(dev, opts); 2216126353Smlaier break; 2217126353Smlaier case 't': 2218130617Smlaier pfctl_show_timeouts(dev, opts); 2219126353Smlaier break; 2220126353Smlaier case 'm': 2221130617Smlaier pfctl_show_limits(dev, opts); 2222126353Smlaier break; 2223126353Smlaier case 'a': 2224130617Smlaier opts |= PF_OPT_SHOWALL; 2225126353Smlaier pfctl_load_fingerprints(dev, opts); 2226126353Smlaier 2227145840Smlaier pfctl_show_nat(dev, opts, anchorname); 2228171172Smlaier pfctl_show_rules(dev, path, opts, 0, anchorname, 0); 2229130617Smlaier pfctl_show_altq(dev, ifaceopt, opts, 0); 2230130617Smlaier pfctl_show_states(dev, ifaceopt, opts); 2231130617Smlaier pfctl_show_src_nodes(dev, opts); 2232130617Smlaier pfctl_show_status(dev, opts); 2233171172Smlaier pfctl_show_rules(dev, path, opts, 1, anchorname, 0); 2234130617Smlaier pfctl_show_timeouts(dev, opts); 2235130617Smlaier pfctl_show_limits(dev, opts); 2236145840Smlaier pfctl_show_tables(anchorname, opts); 2237126353Smlaier pfctl_show_fingerprints(opts); 2238126353Smlaier break; 2239126353Smlaier case 'T': 2240145840Smlaier pfctl_show_tables(anchorname, opts); 2241126353Smlaier break; 2242126353Smlaier case 'o': 2243126353Smlaier pfctl_load_fingerprints(dev, opts); 2244126353Smlaier pfctl_show_fingerprints(opts); 2245126353Smlaier break; 2246130617Smlaier case 'I': 2247130617Smlaier pfctl_show_ifaces(ifaceopt, opts); 2248130617Smlaier break; 2249126353Smlaier } 2250126353Smlaier } 2251126353Smlaier 2252171172Smlaier if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) 2253171172Smlaier pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 2254171172Smlaier anchorname, 0); 2255171172Smlaier 2256126353Smlaier if (clearopt != NULL) { 2257171172Smlaier if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 2258171172Smlaier errx(1, "anchor names beginning with '_' cannot " 2259171172Smlaier "be modified from the command line"); 2260171172Smlaier 2261126353Smlaier switch (*clearopt) { 2262126353Smlaier case 'r': 2263145840Smlaier pfctl_clear_rules(dev, opts, anchorname); 2264126353Smlaier break; 2265126353Smlaier case 'n': 2266145840Smlaier pfctl_clear_nat(dev, opts, anchorname); 2267126353Smlaier break; 2268126353Smlaier case 'q': 2269126353Smlaier pfctl_clear_altq(dev, opts); 2270126353Smlaier break; 2271126353Smlaier case 's': 2272130617Smlaier pfctl_clear_states(dev, ifaceopt, opts); 2273126353Smlaier break; 2274130617Smlaier case 'S': 2275130617Smlaier pfctl_clear_src_nodes(dev, opts); 2276130617Smlaier break; 2277126353Smlaier case 'i': 2278126353Smlaier pfctl_clear_stats(dev, opts); 2279126353Smlaier break; 2280126353Smlaier case 'a': 2281145840Smlaier pfctl_clear_rules(dev, opts, anchorname); 2282145840Smlaier pfctl_clear_nat(dev, opts, anchorname); 2283145840Smlaier pfctl_clear_tables(anchorname, opts); 2284145840Smlaier if (!*anchorname) { 2285130617Smlaier pfctl_clear_altq(dev, opts); 2286130617Smlaier pfctl_clear_states(dev, ifaceopt, opts); 2287130617Smlaier pfctl_clear_src_nodes(dev, opts); 2288130617Smlaier pfctl_clear_stats(dev, opts); 2289130617Smlaier pfctl_clear_fingerprints(dev, opts); 2290145840Smlaier pfctl_clear_interface_flags(dev, opts); 2291130617Smlaier } 2292126353Smlaier break; 2293126353Smlaier case 'o': 2294126353Smlaier pfctl_clear_fingerprints(dev, opts); 2295126353Smlaier break; 2296126353Smlaier case 'T': 2297145840Smlaier pfctl_clear_tables(anchorname, opts); 2298126353Smlaier break; 2299126353Smlaier } 2300126353Smlaier } 2301126353Smlaier if (state_killers) 2302130617Smlaier pfctl_kill_states(dev, ifaceopt, opts); 2303126353Smlaier 2304171172Smlaier if (src_node_killers) 2305171172Smlaier pfctl_kill_src_nodes(dev, ifaceopt, opts); 2306171172Smlaier 2307126353Smlaier if (tblcmdopt != NULL) { 2308126353Smlaier error = pfctl_command_tables(argc, argv, tableopt, 2309145840Smlaier tblcmdopt, rulesopt, anchorname, opts); 2310126353Smlaier rulesopt = NULL; 2311126353Smlaier } 2312171172Smlaier if (optiopt != NULL) { 2313171172Smlaier switch (*optiopt) { 2314171172Smlaier case 'n': 2315171172Smlaier optimize = 0; 2316171172Smlaier break; 2317171172Smlaier case 'b': 2318171172Smlaier optimize |= PF_OPTIMIZE_BASIC; 2319171172Smlaier break; 2320171172Smlaier case 'o': 2321171172Smlaier case 'p': 2322171172Smlaier optimize |= PF_OPTIMIZE_PROFILE; 2323171172Smlaier break; 2324171172Smlaier } 2325171172Smlaier } 2326126353Smlaier 2327171172Smlaier if (rulesopt != NULL) { 2328171172Smlaier if (strcmp(rulesopt, "-") == 0) { 2329171172Smlaier fin = stdin; 2330171172Smlaier rulesopt = "stdin"; 2331171172Smlaier } else { 2332171172Smlaier if ((fin = pfctl_fopen(rulesopt, "r")) == NULL) 2333171172Smlaier err(1, "%s", rulesopt); 2334171172Smlaier } 2335171172Smlaier } 2336171172Smlaier if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) && 2337171172Smlaier !anchorname[0]) 2338145840Smlaier if (pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET)) 2339145840Smlaier error = 1; 2340145840Smlaier 2341145840Smlaier if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) && 2342145840Smlaier !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION)) 2343126353Smlaier if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 2344126353Smlaier error = 1; 2345126353Smlaier 2346126353Smlaier if (rulesopt != NULL) { 2347171172Smlaier if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 2348171172Smlaier errx(1, "anchor names beginning with '_' cannot " 2349171172Smlaier "be modified from the command line"); 2350171172Smlaier if (pfctl_rules(dev, rulesopt, fin, opts, optimize, 2351171172Smlaier anchorname, NULL)) 2352126353Smlaier error = 1; 2353126353Smlaier else if (!(opts & PF_OPT_NOACTION) && 2354126353Smlaier (loadopt & PFCTL_FLAG_TABLE)) 2355126353Smlaier warn_namespace_collision(NULL); 2356126353Smlaier } 2357126353Smlaier 2358126353Smlaier if (opts & PF_OPT_ENABLE) 2359126353Smlaier if (pfctl_enable(dev, opts)) 2360126353Smlaier error = 1; 2361126353Smlaier 2362126353Smlaier if (debugopt != NULL) { 2363126353Smlaier switch (*debugopt) { 2364126353Smlaier case 'n': 2365126353Smlaier pfctl_debug(dev, PF_DEBUG_NONE, opts); 2366126353Smlaier break; 2367126353Smlaier case 'u': 2368126353Smlaier pfctl_debug(dev, PF_DEBUG_URGENT, opts); 2369126353Smlaier break; 2370126353Smlaier case 'm': 2371126353Smlaier pfctl_debug(dev, PF_DEBUG_MISC, opts); 2372126353Smlaier break; 2373126353Smlaier case 'l': 2374126353Smlaier pfctl_debug(dev, PF_DEBUG_NOISY, opts); 2375126353Smlaier break; 2376126353Smlaier } 2377126353Smlaier } 2378126353Smlaier 2379126353Smlaier exit(error); 2380126353Smlaier} 2381