pfctl.c revision 262799
1223637Sbz/* $OpenBSD: pfctl.c,v 1.278 2008/08/31 20:18:17 jmc 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/sbin/pfctl/pfctl.c 262799 2014-03-05 19:26:22Z glebius $"); 36127082Sobrien 37126353Smlaier#include <sys/types.h> 38126353Smlaier#include <sys/ioctl.h> 39126353Smlaier#include <sys/socket.h> 40145840Smlaier#include <sys/stat.h> 41223637Sbz#include <sys/endian.h> 42223637Sbz 43126353Smlaier#include <net/if.h> 44126353Smlaier#include <netinet/in.h> 45126353Smlaier#include <net/pfvar.h> 46126353Smlaier#include <arpa/inet.h> 47126353Smlaier#include <altq/altq.h> 48171172Smlaier#include <sys/sysctl.h> 49126353Smlaier 50126353Smlaier#include <err.h> 51126353Smlaier#include <errno.h> 52126353Smlaier#include <fcntl.h> 53126353Smlaier#include <limits.h> 54126353Smlaier#include <netdb.h> 55262799Sglebius#include <stdint.h> 56126353Smlaier#include <stdio.h> 57126353Smlaier#include <stdlib.h> 58126353Smlaier#include <string.h> 59126353Smlaier#include <unistd.h> 60126353Smlaier 61126353Smlaier#include "pfctl_parser.h" 62126353Smlaier#include "pfctl.h" 63126353Smlaier 64126353Smlaiervoid usage(void); 65126353Smlaierint pfctl_enable(int, int); 66126353Smlaierint pfctl_disable(int, int); 67126353Smlaierint pfctl_clear_stats(int, int); 68145840Smlaierint pfctl_clear_interface_flags(int, int); 69145840Smlaierint pfctl_clear_rules(int, int, char *); 70145840Smlaierint pfctl_clear_nat(int, int, char *); 71126353Smlaierint pfctl_clear_altq(int, int); 72130617Smlaierint pfctl_clear_src_nodes(int, int); 73130617Smlaierint pfctl_clear_states(int, const char *, int); 74171172Smlaiervoid pfctl_addrprefix(char *, struct pf_addr *); 75171172Smlaierint pfctl_kill_src_nodes(int, const char *, int); 76223637Sbzint pfctl_net_kill_states(int, const char *, int); 77223637Sbzint pfctl_label_kill_states(int, const char *, int); 78223637Sbzint pfctl_id_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 129171172Smlaier#define INDENT(d, o) do { \ 130171172Smlaier if (o) { \ 131171172Smlaier int i; \ 132171172Smlaier for (i=0; i < d; i++) \ 133171172Smlaier printf(" "); \ 134171172Smlaier } \ 135171172Smlaier } while (0); \ 136171172Smlaier 137171172Smlaier 138126353Smlaierstatic const struct { 139126353Smlaier const char *name; 140126353Smlaier int index; 141126353Smlaier} pf_limits[] = { 142171172Smlaier { "states", PF_LIMIT_STATES }, 143171172Smlaier { "src-nodes", PF_LIMIT_SRC_NODES }, 144171172Smlaier { "frags", PF_LIMIT_FRAGS }, 145171172Smlaier { "table-entries", PF_LIMIT_TABLE_ENTRIES }, 146171172Smlaier { NULL, 0 } 147126353Smlaier}; 148126353Smlaier 149126353Smlaierstruct pf_hint { 150126353Smlaier const char *name; 151126353Smlaier int timeout; 152126353Smlaier}; 153126353Smlaierstatic const struct pf_hint pf_hint_normal[] = { 154126353Smlaier { "tcp.first", 2 * 60 }, 155126353Smlaier { "tcp.opening", 30 }, 156126353Smlaier { "tcp.established", 24 * 60 * 60 }, 157126353Smlaier { "tcp.closing", 15 * 60 }, 158126353Smlaier { "tcp.finwait", 45 }, 159126353Smlaier { "tcp.closed", 90 }, 160145840Smlaier { "tcp.tsdiff", 30 }, 161126353Smlaier { NULL, 0 } 162126353Smlaier}; 163126353Smlaierstatic const struct pf_hint pf_hint_satellite[] = { 164126353Smlaier { "tcp.first", 3 * 60 }, 165126353Smlaier { "tcp.opening", 30 + 5 }, 166126353Smlaier { "tcp.established", 24 * 60 * 60 }, 167126353Smlaier { "tcp.closing", 15 * 60 + 5 }, 168126353Smlaier { "tcp.finwait", 45 + 5 }, 169126353Smlaier { "tcp.closed", 90 + 5 }, 170145840Smlaier { "tcp.tsdiff", 60 }, 171126353Smlaier { NULL, 0 } 172126353Smlaier}; 173126353Smlaierstatic const struct pf_hint pf_hint_conservative[] = { 174126353Smlaier { "tcp.first", 60 * 60 }, 175126353Smlaier { "tcp.opening", 15 * 60 }, 176126353Smlaier { "tcp.established", 5 * 24 * 60 * 60 }, 177126353Smlaier { "tcp.closing", 60 * 60 }, 178126353Smlaier { "tcp.finwait", 10 * 60 }, 179126353Smlaier { "tcp.closed", 3 * 60 }, 180145840Smlaier { "tcp.tsdiff", 60 }, 181126353Smlaier { NULL, 0 } 182126353Smlaier}; 183126353Smlaierstatic const struct pf_hint pf_hint_aggressive[] = { 184126353Smlaier { "tcp.first", 30 }, 185126353Smlaier { "tcp.opening", 5 }, 186126353Smlaier { "tcp.established", 5 * 60 * 60 }, 187126353Smlaier { "tcp.closing", 60 }, 188126353Smlaier { "tcp.finwait", 30 }, 189126353Smlaier { "tcp.closed", 30 }, 190145840Smlaier { "tcp.tsdiff", 10 }, 191126353Smlaier { NULL, 0 } 192126353Smlaier}; 193126353Smlaier 194126353Smlaierstatic const struct { 195126353Smlaier const char *name; 196126353Smlaier const struct pf_hint *hint; 197126353Smlaier} pf_hints[] = { 198126353Smlaier { "normal", pf_hint_normal }, 199126353Smlaier { "satellite", pf_hint_satellite }, 200126353Smlaier { "high-latency", pf_hint_satellite }, 201126353Smlaier { "conservative", pf_hint_conservative }, 202126353Smlaier { "aggressive", pf_hint_aggressive }, 203126353Smlaier { NULL, NULL } 204126353Smlaier}; 205126353Smlaier 206126353Smlaierstatic const char *clearopt_list[] = { 207130617Smlaier "nat", "queue", "rules", "Sources", 208223637Sbz "states", "info", "Tables", "osfp", "all", NULL 209126353Smlaier}; 210126353Smlaier 211126353Smlaierstatic const char *showopt_list[] = { 212223637Sbz "nat", "queue", "rules", "Anchors", "Sources", "states", "info", 213130617Smlaier "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp", 214130617Smlaier "all", NULL 215126353Smlaier}; 216126353Smlaier 217126353Smlaierstatic const char *tblcmdopt_list[] = { 218126353Smlaier "kill", "flush", "add", "delete", "load", "replace", "show", 219171172Smlaier "test", "zero", "expire", NULL 220126353Smlaier}; 221126353Smlaier 222126353Smlaierstatic const char *debugopt_list[] = { 223126353Smlaier "none", "urgent", "misc", "loud", NULL 224126353Smlaier}; 225126353Smlaier 226171172Smlaierstatic const char *optiopt_list[] = { 227223637Sbz "none", "basic", "profile", NULL 228171172Smlaier}; 229126353Smlaier 230126353Smlaiervoid 231126353Smlaierusage(void) 232126353Smlaier{ 233126353Smlaier extern char *__progname; 234126353Smlaier 235258484Sglebius fprintf(stderr, 236258484Sglebius"usage: %s [-AdeghmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n" 237258484Sglebius "\t[-f file] [-i interface] [-K host | network]\n" 238258484Sglebius "\t[-k host | network | label | id] [-o level] [-p device]\n" 239258484Sglebius "\t[-s modifier] [-t table -T command [address ...]] [-x level]\n", 240258484Sglebius __progname); 241258484Sglebius 242126353Smlaier exit(1); 243126353Smlaier} 244126353Smlaier 245126353Smlaierint 246126353Smlaierpfctl_enable(int dev, int opts) 247126353Smlaier{ 248126353Smlaier if (ioctl(dev, DIOCSTART)) { 249126353Smlaier if (errno == EEXIST) 250126353Smlaier errx(1, "pf already enabled"); 251126355Smlaier else if (errno == ESRCH) 252126355Smlaier errx(1, "pfil registeration failed"); 253126353Smlaier else 254126353Smlaier err(1, "DIOCSTART"); 255126353Smlaier } 256126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 257126353Smlaier fprintf(stderr, "pf enabled\n"); 258126353Smlaier 259126353Smlaier if (altqsupport && ioctl(dev, DIOCSTARTALTQ)) 260126353Smlaier if (errno != EEXIST) 261126353Smlaier err(1, "DIOCSTARTALTQ"); 262126353Smlaier 263126353Smlaier return (0); 264126353Smlaier} 265126353Smlaier 266126353Smlaierint 267126353Smlaierpfctl_disable(int dev, int opts) 268126353Smlaier{ 269126353Smlaier if (ioctl(dev, DIOCSTOP)) { 270126353Smlaier if (errno == ENOENT) 271126353Smlaier errx(1, "pf not enabled"); 272126353Smlaier else 273126353Smlaier err(1, "DIOCSTOP"); 274126353Smlaier } 275126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 276126353Smlaier fprintf(stderr, "pf disabled\n"); 277126353Smlaier 278126353Smlaier if (altqsupport && ioctl(dev, DIOCSTOPALTQ)) 279126353Smlaier if (errno != ENOENT) 280126353Smlaier err(1, "DIOCSTOPALTQ"); 281126353Smlaier 282126353Smlaier return (0); 283126353Smlaier} 284126353Smlaier 285126353Smlaierint 286126353Smlaierpfctl_clear_stats(int dev, int opts) 287126353Smlaier{ 288126353Smlaier if (ioctl(dev, DIOCCLRSTATUS)) 289126353Smlaier err(1, "DIOCCLRSTATUS"); 290126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 291126353Smlaier fprintf(stderr, "pf: statistics cleared\n"); 292126353Smlaier return (0); 293126353Smlaier} 294126353Smlaier 295126353Smlaierint 296145840Smlaierpfctl_clear_interface_flags(int dev, int opts) 297126353Smlaier{ 298145840Smlaier struct pfioc_iface pi; 299126353Smlaier 300145840Smlaier if ((opts & PF_OPT_NOACTION) == 0) { 301145840Smlaier bzero(&pi, sizeof(pi)); 302171172Smlaier pi.pfiio_flags = PFI_IFLAG_SKIP; 303126353Smlaier 304145840Smlaier if (ioctl(dev, DIOCCLRIFFLAG, &pi)) 305145840Smlaier err(1, "DIOCCLRIFFLAG"); 306126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 307145840Smlaier fprintf(stderr, "pf: interface flags reset\n"); 308126353Smlaier } 309145840Smlaier return (0); 310145840Smlaier} 311145840Smlaier 312145840Smlaierint 313145840Smlaierpfctl_clear_rules(int dev, int opts, char *anchorname) 314145840Smlaier{ 315145840Smlaier struct pfr_buffer t; 316145840Smlaier 317130617Smlaier memset(&t, 0, sizeof(t)); 318130617Smlaier t.pfrb_type = PFRB_TRANS; 319145840Smlaier if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname) || 320145840Smlaier pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) || 321130617Smlaier pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 322130617Smlaier pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 323130617Smlaier err(1, "pfctl_clear_rules"); 324126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 325126353Smlaier fprintf(stderr, "rules cleared\n"); 326126353Smlaier return (0); 327126353Smlaier} 328126353Smlaier 329126353Smlaierint 330145840Smlaierpfctl_clear_nat(int dev, int opts, char *anchorname) 331126353Smlaier{ 332130617Smlaier struct pfr_buffer t; 333126353Smlaier 334130617Smlaier memset(&t, 0, sizeof(t)); 335130617Smlaier t.pfrb_type = PFRB_TRANS; 336145840Smlaier if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname) || 337145840Smlaier pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname) || 338145840Smlaier pfctl_add_trans(&t, PF_RULESET_RDR, anchorname) || 339130617Smlaier pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 340130617Smlaier pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 341130617Smlaier err(1, "pfctl_clear_nat"); 342126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 343126353Smlaier fprintf(stderr, "nat cleared\n"); 344126353Smlaier return (0); 345126353Smlaier} 346126353Smlaier 347126353Smlaierint 348126353Smlaierpfctl_clear_altq(int dev, int opts) 349126353Smlaier{ 350130617Smlaier struct pfr_buffer t; 351126353Smlaier 352126353Smlaier if (!altqsupport) 353126353Smlaier return (-1); 354130617Smlaier memset(&t, 0, sizeof(t)); 355130617Smlaier t.pfrb_type = PFRB_TRANS; 356145840Smlaier if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") || 357130617Smlaier pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 358130617Smlaier pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 359130617Smlaier err(1, "pfctl_clear_altq"); 360126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 361126353Smlaier fprintf(stderr, "altq cleared\n"); 362126353Smlaier return (0); 363126353Smlaier} 364126353Smlaier 365126353Smlaierint 366130617Smlaierpfctl_clear_src_nodes(int dev, int opts) 367126353Smlaier{ 368130617Smlaier if (ioctl(dev, DIOCCLRSRCNODES)) 369130617Smlaier err(1, "DIOCCLRSRCNODES"); 370130617Smlaier if ((opts & PF_OPT_QUIET) == 0) 371130617Smlaier fprintf(stderr, "source tracking entries cleared\n"); 372130617Smlaier return (0); 373130617Smlaier} 374130617Smlaier 375130617Smlaierint 376130617Smlaierpfctl_clear_states(int dev, const char *iface, int opts) 377130617Smlaier{ 378130617Smlaier struct pfioc_state_kill psk; 379130617Smlaier 380130617Smlaier memset(&psk, 0, sizeof(psk)); 381130617Smlaier if (iface != NULL && strlcpy(psk.psk_ifname, iface, 382130617Smlaier sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 383130617Smlaier errx(1, "invalid interface: %s", iface); 384130617Smlaier 385130617Smlaier if (ioctl(dev, DIOCCLRSTATES, &psk)) 386126353Smlaier err(1, "DIOCCLRSTATES"); 387126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 388223637Sbz fprintf(stderr, "%d states cleared\n", psk.psk_killed); 389126353Smlaier return (0); 390126353Smlaier} 391126353Smlaier 392171172Smlaiervoid 393171172Smlaierpfctl_addrprefix(char *addr, struct pf_addr *mask) 394171172Smlaier{ 395171172Smlaier char *p; 396171172Smlaier const char *errstr; 397171172Smlaier int prefix, ret_ga, q, r; 398171172Smlaier struct addrinfo hints, *res; 399171172Smlaier 400171172Smlaier if ((p = strchr(addr, '/')) == NULL) 401171172Smlaier return; 402171172Smlaier 403171172Smlaier *p++ = '\0'; 404171172Smlaier prefix = strtonum(p, 0, 128, &errstr); 405171172Smlaier if (errstr) 406171172Smlaier errx(1, "prefix is %s: %s", errstr, p); 407171172Smlaier 408171172Smlaier bzero(&hints, sizeof(hints)); 409171172Smlaier /* prefix only with numeric addresses */ 410171172Smlaier hints.ai_flags |= AI_NUMERICHOST; 411171172Smlaier 412171172Smlaier if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) { 413171172Smlaier errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 414171172Smlaier /* NOTREACHED */ 415171172Smlaier } 416171172Smlaier 417171172Smlaier if (res->ai_family == AF_INET && prefix > 32) 418171172Smlaier errx(1, "prefix too long for AF_INET"); 419171172Smlaier else if (res->ai_family == AF_INET6 && prefix > 128) 420171172Smlaier errx(1, "prefix too long for AF_INET6"); 421171172Smlaier 422171172Smlaier q = prefix >> 3; 423171172Smlaier r = prefix & 7; 424171172Smlaier switch (res->ai_family) { 425171172Smlaier case AF_INET: 426171172Smlaier bzero(&mask->v4, sizeof(mask->v4)); 427171172Smlaier mask->v4.s_addr = htonl((u_int32_t) 428171172Smlaier (0xffffffffffULL << (32 - prefix))); 429171172Smlaier break; 430171172Smlaier case AF_INET6: 431171172Smlaier bzero(&mask->v6, sizeof(mask->v6)); 432171172Smlaier if (q > 0) 433171172Smlaier memset((void *)&mask->v6, 0xff, q); 434171172Smlaier if (r > 0) 435171172Smlaier *((u_char *)&mask->v6 + q) = 436171172Smlaier (0xff00 >> r) & 0xff; 437171172Smlaier break; 438171172Smlaier } 439171172Smlaier freeaddrinfo(res); 440171172Smlaier} 441171172Smlaier 442126353Smlaierint 443171172Smlaierpfctl_kill_src_nodes(int dev, const char *iface, int opts) 444171172Smlaier{ 445171172Smlaier struct pfioc_src_node_kill psnk; 446171172Smlaier struct addrinfo *res[2], *resp[2]; 447171172Smlaier struct sockaddr last_src, last_dst; 448171172Smlaier int killed, sources, dests; 449171172Smlaier int ret_ga; 450171172Smlaier 451171172Smlaier killed = sources = dests = 0; 452171172Smlaier 453171172Smlaier memset(&psnk, 0, sizeof(psnk)); 454171172Smlaier memset(&psnk.psnk_src.addr.v.a.mask, 0xff, 455171172Smlaier sizeof(psnk.psnk_src.addr.v.a.mask)); 456171172Smlaier memset(&last_src, 0xff, sizeof(last_src)); 457171172Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 458171172Smlaier 459171172Smlaier pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask); 460171172Smlaier 461171172Smlaier if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) { 462171172Smlaier errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 463171172Smlaier /* NOTREACHED */ 464171172Smlaier } 465171172Smlaier for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 466171172Smlaier if (resp[0]->ai_addr == NULL) 467171172Smlaier continue; 468171172Smlaier /* We get lots of duplicates. Catch the easy ones */ 469171172Smlaier if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 470171172Smlaier continue; 471171172Smlaier last_src = *(struct sockaddr *)resp[0]->ai_addr; 472171172Smlaier 473171172Smlaier psnk.psnk_af = resp[0]->ai_family; 474171172Smlaier sources++; 475171172Smlaier 476171172Smlaier if (psnk.psnk_af == AF_INET) 477171172Smlaier psnk.psnk_src.addr.v.a.addr.v4 = 478171172Smlaier ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 479171172Smlaier else if (psnk.psnk_af == AF_INET6) 480171172Smlaier psnk.psnk_src.addr.v.a.addr.v6 = 481171172Smlaier ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 482171172Smlaier sin6_addr; 483171172Smlaier else 484171172Smlaier errx(1, "Unknown address family %d", psnk.psnk_af); 485171172Smlaier 486171172Smlaier if (src_node_killers > 1) { 487171172Smlaier dests = 0; 488171172Smlaier memset(&psnk.psnk_dst.addr.v.a.mask, 0xff, 489171172Smlaier sizeof(psnk.psnk_dst.addr.v.a.mask)); 490171172Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 491171172Smlaier pfctl_addrprefix(src_node_kill[1], 492171172Smlaier &psnk.psnk_dst.addr.v.a.mask); 493171172Smlaier if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL, 494171172Smlaier &res[1]))) { 495171172Smlaier errx(1, "getaddrinfo: %s", 496171172Smlaier gai_strerror(ret_ga)); 497171172Smlaier /* NOTREACHED */ 498171172Smlaier } 499171172Smlaier for (resp[1] = res[1]; resp[1]; 500171172Smlaier resp[1] = resp[1]->ai_next) { 501171172Smlaier if (resp[1]->ai_addr == NULL) 502171172Smlaier continue; 503171172Smlaier if (psnk.psnk_af != resp[1]->ai_family) 504171172Smlaier continue; 505171172Smlaier 506171172Smlaier if (memcmp(&last_dst, resp[1]->ai_addr, 507171172Smlaier sizeof(last_dst)) == 0) 508171172Smlaier continue; 509171172Smlaier last_dst = *(struct sockaddr *)resp[1]->ai_addr; 510171172Smlaier 511171172Smlaier dests++; 512171172Smlaier 513171172Smlaier if (psnk.psnk_af == AF_INET) 514171172Smlaier psnk.psnk_dst.addr.v.a.addr.v4 = 515171172Smlaier ((struct sockaddr_in *)resp[1]-> 516171172Smlaier ai_addr)->sin_addr; 517171172Smlaier else if (psnk.psnk_af == AF_INET6) 518171172Smlaier psnk.psnk_dst.addr.v.a.addr.v6 = 519171172Smlaier ((struct sockaddr_in6 *)resp[1]-> 520171172Smlaier ai_addr)->sin6_addr; 521171172Smlaier else 522171172Smlaier errx(1, "Unknown address family %d", 523171172Smlaier psnk.psnk_af); 524171172Smlaier 525171172Smlaier if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 526171172Smlaier err(1, "DIOCKILLSRCNODES"); 527223637Sbz killed += psnk.psnk_killed; 528171172Smlaier } 529171172Smlaier freeaddrinfo(res[1]); 530171172Smlaier } else { 531171172Smlaier if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 532171172Smlaier err(1, "DIOCKILLSRCNODES"); 533223637Sbz killed += psnk.psnk_killed; 534171172Smlaier } 535171172Smlaier } 536171172Smlaier 537171172Smlaier freeaddrinfo(res[0]); 538171172Smlaier 539171172Smlaier if ((opts & PF_OPT_QUIET) == 0) 540171172Smlaier fprintf(stderr, "killed %d src nodes from %d sources and %d " 541171172Smlaier "destinations\n", killed, sources, dests); 542171172Smlaier return (0); 543171172Smlaier} 544171172Smlaier 545171172Smlaierint 546223637Sbzpfctl_net_kill_states(int dev, const char *iface, int opts) 547126353Smlaier{ 548126353Smlaier struct pfioc_state_kill psk; 549126353Smlaier struct addrinfo *res[2], *resp[2]; 550126353Smlaier struct sockaddr last_src, last_dst; 551126353Smlaier int killed, sources, dests; 552126353Smlaier int ret_ga; 553126353Smlaier 554126353Smlaier killed = sources = dests = 0; 555126353Smlaier 556126353Smlaier memset(&psk, 0, sizeof(psk)); 557126353Smlaier memset(&psk.psk_src.addr.v.a.mask, 0xff, 558126353Smlaier sizeof(psk.psk_src.addr.v.a.mask)); 559126353Smlaier memset(&last_src, 0xff, sizeof(last_src)); 560126353Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 561130617Smlaier if (iface != NULL && strlcpy(psk.psk_ifname, iface, 562130617Smlaier sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 563130617Smlaier errx(1, "invalid interface: %s", iface); 564126353Smlaier 565171172Smlaier pfctl_addrprefix(state_kill[0], &psk.psk_src.addr.v.a.mask); 566171172Smlaier 567126353Smlaier if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) { 568126353Smlaier errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 569126353Smlaier /* NOTREACHED */ 570126353Smlaier } 571126353Smlaier for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 572126353Smlaier if (resp[0]->ai_addr == NULL) 573126353Smlaier continue; 574126353Smlaier /* We get lots of duplicates. Catch the easy ones */ 575126353Smlaier if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 576126353Smlaier continue; 577126353Smlaier last_src = *(struct sockaddr *)resp[0]->ai_addr; 578126353Smlaier 579126353Smlaier psk.psk_af = resp[0]->ai_family; 580126353Smlaier sources++; 581126353Smlaier 582126353Smlaier if (psk.psk_af == AF_INET) 583126353Smlaier psk.psk_src.addr.v.a.addr.v4 = 584126353Smlaier ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 585126353Smlaier else if (psk.psk_af == AF_INET6) 586126353Smlaier psk.psk_src.addr.v.a.addr.v6 = 587126353Smlaier ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 588126353Smlaier sin6_addr; 589126353Smlaier else 590126353Smlaier errx(1, "Unknown address family %d", psk.psk_af); 591126353Smlaier 592126353Smlaier if (state_killers > 1) { 593126353Smlaier dests = 0; 594126353Smlaier memset(&psk.psk_dst.addr.v.a.mask, 0xff, 595126353Smlaier sizeof(psk.psk_dst.addr.v.a.mask)); 596126353Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 597171172Smlaier pfctl_addrprefix(state_kill[1], 598171172Smlaier &psk.psk_dst.addr.v.a.mask); 599126353Smlaier if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, 600126353Smlaier &res[1]))) { 601130617Smlaier errx(1, "getaddrinfo: %s", 602130617Smlaier gai_strerror(ret_ga)); 603126353Smlaier /* NOTREACHED */ 604126353Smlaier } 605126353Smlaier for (resp[1] = res[1]; resp[1]; 606126353Smlaier resp[1] = resp[1]->ai_next) { 607126353Smlaier if (resp[1]->ai_addr == NULL) 608126353Smlaier continue; 609126353Smlaier if (psk.psk_af != resp[1]->ai_family) 610126353Smlaier continue; 611126353Smlaier 612126353Smlaier if (memcmp(&last_dst, resp[1]->ai_addr, 613126353Smlaier sizeof(last_dst)) == 0) 614126353Smlaier continue; 615126353Smlaier last_dst = *(struct sockaddr *)resp[1]->ai_addr; 616126353Smlaier 617126353Smlaier dests++; 618126353Smlaier 619126353Smlaier if (psk.psk_af == AF_INET) 620126353Smlaier psk.psk_dst.addr.v.a.addr.v4 = 621126353Smlaier ((struct sockaddr_in *)resp[1]-> 622126353Smlaier ai_addr)->sin_addr; 623126353Smlaier else if (psk.psk_af == AF_INET6) 624126353Smlaier psk.psk_dst.addr.v.a.addr.v6 = 625126353Smlaier ((struct sockaddr_in6 *)resp[1]-> 626126353Smlaier ai_addr)->sin6_addr; 627126353Smlaier else 628126353Smlaier errx(1, "Unknown address family %d", 629126353Smlaier psk.psk_af); 630126353Smlaier 631126353Smlaier if (ioctl(dev, DIOCKILLSTATES, &psk)) 632126353Smlaier err(1, "DIOCKILLSTATES"); 633223637Sbz killed += psk.psk_killed; 634126353Smlaier } 635126353Smlaier freeaddrinfo(res[1]); 636126353Smlaier } else { 637126353Smlaier if (ioctl(dev, DIOCKILLSTATES, &psk)) 638126353Smlaier err(1, "DIOCKILLSTATES"); 639223637Sbz killed += psk.psk_killed; 640126353Smlaier } 641126353Smlaier } 642126353Smlaier 643126353Smlaier freeaddrinfo(res[0]); 644126353Smlaier 645126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 646126353Smlaier fprintf(stderr, "killed %d states from %d sources and %d " 647126353Smlaier "destinations\n", killed, sources, dests); 648126353Smlaier return (0); 649126353Smlaier} 650126353Smlaier 651126353Smlaierint 652223637Sbzpfctl_label_kill_states(int dev, const char *iface, int opts) 653223637Sbz{ 654223637Sbz struct pfioc_state_kill psk; 655223637Sbz 656223637Sbz if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 657223637Sbz warnx("no label specified"); 658223637Sbz usage(); 659223637Sbz } 660223637Sbz memset(&psk, 0, sizeof(psk)); 661223637Sbz if (iface != NULL && strlcpy(psk.psk_ifname, iface, 662223637Sbz sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 663223637Sbz errx(1, "invalid interface: %s", iface); 664223637Sbz 665223637Sbz if (strlcpy(psk.psk_label, state_kill[1], sizeof(psk.psk_label)) >= 666223637Sbz sizeof(psk.psk_label)) 667223637Sbz errx(1, "label too long: %s", state_kill[1]); 668223637Sbz 669223637Sbz if (ioctl(dev, DIOCKILLSTATES, &psk)) 670223637Sbz err(1, "DIOCKILLSTATES"); 671223637Sbz 672223637Sbz if ((opts & PF_OPT_QUIET) == 0) 673223637Sbz fprintf(stderr, "killed %d states\n", psk.psk_killed); 674223637Sbz 675223637Sbz return (0); 676223637Sbz} 677223637Sbz 678223637Sbzint 679223637Sbzpfctl_id_kill_states(int dev, const char *iface, int opts) 680223637Sbz{ 681223637Sbz struct pfioc_state_kill psk; 682223637Sbz 683223637Sbz if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 684223637Sbz warnx("no id specified"); 685223637Sbz usage(); 686223637Sbz } 687223637Sbz 688223637Sbz memset(&psk, 0, sizeof(psk)); 689223637Sbz if ((sscanf(state_kill[1], "%jx/%x", 690223637Sbz &psk.psk_pfcmp.id, &psk.psk_pfcmp.creatorid)) == 2) 691223637Sbz HTONL(psk.psk_pfcmp.creatorid); 692223637Sbz else if ((sscanf(state_kill[1], "%jx", &psk.psk_pfcmp.id)) == 1) { 693223637Sbz psk.psk_pfcmp.creatorid = 0; 694223637Sbz } else { 695223637Sbz warnx("wrong id format specified"); 696223637Sbz usage(); 697223637Sbz } 698223637Sbz if (psk.psk_pfcmp.id == 0) { 699223637Sbz warnx("cannot kill id 0"); 700223637Sbz usage(); 701223637Sbz } 702223637Sbz 703223637Sbz psk.psk_pfcmp.id = htobe64(psk.psk_pfcmp.id); 704223637Sbz if (ioctl(dev, DIOCKILLSTATES, &psk)) 705223637Sbz err(1, "DIOCKILLSTATES"); 706223637Sbz 707223637Sbz if ((opts & PF_OPT_QUIET) == 0) 708223637Sbz fprintf(stderr, "killed %d states\n", psk.psk_killed); 709223637Sbz 710223637Sbz return (0); 711223637Sbz} 712223637Sbz 713223637Sbzint 714126353Smlaierpfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr, 715145840Smlaier u_int32_t ticket, int r_action, char *anchorname) 716126353Smlaier{ 717126353Smlaier struct pfioc_pooladdr pp; 718126353Smlaier struct pf_pooladdr *pa; 719126353Smlaier u_int32_t pnr, mpnr; 720126353Smlaier 721126353Smlaier memset(&pp, 0, sizeof(pp)); 722126353Smlaier memcpy(pp.anchor, anchorname, sizeof(pp.anchor)); 723126353Smlaier pp.r_action = r_action; 724126353Smlaier pp.r_num = nr; 725126353Smlaier pp.ticket = ticket; 726126353Smlaier if (ioctl(dev, DIOCGETADDRS, &pp)) { 727126353Smlaier warn("DIOCGETADDRS"); 728126353Smlaier return (-1); 729126353Smlaier } 730126353Smlaier mpnr = pp.nr; 731126353Smlaier TAILQ_INIT(&pool->list); 732126353Smlaier for (pnr = 0; pnr < mpnr; ++pnr) { 733126353Smlaier pp.nr = pnr; 734126353Smlaier if (ioctl(dev, DIOCGETADDR, &pp)) { 735126353Smlaier warn("DIOCGETADDR"); 736126353Smlaier return (-1); 737126353Smlaier } 738126353Smlaier pa = calloc(1, sizeof(struct pf_pooladdr)); 739126353Smlaier if (pa == NULL) 740126353Smlaier err(1, "calloc"); 741126353Smlaier bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr)); 742126353Smlaier TAILQ_INSERT_TAIL(&pool->list, pa, entries); 743126353Smlaier } 744126353Smlaier 745126353Smlaier return (0); 746126353Smlaier} 747126353Smlaier 748126353Smlaiervoid 749171172Smlaierpfctl_move_pool(struct pf_pool *src, struct pf_pool *dst) 750171172Smlaier{ 751171172Smlaier struct pf_pooladdr *pa; 752171172Smlaier 753171172Smlaier while ((pa = TAILQ_FIRST(&src->list)) != NULL) { 754171172Smlaier TAILQ_REMOVE(&src->list, pa, entries); 755171172Smlaier TAILQ_INSERT_TAIL(&dst->list, pa, entries); 756171172Smlaier } 757171172Smlaier} 758171172Smlaier 759171172Smlaiervoid 760126353Smlaierpfctl_clear_pool(struct pf_pool *pool) 761126353Smlaier{ 762126353Smlaier struct pf_pooladdr *pa; 763126353Smlaier 764126353Smlaier while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { 765126353Smlaier TAILQ_REMOVE(&pool->list, pa, entries); 766126353Smlaier free(pa); 767126353Smlaier } 768126353Smlaier} 769126353Smlaier 770126353Smlaiervoid 771126353Smlaierpfctl_print_rule_counters(struct pf_rule *rule, int opts) 772126353Smlaier{ 773126353Smlaier if (opts & PF_OPT_DEBUG) { 774126353Smlaier const char *t[PF_SKIP_COUNT] = { "i", "d", "f", 775126353Smlaier "p", "sa", "sp", "da", "dp" }; 776126353Smlaier int i; 777126353Smlaier 778126353Smlaier printf(" [ Skip steps: "); 779126353Smlaier for (i = 0; i < PF_SKIP_COUNT; ++i) { 780126353Smlaier if (rule->skip[i].nr == rule->nr + 1) 781126353Smlaier continue; 782126353Smlaier printf("%s=", t[i]); 783126353Smlaier if (rule->skip[i].nr == -1) 784126353Smlaier printf("end "); 785126353Smlaier else 786126353Smlaier printf("%u ", rule->skip[i].nr); 787126353Smlaier } 788126353Smlaier printf("]\n"); 789126353Smlaier 790126353Smlaier printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n", 791126353Smlaier rule->qname, rule->qid, rule->pqname, rule->pqid); 792126353Smlaier } 793171172Smlaier if (opts & PF_OPT_VERBOSE) { 794127024Smlaier printf(" [ Evaluations: %-8llu Packets: %-8llu " 795262799Sglebius "Bytes: %-10llu States: %-6ju]\n", 796127024Smlaier (unsigned long long)rule->evaluations, 797171172Smlaier (unsigned long long)(rule->packets[0] + 798171172Smlaier rule->packets[1]), 799171172Smlaier (unsigned long long)(rule->bytes[0] + 800262799Sglebius rule->bytes[1]), (uintmax_t)rule->u_states_cur); 801171172Smlaier if (!(opts & PF_OPT_DEBUG)) 802223637Sbz printf(" [ Inserted: uid %u pid %u " 803262799Sglebius "State Creations: %-6ju]\n", 804223637Sbz (unsigned)rule->cuid, (unsigned)rule->cpid, 805262799Sglebius (uintmax_t)rule->u_states_tot); 806171172Smlaier } 807126353Smlaier} 808126353Smlaier 809130617Smlaiervoid 810130617Smlaierpfctl_print_title(char *title) 811130617Smlaier{ 812130617Smlaier if (!first_title) 813130617Smlaier printf("\n"); 814130617Smlaier first_title = 0; 815130617Smlaier printf("%s\n", title); 816130617Smlaier} 817130617Smlaier 818126353Smlaierint 819171172Smlaierpfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, 820171172Smlaier char *anchorname, int depth) 821126353Smlaier{ 822126353Smlaier struct pfioc_rule pr; 823130617Smlaier u_int32_t nr, mnr, header = 0; 824126353Smlaier int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); 825223057Sbz int numeric = opts & PF_OPT_NUMERIC; 826171172Smlaier int len = strlen(path); 827171172Smlaier int brace; 828171172Smlaier char *p; 829126353Smlaier 830171172Smlaier if (path[0]) 831171172Smlaier snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 832171172Smlaier else 833171172Smlaier snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 834171172Smlaier 835126353Smlaier memset(&pr, 0, sizeof(pr)); 836171172Smlaier memcpy(pr.anchor, path, sizeof(pr.anchor)); 837130617Smlaier if (opts & PF_OPT_SHOWALL) { 838130617Smlaier pr.rule.action = PF_PASS; 839130617Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 840130617Smlaier warn("DIOCGETRULES"); 841171172Smlaier goto error; 842130617Smlaier } 843130617Smlaier header++; 844130617Smlaier } 845126353Smlaier pr.rule.action = PF_SCRUB; 846126353Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 847126353Smlaier warn("DIOCGETRULES"); 848171172Smlaier goto error; 849126353Smlaier } 850130617Smlaier if (opts & PF_OPT_SHOWALL) { 851171172Smlaier if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header)) 852130617Smlaier pfctl_print_title("FILTER RULES:"); 853171172Smlaier else if (format == PFCTL_SHOW_LABELS && labels) 854130617Smlaier pfctl_print_title("LABEL COUNTERS:"); 855130617Smlaier } 856126353Smlaier mnr = pr.nr; 857171172Smlaier if (opts & PF_OPT_CLRRULECTRS) 858171172Smlaier pr.action = PF_GET_CLR_CNTR; 859171172Smlaier 860126353Smlaier for (nr = 0; nr < mnr; ++nr) { 861126353Smlaier pr.nr = nr; 862126353Smlaier if (ioctl(dev, DIOCGETRULE, &pr)) { 863126353Smlaier warn("DIOCGETRULE"); 864171172Smlaier goto error; 865126353Smlaier } 866126353Smlaier 867126353Smlaier if (pfctl_get_pool(dev, &pr.rule.rpool, 868171172Smlaier nr, pr.ticket, PF_SCRUB, path) != 0) 869171172Smlaier goto error; 870126353Smlaier 871126353Smlaier switch (format) { 872171172Smlaier case PFCTL_SHOW_LABELS: 873126353Smlaier break; 874171172Smlaier case PFCTL_SHOW_RULES: 875130617Smlaier if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) 876130617Smlaier labels = 1; 877223057Sbz print_rule(&pr.rule, pr.anchor_call, rule_numbers, numeric); 878171172Smlaier printf("\n"); 879126353Smlaier pfctl_print_rule_counters(&pr.rule, opts); 880171172Smlaier break; 881171172Smlaier case PFCTL_SHOW_NOTHING: 882171172Smlaier break; 883126353Smlaier } 884126353Smlaier pfctl_clear_pool(&pr.rule.rpool); 885126353Smlaier } 886126353Smlaier pr.rule.action = PF_PASS; 887126353Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 888126353Smlaier warn("DIOCGETRULES"); 889171172Smlaier goto error; 890126353Smlaier } 891126353Smlaier mnr = pr.nr; 892126353Smlaier for (nr = 0; nr < mnr; ++nr) { 893126353Smlaier pr.nr = nr; 894126353Smlaier if (ioctl(dev, DIOCGETRULE, &pr)) { 895126353Smlaier warn("DIOCGETRULE"); 896171172Smlaier goto error; 897126353Smlaier } 898126353Smlaier 899126353Smlaier if (pfctl_get_pool(dev, &pr.rule.rpool, 900171172Smlaier nr, pr.ticket, PF_PASS, path) != 0) 901171172Smlaier goto error; 902126353Smlaier 903126353Smlaier switch (format) { 904171172Smlaier case PFCTL_SHOW_LABELS: 905126353Smlaier if (pr.rule.label[0]) { 906223637Sbz printf("%s %llu %llu %llu %llu" 907262799Sglebius " %llu %llu %llu %ju\n", 908223637Sbz pr.rule.label, 909127024Smlaier (unsigned long long)pr.rule.evaluations, 910171172Smlaier (unsigned long long)(pr.rule.packets[0] + 911171172Smlaier pr.rule.packets[1]), 912171172Smlaier (unsigned long long)(pr.rule.bytes[0] + 913171172Smlaier pr.rule.bytes[1]), 914171172Smlaier (unsigned long long)pr.rule.packets[0], 915171172Smlaier (unsigned long long)pr.rule.bytes[0], 916171172Smlaier (unsigned long long)pr.rule.packets[1], 917223637Sbz (unsigned long long)pr.rule.bytes[1], 918262799Sglebius (uintmax_t)pr.rule.u_states_tot); 919126353Smlaier } 920126353Smlaier break; 921171172Smlaier case PFCTL_SHOW_RULES: 922171172Smlaier brace = 0; 923130617Smlaier if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) 924130617Smlaier labels = 1; 925171172Smlaier INDENT(depth, !(opts & PF_OPT_VERBOSE)); 926171172Smlaier if (pr.anchor_call[0] && 927171172Smlaier ((((p = strrchr(pr.anchor_call, '_')) != NULL) && 928171172Smlaier ((void *)p == (void *)pr.anchor_call || 929171172Smlaier *(--p) == '/')) || (opts & PF_OPT_RECURSE))) { 930171172Smlaier brace++; 931171172Smlaier if ((p = strrchr(pr.anchor_call, '/')) != 932171172Smlaier NULL) 933171172Smlaier p++; 934171172Smlaier else 935171172Smlaier p = &pr.anchor_call[0]; 936171172Smlaier } else 937171172Smlaier p = &pr.anchor_call[0]; 938171172Smlaier 939223057Sbz print_rule(&pr.rule, p, rule_numbers, numeric); 940171172Smlaier if (brace) 941171172Smlaier printf(" {\n"); 942171172Smlaier else 943171172Smlaier printf("\n"); 944126353Smlaier pfctl_print_rule_counters(&pr.rule, opts); 945171172Smlaier if (brace) { 946171172Smlaier pfctl_show_rules(dev, path, opts, format, 947171172Smlaier p, depth + 1); 948171172Smlaier INDENT(depth, !(opts & PF_OPT_VERBOSE)); 949171172Smlaier printf("}\n"); 950171172Smlaier } 951171172Smlaier break; 952171172Smlaier case PFCTL_SHOW_NOTHING: 953171172Smlaier break; 954126353Smlaier } 955126353Smlaier pfctl_clear_pool(&pr.rule.rpool); 956126353Smlaier } 957171172Smlaier path[len] = '\0'; 958126353Smlaier return (0); 959171172Smlaier 960171172Smlaier error: 961171172Smlaier path[len] = '\0'; 962171172Smlaier return (-1); 963126353Smlaier} 964126353Smlaier 965126353Smlaierint 966145840Smlaierpfctl_show_nat(int dev, int opts, char *anchorname) 967126353Smlaier{ 968126353Smlaier struct pfioc_rule pr; 969126353Smlaier u_int32_t mnr, nr; 970126353Smlaier static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; 971130617Smlaier int i, dotitle = opts & PF_OPT_SHOWALL; 972126353Smlaier 973126353Smlaier memset(&pr, 0, sizeof(pr)); 974126353Smlaier memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 975126353Smlaier for (i = 0; i < 3; i++) { 976126353Smlaier pr.rule.action = nattype[i]; 977126353Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 978126353Smlaier warn("DIOCGETRULES"); 979126353Smlaier return (-1); 980126353Smlaier } 981126353Smlaier mnr = pr.nr; 982126353Smlaier for (nr = 0; nr < mnr; ++nr) { 983126353Smlaier pr.nr = nr; 984126353Smlaier if (ioctl(dev, DIOCGETRULE, &pr)) { 985126353Smlaier warn("DIOCGETRULE"); 986126353Smlaier return (-1); 987126353Smlaier } 988126353Smlaier if (pfctl_get_pool(dev, &pr.rule.rpool, nr, 989145840Smlaier pr.ticket, nattype[i], anchorname) != 0) 990126353Smlaier return (-1); 991130617Smlaier if (dotitle) { 992130617Smlaier pfctl_print_title("TRANSLATION RULES:"); 993130617Smlaier dotitle = 0; 994130617Smlaier } 995145840Smlaier print_rule(&pr.rule, pr.anchor_call, 996223057Sbz opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC); 997171172Smlaier printf("\n"); 998126353Smlaier pfctl_print_rule_counters(&pr.rule, opts); 999126353Smlaier pfctl_clear_pool(&pr.rule.rpool); 1000126353Smlaier } 1001126353Smlaier } 1002126353Smlaier return (0); 1003126353Smlaier} 1004126353Smlaier 1005126353Smlaierint 1006130617Smlaierpfctl_show_src_nodes(int dev, int opts) 1007126353Smlaier{ 1008130617Smlaier struct pfioc_src_nodes psn; 1009130617Smlaier struct pf_src_node *p; 1010130617Smlaier char *inbuf = NULL, *newinbuf = NULL; 1011223637Sbz unsigned int len = 0; 1012130617Smlaier int i; 1013130617Smlaier 1014130617Smlaier memset(&psn, 0, sizeof(psn)); 1015130617Smlaier for (;;) { 1016130617Smlaier psn.psn_len = len; 1017130617Smlaier if (len) { 1018130617Smlaier newinbuf = realloc(inbuf, len); 1019130617Smlaier if (newinbuf == NULL) 1020130617Smlaier err(1, "realloc"); 1021130617Smlaier psn.psn_buf = inbuf = newinbuf; 1022130617Smlaier } 1023130617Smlaier if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) { 1024130617Smlaier warn("DIOCGETSRCNODES"); 1025171172Smlaier free(inbuf); 1026130617Smlaier return (-1); 1027130617Smlaier } 1028130617Smlaier if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len) 1029130617Smlaier break; 1030130617Smlaier if (len == 0 && psn.psn_len == 0) 1031171172Smlaier goto done; 1032130617Smlaier if (len == 0 && psn.psn_len != 0) 1033130617Smlaier len = psn.psn_len; 1034130617Smlaier if (psn.psn_len == 0) 1035171172Smlaier goto done; /* no src_nodes */ 1036130617Smlaier len *= 2; 1037130617Smlaier } 1038130617Smlaier p = psn.psn_src_nodes; 1039130617Smlaier if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL)) 1040130617Smlaier pfctl_print_title("SOURCE TRACKING NODES:"); 1041130617Smlaier for (i = 0; i < psn.psn_len; i += sizeof(*p)) { 1042130617Smlaier print_src_node(p, opts); 1043130617Smlaier p++; 1044130617Smlaier } 1045171172Smlaierdone: 1046171172Smlaier free(inbuf); 1047130617Smlaier return (0); 1048130617Smlaier} 1049130617Smlaier 1050130617Smlaierint 1051130617Smlaierpfctl_show_states(int dev, const char *iface, int opts) 1052130617Smlaier{ 1053126353Smlaier struct pfioc_states ps; 1054223637Sbz struct pfsync_state *p; 1055130617Smlaier char *inbuf = NULL, *newinbuf = NULL; 1056223637Sbz unsigned int len = 0; 1057130617Smlaier int i, dotitle = (opts & PF_OPT_SHOWALL); 1058126353Smlaier 1059126353Smlaier memset(&ps, 0, sizeof(ps)); 1060126353Smlaier for (;;) { 1061126353Smlaier ps.ps_len = len; 1062126353Smlaier if (len) { 1063130617Smlaier newinbuf = realloc(inbuf, len); 1064130617Smlaier if (newinbuf == NULL) 1065126353Smlaier err(1, "realloc"); 1066130617Smlaier ps.ps_buf = inbuf = newinbuf; 1067126353Smlaier } 1068126353Smlaier if (ioctl(dev, DIOCGETSTATES, &ps) < 0) { 1069126353Smlaier warn("DIOCGETSTATES"); 1070171172Smlaier free(inbuf); 1071126353Smlaier return (-1); 1072126353Smlaier } 1073126353Smlaier if (ps.ps_len + sizeof(struct pfioc_states) < len) 1074126353Smlaier break; 1075126353Smlaier if (len == 0 && ps.ps_len == 0) 1076171172Smlaier goto done; 1077126353Smlaier if (len == 0 && ps.ps_len != 0) 1078126353Smlaier len = ps.ps_len; 1079126353Smlaier if (ps.ps_len == 0) 1080171172Smlaier goto done; /* no states */ 1081126353Smlaier len *= 2; 1082126353Smlaier } 1083126353Smlaier p = ps.ps_states; 1084130617Smlaier for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) { 1085223637Sbz if (iface != NULL && strcmp(p->ifname, iface)) 1086130617Smlaier continue; 1087130617Smlaier if (dotitle) { 1088130617Smlaier pfctl_print_title("STATES:"); 1089130617Smlaier dotitle = 0; 1090130617Smlaier } 1091130617Smlaier print_state(p, opts); 1092126353Smlaier } 1093171172Smlaierdone: 1094171172Smlaier free(inbuf); 1095126353Smlaier return (0); 1096126353Smlaier} 1097126353Smlaier 1098126353Smlaierint 1099130617Smlaierpfctl_show_status(int dev, int opts) 1100126353Smlaier{ 1101126353Smlaier struct pf_status status; 1102126353Smlaier 1103126353Smlaier if (ioctl(dev, DIOCGETSTATUS, &status)) { 1104126353Smlaier warn("DIOCGETSTATUS"); 1105126353Smlaier return (-1); 1106126353Smlaier } 1107130617Smlaier if (opts & PF_OPT_SHOWALL) 1108130617Smlaier pfctl_print_title("INFO:"); 1109130617Smlaier print_status(&status, opts); 1110126353Smlaier return (0); 1111126353Smlaier} 1112126353Smlaier 1113126353Smlaierint 1114130617Smlaierpfctl_show_timeouts(int dev, int opts) 1115126353Smlaier{ 1116126353Smlaier struct pfioc_tm pt; 1117126353Smlaier int i; 1118126353Smlaier 1119130617Smlaier if (opts & PF_OPT_SHOWALL) 1120130617Smlaier pfctl_print_title("TIMEOUTS:"); 1121126353Smlaier memset(&pt, 0, sizeof(pt)); 1122126353Smlaier for (i = 0; pf_timeouts[i].name; i++) { 1123126353Smlaier pt.timeout = pf_timeouts[i].timeout; 1124126353Smlaier if (ioctl(dev, DIOCGETTIMEOUT, &pt)) 1125126353Smlaier err(1, "DIOCGETTIMEOUT"); 1126126353Smlaier printf("%-20s %10d", pf_timeouts[i].name, pt.seconds); 1127145840Smlaier if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && 1128145840Smlaier pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) 1129126353Smlaier printf(" states"); 1130126353Smlaier else 1131126353Smlaier printf("s"); 1132126353Smlaier printf("\n"); 1133126353Smlaier } 1134126353Smlaier return (0); 1135126353Smlaier 1136126353Smlaier} 1137126353Smlaier 1138126353Smlaierint 1139130617Smlaierpfctl_show_limits(int dev, int opts) 1140126353Smlaier{ 1141126353Smlaier struct pfioc_limit pl; 1142126353Smlaier int i; 1143126353Smlaier 1144130617Smlaier if (opts & PF_OPT_SHOWALL) 1145130617Smlaier pfctl_print_title("LIMITS:"); 1146126353Smlaier memset(&pl, 0, sizeof(pl)); 1147126353Smlaier for (i = 0; pf_limits[i].name; i++) { 1148130617Smlaier pl.index = pf_limits[i].index; 1149126353Smlaier if (ioctl(dev, DIOCGETLIMIT, &pl)) 1150126353Smlaier err(1, "DIOCGETLIMIT"); 1151171172Smlaier printf("%-13s ", pf_limits[i].name); 1152126353Smlaier if (pl.limit == UINT_MAX) 1153126353Smlaier printf("unlimited\n"); 1154126353Smlaier else 1155171172Smlaier printf("hard limit %8u\n", pl.limit); 1156126353Smlaier } 1157126353Smlaier return (0); 1158126353Smlaier} 1159126353Smlaier 1160126353Smlaier/* callbacks for rule/nat/rdr/addr */ 1161126353Smlaierint 1162126353Smlaierpfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af) 1163126353Smlaier{ 1164126353Smlaier struct pf_pooladdr *pa; 1165126353Smlaier 1166126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1167126353Smlaier if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) 1168126353Smlaier err(1, "DIOCBEGINADDRS"); 1169126353Smlaier } 1170126353Smlaier 1171126353Smlaier pf->paddr.af = af; 1172126353Smlaier TAILQ_FOREACH(pa, &p->list, entries) { 1173126353Smlaier memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr)); 1174126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1175126353Smlaier if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) 1176126353Smlaier err(1, "DIOCADDADDR"); 1177126353Smlaier } 1178126353Smlaier } 1179126353Smlaier return (0); 1180126353Smlaier} 1181126353Smlaier 1182126353Smlaierint 1183145840Smlaierpfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call) 1184126353Smlaier{ 1185130617Smlaier u_int8_t rs_num; 1186171172Smlaier struct pf_rule *rule; 1187171172Smlaier struct pf_ruleset *rs; 1188171172Smlaier char *p; 1189126353Smlaier 1190171172Smlaier rs_num = pf_get_ruleset_number(r->action); 1191171172Smlaier if (rs_num == PF_RULESET_MAX) 1192145840Smlaier errx(1, "Invalid rule type %d", r->action); 1193126353Smlaier 1194171172Smlaier rs = &pf->anchor->ruleset; 1195145840Smlaier 1196171172Smlaier if (anchor_call[0] && r->anchor == NULL) { 1197171172Smlaier /* 1198171172Smlaier * Don't make non-brace anchors part of the main anchor pool. 1199145840Smlaier */ 1200171172Smlaier if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 1201171172Smlaier err(1, "pfctl_add_rule: calloc"); 1202171172Smlaier 1203171172Smlaier pf_init_ruleset(&r->anchor->ruleset); 1204171172Smlaier r->anchor->ruleset.anchor = r->anchor; 1205171172Smlaier if (strlcpy(r->anchor->path, anchor_call, 1206171172Smlaier sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 1207223637Sbz errx(1, "pfctl_add_rule: strlcpy"); 1208171172Smlaier if ((p = strrchr(anchor_call, '/')) != NULL) { 1209171172Smlaier if (!strlen(p)) 1210171172Smlaier err(1, "pfctl_add_rule: bad anchor name %s", 1211171172Smlaier anchor_call); 1212171172Smlaier } else 1213171172Smlaier p = (char *)anchor_call; 1214171172Smlaier if (strlcpy(r->anchor->name, p, 1215171172Smlaier sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 1216223637Sbz errx(1, "pfctl_add_rule: strlcpy"); 1217171172Smlaier } 1218145840Smlaier 1219171172Smlaier if ((rule = calloc(1, sizeof(*rule))) == NULL) 1220171172Smlaier err(1, "calloc"); 1221171172Smlaier bcopy(r, rule, sizeof(*rule)); 1222171172Smlaier TAILQ_INIT(&rule->rpool.list); 1223171172Smlaier pfctl_move_pool(&r->rpool, &rule->rpool); 1224145840Smlaier 1225171172Smlaier TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries); 1226171172Smlaier return (0); 1227171172Smlaier} 1228171172Smlaier 1229171172Smlaierint 1230171172Smlaierpfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a) 1231171172Smlaier{ 1232171172Smlaier int osize = pf->trans->pfrb_size; 1233171172Smlaier 1234171172Smlaier if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { 1235171172Smlaier if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || 1236171172Smlaier pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || 1237171172Smlaier pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) 1238171172Smlaier return (1); 1239171172Smlaier } 1240171172Smlaier if (a == pf->astack[0] && ((altqsupport && 1241223637Sbz (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) { 1242171172Smlaier if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path)) 1243171172Smlaier return (2); 1244171172Smlaier } 1245171172Smlaier if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) { 1246171172Smlaier if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) || 1247171172Smlaier pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path)) 1248171172Smlaier return (3); 1249171172Smlaier } 1250171172Smlaier if (pf->loadopt & PFCTL_FLAG_TABLE) 1251171172Smlaier if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path)) 1252171172Smlaier return (4); 1253171172Smlaier if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1254171172Smlaier return (5); 1255171172Smlaier 1256171172Smlaier return (0); 1257171172Smlaier} 1258171172Smlaier 1259171172Smlaierint 1260171172Smlaierpfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs, 1261171172Smlaier int rs_num, int depth) 1262171172Smlaier{ 1263171172Smlaier struct pf_rule *r; 1264171172Smlaier int error, len = strlen(path); 1265171172Smlaier int brace = 0; 1266171172Smlaier 1267171172Smlaier pf->anchor = rs->anchor; 1268171172Smlaier 1269171172Smlaier if (path[0]) 1270171172Smlaier snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name); 1271171172Smlaier else 1272171172Smlaier snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name); 1273171172Smlaier 1274171172Smlaier if (depth) { 1275171172Smlaier if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) { 1276171172Smlaier brace++; 1277171172Smlaier if (pf->opts & PF_OPT_VERBOSE) 1278171172Smlaier printf(" {\n"); 1279171172Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0 && 1280171172Smlaier (error = pfctl_ruleset_trans(pf, 1281171172Smlaier path, rs->anchor))) { 1282171172Smlaier printf("pfctl_load_rulesets: " 1283171172Smlaier "pfctl_ruleset_trans %d\n", error); 1284171172Smlaier goto error; 1285145840Smlaier } 1286171172Smlaier } else if (pf->opts & PF_OPT_VERBOSE) 1287171172Smlaier printf("\n"); 1288145840Smlaier 1289145840Smlaier } 1290145840Smlaier 1291171172Smlaier if (pf->optimize && rs_num == PF_RULESET_FILTER) 1292171172Smlaier pfctl_optimize_ruleset(pf, rs); 1293171172Smlaier 1294171172Smlaier while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) { 1295171172Smlaier TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries); 1296171172Smlaier if ((error = pfctl_load_rule(pf, path, r, depth))) 1297171172Smlaier goto error; 1298171172Smlaier if (r->anchor) { 1299171172Smlaier if ((error = pfctl_load_ruleset(pf, path, 1300171172Smlaier &r->anchor->ruleset, rs_num, depth + 1))) 1301171172Smlaier goto error; 1302171172Smlaier } else if (pf->opts & PF_OPT_VERBOSE) 1303171172Smlaier printf("\n"); 1304171172Smlaier free(r); 1305171172Smlaier } 1306171172Smlaier if (brace && pf->opts & PF_OPT_VERBOSE) { 1307171172Smlaier INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1308171172Smlaier printf("}\n"); 1309171172Smlaier } 1310171172Smlaier path[len] = '\0'; 1311171172Smlaier return (0); 1312171172Smlaier 1313171172Smlaier error: 1314171172Smlaier path[len] = '\0'; 1315171172Smlaier return (error); 1316171172Smlaier 1317171172Smlaier} 1318171172Smlaier 1319171172Smlaierint 1320171172Smlaierpfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) 1321171172Smlaier{ 1322171172Smlaier u_int8_t rs_num = pf_get_ruleset_number(r->action); 1323171172Smlaier char *name; 1324171172Smlaier struct pfioc_rule pr; 1325171172Smlaier int len = strlen(path); 1326171172Smlaier 1327171172Smlaier bzero(&pr, sizeof(pr)); 1328171172Smlaier /* set up anchor before adding to path for anchor_call */ 1329171172Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) 1330171172Smlaier pr.ticket = pfctl_get_ticket(pf->trans, rs_num, path); 1331171172Smlaier if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >= sizeof(pr.anchor)) 1332171172Smlaier errx(1, "pfctl_load_rule: strlcpy"); 1333171172Smlaier 1334171172Smlaier if (r->anchor) { 1335171172Smlaier if (r->anchor->match) { 1336171172Smlaier if (path[0]) 1337171172Smlaier snprintf(&path[len], MAXPATHLEN - len, 1338171172Smlaier "/%s", r->anchor->name); 1339171172Smlaier else 1340171172Smlaier snprintf(&path[len], MAXPATHLEN - len, 1341171172Smlaier "%s", r->anchor->name); 1342171172Smlaier name = path; 1343171172Smlaier } else 1344171172Smlaier name = r->anchor->path; 1345171172Smlaier } else 1346171172Smlaier name = ""; 1347171172Smlaier 1348126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1349126353Smlaier if (pfctl_add_pool(pf, &r->rpool, r->af)) 1350126353Smlaier return (1); 1351130617Smlaier pr.pool_ticket = pf->paddr.ticket; 1352130617Smlaier memcpy(&pr.rule, r, sizeof(pr.rule)); 1353171172Smlaier if (r->anchor && strlcpy(pr.anchor_call, name, 1354171172Smlaier sizeof(pr.anchor_call)) >= sizeof(pr.anchor_call)) 1355171172Smlaier errx(1, "pfctl_load_rule: strlcpy"); 1356130617Smlaier if (ioctl(pf->dev, DIOCADDRULE, &pr)) 1357126353Smlaier err(1, "DIOCADDRULE"); 1358126353Smlaier } 1359171172Smlaier 1360171172Smlaier if (pf->opts & PF_OPT_VERBOSE) { 1361171172Smlaier INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 1362171172Smlaier print_rule(r, r->anchor ? r->anchor->name : "", 1363223057Sbz pf->opts & PF_OPT_VERBOSE2, 1364223057Sbz pf->opts & PF_OPT_NUMERIC); 1365171172Smlaier } 1366171172Smlaier path[len] = '\0'; 1367126353Smlaier pfctl_clear_pool(&r->rpool); 1368126353Smlaier return (0); 1369126353Smlaier} 1370126353Smlaier 1371126353Smlaierint 1372126353Smlaierpfctl_add_altq(struct pfctl *pf, struct pf_altq *a) 1373126353Smlaier{ 1374126353Smlaier if (altqsupport && 1375126353Smlaier (loadopt & PFCTL_FLAG_ALTQ) != 0) { 1376126353Smlaier memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq)); 1377126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1378126353Smlaier if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) { 1379126353Smlaier if (errno == ENXIO) 1380126353Smlaier errx(1, "qtype not configured"); 1381126353Smlaier else if (errno == ENODEV) 1382126353Smlaier errx(1, "%s: driver does not support " 1383126353Smlaier "altq", a->ifname); 1384126353Smlaier else 1385126353Smlaier err(1, "DIOCADDALTQ"); 1386126353Smlaier } 1387126353Smlaier } 1388126353Smlaier pfaltq_store(&pf->paltq->altq); 1389126353Smlaier } 1390126353Smlaier return (0); 1391126353Smlaier} 1392126353Smlaier 1393126353Smlaierint 1394223637Sbzpfctl_rules(int dev, char *filename, int opts, int optimize, 1395171172Smlaier char *anchorname, struct pfr_buffer *trans) 1396126353Smlaier{ 1397126353Smlaier#define ERR(x) do { warn(x); goto _error; } while(0) 1398126353Smlaier#define ERRX(x) do { warnx(x); goto _error; } while(0) 1399126353Smlaier 1400130617Smlaier struct pfr_buffer *t, buf; 1401130617Smlaier struct pfioc_altq pa; 1402130617Smlaier struct pfctl pf; 1403171172Smlaier struct pf_ruleset *rs; 1404130617Smlaier struct pfr_table trs; 1405171172Smlaier char *path; 1406130617Smlaier int osize; 1407126353Smlaier 1408171172Smlaier RB_INIT(&pf_anchors); 1409171172Smlaier memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); 1410171172Smlaier pf_init_ruleset(&pf_main_anchor.ruleset); 1411171172Smlaier pf_main_anchor.ruleset.anchor = &pf_main_anchor; 1412130617Smlaier if (trans == NULL) { 1413171172Smlaier bzero(&buf, sizeof(buf)); 1414171172Smlaier buf.pfrb_type = PFRB_TRANS; 1415171172Smlaier t = &buf; 1416171172Smlaier osize = 0; 1417130617Smlaier } else { 1418171172Smlaier t = trans; 1419171172Smlaier osize = t->pfrb_size; 1420130617Smlaier } 1421130617Smlaier 1422126353Smlaier memset(&pa, 0, sizeof(pa)); 1423126353Smlaier memset(&pf, 0, sizeof(pf)); 1424126353Smlaier memset(&trs, 0, sizeof(trs)); 1425171172Smlaier if ((path = calloc(1, MAXPATHLEN)) == NULL) 1426171172Smlaier ERRX("pfctl_rules: calloc"); 1427126353Smlaier if (strlcpy(trs.pfrt_anchor, anchorname, 1428145840Smlaier sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) 1429126353Smlaier ERRX("pfctl_rules: strlcpy"); 1430126353Smlaier pf.dev = dev; 1431126353Smlaier pf.opts = opts; 1432171172Smlaier pf.optimize = optimize; 1433126353Smlaier pf.loadopt = loadopt; 1434171172Smlaier 1435171172Smlaier /* non-brace anchor, create without resolving the path */ 1436171172Smlaier if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) 1437171172Smlaier ERRX("pfctl_rules: calloc"); 1438171172Smlaier rs = &pf.anchor->ruleset; 1439171172Smlaier pf_init_ruleset(rs); 1440171172Smlaier rs->anchor = pf.anchor; 1441171172Smlaier if (strlcpy(pf.anchor->path, anchorname, 1442171172Smlaier sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 1443171172Smlaier errx(1, "pfctl_add_rule: strlcpy"); 1444171172Smlaier if (strlcpy(pf.anchor->name, anchorname, 1445171172Smlaier sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 1446171172Smlaier errx(1, "pfctl_add_rule: strlcpy"); 1447171172Smlaier 1448171172Smlaier 1449171172Smlaier pf.astack[0] = pf.anchor; 1450171172Smlaier pf.asd = 0; 1451130617Smlaier if (anchorname[0]) 1452130617Smlaier pf.loadopt &= ~PFCTL_FLAG_ALTQ; 1453126353Smlaier pf.paltq = &pa; 1454130617Smlaier pf.trans = t; 1455145840Smlaier pfctl_init_options(&pf); 1456130617Smlaier 1457130617Smlaier if ((opts & PF_OPT_NOACTION) == 0) { 1458171172Smlaier /* 1459171172Smlaier * XXX For the time being we need to open transactions for 1460171172Smlaier * the main ruleset before parsing, because tables are still 1461171172Smlaier * loaded at parse time. 1462171172Smlaier */ 1463171172Smlaier if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor)) 1464171172Smlaier ERRX("pfctl_rules"); 1465130617Smlaier if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) 1466171172Smlaier pa.ticket = 1467171172Smlaier pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname); 1468130617Smlaier if (pf.loadopt & PFCTL_FLAG_TABLE) 1469171172Smlaier pf.astack[0]->ruleset.tticket = 1470171172Smlaier pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname); 1471130617Smlaier } 1472171172Smlaier 1473223637Sbz if (parse_config(filename, &pf) < 0) { 1474126353Smlaier if ((opts & PF_OPT_NOACTION) == 0) 1475126353Smlaier ERRX("Syntax error in config file: " 1476126353Smlaier "pf rules not loaded"); 1477126353Smlaier else 1478126353Smlaier goto _error; 1479126353Smlaier } 1480171172Smlaier 1481171172Smlaier if ((pf.loadopt & PFCTL_FLAG_FILTER && 1482171172Smlaier (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) || 1483171172Smlaier (pf.loadopt & PFCTL_FLAG_NAT && 1484171172Smlaier (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) || 1485171172Smlaier pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) || 1486171172Smlaier pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) || 1487171172Smlaier (pf.loadopt & PFCTL_FLAG_FILTER && 1488171172Smlaier pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) { 1489171172Smlaier if ((opts & PF_OPT_NOACTION) == 0) 1490171172Smlaier ERRX("Unable to load rules into kernel"); 1491171172Smlaier else 1492171172Smlaier goto _error; 1493145840Smlaier } 1494145840Smlaier 1495130617Smlaier if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0)) 1496126353Smlaier if (check_commit_altq(dev, opts) != 0) 1497126353Smlaier ERRX("errors in altq config"); 1498145840Smlaier 1499126353Smlaier /* process "load anchor" directives */ 1500145840Smlaier if (!anchorname[0]) 1501171172Smlaier if (pfctl_load_anchors(dev, &pf, t) == -1) 1502126353Smlaier ERRX("load anchors"); 1503126353Smlaier 1504145840Smlaier if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) { 1505145840Smlaier if (!anchorname[0]) 1506145840Smlaier if (pfctl_load_options(&pf)) 1507145840Smlaier goto _error; 1508171172Smlaier if (pfctl_trans(dev, t, DIOCXCOMMIT, osize)) 1509130617Smlaier ERR("DIOCXCOMMIT"); 1510145840Smlaier } 1511126353Smlaier return (0); 1512126353Smlaier 1513126353Smlaier_error: 1514130617Smlaier if (trans == NULL) { /* main ruleset */ 1515130617Smlaier if ((opts & PF_OPT_NOACTION) == 0) 1516171172Smlaier if (pfctl_trans(dev, t, DIOCXROLLBACK, osize)) 1517130617Smlaier err(1, "DIOCXROLLBACK"); 1518130617Smlaier exit(1); 1519145840Smlaier } else { /* sub ruleset */ 1520130617Smlaier return (-1); 1521145840Smlaier } 1522126353Smlaier 1523126353Smlaier#undef ERR 1524126353Smlaier#undef ERRX 1525126353Smlaier} 1526126353Smlaier 1527145840SmlaierFILE * 1528145840Smlaierpfctl_fopen(const char *name, const char *mode) 1529145840Smlaier{ 1530145840Smlaier struct stat st; 1531145840Smlaier FILE *fp; 1532145840Smlaier 1533145840Smlaier fp = fopen(name, mode); 1534145840Smlaier if (fp == NULL) 1535145840Smlaier return (NULL); 1536145840Smlaier if (fstat(fileno(fp), &st)) { 1537145840Smlaier fclose(fp); 1538145840Smlaier return (NULL); 1539145840Smlaier } 1540145840Smlaier if (S_ISDIR(st.st_mode)) { 1541145840Smlaier fclose(fp); 1542145840Smlaier errno = EISDIR; 1543145840Smlaier return (NULL); 1544145840Smlaier } 1545145840Smlaier return (fp); 1546145840Smlaier} 1547145840Smlaier 1548145840Smlaiervoid 1549145840Smlaierpfctl_init_options(struct pfctl *pf) 1550145840Smlaier{ 1551171172Smlaier 1552145840Smlaier pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 1553145840Smlaier pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; 1554145840Smlaier pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 1555145840Smlaier pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; 1556145840Smlaier pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; 1557145840Smlaier pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; 1558145840Smlaier pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; 1559145840Smlaier pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; 1560145840Smlaier pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; 1561145840Smlaier pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; 1562145840Smlaier pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; 1563145840Smlaier pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; 1564145840Smlaier pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; 1565145840Smlaier pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; 1566145840Smlaier pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; 1567145840Smlaier pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; 1568145840Smlaier pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; 1569145840Smlaier pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; 1570171172Smlaier pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; 1571171172Smlaier pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; 1572145840Smlaier 1573171172Smlaier pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; 1574171172Smlaier pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT; 1575171172Smlaier pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; 1576171172Smlaier pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; 1577145840Smlaier 1578145840Smlaier pf->debug = PF_DEBUG_URGENT; 1579145840Smlaier} 1580145840Smlaier 1581126353Smlaierint 1582145840Smlaierpfctl_load_options(struct pfctl *pf) 1583126353Smlaier{ 1584145840Smlaier int i, error = 0; 1585126353Smlaier 1586126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1587126353Smlaier return (0); 1588126353Smlaier 1589145840Smlaier /* load limits */ 1590145840Smlaier for (i = 0; i < PF_LIMIT_MAX; i++) { 1591145840Smlaier if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i]) 1592145840Smlaier continue; 1593145840Smlaier if (pfctl_load_limit(pf, i, pf->limit[i])) 1594145840Smlaier error = 1; 1595145840Smlaier } 1596145840Smlaier 1597171172Smlaier /* 1598223637Sbz * If we've set the limit, but haven't explicitly set adaptive 1599171172Smlaier * timeouts, do it now with a start of 60% and end of 120%. 1600171172Smlaier */ 1601171172Smlaier if (pf->limit_set[PF_LIMIT_STATES] && 1602171172Smlaier !pf->timeout_set[PFTM_ADAPTIVE_START] && 1603171172Smlaier !pf->timeout_set[PFTM_ADAPTIVE_END]) { 1604171172Smlaier pf->timeout[PFTM_ADAPTIVE_START] = 1605171172Smlaier (pf->limit[PF_LIMIT_STATES] / 10) * 6; 1606171172Smlaier pf->timeout_set[PFTM_ADAPTIVE_START] = 1; 1607171172Smlaier pf->timeout[PFTM_ADAPTIVE_END] = 1608171172Smlaier (pf->limit[PF_LIMIT_STATES] / 10) * 12; 1609171172Smlaier pf->timeout_set[PFTM_ADAPTIVE_END] = 1; 1610171172Smlaier } 1611171172Smlaier 1612145840Smlaier /* load timeouts */ 1613145840Smlaier for (i = 0; i < PFTM_MAX; i++) { 1614145840Smlaier if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i]) 1615145840Smlaier continue; 1616145840Smlaier if (pfctl_load_timeout(pf, i, pf->timeout[i])) 1617145840Smlaier error = 1; 1618145840Smlaier } 1619145840Smlaier 1620145840Smlaier /* load debug */ 1621145840Smlaier if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set) 1622145840Smlaier if (pfctl_load_debug(pf, pf->debug)) 1623145840Smlaier error = 1; 1624145840Smlaier 1625145840Smlaier /* load logif */ 1626145840Smlaier if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set) 1627145840Smlaier if (pfctl_load_logif(pf, pf->ifname)) 1628145840Smlaier error = 1; 1629145840Smlaier 1630145840Smlaier /* load hostid */ 1631145840Smlaier if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set) 1632145840Smlaier if (pfctl_load_hostid(pf, pf->hostid)) 1633145840Smlaier error = 1; 1634145840Smlaier 1635145840Smlaier return (error); 1636145840Smlaier} 1637145840Smlaier 1638145840Smlaierint 1639145840Smlaierpfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) 1640145840Smlaier{ 1641145840Smlaier int i; 1642145840Smlaier 1643145840Smlaier 1644126353Smlaier for (i = 0; pf_limits[i].name; i++) { 1645126353Smlaier if (strcasecmp(opt, pf_limits[i].name) == 0) { 1646145840Smlaier pf->limit[pf_limits[i].index] = limit; 1647145840Smlaier pf->limit_set[pf_limits[i].index] = 1; 1648126353Smlaier break; 1649126353Smlaier } 1650126353Smlaier } 1651126353Smlaier if (pf_limits[i].name == NULL) { 1652126353Smlaier warnx("Bad pool name."); 1653126353Smlaier return (1); 1654126353Smlaier } 1655126353Smlaier 1656126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 1657126353Smlaier printf("set limit %s %d\n", opt, limit); 1658126353Smlaier 1659126353Smlaier return (0); 1660126353Smlaier} 1661126353Smlaier 1662126353Smlaierint 1663145840Smlaierpfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) 1664145840Smlaier{ 1665145840Smlaier struct pfioc_limit pl; 1666145840Smlaier 1667145840Smlaier memset(&pl, 0, sizeof(pl)); 1668145840Smlaier pl.index = index; 1669145840Smlaier pl.limit = limit; 1670145840Smlaier if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) { 1671145840Smlaier if (errno == EBUSY) 1672145840Smlaier warnx("Current pool size exceeds requested hard limit"); 1673145840Smlaier else 1674145840Smlaier warnx("DIOCSETLIMIT"); 1675145840Smlaier return (1); 1676145840Smlaier } 1677145840Smlaier return (0); 1678145840Smlaier} 1679145840Smlaier 1680145840Smlaierint 1681126353Smlaierpfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 1682126353Smlaier{ 1683126353Smlaier int i; 1684126353Smlaier 1685126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1686126353Smlaier return (0); 1687126353Smlaier 1688126353Smlaier for (i = 0; pf_timeouts[i].name; i++) { 1689126353Smlaier if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 1690145840Smlaier pf->timeout[pf_timeouts[i].timeout] = seconds; 1691145840Smlaier pf->timeout_set[pf_timeouts[i].timeout] = 1; 1692126353Smlaier break; 1693126353Smlaier } 1694126353Smlaier } 1695126353Smlaier 1696126353Smlaier if (pf_timeouts[i].name == NULL) { 1697126353Smlaier warnx("Bad timeout name."); 1698126353Smlaier return (1); 1699126353Smlaier } 1700126353Smlaier 1701126353Smlaier 1702126353Smlaier if (pf->opts & PF_OPT_VERBOSE && ! quiet) 1703126353Smlaier printf("set timeout %s %d\n", opt, seconds); 1704126353Smlaier 1705126353Smlaier return (0); 1706126353Smlaier} 1707126353Smlaier 1708126353Smlaierint 1709145840Smlaierpfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) 1710145840Smlaier{ 1711145840Smlaier struct pfioc_tm pt; 1712145840Smlaier 1713145840Smlaier memset(&pt, 0, sizeof(pt)); 1714145840Smlaier pt.timeout = timeout; 1715145840Smlaier pt.seconds = seconds; 1716145840Smlaier if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) { 1717145840Smlaier warnx("DIOCSETTIMEOUT"); 1718145840Smlaier return (1); 1719145840Smlaier } 1720145840Smlaier return (0); 1721145840Smlaier} 1722145840Smlaier 1723145840Smlaierint 1724126353Smlaierpfctl_set_optimization(struct pfctl *pf, const char *opt) 1725126353Smlaier{ 1726126353Smlaier const struct pf_hint *hint; 1727126353Smlaier int i, r; 1728126353Smlaier 1729126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1730126353Smlaier return (0); 1731126353Smlaier 1732126353Smlaier for (i = 0; pf_hints[i].name; i++) 1733126353Smlaier if (strcasecmp(opt, pf_hints[i].name) == 0) 1734126353Smlaier break; 1735126353Smlaier 1736126353Smlaier hint = pf_hints[i].hint; 1737126353Smlaier if (hint == NULL) { 1738171172Smlaier warnx("invalid state timeouts optimization"); 1739126353Smlaier return (1); 1740126353Smlaier } 1741126353Smlaier 1742126353Smlaier for (i = 0; hint[i].name; i++) 1743126353Smlaier if ((r = pfctl_set_timeout(pf, hint[i].name, 1744126353Smlaier hint[i].timeout, 1))) 1745126353Smlaier return (r); 1746126353Smlaier 1747126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 1748126353Smlaier printf("set optimization %s\n", opt); 1749126353Smlaier 1750126353Smlaier return (0); 1751126353Smlaier} 1752126353Smlaier 1753126353Smlaierint 1754126353Smlaierpfctl_set_logif(struct pfctl *pf, char *ifname) 1755126353Smlaier{ 1756126353Smlaier 1757126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1758126353Smlaier return (0); 1759126353Smlaier 1760145840Smlaier if (!strcmp(ifname, "none")) { 1761145840Smlaier free(pf->ifname); 1762145840Smlaier pf->ifname = NULL; 1763145840Smlaier } else { 1764145840Smlaier pf->ifname = strdup(ifname); 1765145840Smlaier if (!pf->ifname) 1766145840Smlaier errx(1, "pfctl_set_logif: strdup"); 1767126353Smlaier } 1768145840Smlaier pf->ifname_set = 1; 1769126353Smlaier 1770126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 1771126353Smlaier printf("set loginterface %s\n", ifname); 1772126353Smlaier 1773126353Smlaier return (0); 1774126353Smlaier} 1775126353Smlaier 1776126353Smlaierint 1777145840Smlaierpfctl_load_logif(struct pfctl *pf, char *ifname) 1778145840Smlaier{ 1779145840Smlaier struct pfioc_if pi; 1780145840Smlaier 1781145840Smlaier memset(&pi, 0, sizeof(pi)); 1782145840Smlaier if (ifname && strlcpy(pi.ifname, ifname, 1783145840Smlaier sizeof(pi.ifname)) >= sizeof(pi.ifname)) { 1784171172Smlaier warnx("pfctl_load_logif: strlcpy"); 1785145840Smlaier return (1); 1786145840Smlaier } 1787145840Smlaier if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) { 1788145840Smlaier warnx("DIOCSETSTATUSIF"); 1789145840Smlaier return (1); 1790145840Smlaier } 1791145840Smlaier return (0); 1792145840Smlaier} 1793145840Smlaier 1794145840Smlaierint 1795130617Smlaierpfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 1796130617Smlaier{ 1797130617Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1798130617Smlaier return (0); 1799130617Smlaier 1800130617Smlaier HTONL(hostid); 1801130617Smlaier 1802145840Smlaier pf->hostid = hostid; 1803145840Smlaier pf->hostid_set = 1; 1804130617Smlaier 1805130617Smlaier if (pf->opts & PF_OPT_VERBOSE) 1806130617Smlaier printf("set hostid 0x%08x\n", ntohl(hostid)); 1807130617Smlaier 1808130617Smlaier return (0); 1809130617Smlaier} 1810130617Smlaier 1811130617Smlaierint 1812145840Smlaierpfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) 1813145840Smlaier{ 1814145840Smlaier if (ioctl(dev, DIOCSETHOSTID, &hostid)) { 1815145840Smlaier warnx("DIOCSETHOSTID"); 1816145840Smlaier return (1); 1817145840Smlaier } 1818145840Smlaier return (0); 1819145840Smlaier} 1820145840Smlaier 1821145840Smlaierint 1822130617Smlaierpfctl_set_debug(struct pfctl *pf, char *d) 1823130617Smlaier{ 1824130617Smlaier u_int32_t level; 1825130617Smlaier 1826130617Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1827130617Smlaier return (0); 1828130617Smlaier 1829130617Smlaier if (!strcmp(d, "none")) 1830145840Smlaier pf->debug = PF_DEBUG_NONE; 1831130617Smlaier else if (!strcmp(d, "urgent")) 1832145840Smlaier pf->debug = PF_DEBUG_URGENT; 1833130617Smlaier else if (!strcmp(d, "misc")) 1834145840Smlaier pf->debug = PF_DEBUG_MISC; 1835130617Smlaier else if (!strcmp(d, "loud")) 1836145840Smlaier pf->debug = PF_DEBUG_NOISY; 1837130617Smlaier else { 1838130617Smlaier warnx("unknown debug level \"%s\"", d); 1839130617Smlaier return (-1); 1840130617Smlaier } 1841130617Smlaier 1842145840Smlaier pf->debug_set = 1; 1843145840Smlaier 1844130617Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) 1845130617Smlaier if (ioctl(dev, DIOCSETDEBUG, &level)) 1846130617Smlaier err(1, "DIOCSETDEBUG"); 1847130617Smlaier 1848130617Smlaier if (pf->opts & PF_OPT_VERBOSE) 1849130617Smlaier printf("set debug %s\n", d); 1850130617Smlaier 1851130617Smlaier return (0); 1852130617Smlaier} 1853130617Smlaier 1854130617Smlaierint 1855145840Smlaierpfctl_load_debug(struct pfctl *pf, unsigned int level) 1856145840Smlaier{ 1857145840Smlaier if (ioctl(pf->dev, DIOCSETDEBUG, &level)) { 1858145840Smlaier warnx("DIOCSETDEBUG"); 1859145840Smlaier return (1); 1860145840Smlaier } 1861145840Smlaier return (0); 1862145840Smlaier} 1863145840Smlaier 1864145840Smlaierint 1865145840Smlaierpfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) 1866145840Smlaier{ 1867145840Smlaier struct pfioc_iface pi; 1868145840Smlaier 1869145840Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1870145840Smlaier return (0); 1871145840Smlaier 1872145840Smlaier bzero(&pi, sizeof(pi)); 1873145840Smlaier 1874145840Smlaier pi.pfiio_flags = flags; 1875145840Smlaier 1876145840Smlaier if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= 1877145840Smlaier sizeof(pi.pfiio_name)) 1878145840Smlaier errx(1, "pfctl_set_interface_flags: strlcpy"); 1879145840Smlaier 1880145840Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1881145840Smlaier if (how == 0) { 1882145840Smlaier if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi)) 1883145840Smlaier err(1, "DIOCCLRIFFLAG"); 1884145840Smlaier } else { 1885145840Smlaier if (ioctl(pf->dev, DIOCSETIFFLAG, &pi)) 1886145840Smlaier err(1, "DIOCSETIFFLAG"); 1887145840Smlaier } 1888145840Smlaier } 1889145840Smlaier return (0); 1890145840Smlaier} 1891145840Smlaier 1892145840Smlaiervoid 1893126353Smlaierpfctl_debug(int dev, u_int32_t level, int opts) 1894126353Smlaier{ 1895126353Smlaier if (ioctl(dev, DIOCSETDEBUG, &level)) 1896126353Smlaier err(1, "DIOCSETDEBUG"); 1897126353Smlaier if ((opts & PF_OPT_QUIET) == 0) { 1898126353Smlaier fprintf(stderr, "debug level set to '"); 1899126353Smlaier switch (level) { 1900126353Smlaier case PF_DEBUG_NONE: 1901126353Smlaier fprintf(stderr, "none"); 1902126353Smlaier break; 1903126353Smlaier case PF_DEBUG_URGENT: 1904126353Smlaier fprintf(stderr, "urgent"); 1905126353Smlaier break; 1906126353Smlaier case PF_DEBUG_MISC: 1907126353Smlaier fprintf(stderr, "misc"); 1908126353Smlaier break; 1909126353Smlaier case PF_DEBUG_NOISY: 1910126353Smlaier fprintf(stderr, "loud"); 1911126353Smlaier break; 1912126353Smlaier default: 1913126353Smlaier fprintf(stderr, "<invalid>"); 1914126353Smlaier break; 1915126353Smlaier } 1916126353Smlaier fprintf(stderr, "'\n"); 1917126353Smlaier } 1918126353Smlaier} 1919126353Smlaier 1920126353Smlaierint 1921126353Smlaierpfctl_test_altqsupport(int dev, int opts) 1922126353Smlaier{ 1923126353Smlaier struct pfioc_altq pa; 1924126353Smlaier 1925126353Smlaier if (ioctl(dev, DIOCGETALTQS, &pa)) { 1926126353Smlaier if (errno == ENODEV) { 1927126353Smlaier if (!(opts & PF_OPT_QUIET)) 1928126353Smlaier fprintf(stderr, "No ALTQ support in kernel\n" 1929126353Smlaier "ALTQ related functions disabled\n"); 1930126353Smlaier return (0); 1931126353Smlaier } else 1932126353Smlaier err(1, "DIOCGETALTQS"); 1933126353Smlaier } 1934126353Smlaier return (1); 1935126353Smlaier} 1936126353Smlaier 1937126353Smlaierint 1938126353Smlaierpfctl_show_anchors(int dev, int opts, char *anchorname) 1939126353Smlaier{ 1940145840Smlaier struct pfioc_ruleset pr; 1941145840Smlaier u_int32_t mnr, nr; 1942126353Smlaier 1943145840Smlaier memset(&pr, 0, sizeof(pr)); 1944145840Smlaier memcpy(pr.path, anchorname, sizeof(pr.path)); 1945145840Smlaier if (ioctl(dev, DIOCGETRULESETS, &pr)) { 1946145840Smlaier if (errno == EINVAL) 1947145840Smlaier fprintf(stderr, "Anchor '%s' not found.\n", 1948145840Smlaier anchorname); 1949145840Smlaier else 1950145840Smlaier err(1, "DIOCGETRULESETS"); 1951145840Smlaier return (-1); 1952145840Smlaier } 1953145840Smlaier mnr = pr.nr; 1954145840Smlaier for (nr = 0; nr < mnr; ++nr) { 1955145840Smlaier char sub[MAXPATHLEN]; 1956126353Smlaier 1957145840Smlaier pr.nr = nr; 1958145840Smlaier if (ioctl(dev, DIOCGETRULESET, &pr)) 1959145840Smlaier err(1, "DIOCGETRULESET"); 1960145840Smlaier if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) 1961145840Smlaier continue; 1962145840Smlaier sub[0] = 0; 1963145840Smlaier if (pr.path[0]) { 1964145840Smlaier strlcat(sub, pr.path, sizeof(sub)); 1965145840Smlaier strlcat(sub, "/", sizeof(sub)); 1966126353Smlaier } 1967145840Smlaier strlcat(sub, pr.name, sizeof(sub)); 1968171172Smlaier if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 1969171172Smlaier printf(" %s\n", sub); 1970171172Smlaier if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub)) 1971126353Smlaier return (-1); 1972126353Smlaier } 1973126353Smlaier return (0); 1974126353Smlaier} 1975126353Smlaier 1976126353Smlaierconst char * 1977126353Smlaierpfctl_lookup_option(char *cmd, const char **list) 1978126353Smlaier{ 1979126353Smlaier if (cmd != NULL && *cmd) 1980126353Smlaier for (; *list; list++) 1981126353Smlaier if (!strncmp(cmd, *list, strlen(cmd))) 1982126353Smlaier return (*list); 1983126353Smlaier return (NULL); 1984126353Smlaier} 1985126353Smlaier 1986126353Smlaierint 1987126353Smlaiermain(int argc, char *argv[]) 1988126353Smlaier{ 1989171172Smlaier int error = 0; 1990171172Smlaier int ch; 1991171172Smlaier int mode = O_RDONLY; 1992171172Smlaier int opts = 0; 1993223637Sbz int optimize = PF_OPTIMIZE_BASIC; 1994171172Smlaier char anchorname[MAXPATHLEN]; 1995171172Smlaier char *path; 1996126353Smlaier 1997126353Smlaier if (argc < 2) 1998126353Smlaier usage(); 1999126353Smlaier 2000130617Smlaier while ((ch = getopt(argc, argv, 2001223637Sbz "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:z")) != -1) { 2002126353Smlaier switch (ch) { 2003126353Smlaier case 'a': 2004126353Smlaier anchoropt = optarg; 2005126353Smlaier break; 2006126353Smlaier case 'd': 2007126353Smlaier opts |= PF_OPT_DISABLE; 2008126353Smlaier mode = O_RDWR; 2009126353Smlaier break; 2010126353Smlaier case 'D': 2011126353Smlaier if (pfctl_cmdline_symset(optarg) < 0) 2012126353Smlaier warnx("could not parse macro definition %s", 2013126353Smlaier optarg); 2014126353Smlaier break; 2015126353Smlaier case 'e': 2016126353Smlaier opts |= PF_OPT_ENABLE; 2017126353Smlaier mode = O_RDWR; 2018126353Smlaier break; 2019126353Smlaier case 'q': 2020126353Smlaier opts |= PF_OPT_QUIET; 2021126353Smlaier break; 2022126353Smlaier case 'F': 2023126353Smlaier clearopt = pfctl_lookup_option(optarg, clearopt_list); 2024126353Smlaier if (clearopt == NULL) { 2025126353Smlaier warnx("Unknown flush modifier '%s'", optarg); 2026126353Smlaier usage(); 2027126353Smlaier } 2028126353Smlaier mode = O_RDWR; 2029126353Smlaier break; 2030130617Smlaier case 'i': 2031130617Smlaier ifaceopt = optarg; 2032130617Smlaier break; 2033126353Smlaier case 'k': 2034126353Smlaier if (state_killers >= 2) { 2035126353Smlaier warnx("can only specify -k twice"); 2036126353Smlaier usage(); 2037126353Smlaier /* NOTREACHED */ 2038126353Smlaier } 2039126353Smlaier state_kill[state_killers++] = optarg; 2040126353Smlaier mode = O_RDWR; 2041126353Smlaier break; 2042171172Smlaier case 'K': 2043171172Smlaier if (src_node_killers >= 2) { 2044171172Smlaier warnx("can only specify -K twice"); 2045171172Smlaier usage(); 2046171172Smlaier /* NOTREACHED */ 2047171172Smlaier } 2048171172Smlaier src_node_kill[src_node_killers++] = optarg; 2049171172Smlaier mode = O_RDWR; 2050171172Smlaier break; 2051145840Smlaier case 'm': 2052145840Smlaier opts |= PF_OPT_MERGE; 2053145840Smlaier break; 2054126353Smlaier case 'n': 2055126353Smlaier opts |= PF_OPT_NOACTION; 2056126353Smlaier break; 2057126353Smlaier case 'N': 2058126353Smlaier loadopt |= PFCTL_FLAG_NAT; 2059126353Smlaier break; 2060126353Smlaier case 'r': 2061126353Smlaier opts |= PF_OPT_USEDNS; 2062126353Smlaier break; 2063126353Smlaier case 'f': 2064126353Smlaier rulesopt = optarg; 2065126353Smlaier mode = O_RDWR; 2066126353Smlaier break; 2067126353Smlaier case 'g': 2068126353Smlaier opts |= PF_OPT_DEBUG; 2069126353Smlaier break; 2070126353Smlaier case 'A': 2071126353Smlaier loadopt |= PFCTL_FLAG_ALTQ; 2072126353Smlaier break; 2073126353Smlaier case 'R': 2074126353Smlaier loadopt |= PFCTL_FLAG_FILTER; 2075126353Smlaier break; 2076145840Smlaier case 'o': 2077223637Sbz optiopt = pfctl_lookup_option(optarg, optiopt_list); 2078223637Sbz if (optiopt == NULL) { 2079223637Sbz warnx("Unknown optimization '%s'", optarg); 2080223637Sbz usage(); 2081171172Smlaier } 2082171172Smlaier opts |= PF_OPT_OPTIMIZE; 2083145840Smlaier break; 2084126353Smlaier case 'O': 2085126353Smlaier loadopt |= PFCTL_FLAG_OPTION; 2086126353Smlaier break; 2087130617Smlaier case 'p': 2088130617Smlaier pf_device = optarg; 2089130617Smlaier break; 2090223057Sbz case 'P': 2091223057Sbz opts |= PF_OPT_NUMERIC; 2092223057Sbz break; 2093126353Smlaier case 's': 2094126353Smlaier showopt = pfctl_lookup_option(optarg, showopt_list); 2095126353Smlaier if (showopt == NULL) { 2096126353Smlaier warnx("Unknown show modifier '%s'", optarg); 2097126353Smlaier usage(); 2098126353Smlaier } 2099126353Smlaier break; 2100126353Smlaier case 't': 2101126353Smlaier tableopt = optarg; 2102126353Smlaier break; 2103126353Smlaier case 'T': 2104126353Smlaier tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 2105126353Smlaier if (tblcmdopt == NULL) { 2106126353Smlaier warnx("Unknown table command '%s'", optarg); 2107126353Smlaier usage(); 2108126353Smlaier } 2109126353Smlaier break; 2110126353Smlaier case 'v': 2111126353Smlaier if (opts & PF_OPT_VERBOSE) 2112126353Smlaier opts |= PF_OPT_VERBOSE2; 2113126353Smlaier opts |= PF_OPT_VERBOSE; 2114126353Smlaier break; 2115126353Smlaier case 'x': 2116126353Smlaier debugopt = pfctl_lookup_option(optarg, debugopt_list); 2117126353Smlaier if (debugopt == NULL) { 2118126353Smlaier warnx("Unknown debug level '%s'", optarg); 2119126353Smlaier usage(); 2120126353Smlaier } 2121126353Smlaier mode = O_RDWR; 2122126353Smlaier break; 2123126353Smlaier case 'z': 2124126353Smlaier opts |= PF_OPT_CLRRULECTRS; 2125126353Smlaier mode = O_RDWR; 2126126353Smlaier break; 2127126353Smlaier case 'h': 2128126353Smlaier /* FALLTHROUGH */ 2129126353Smlaier default: 2130126353Smlaier usage(); 2131126353Smlaier /* NOTREACHED */ 2132126353Smlaier } 2133126353Smlaier } 2134126353Smlaier 2135126353Smlaier if (tblcmdopt != NULL) { 2136126353Smlaier argc -= optind; 2137126353Smlaier argv += optind; 2138126353Smlaier ch = *tblcmdopt; 2139126353Smlaier if (ch == 'l') { 2140126353Smlaier loadopt |= PFCTL_FLAG_TABLE; 2141126353Smlaier tblcmdopt = NULL; 2142130617Smlaier } else 2143171172Smlaier mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY; 2144126353Smlaier } else if (argc != optind) { 2145126353Smlaier warnx("unknown command line argument: %s ...", argv[optind]); 2146126353Smlaier usage(); 2147126353Smlaier /* NOTREACHED */ 2148126353Smlaier } 2149126353Smlaier if (loadopt == 0) 2150126353Smlaier loadopt = ~0; 2151126353Smlaier 2152171172Smlaier if ((path = calloc(1, MAXPATHLEN)) == NULL) 2153171172Smlaier errx(1, "pfctl: calloc"); 2154126353Smlaier memset(anchorname, 0, sizeof(anchorname)); 2155126353Smlaier if (anchoropt != NULL) { 2156171172Smlaier int len = strlen(anchoropt); 2157171172Smlaier 2158171172Smlaier if (anchoropt[len - 1] == '*') { 2159171172Smlaier if (len >= 2 && anchoropt[len - 2] == '/') 2160171172Smlaier anchoropt[len - 2] = '\0'; 2161171172Smlaier else 2162171172Smlaier anchoropt[len - 1] = '\0'; 2163171172Smlaier opts |= PF_OPT_RECURSE; 2164171172Smlaier } 2165145840Smlaier if (strlcpy(anchorname, anchoropt, 2166145840Smlaier sizeof(anchorname)) >= sizeof(anchorname)) 2167145840Smlaier errx(1, "anchor name '%s' too long", 2168145840Smlaier anchoropt); 2169126353Smlaier loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE; 2170126353Smlaier } 2171126353Smlaier 2172126353Smlaier if ((opts & PF_OPT_NOACTION) == 0) { 2173130617Smlaier dev = open(pf_device, mode); 2174126353Smlaier if (dev == -1) 2175130617Smlaier err(1, "%s", pf_device); 2176126353Smlaier altqsupport = pfctl_test_altqsupport(dev, opts); 2177126353Smlaier } else { 2178130617Smlaier dev = open(pf_device, O_RDONLY); 2179130617Smlaier if (dev >= 0) 2180130617Smlaier opts |= PF_OPT_DUMMYACTION; 2181126353Smlaier /* turn off options */ 2182126353Smlaier opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 2183126353Smlaier clearopt = showopt = debugopt = NULL; 2184258485Sglebius#if !defined(ENABLE_ALTQ) 2185126355Smlaier altqsupport = 0; 2186126355Smlaier#else 2187126353Smlaier altqsupport = 1; 2188126355Smlaier#endif 2189126353Smlaier } 2190126353Smlaier 2191126353Smlaier if (opts & PF_OPT_DISABLE) 2192126353Smlaier if (pfctl_disable(dev, opts)) 2193126353Smlaier error = 1; 2194126353Smlaier 2195126353Smlaier if (showopt != NULL) { 2196126353Smlaier switch (*showopt) { 2197126353Smlaier case 'A': 2198126353Smlaier pfctl_show_anchors(dev, opts, anchorname); 2199126353Smlaier break; 2200126353Smlaier case 'r': 2201126353Smlaier pfctl_load_fingerprints(dev, opts); 2202171172Smlaier pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 2203171172Smlaier anchorname, 0); 2204126353Smlaier break; 2205126353Smlaier case 'l': 2206126353Smlaier pfctl_load_fingerprints(dev, opts); 2207171172Smlaier pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 2208171172Smlaier anchorname, 0); 2209126353Smlaier break; 2210126353Smlaier case 'n': 2211126353Smlaier pfctl_load_fingerprints(dev, opts); 2212145840Smlaier pfctl_show_nat(dev, opts, anchorname); 2213126353Smlaier break; 2214126353Smlaier case 'q': 2215130617Smlaier pfctl_show_altq(dev, ifaceopt, opts, 2216130617Smlaier opts & PF_OPT_VERBOSE2); 2217126353Smlaier break; 2218126353Smlaier case 's': 2219130617Smlaier pfctl_show_states(dev, ifaceopt, opts); 2220126353Smlaier break; 2221130617Smlaier case 'S': 2222130617Smlaier pfctl_show_src_nodes(dev, opts); 2223130617Smlaier break; 2224126353Smlaier case 'i': 2225130617Smlaier pfctl_show_status(dev, opts); 2226126353Smlaier break; 2227126353Smlaier case 't': 2228130617Smlaier pfctl_show_timeouts(dev, opts); 2229126353Smlaier break; 2230126353Smlaier case 'm': 2231130617Smlaier pfctl_show_limits(dev, opts); 2232126353Smlaier break; 2233126353Smlaier case 'a': 2234130617Smlaier opts |= PF_OPT_SHOWALL; 2235126353Smlaier pfctl_load_fingerprints(dev, opts); 2236126353Smlaier 2237145840Smlaier pfctl_show_nat(dev, opts, anchorname); 2238171172Smlaier pfctl_show_rules(dev, path, opts, 0, anchorname, 0); 2239130617Smlaier pfctl_show_altq(dev, ifaceopt, opts, 0); 2240130617Smlaier pfctl_show_states(dev, ifaceopt, opts); 2241130617Smlaier pfctl_show_src_nodes(dev, opts); 2242130617Smlaier pfctl_show_status(dev, opts); 2243171172Smlaier pfctl_show_rules(dev, path, opts, 1, anchorname, 0); 2244130617Smlaier pfctl_show_timeouts(dev, opts); 2245130617Smlaier pfctl_show_limits(dev, opts); 2246145840Smlaier pfctl_show_tables(anchorname, opts); 2247126353Smlaier pfctl_show_fingerprints(opts); 2248126353Smlaier break; 2249126353Smlaier case 'T': 2250145840Smlaier pfctl_show_tables(anchorname, opts); 2251126353Smlaier break; 2252126353Smlaier case 'o': 2253126353Smlaier pfctl_load_fingerprints(dev, opts); 2254126353Smlaier pfctl_show_fingerprints(opts); 2255126353Smlaier break; 2256130617Smlaier case 'I': 2257130617Smlaier pfctl_show_ifaces(ifaceopt, opts); 2258130617Smlaier break; 2259126353Smlaier } 2260126353Smlaier } 2261126353Smlaier 2262171172Smlaier if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) 2263171172Smlaier pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 2264171172Smlaier anchorname, 0); 2265171172Smlaier 2266126353Smlaier if (clearopt != NULL) { 2267171172Smlaier if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 2268171172Smlaier errx(1, "anchor names beginning with '_' cannot " 2269171172Smlaier "be modified from the command line"); 2270171172Smlaier 2271126353Smlaier switch (*clearopt) { 2272126353Smlaier case 'r': 2273145840Smlaier pfctl_clear_rules(dev, opts, anchorname); 2274126353Smlaier break; 2275126353Smlaier case 'n': 2276145840Smlaier pfctl_clear_nat(dev, opts, anchorname); 2277126353Smlaier break; 2278126353Smlaier case 'q': 2279126353Smlaier pfctl_clear_altq(dev, opts); 2280126353Smlaier break; 2281126353Smlaier case 's': 2282130617Smlaier pfctl_clear_states(dev, ifaceopt, opts); 2283126353Smlaier break; 2284130617Smlaier case 'S': 2285130617Smlaier pfctl_clear_src_nodes(dev, opts); 2286130617Smlaier break; 2287126353Smlaier case 'i': 2288126353Smlaier pfctl_clear_stats(dev, opts); 2289126353Smlaier break; 2290126353Smlaier case 'a': 2291145840Smlaier pfctl_clear_rules(dev, opts, anchorname); 2292145840Smlaier pfctl_clear_nat(dev, opts, anchorname); 2293145840Smlaier pfctl_clear_tables(anchorname, opts); 2294145840Smlaier if (!*anchorname) { 2295130617Smlaier pfctl_clear_altq(dev, opts); 2296130617Smlaier pfctl_clear_states(dev, ifaceopt, opts); 2297130617Smlaier pfctl_clear_src_nodes(dev, opts); 2298130617Smlaier pfctl_clear_stats(dev, opts); 2299130617Smlaier pfctl_clear_fingerprints(dev, opts); 2300145840Smlaier pfctl_clear_interface_flags(dev, opts); 2301130617Smlaier } 2302126353Smlaier break; 2303126353Smlaier case 'o': 2304126353Smlaier pfctl_clear_fingerprints(dev, opts); 2305126353Smlaier break; 2306126353Smlaier case 'T': 2307145840Smlaier pfctl_clear_tables(anchorname, opts); 2308126353Smlaier break; 2309126353Smlaier } 2310126353Smlaier } 2311223637Sbz if (state_killers) { 2312223637Sbz if (!strcmp(state_kill[0], "label")) 2313223637Sbz pfctl_label_kill_states(dev, ifaceopt, opts); 2314223637Sbz else if (!strcmp(state_kill[0], "id")) 2315223637Sbz pfctl_id_kill_states(dev, ifaceopt, opts); 2316223637Sbz else 2317223637Sbz pfctl_net_kill_states(dev, ifaceopt, opts); 2318223637Sbz } 2319126353Smlaier 2320171172Smlaier if (src_node_killers) 2321171172Smlaier pfctl_kill_src_nodes(dev, ifaceopt, opts); 2322171172Smlaier 2323126353Smlaier if (tblcmdopt != NULL) { 2324126353Smlaier error = pfctl_command_tables(argc, argv, tableopt, 2325145840Smlaier tblcmdopt, rulesopt, anchorname, opts); 2326126353Smlaier rulesopt = NULL; 2327126353Smlaier } 2328171172Smlaier if (optiopt != NULL) { 2329171172Smlaier switch (*optiopt) { 2330171172Smlaier case 'n': 2331171172Smlaier optimize = 0; 2332171172Smlaier break; 2333171172Smlaier case 'b': 2334171172Smlaier optimize |= PF_OPTIMIZE_BASIC; 2335171172Smlaier break; 2336171172Smlaier case 'o': 2337171172Smlaier case 'p': 2338171172Smlaier optimize |= PF_OPTIMIZE_PROFILE; 2339171172Smlaier break; 2340171172Smlaier } 2341171172Smlaier } 2342126353Smlaier 2343171172Smlaier if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) && 2344171172Smlaier !anchorname[0]) 2345145840Smlaier if (pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET)) 2346145840Smlaier error = 1; 2347145840Smlaier 2348145840Smlaier if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) && 2349145840Smlaier !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION)) 2350126353Smlaier if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 2351126353Smlaier error = 1; 2352126353Smlaier 2353126353Smlaier if (rulesopt != NULL) { 2354171172Smlaier if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 2355171172Smlaier errx(1, "anchor names beginning with '_' cannot " 2356171172Smlaier "be modified from the command line"); 2357223637Sbz if (pfctl_rules(dev, rulesopt, opts, optimize, 2358171172Smlaier anchorname, NULL)) 2359126353Smlaier error = 1; 2360126353Smlaier else if (!(opts & PF_OPT_NOACTION) && 2361126353Smlaier (loadopt & PFCTL_FLAG_TABLE)) 2362126353Smlaier warn_namespace_collision(NULL); 2363126353Smlaier } 2364126353Smlaier 2365126353Smlaier if (opts & PF_OPT_ENABLE) 2366126353Smlaier if (pfctl_enable(dev, opts)) 2367126353Smlaier error = 1; 2368126353Smlaier 2369126353Smlaier if (debugopt != NULL) { 2370126353Smlaier switch (*debugopt) { 2371126353Smlaier case 'n': 2372126353Smlaier pfctl_debug(dev, PF_DEBUG_NONE, opts); 2373126353Smlaier break; 2374126353Smlaier case 'u': 2375126353Smlaier pfctl_debug(dev, PF_DEBUG_URGENT, opts); 2376126353Smlaier break; 2377126353Smlaier case 'm': 2378126353Smlaier pfctl_debug(dev, PF_DEBUG_MISC, opts); 2379126353Smlaier break; 2380126353Smlaier case 'l': 2381126353Smlaier pfctl_debug(dev, PF_DEBUG_NOISY, opts); 2382126353Smlaier break; 2383126353Smlaier } 2384126353Smlaier } 2385126353Smlaier 2386126353Smlaier exit(error); 2387126353Smlaier} 2388