pfctl.c revision 333181
1223637Sbz/* $OpenBSD: pfctl.c,v 1.278 2008/08/31 20:18:17 jmc Exp $ */ 2126353Smlaier 3330449Seadler/*- 4330449Seadler * SPDX-License-Identifier: BSD-2-Clause 5330449Seadler * 6126353Smlaier * Copyright (c) 2001 Daniel Hartmeier 7130617Smlaier * Copyright (c) 2002,2003 Henning Brauer 8126353Smlaier * All rights reserved. 9126353Smlaier * 10126353Smlaier * Redistribution and use in source and binary forms, with or without 11126353Smlaier * modification, are permitted provided that the following conditions 12126353Smlaier * are met: 13126353Smlaier * 14126353Smlaier * - Redistributions of source code must retain the above copyright 15126353Smlaier * notice, this list of conditions and the following disclaimer. 16126353Smlaier * - Redistributions in binary form must reproduce the above 17126353Smlaier * copyright notice, this list of conditions and the following 18126353Smlaier * disclaimer in the documentation and/or other materials provided 19126353Smlaier * with the distribution. 20126353Smlaier * 21126353Smlaier * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22126353Smlaier * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23126353Smlaier * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24126353Smlaier * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25126353Smlaier * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26126353Smlaier * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27126353Smlaier * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28126353Smlaier * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29126353Smlaier * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30126353Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31126353Smlaier * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32126353Smlaier * POSSIBILITY OF SUCH DAMAGE. 33126353Smlaier * 34126353Smlaier */ 35126353Smlaier 36127082Sobrien#include <sys/cdefs.h> 37127082Sobrien__FBSDID("$FreeBSD: stable/11/sbin/pfctl/pfctl.c 333181 2018-05-02 20:15:02Z kp $"); 38127082Sobrien 39126353Smlaier#include <sys/types.h> 40126353Smlaier#include <sys/ioctl.h> 41126353Smlaier#include <sys/socket.h> 42145840Smlaier#include <sys/stat.h> 43223637Sbz#include <sys/endian.h> 44223637Sbz 45126353Smlaier#include <net/if.h> 46126353Smlaier#include <netinet/in.h> 47126353Smlaier#include <net/pfvar.h> 48126353Smlaier#include <arpa/inet.h> 49281613Sglebius#include <net/altq/altq.h> 50171172Smlaier#include <sys/sysctl.h> 51126353Smlaier 52126353Smlaier#include <err.h> 53126353Smlaier#include <errno.h> 54126353Smlaier#include <fcntl.h> 55126353Smlaier#include <limits.h> 56126353Smlaier#include <netdb.h> 57262799Sglebius#include <stdint.h> 58126353Smlaier#include <stdio.h> 59126353Smlaier#include <stdlib.h> 60126353Smlaier#include <string.h> 61126353Smlaier#include <unistd.h> 62126353Smlaier 63126353Smlaier#include "pfctl_parser.h" 64126353Smlaier#include "pfctl.h" 65126353Smlaier 66126353Smlaiervoid usage(void); 67126353Smlaierint pfctl_enable(int, int); 68126353Smlaierint pfctl_disable(int, int); 69126353Smlaierint pfctl_clear_stats(int, int); 70333181Skpint pfctl_get_skip_ifaces(void); 71333181Skpint pfctl_check_skip_ifaces(char *); 72333181Skpint pfctl_clear_skip_ifaces(struct pfctl *); 73145840Smlaierint pfctl_clear_interface_flags(int, int); 74145840Smlaierint pfctl_clear_rules(int, int, char *); 75145840Smlaierint pfctl_clear_nat(int, int, char *); 76126353Smlaierint pfctl_clear_altq(int, int); 77130617Smlaierint pfctl_clear_src_nodes(int, int); 78130617Smlaierint pfctl_clear_states(int, const char *, int); 79171172Smlaiervoid pfctl_addrprefix(char *, struct pf_addr *); 80171172Smlaierint pfctl_kill_src_nodes(int, const char *, int); 81223637Sbzint pfctl_net_kill_states(int, const char *, int); 82223637Sbzint pfctl_label_kill_states(int, const char *, int); 83223637Sbzint pfctl_id_kill_states(int, const char *, int); 84145840Smlaiervoid pfctl_init_options(struct pfctl *); 85145840Smlaierint pfctl_load_options(struct pfctl *); 86145840Smlaierint pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); 87145840Smlaierint pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); 88145840Smlaierint pfctl_load_debug(struct pfctl *, unsigned int); 89145840Smlaierint pfctl_load_logif(struct pfctl *, char *); 90145840Smlaierint pfctl_load_hostid(struct pfctl *, unsigned int); 91126353Smlaierint pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int, 92145840Smlaier char *); 93126353Smlaiervoid pfctl_print_rule_counters(struct pf_rule *, int); 94171172Smlaierint pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int); 95145840Smlaierint pfctl_show_nat(int, int, char *); 96130617Smlaierint pfctl_show_src_nodes(int, int); 97130617Smlaierint pfctl_show_states(int, const char *, int); 98130617Smlaierint pfctl_show_status(int, int); 99130617Smlaierint pfctl_show_timeouts(int, int); 100130617Smlaierint pfctl_show_limits(int, int); 101145840Smlaiervoid pfctl_debug(int, u_int32_t, int); 102126353Smlaierint pfctl_test_altqsupport(int, int); 103126353Smlaierint pfctl_show_anchors(int, int, char *); 104171172Smlaierint pfctl_ruleset_trans(struct pfctl *, char *, struct pf_anchor *); 105171172Smlaierint pfctl_load_ruleset(struct pfctl *, char *, 106171172Smlaier struct pf_ruleset *, int, int); 107171172Smlaierint pfctl_load_rule(struct pfctl *, char *, struct pf_rule *, int); 108126353Smlaierconst char *pfctl_lookup_option(char *, const char **); 109126353Smlaier 110171172Smlaierstruct pf_anchor_global pf_anchors; 111171172Smlaierstruct pf_anchor pf_main_anchor; 112333181Skpstatic struct pfr_buffer skip_b; 113171172Smlaier 114126353Smlaierconst char *clearopt; 115126353Smlaierchar *rulesopt; 116126353Smlaierconst char *showopt; 117126353Smlaierconst char *debugopt; 118126353Smlaierchar *anchoropt; 119171172Smlaierconst char *optiopt = NULL; 120130617Smlaierchar *pf_device = "/dev/pf"; 121130617Smlaierchar *ifaceopt; 122126353Smlaierchar *tableopt; 123126353Smlaierconst char *tblcmdopt; 124171172Smlaierint src_node_killers; 125171172Smlaierchar *src_node_kill[2]; 126126353Smlaierint state_killers; 127126353Smlaierchar *state_kill[2]; 128126353Smlaierint loadopt; 129126353Smlaierint altqsupport; 130126353Smlaier 131126353Smlaierint dev = -1; 132130617Smlaierint first_title = 1; 133130617Smlaierint labels = 0; 134126353Smlaier 135171172Smlaier#define INDENT(d, o) do { \ 136171172Smlaier if (o) { \ 137171172Smlaier int i; \ 138171172Smlaier for (i=0; i < d; i++) \ 139171172Smlaier printf(" "); \ 140171172Smlaier } \ 141171172Smlaier } while (0); \ 142171172Smlaier 143171172Smlaier 144126353Smlaierstatic const struct { 145126353Smlaier const char *name; 146126353Smlaier int index; 147126353Smlaier} pf_limits[] = { 148171172Smlaier { "states", PF_LIMIT_STATES }, 149171172Smlaier { "src-nodes", PF_LIMIT_SRC_NODES }, 150171172Smlaier { "frags", PF_LIMIT_FRAGS }, 151171172Smlaier { "table-entries", PF_LIMIT_TABLE_ENTRIES }, 152171172Smlaier { NULL, 0 } 153126353Smlaier}; 154126353Smlaier 155126353Smlaierstruct pf_hint { 156126353Smlaier const char *name; 157126353Smlaier int timeout; 158126353Smlaier}; 159126353Smlaierstatic const struct pf_hint pf_hint_normal[] = { 160126353Smlaier { "tcp.first", 2 * 60 }, 161126353Smlaier { "tcp.opening", 30 }, 162126353Smlaier { "tcp.established", 24 * 60 * 60 }, 163126353Smlaier { "tcp.closing", 15 * 60 }, 164126353Smlaier { "tcp.finwait", 45 }, 165126353Smlaier { "tcp.closed", 90 }, 166145840Smlaier { "tcp.tsdiff", 30 }, 167126353Smlaier { NULL, 0 } 168126353Smlaier}; 169126353Smlaierstatic const struct pf_hint pf_hint_satellite[] = { 170126353Smlaier { "tcp.first", 3 * 60 }, 171126353Smlaier { "tcp.opening", 30 + 5 }, 172126353Smlaier { "tcp.established", 24 * 60 * 60 }, 173126353Smlaier { "tcp.closing", 15 * 60 + 5 }, 174126353Smlaier { "tcp.finwait", 45 + 5 }, 175126353Smlaier { "tcp.closed", 90 + 5 }, 176145840Smlaier { "tcp.tsdiff", 60 }, 177126353Smlaier { NULL, 0 } 178126353Smlaier}; 179126353Smlaierstatic const struct pf_hint pf_hint_conservative[] = { 180126353Smlaier { "tcp.first", 60 * 60 }, 181126353Smlaier { "tcp.opening", 15 * 60 }, 182126353Smlaier { "tcp.established", 5 * 24 * 60 * 60 }, 183126353Smlaier { "tcp.closing", 60 * 60 }, 184126353Smlaier { "tcp.finwait", 10 * 60 }, 185126353Smlaier { "tcp.closed", 3 * 60 }, 186145840Smlaier { "tcp.tsdiff", 60 }, 187126353Smlaier { NULL, 0 } 188126353Smlaier}; 189126353Smlaierstatic const struct pf_hint pf_hint_aggressive[] = { 190126353Smlaier { "tcp.first", 30 }, 191126353Smlaier { "tcp.opening", 5 }, 192126353Smlaier { "tcp.established", 5 * 60 * 60 }, 193126353Smlaier { "tcp.closing", 60 }, 194126353Smlaier { "tcp.finwait", 30 }, 195126353Smlaier { "tcp.closed", 30 }, 196145840Smlaier { "tcp.tsdiff", 10 }, 197126353Smlaier { NULL, 0 } 198126353Smlaier}; 199126353Smlaier 200126353Smlaierstatic const struct { 201126353Smlaier const char *name; 202126353Smlaier const struct pf_hint *hint; 203126353Smlaier} pf_hints[] = { 204126353Smlaier { "normal", pf_hint_normal }, 205126353Smlaier { "satellite", pf_hint_satellite }, 206126353Smlaier { "high-latency", pf_hint_satellite }, 207126353Smlaier { "conservative", pf_hint_conservative }, 208126353Smlaier { "aggressive", pf_hint_aggressive }, 209126353Smlaier { NULL, NULL } 210126353Smlaier}; 211126353Smlaier 212126353Smlaierstatic const char *clearopt_list[] = { 213130617Smlaier "nat", "queue", "rules", "Sources", 214223637Sbz "states", "info", "Tables", "osfp", "all", NULL 215126353Smlaier}; 216126353Smlaier 217126353Smlaierstatic const char *showopt_list[] = { 218223637Sbz "nat", "queue", "rules", "Anchors", "Sources", "states", "info", 219130617Smlaier "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp", 220130617Smlaier "all", NULL 221126353Smlaier}; 222126353Smlaier 223126353Smlaierstatic const char *tblcmdopt_list[] = { 224126353Smlaier "kill", "flush", "add", "delete", "load", "replace", "show", 225171172Smlaier "test", "zero", "expire", NULL 226126353Smlaier}; 227126353Smlaier 228126353Smlaierstatic const char *debugopt_list[] = { 229126353Smlaier "none", "urgent", "misc", "loud", NULL 230126353Smlaier}; 231126353Smlaier 232171172Smlaierstatic const char *optiopt_list[] = { 233223637Sbz "none", "basic", "profile", NULL 234171172Smlaier}; 235126353Smlaier 236126353Smlaiervoid 237126353Smlaierusage(void) 238126353Smlaier{ 239126353Smlaier extern char *__progname; 240126353Smlaier 241258484Sglebius fprintf(stderr, 242258484Sglebius"usage: %s [-AdeghmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n" 243258484Sglebius "\t[-f file] [-i interface] [-K host | network]\n" 244258484Sglebius "\t[-k host | network | label | id] [-o level] [-p device]\n" 245258484Sglebius "\t[-s modifier] [-t table -T command [address ...]] [-x level]\n", 246258484Sglebius __progname); 247258484Sglebius 248126353Smlaier exit(1); 249126353Smlaier} 250126353Smlaier 251126353Smlaierint 252126353Smlaierpfctl_enable(int dev, int opts) 253126353Smlaier{ 254126353Smlaier if (ioctl(dev, DIOCSTART)) { 255126353Smlaier if (errno == EEXIST) 256126353Smlaier errx(1, "pf already enabled"); 257126355Smlaier else if (errno == ESRCH) 258126355Smlaier errx(1, "pfil registeration failed"); 259126353Smlaier else 260126353Smlaier err(1, "DIOCSTART"); 261126353Smlaier } 262126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 263126353Smlaier fprintf(stderr, "pf enabled\n"); 264126353Smlaier 265126353Smlaier if (altqsupport && ioctl(dev, DIOCSTARTALTQ)) 266126353Smlaier if (errno != EEXIST) 267126353Smlaier err(1, "DIOCSTARTALTQ"); 268126353Smlaier 269126353Smlaier return (0); 270126353Smlaier} 271126353Smlaier 272126353Smlaierint 273126353Smlaierpfctl_disable(int dev, int opts) 274126353Smlaier{ 275126353Smlaier if (ioctl(dev, DIOCSTOP)) { 276126353Smlaier if (errno == ENOENT) 277126353Smlaier errx(1, "pf not enabled"); 278126353Smlaier else 279126353Smlaier err(1, "DIOCSTOP"); 280126353Smlaier } 281126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 282126353Smlaier fprintf(stderr, "pf disabled\n"); 283126353Smlaier 284126353Smlaier if (altqsupport && ioctl(dev, DIOCSTOPALTQ)) 285126353Smlaier if (errno != ENOENT) 286126353Smlaier err(1, "DIOCSTOPALTQ"); 287126353Smlaier 288126353Smlaier return (0); 289126353Smlaier} 290126353Smlaier 291126353Smlaierint 292126353Smlaierpfctl_clear_stats(int dev, int opts) 293126353Smlaier{ 294126353Smlaier if (ioctl(dev, DIOCCLRSTATUS)) 295126353Smlaier err(1, "DIOCCLRSTATUS"); 296126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 297126353Smlaier fprintf(stderr, "pf: statistics cleared\n"); 298126353Smlaier return (0); 299126353Smlaier} 300126353Smlaier 301126353Smlaierint 302333181Skppfctl_get_skip_ifaces(void) 303333181Skp{ 304333181Skp bzero(&skip_b, sizeof(skip_b)); 305333181Skp skip_b.pfrb_type = PFRB_IFACES; 306333181Skp for (;;) { 307333181Skp pfr_buf_grow(&skip_b, skip_b.pfrb_size); 308333181Skp skip_b.pfrb_size = skip_b.pfrb_msize; 309333181Skp if (pfi_get_ifaces(NULL, skip_b.pfrb_caddr, &skip_b.pfrb_size)) 310333181Skp err(1, "pfi_get_ifaces"); 311333181Skp if (skip_b.pfrb_size <= skip_b.pfrb_msize) 312333181Skp break; 313333181Skp } 314333181Skp return (0); 315333181Skp} 316333181Skp 317333181Skpint 318333181Skppfctl_check_skip_ifaces(char *ifname) 319333181Skp{ 320333181Skp struct pfi_kif *p; 321333181Skp 322333181Skp PFRB_FOREACH(p, &skip_b) 323333181Skp if ((p->pfik_flags & PFI_IFLAG_SKIP) && !strcmp(ifname, p->pfik_name)) 324333181Skp p->pfik_flags &= ~PFI_IFLAG_SKIP; 325333181Skp return (0); 326333181Skp} 327333181Skp 328333181Skpint 329333181Skppfctl_clear_skip_ifaces(struct pfctl *pf) 330333181Skp{ 331333181Skp struct pfi_kif *p; 332333181Skp 333333181Skp PFRB_FOREACH(p, &skip_b) 334333181Skp if (p->pfik_flags & PFI_IFLAG_SKIP) 335333181Skp pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0); 336333181Skp return (0); 337333181Skp} 338333181Skp 339333181Skpint 340145840Smlaierpfctl_clear_interface_flags(int dev, int opts) 341126353Smlaier{ 342145840Smlaier struct pfioc_iface pi; 343126353Smlaier 344145840Smlaier if ((opts & PF_OPT_NOACTION) == 0) { 345145840Smlaier bzero(&pi, sizeof(pi)); 346171172Smlaier pi.pfiio_flags = PFI_IFLAG_SKIP; 347126353Smlaier 348145840Smlaier if (ioctl(dev, DIOCCLRIFFLAG, &pi)) 349145840Smlaier err(1, "DIOCCLRIFFLAG"); 350126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 351145840Smlaier fprintf(stderr, "pf: interface flags reset\n"); 352126353Smlaier } 353145840Smlaier return (0); 354145840Smlaier} 355145840Smlaier 356145840Smlaierint 357145840Smlaierpfctl_clear_rules(int dev, int opts, char *anchorname) 358145840Smlaier{ 359145840Smlaier struct pfr_buffer t; 360145840Smlaier 361130617Smlaier memset(&t, 0, sizeof(t)); 362130617Smlaier t.pfrb_type = PFRB_TRANS; 363145840Smlaier if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname) || 364145840Smlaier pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) || 365130617Smlaier pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 366130617Smlaier pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 367130617Smlaier err(1, "pfctl_clear_rules"); 368126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 369126353Smlaier fprintf(stderr, "rules cleared\n"); 370126353Smlaier return (0); 371126353Smlaier} 372126353Smlaier 373126353Smlaierint 374145840Smlaierpfctl_clear_nat(int dev, int opts, char *anchorname) 375126353Smlaier{ 376130617Smlaier struct pfr_buffer t; 377126353Smlaier 378130617Smlaier memset(&t, 0, sizeof(t)); 379130617Smlaier t.pfrb_type = PFRB_TRANS; 380145840Smlaier if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname) || 381145840Smlaier pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname) || 382145840Smlaier pfctl_add_trans(&t, PF_RULESET_RDR, anchorname) || 383130617Smlaier pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 384130617Smlaier pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 385130617Smlaier err(1, "pfctl_clear_nat"); 386126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 387126353Smlaier fprintf(stderr, "nat cleared\n"); 388126353Smlaier return (0); 389126353Smlaier} 390126353Smlaier 391126353Smlaierint 392126353Smlaierpfctl_clear_altq(int dev, int opts) 393126353Smlaier{ 394130617Smlaier struct pfr_buffer t; 395126353Smlaier 396126353Smlaier if (!altqsupport) 397126353Smlaier return (-1); 398130617Smlaier memset(&t, 0, sizeof(t)); 399130617Smlaier t.pfrb_type = PFRB_TRANS; 400145840Smlaier if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") || 401130617Smlaier pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 402130617Smlaier pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 403130617Smlaier err(1, "pfctl_clear_altq"); 404126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 405126353Smlaier fprintf(stderr, "altq cleared\n"); 406126353Smlaier return (0); 407126353Smlaier} 408126353Smlaier 409126353Smlaierint 410130617Smlaierpfctl_clear_src_nodes(int dev, int opts) 411126353Smlaier{ 412130617Smlaier if (ioctl(dev, DIOCCLRSRCNODES)) 413130617Smlaier err(1, "DIOCCLRSRCNODES"); 414130617Smlaier if ((opts & PF_OPT_QUIET) == 0) 415130617Smlaier fprintf(stderr, "source tracking entries cleared\n"); 416130617Smlaier return (0); 417130617Smlaier} 418130617Smlaier 419130617Smlaierint 420130617Smlaierpfctl_clear_states(int dev, const char *iface, int opts) 421130617Smlaier{ 422130617Smlaier struct pfioc_state_kill psk; 423130617Smlaier 424130617Smlaier memset(&psk, 0, sizeof(psk)); 425130617Smlaier if (iface != NULL && strlcpy(psk.psk_ifname, iface, 426130617Smlaier sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 427130617Smlaier errx(1, "invalid interface: %s", iface); 428130617Smlaier 429130617Smlaier if (ioctl(dev, DIOCCLRSTATES, &psk)) 430126353Smlaier err(1, "DIOCCLRSTATES"); 431126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 432223637Sbz fprintf(stderr, "%d states cleared\n", psk.psk_killed); 433126353Smlaier return (0); 434126353Smlaier} 435126353Smlaier 436171172Smlaiervoid 437171172Smlaierpfctl_addrprefix(char *addr, struct pf_addr *mask) 438171172Smlaier{ 439171172Smlaier char *p; 440171172Smlaier const char *errstr; 441171172Smlaier int prefix, ret_ga, q, r; 442171172Smlaier struct addrinfo hints, *res; 443171172Smlaier 444171172Smlaier if ((p = strchr(addr, '/')) == NULL) 445171172Smlaier return; 446171172Smlaier 447171172Smlaier *p++ = '\0'; 448171172Smlaier prefix = strtonum(p, 0, 128, &errstr); 449171172Smlaier if (errstr) 450171172Smlaier errx(1, "prefix is %s: %s", errstr, p); 451171172Smlaier 452171172Smlaier bzero(&hints, sizeof(hints)); 453171172Smlaier /* prefix only with numeric addresses */ 454171172Smlaier hints.ai_flags |= AI_NUMERICHOST; 455171172Smlaier 456171172Smlaier if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) { 457171172Smlaier errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 458171172Smlaier /* NOTREACHED */ 459171172Smlaier } 460171172Smlaier 461171172Smlaier if (res->ai_family == AF_INET && prefix > 32) 462171172Smlaier errx(1, "prefix too long for AF_INET"); 463171172Smlaier else if (res->ai_family == AF_INET6 && prefix > 128) 464171172Smlaier errx(1, "prefix too long for AF_INET6"); 465171172Smlaier 466171172Smlaier q = prefix >> 3; 467171172Smlaier r = prefix & 7; 468171172Smlaier switch (res->ai_family) { 469171172Smlaier case AF_INET: 470171172Smlaier bzero(&mask->v4, sizeof(mask->v4)); 471171172Smlaier mask->v4.s_addr = htonl((u_int32_t) 472171172Smlaier (0xffffffffffULL << (32 - prefix))); 473171172Smlaier break; 474171172Smlaier case AF_INET6: 475171172Smlaier bzero(&mask->v6, sizeof(mask->v6)); 476171172Smlaier if (q > 0) 477171172Smlaier memset((void *)&mask->v6, 0xff, q); 478171172Smlaier if (r > 0) 479171172Smlaier *((u_char *)&mask->v6 + q) = 480171172Smlaier (0xff00 >> r) & 0xff; 481171172Smlaier break; 482171172Smlaier } 483171172Smlaier freeaddrinfo(res); 484171172Smlaier} 485171172Smlaier 486126353Smlaierint 487171172Smlaierpfctl_kill_src_nodes(int dev, const char *iface, int opts) 488171172Smlaier{ 489171172Smlaier struct pfioc_src_node_kill psnk; 490171172Smlaier struct addrinfo *res[2], *resp[2]; 491171172Smlaier struct sockaddr last_src, last_dst; 492171172Smlaier int killed, sources, dests; 493171172Smlaier int ret_ga; 494171172Smlaier 495171172Smlaier killed = sources = dests = 0; 496171172Smlaier 497171172Smlaier memset(&psnk, 0, sizeof(psnk)); 498171172Smlaier memset(&psnk.psnk_src.addr.v.a.mask, 0xff, 499171172Smlaier sizeof(psnk.psnk_src.addr.v.a.mask)); 500171172Smlaier memset(&last_src, 0xff, sizeof(last_src)); 501171172Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 502171172Smlaier 503171172Smlaier pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask); 504171172Smlaier 505171172Smlaier if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) { 506171172Smlaier errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 507171172Smlaier /* NOTREACHED */ 508171172Smlaier } 509171172Smlaier for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 510171172Smlaier if (resp[0]->ai_addr == NULL) 511171172Smlaier continue; 512171172Smlaier /* We get lots of duplicates. Catch the easy ones */ 513171172Smlaier if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 514171172Smlaier continue; 515171172Smlaier last_src = *(struct sockaddr *)resp[0]->ai_addr; 516171172Smlaier 517171172Smlaier psnk.psnk_af = resp[0]->ai_family; 518171172Smlaier sources++; 519171172Smlaier 520171172Smlaier if (psnk.psnk_af == AF_INET) 521171172Smlaier psnk.psnk_src.addr.v.a.addr.v4 = 522171172Smlaier ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 523171172Smlaier else if (psnk.psnk_af == AF_INET6) 524171172Smlaier psnk.psnk_src.addr.v.a.addr.v6 = 525171172Smlaier ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 526171172Smlaier sin6_addr; 527171172Smlaier else 528171172Smlaier errx(1, "Unknown address family %d", psnk.psnk_af); 529171172Smlaier 530171172Smlaier if (src_node_killers > 1) { 531171172Smlaier dests = 0; 532171172Smlaier memset(&psnk.psnk_dst.addr.v.a.mask, 0xff, 533171172Smlaier sizeof(psnk.psnk_dst.addr.v.a.mask)); 534171172Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 535171172Smlaier pfctl_addrprefix(src_node_kill[1], 536171172Smlaier &psnk.psnk_dst.addr.v.a.mask); 537171172Smlaier if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL, 538171172Smlaier &res[1]))) { 539171172Smlaier errx(1, "getaddrinfo: %s", 540171172Smlaier gai_strerror(ret_ga)); 541171172Smlaier /* NOTREACHED */ 542171172Smlaier } 543171172Smlaier for (resp[1] = res[1]; resp[1]; 544171172Smlaier resp[1] = resp[1]->ai_next) { 545171172Smlaier if (resp[1]->ai_addr == NULL) 546171172Smlaier continue; 547171172Smlaier if (psnk.psnk_af != resp[1]->ai_family) 548171172Smlaier continue; 549171172Smlaier 550171172Smlaier if (memcmp(&last_dst, resp[1]->ai_addr, 551171172Smlaier sizeof(last_dst)) == 0) 552171172Smlaier continue; 553171172Smlaier last_dst = *(struct sockaddr *)resp[1]->ai_addr; 554171172Smlaier 555171172Smlaier dests++; 556171172Smlaier 557171172Smlaier if (psnk.psnk_af == AF_INET) 558171172Smlaier psnk.psnk_dst.addr.v.a.addr.v4 = 559171172Smlaier ((struct sockaddr_in *)resp[1]-> 560171172Smlaier ai_addr)->sin_addr; 561171172Smlaier else if (psnk.psnk_af == AF_INET6) 562171172Smlaier psnk.psnk_dst.addr.v.a.addr.v6 = 563171172Smlaier ((struct sockaddr_in6 *)resp[1]-> 564171172Smlaier ai_addr)->sin6_addr; 565171172Smlaier else 566171172Smlaier errx(1, "Unknown address family %d", 567171172Smlaier psnk.psnk_af); 568171172Smlaier 569171172Smlaier if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 570171172Smlaier err(1, "DIOCKILLSRCNODES"); 571223637Sbz killed += psnk.psnk_killed; 572171172Smlaier } 573171172Smlaier freeaddrinfo(res[1]); 574171172Smlaier } else { 575171172Smlaier if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 576171172Smlaier err(1, "DIOCKILLSRCNODES"); 577223637Sbz killed += psnk.psnk_killed; 578171172Smlaier } 579171172Smlaier } 580171172Smlaier 581171172Smlaier freeaddrinfo(res[0]); 582171172Smlaier 583171172Smlaier if ((opts & PF_OPT_QUIET) == 0) 584171172Smlaier fprintf(stderr, "killed %d src nodes from %d sources and %d " 585171172Smlaier "destinations\n", killed, sources, dests); 586171172Smlaier return (0); 587171172Smlaier} 588171172Smlaier 589171172Smlaierint 590223637Sbzpfctl_net_kill_states(int dev, const char *iface, int opts) 591126353Smlaier{ 592126353Smlaier struct pfioc_state_kill psk; 593126353Smlaier struct addrinfo *res[2], *resp[2]; 594126353Smlaier struct sockaddr last_src, last_dst; 595126353Smlaier int killed, sources, dests; 596126353Smlaier int ret_ga; 597126353Smlaier 598126353Smlaier killed = sources = dests = 0; 599126353Smlaier 600126353Smlaier memset(&psk, 0, sizeof(psk)); 601126353Smlaier memset(&psk.psk_src.addr.v.a.mask, 0xff, 602126353Smlaier sizeof(psk.psk_src.addr.v.a.mask)); 603126353Smlaier memset(&last_src, 0xff, sizeof(last_src)); 604126353Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 605130617Smlaier if (iface != NULL && strlcpy(psk.psk_ifname, iface, 606130617Smlaier sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 607130617Smlaier errx(1, "invalid interface: %s", iface); 608126353Smlaier 609171172Smlaier pfctl_addrprefix(state_kill[0], &psk.psk_src.addr.v.a.mask); 610171172Smlaier 611126353Smlaier if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) { 612126353Smlaier errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 613126353Smlaier /* NOTREACHED */ 614126353Smlaier } 615126353Smlaier for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 616126353Smlaier if (resp[0]->ai_addr == NULL) 617126353Smlaier continue; 618126353Smlaier /* We get lots of duplicates. Catch the easy ones */ 619126353Smlaier if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 620126353Smlaier continue; 621126353Smlaier last_src = *(struct sockaddr *)resp[0]->ai_addr; 622126353Smlaier 623126353Smlaier psk.psk_af = resp[0]->ai_family; 624126353Smlaier sources++; 625126353Smlaier 626126353Smlaier if (psk.psk_af == AF_INET) 627126353Smlaier psk.psk_src.addr.v.a.addr.v4 = 628126353Smlaier ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 629126353Smlaier else if (psk.psk_af == AF_INET6) 630126353Smlaier psk.psk_src.addr.v.a.addr.v6 = 631126353Smlaier ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 632126353Smlaier sin6_addr; 633126353Smlaier else 634126353Smlaier errx(1, "Unknown address family %d", psk.psk_af); 635126353Smlaier 636126353Smlaier if (state_killers > 1) { 637126353Smlaier dests = 0; 638126353Smlaier memset(&psk.psk_dst.addr.v.a.mask, 0xff, 639126353Smlaier sizeof(psk.psk_dst.addr.v.a.mask)); 640126353Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 641171172Smlaier pfctl_addrprefix(state_kill[1], 642171172Smlaier &psk.psk_dst.addr.v.a.mask); 643126353Smlaier if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, 644126353Smlaier &res[1]))) { 645130617Smlaier errx(1, "getaddrinfo: %s", 646130617Smlaier gai_strerror(ret_ga)); 647126353Smlaier /* NOTREACHED */ 648126353Smlaier } 649126353Smlaier for (resp[1] = res[1]; resp[1]; 650126353Smlaier resp[1] = resp[1]->ai_next) { 651126353Smlaier if (resp[1]->ai_addr == NULL) 652126353Smlaier continue; 653126353Smlaier if (psk.psk_af != resp[1]->ai_family) 654126353Smlaier continue; 655126353Smlaier 656126353Smlaier if (memcmp(&last_dst, resp[1]->ai_addr, 657126353Smlaier sizeof(last_dst)) == 0) 658126353Smlaier continue; 659126353Smlaier last_dst = *(struct sockaddr *)resp[1]->ai_addr; 660126353Smlaier 661126353Smlaier dests++; 662126353Smlaier 663126353Smlaier if (psk.psk_af == AF_INET) 664126353Smlaier psk.psk_dst.addr.v.a.addr.v4 = 665126353Smlaier ((struct sockaddr_in *)resp[1]-> 666126353Smlaier ai_addr)->sin_addr; 667126353Smlaier else if (psk.psk_af == AF_INET6) 668126353Smlaier psk.psk_dst.addr.v.a.addr.v6 = 669126353Smlaier ((struct sockaddr_in6 *)resp[1]-> 670126353Smlaier ai_addr)->sin6_addr; 671126353Smlaier else 672126353Smlaier errx(1, "Unknown address family %d", 673126353Smlaier psk.psk_af); 674126353Smlaier 675126353Smlaier if (ioctl(dev, DIOCKILLSTATES, &psk)) 676126353Smlaier err(1, "DIOCKILLSTATES"); 677223637Sbz killed += psk.psk_killed; 678126353Smlaier } 679126353Smlaier freeaddrinfo(res[1]); 680126353Smlaier } else { 681126353Smlaier if (ioctl(dev, DIOCKILLSTATES, &psk)) 682126353Smlaier err(1, "DIOCKILLSTATES"); 683223637Sbz killed += psk.psk_killed; 684126353Smlaier } 685126353Smlaier } 686126353Smlaier 687126353Smlaier freeaddrinfo(res[0]); 688126353Smlaier 689126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 690126353Smlaier fprintf(stderr, "killed %d states from %d sources and %d " 691126353Smlaier "destinations\n", killed, sources, dests); 692126353Smlaier return (0); 693126353Smlaier} 694126353Smlaier 695126353Smlaierint 696223637Sbzpfctl_label_kill_states(int dev, const char *iface, int opts) 697223637Sbz{ 698223637Sbz struct pfioc_state_kill psk; 699223637Sbz 700223637Sbz if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 701223637Sbz warnx("no label specified"); 702223637Sbz usage(); 703223637Sbz } 704223637Sbz memset(&psk, 0, sizeof(psk)); 705223637Sbz if (iface != NULL && strlcpy(psk.psk_ifname, iface, 706223637Sbz sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 707223637Sbz errx(1, "invalid interface: %s", iface); 708223637Sbz 709223637Sbz if (strlcpy(psk.psk_label, state_kill[1], sizeof(psk.psk_label)) >= 710223637Sbz sizeof(psk.psk_label)) 711223637Sbz errx(1, "label too long: %s", state_kill[1]); 712223637Sbz 713223637Sbz if (ioctl(dev, DIOCKILLSTATES, &psk)) 714223637Sbz err(1, "DIOCKILLSTATES"); 715223637Sbz 716223637Sbz if ((opts & PF_OPT_QUIET) == 0) 717223637Sbz fprintf(stderr, "killed %d states\n", psk.psk_killed); 718223637Sbz 719223637Sbz return (0); 720223637Sbz} 721223637Sbz 722223637Sbzint 723223637Sbzpfctl_id_kill_states(int dev, const char *iface, int opts) 724223637Sbz{ 725223637Sbz struct pfioc_state_kill psk; 726223637Sbz 727223637Sbz if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 728223637Sbz warnx("no id specified"); 729223637Sbz usage(); 730223637Sbz } 731223637Sbz 732223637Sbz memset(&psk, 0, sizeof(psk)); 733223637Sbz if ((sscanf(state_kill[1], "%jx/%x", 734223637Sbz &psk.psk_pfcmp.id, &psk.psk_pfcmp.creatorid)) == 2) 735223637Sbz HTONL(psk.psk_pfcmp.creatorid); 736223637Sbz else if ((sscanf(state_kill[1], "%jx", &psk.psk_pfcmp.id)) == 1) { 737223637Sbz psk.psk_pfcmp.creatorid = 0; 738223637Sbz } else { 739223637Sbz warnx("wrong id format specified"); 740223637Sbz usage(); 741223637Sbz } 742223637Sbz if (psk.psk_pfcmp.id == 0) { 743223637Sbz warnx("cannot kill id 0"); 744223637Sbz usage(); 745223637Sbz } 746223637Sbz 747223637Sbz psk.psk_pfcmp.id = htobe64(psk.psk_pfcmp.id); 748223637Sbz if (ioctl(dev, DIOCKILLSTATES, &psk)) 749223637Sbz err(1, "DIOCKILLSTATES"); 750223637Sbz 751223637Sbz if ((opts & PF_OPT_QUIET) == 0) 752223637Sbz fprintf(stderr, "killed %d states\n", psk.psk_killed); 753223637Sbz 754223637Sbz return (0); 755223637Sbz} 756223637Sbz 757223637Sbzint 758126353Smlaierpfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr, 759145840Smlaier u_int32_t ticket, int r_action, char *anchorname) 760126353Smlaier{ 761126353Smlaier struct pfioc_pooladdr pp; 762126353Smlaier struct pf_pooladdr *pa; 763126353Smlaier u_int32_t pnr, mpnr; 764126353Smlaier 765126353Smlaier memset(&pp, 0, sizeof(pp)); 766126353Smlaier memcpy(pp.anchor, anchorname, sizeof(pp.anchor)); 767126353Smlaier pp.r_action = r_action; 768126353Smlaier pp.r_num = nr; 769126353Smlaier pp.ticket = ticket; 770126353Smlaier if (ioctl(dev, DIOCGETADDRS, &pp)) { 771126353Smlaier warn("DIOCGETADDRS"); 772126353Smlaier return (-1); 773126353Smlaier } 774126353Smlaier mpnr = pp.nr; 775126353Smlaier TAILQ_INIT(&pool->list); 776126353Smlaier for (pnr = 0; pnr < mpnr; ++pnr) { 777126353Smlaier pp.nr = pnr; 778126353Smlaier if (ioctl(dev, DIOCGETADDR, &pp)) { 779126353Smlaier warn("DIOCGETADDR"); 780126353Smlaier return (-1); 781126353Smlaier } 782126353Smlaier pa = calloc(1, sizeof(struct pf_pooladdr)); 783126353Smlaier if (pa == NULL) 784126353Smlaier err(1, "calloc"); 785126353Smlaier bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr)); 786126353Smlaier TAILQ_INSERT_TAIL(&pool->list, pa, entries); 787126353Smlaier } 788126353Smlaier 789126353Smlaier return (0); 790126353Smlaier} 791126353Smlaier 792126353Smlaiervoid 793171172Smlaierpfctl_move_pool(struct pf_pool *src, struct pf_pool *dst) 794171172Smlaier{ 795171172Smlaier struct pf_pooladdr *pa; 796171172Smlaier 797171172Smlaier while ((pa = TAILQ_FIRST(&src->list)) != NULL) { 798171172Smlaier TAILQ_REMOVE(&src->list, pa, entries); 799171172Smlaier TAILQ_INSERT_TAIL(&dst->list, pa, entries); 800171172Smlaier } 801171172Smlaier} 802171172Smlaier 803171172Smlaiervoid 804126353Smlaierpfctl_clear_pool(struct pf_pool *pool) 805126353Smlaier{ 806126353Smlaier struct pf_pooladdr *pa; 807126353Smlaier 808126353Smlaier while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { 809126353Smlaier TAILQ_REMOVE(&pool->list, pa, entries); 810126353Smlaier free(pa); 811126353Smlaier } 812126353Smlaier} 813126353Smlaier 814126353Smlaiervoid 815126353Smlaierpfctl_print_rule_counters(struct pf_rule *rule, int opts) 816126353Smlaier{ 817126353Smlaier if (opts & PF_OPT_DEBUG) { 818126353Smlaier const char *t[PF_SKIP_COUNT] = { "i", "d", "f", 819126353Smlaier "p", "sa", "sp", "da", "dp" }; 820126353Smlaier int i; 821126353Smlaier 822126353Smlaier printf(" [ Skip steps: "); 823126353Smlaier for (i = 0; i < PF_SKIP_COUNT; ++i) { 824126353Smlaier if (rule->skip[i].nr == rule->nr + 1) 825126353Smlaier continue; 826126353Smlaier printf("%s=", t[i]); 827126353Smlaier if (rule->skip[i].nr == -1) 828126353Smlaier printf("end "); 829126353Smlaier else 830126353Smlaier printf("%u ", rule->skip[i].nr); 831126353Smlaier } 832126353Smlaier printf("]\n"); 833126353Smlaier 834126353Smlaier printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n", 835126353Smlaier rule->qname, rule->qid, rule->pqname, rule->pqid); 836126353Smlaier } 837171172Smlaier if (opts & PF_OPT_VERBOSE) { 838127024Smlaier printf(" [ Evaluations: %-8llu Packets: %-8llu " 839262799Sglebius "Bytes: %-10llu States: %-6ju]\n", 840127024Smlaier (unsigned long long)rule->evaluations, 841171172Smlaier (unsigned long long)(rule->packets[0] + 842171172Smlaier rule->packets[1]), 843171172Smlaier (unsigned long long)(rule->bytes[0] + 844262799Sglebius rule->bytes[1]), (uintmax_t)rule->u_states_cur); 845171172Smlaier if (!(opts & PF_OPT_DEBUG)) 846223637Sbz printf(" [ Inserted: uid %u pid %u " 847262799Sglebius "State Creations: %-6ju]\n", 848223637Sbz (unsigned)rule->cuid, (unsigned)rule->cpid, 849262799Sglebius (uintmax_t)rule->u_states_tot); 850171172Smlaier } 851126353Smlaier} 852126353Smlaier 853130617Smlaiervoid 854130617Smlaierpfctl_print_title(char *title) 855130617Smlaier{ 856130617Smlaier if (!first_title) 857130617Smlaier printf("\n"); 858130617Smlaier first_title = 0; 859130617Smlaier printf("%s\n", title); 860130617Smlaier} 861130617Smlaier 862126353Smlaierint 863171172Smlaierpfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, 864171172Smlaier char *anchorname, int depth) 865126353Smlaier{ 866126353Smlaier struct pfioc_rule pr; 867130617Smlaier u_int32_t nr, mnr, header = 0; 868126353Smlaier int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); 869223057Sbz int numeric = opts & PF_OPT_NUMERIC; 870171172Smlaier int len = strlen(path); 871171172Smlaier int brace; 872171172Smlaier char *p; 873126353Smlaier 874171172Smlaier if (path[0]) 875171172Smlaier snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 876171172Smlaier else 877171172Smlaier snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 878171172Smlaier 879126353Smlaier memset(&pr, 0, sizeof(pr)); 880171172Smlaier memcpy(pr.anchor, path, sizeof(pr.anchor)); 881130617Smlaier if (opts & PF_OPT_SHOWALL) { 882130617Smlaier pr.rule.action = PF_PASS; 883130617Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 884130617Smlaier warn("DIOCGETRULES"); 885171172Smlaier goto error; 886130617Smlaier } 887130617Smlaier header++; 888130617Smlaier } 889126353Smlaier pr.rule.action = PF_SCRUB; 890126353Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 891126353Smlaier warn("DIOCGETRULES"); 892171172Smlaier goto error; 893126353Smlaier } 894130617Smlaier if (opts & PF_OPT_SHOWALL) { 895171172Smlaier if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header)) 896130617Smlaier pfctl_print_title("FILTER RULES:"); 897171172Smlaier else if (format == PFCTL_SHOW_LABELS && labels) 898130617Smlaier pfctl_print_title("LABEL COUNTERS:"); 899130617Smlaier } 900126353Smlaier mnr = pr.nr; 901171172Smlaier if (opts & PF_OPT_CLRRULECTRS) 902171172Smlaier pr.action = PF_GET_CLR_CNTR; 903171172Smlaier 904126353Smlaier for (nr = 0; nr < mnr; ++nr) { 905126353Smlaier pr.nr = nr; 906126353Smlaier if (ioctl(dev, DIOCGETRULE, &pr)) { 907126353Smlaier warn("DIOCGETRULE"); 908171172Smlaier goto error; 909126353Smlaier } 910126353Smlaier 911126353Smlaier if (pfctl_get_pool(dev, &pr.rule.rpool, 912171172Smlaier nr, pr.ticket, PF_SCRUB, path) != 0) 913171172Smlaier goto error; 914126353Smlaier 915126353Smlaier switch (format) { 916171172Smlaier case PFCTL_SHOW_LABELS: 917126353Smlaier break; 918171172Smlaier case PFCTL_SHOW_RULES: 919130617Smlaier if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) 920130617Smlaier labels = 1; 921223057Sbz print_rule(&pr.rule, pr.anchor_call, rule_numbers, numeric); 922171172Smlaier printf("\n"); 923126353Smlaier pfctl_print_rule_counters(&pr.rule, opts); 924171172Smlaier break; 925171172Smlaier case PFCTL_SHOW_NOTHING: 926171172Smlaier break; 927126353Smlaier } 928126353Smlaier pfctl_clear_pool(&pr.rule.rpool); 929126353Smlaier } 930126353Smlaier pr.rule.action = PF_PASS; 931126353Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 932126353Smlaier warn("DIOCGETRULES"); 933171172Smlaier goto error; 934126353Smlaier } 935126353Smlaier mnr = pr.nr; 936126353Smlaier for (nr = 0; nr < mnr; ++nr) { 937126353Smlaier pr.nr = nr; 938126353Smlaier if (ioctl(dev, DIOCGETRULE, &pr)) { 939126353Smlaier warn("DIOCGETRULE"); 940171172Smlaier goto error; 941126353Smlaier } 942126353Smlaier 943126353Smlaier if (pfctl_get_pool(dev, &pr.rule.rpool, 944171172Smlaier nr, pr.ticket, PF_PASS, path) != 0) 945171172Smlaier goto error; 946126353Smlaier 947126353Smlaier switch (format) { 948171172Smlaier case PFCTL_SHOW_LABELS: 949126353Smlaier if (pr.rule.label[0]) { 950223637Sbz printf("%s %llu %llu %llu %llu" 951262799Sglebius " %llu %llu %llu %ju\n", 952223637Sbz pr.rule.label, 953127024Smlaier (unsigned long long)pr.rule.evaluations, 954171172Smlaier (unsigned long long)(pr.rule.packets[0] + 955171172Smlaier pr.rule.packets[1]), 956171172Smlaier (unsigned long long)(pr.rule.bytes[0] + 957171172Smlaier pr.rule.bytes[1]), 958171172Smlaier (unsigned long long)pr.rule.packets[0], 959171172Smlaier (unsigned long long)pr.rule.bytes[0], 960171172Smlaier (unsigned long long)pr.rule.packets[1], 961223637Sbz (unsigned long long)pr.rule.bytes[1], 962262799Sglebius (uintmax_t)pr.rule.u_states_tot); 963126353Smlaier } 964126353Smlaier break; 965171172Smlaier case PFCTL_SHOW_RULES: 966171172Smlaier brace = 0; 967130617Smlaier if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) 968130617Smlaier labels = 1; 969171172Smlaier INDENT(depth, !(opts & PF_OPT_VERBOSE)); 970171172Smlaier if (pr.anchor_call[0] && 971171172Smlaier ((((p = strrchr(pr.anchor_call, '_')) != NULL) && 972171172Smlaier ((void *)p == (void *)pr.anchor_call || 973171172Smlaier *(--p) == '/')) || (opts & PF_OPT_RECURSE))) { 974171172Smlaier brace++; 975171172Smlaier if ((p = strrchr(pr.anchor_call, '/')) != 976171172Smlaier NULL) 977171172Smlaier p++; 978171172Smlaier else 979171172Smlaier p = &pr.anchor_call[0]; 980171172Smlaier } else 981171172Smlaier p = &pr.anchor_call[0]; 982171172Smlaier 983223057Sbz print_rule(&pr.rule, p, rule_numbers, numeric); 984171172Smlaier if (brace) 985171172Smlaier printf(" {\n"); 986171172Smlaier else 987171172Smlaier printf("\n"); 988126353Smlaier pfctl_print_rule_counters(&pr.rule, opts); 989171172Smlaier if (brace) { 990171172Smlaier pfctl_show_rules(dev, path, opts, format, 991171172Smlaier p, depth + 1); 992171172Smlaier INDENT(depth, !(opts & PF_OPT_VERBOSE)); 993171172Smlaier printf("}\n"); 994171172Smlaier } 995171172Smlaier break; 996171172Smlaier case PFCTL_SHOW_NOTHING: 997171172Smlaier break; 998126353Smlaier } 999126353Smlaier pfctl_clear_pool(&pr.rule.rpool); 1000126353Smlaier } 1001171172Smlaier path[len] = '\0'; 1002126353Smlaier return (0); 1003171172Smlaier 1004171172Smlaier error: 1005171172Smlaier path[len] = '\0'; 1006171172Smlaier return (-1); 1007126353Smlaier} 1008126353Smlaier 1009126353Smlaierint 1010145840Smlaierpfctl_show_nat(int dev, int opts, char *anchorname) 1011126353Smlaier{ 1012126353Smlaier struct pfioc_rule pr; 1013126353Smlaier u_int32_t mnr, nr; 1014126353Smlaier static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; 1015130617Smlaier int i, dotitle = opts & PF_OPT_SHOWALL; 1016126353Smlaier 1017126353Smlaier memset(&pr, 0, sizeof(pr)); 1018126353Smlaier memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 1019126353Smlaier for (i = 0; i < 3; i++) { 1020126353Smlaier pr.rule.action = nattype[i]; 1021126353Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 1022126353Smlaier warn("DIOCGETRULES"); 1023126353Smlaier return (-1); 1024126353Smlaier } 1025126353Smlaier mnr = pr.nr; 1026126353Smlaier for (nr = 0; nr < mnr; ++nr) { 1027126353Smlaier pr.nr = nr; 1028126353Smlaier if (ioctl(dev, DIOCGETRULE, &pr)) { 1029126353Smlaier warn("DIOCGETRULE"); 1030126353Smlaier return (-1); 1031126353Smlaier } 1032126353Smlaier if (pfctl_get_pool(dev, &pr.rule.rpool, nr, 1033145840Smlaier pr.ticket, nattype[i], anchorname) != 0) 1034126353Smlaier return (-1); 1035130617Smlaier if (dotitle) { 1036130617Smlaier pfctl_print_title("TRANSLATION RULES:"); 1037130617Smlaier dotitle = 0; 1038130617Smlaier } 1039145840Smlaier print_rule(&pr.rule, pr.anchor_call, 1040223057Sbz opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC); 1041171172Smlaier printf("\n"); 1042126353Smlaier pfctl_print_rule_counters(&pr.rule, opts); 1043126353Smlaier pfctl_clear_pool(&pr.rule.rpool); 1044126353Smlaier } 1045126353Smlaier } 1046126353Smlaier return (0); 1047126353Smlaier} 1048126353Smlaier 1049126353Smlaierint 1050130617Smlaierpfctl_show_src_nodes(int dev, int opts) 1051126353Smlaier{ 1052130617Smlaier struct pfioc_src_nodes psn; 1053130617Smlaier struct pf_src_node *p; 1054130617Smlaier char *inbuf = NULL, *newinbuf = NULL; 1055223637Sbz unsigned int len = 0; 1056130617Smlaier int i; 1057130617Smlaier 1058130617Smlaier memset(&psn, 0, sizeof(psn)); 1059130617Smlaier for (;;) { 1060130617Smlaier psn.psn_len = len; 1061130617Smlaier if (len) { 1062130617Smlaier newinbuf = realloc(inbuf, len); 1063130617Smlaier if (newinbuf == NULL) 1064130617Smlaier err(1, "realloc"); 1065130617Smlaier psn.psn_buf = inbuf = newinbuf; 1066130617Smlaier } 1067130617Smlaier if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) { 1068130617Smlaier warn("DIOCGETSRCNODES"); 1069171172Smlaier free(inbuf); 1070130617Smlaier return (-1); 1071130617Smlaier } 1072130617Smlaier if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len) 1073130617Smlaier break; 1074130617Smlaier if (len == 0 && psn.psn_len == 0) 1075171172Smlaier goto done; 1076130617Smlaier if (len == 0 && psn.psn_len != 0) 1077130617Smlaier len = psn.psn_len; 1078130617Smlaier if (psn.psn_len == 0) 1079171172Smlaier goto done; /* no src_nodes */ 1080130617Smlaier len *= 2; 1081130617Smlaier } 1082130617Smlaier p = psn.psn_src_nodes; 1083130617Smlaier if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL)) 1084130617Smlaier pfctl_print_title("SOURCE TRACKING NODES:"); 1085130617Smlaier for (i = 0; i < psn.psn_len; i += sizeof(*p)) { 1086130617Smlaier print_src_node(p, opts); 1087130617Smlaier p++; 1088130617Smlaier } 1089171172Smlaierdone: 1090171172Smlaier free(inbuf); 1091130617Smlaier return (0); 1092130617Smlaier} 1093130617Smlaier 1094130617Smlaierint 1095130617Smlaierpfctl_show_states(int dev, const char *iface, int opts) 1096130617Smlaier{ 1097126353Smlaier struct pfioc_states ps; 1098223637Sbz struct pfsync_state *p; 1099130617Smlaier char *inbuf = NULL, *newinbuf = NULL; 1100223637Sbz unsigned int len = 0; 1101130617Smlaier int i, dotitle = (opts & PF_OPT_SHOWALL); 1102126353Smlaier 1103126353Smlaier memset(&ps, 0, sizeof(ps)); 1104126353Smlaier for (;;) { 1105126353Smlaier ps.ps_len = len; 1106126353Smlaier if (len) { 1107130617Smlaier newinbuf = realloc(inbuf, len); 1108130617Smlaier if (newinbuf == NULL) 1109126353Smlaier err(1, "realloc"); 1110130617Smlaier ps.ps_buf = inbuf = newinbuf; 1111126353Smlaier } 1112126353Smlaier if (ioctl(dev, DIOCGETSTATES, &ps) < 0) { 1113126353Smlaier warn("DIOCGETSTATES"); 1114171172Smlaier free(inbuf); 1115126353Smlaier return (-1); 1116126353Smlaier } 1117126353Smlaier if (ps.ps_len + sizeof(struct pfioc_states) < len) 1118126353Smlaier break; 1119126353Smlaier if (len == 0 && ps.ps_len == 0) 1120171172Smlaier goto done; 1121126353Smlaier if (len == 0 && ps.ps_len != 0) 1122126353Smlaier len = ps.ps_len; 1123126353Smlaier if (ps.ps_len == 0) 1124171172Smlaier goto done; /* no states */ 1125126353Smlaier len *= 2; 1126126353Smlaier } 1127126353Smlaier p = ps.ps_states; 1128130617Smlaier for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) { 1129223637Sbz if (iface != NULL && strcmp(p->ifname, iface)) 1130130617Smlaier continue; 1131130617Smlaier if (dotitle) { 1132130617Smlaier pfctl_print_title("STATES:"); 1133130617Smlaier dotitle = 0; 1134130617Smlaier } 1135130617Smlaier print_state(p, opts); 1136126353Smlaier } 1137171172Smlaierdone: 1138171172Smlaier free(inbuf); 1139126353Smlaier return (0); 1140126353Smlaier} 1141126353Smlaier 1142126353Smlaierint 1143130617Smlaierpfctl_show_status(int dev, int opts) 1144126353Smlaier{ 1145126353Smlaier struct pf_status status; 1146126353Smlaier 1147126353Smlaier if (ioctl(dev, DIOCGETSTATUS, &status)) { 1148126353Smlaier warn("DIOCGETSTATUS"); 1149126353Smlaier return (-1); 1150126353Smlaier } 1151130617Smlaier if (opts & PF_OPT_SHOWALL) 1152130617Smlaier pfctl_print_title("INFO:"); 1153130617Smlaier print_status(&status, opts); 1154126353Smlaier return (0); 1155126353Smlaier} 1156126353Smlaier 1157126353Smlaierint 1158130617Smlaierpfctl_show_timeouts(int dev, int opts) 1159126353Smlaier{ 1160126353Smlaier struct pfioc_tm pt; 1161126353Smlaier int i; 1162126353Smlaier 1163130617Smlaier if (opts & PF_OPT_SHOWALL) 1164130617Smlaier pfctl_print_title("TIMEOUTS:"); 1165126353Smlaier memset(&pt, 0, sizeof(pt)); 1166126353Smlaier for (i = 0; pf_timeouts[i].name; i++) { 1167126353Smlaier pt.timeout = pf_timeouts[i].timeout; 1168126353Smlaier if (ioctl(dev, DIOCGETTIMEOUT, &pt)) 1169126353Smlaier err(1, "DIOCGETTIMEOUT"); 1170126353Smlaier printf("%-20s %10d", pf_timeouts[i].name, pt.seconds); 1171145840Smlaier if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && 1172145840Smlaier pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) 1173126353Smlaier printf(" states"); 1174126353Smlaier else 1175126353Smlaier printf("s"); 1176126353Smlaier printf("\n"); 1177126353Smlaier } 1178126353Smlaier return (0); 1179126353Smlaier 1180126353Smlaier} 1181126353Smlaier 1182126353Smlaierint 1183130617Smlaierpfctl_show_limits(int dev, int opts) 1184126353Smlaier{ 1185126353Smlaier struct pfioc_limit pl; 1186126353Smlaier int i; 1187126353Smlaier 1188130617Smlaier if (opts & PF_OPT_SHOWALL) 1189130617Smlaier pfctl_print_title("LIMITS:"); 1190126353Smlaier memset(&pl, 0, sizeof(pl)); 1191126353Smlaier for (i = 0; pf_limits[i].name; i++) { 1192130617Smlaier pl.index = pf_limits[i].index; 1193126353Smlaier if (ioctl(dev, DIOCGETLIMIT, &pl)) 1194126353Smlaier err(1, "DIOCGETLIMIT"); 1195171172Smlaier printf("%-13s ", pf_limits[i].name); 1196126353Smlaier if (pl.limit == UINT_MAX) 1197126353Smlaier printf("unlimited\n"); 1198126353Smlaier else 1199171172Smlaier printf("hard limit %8u\n", pl.limit); 1200126353Smlaier } 1201126353Smlaier return (0); 1202126353Smlaier} 1203126353Smlaier 1204126353Smlaier/* callbacks for rule/nat/rdr/addr */ 1205126353Smlaierint 1206126353Smlaierpfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af) 1207126353Smlaier{ 1208126353Smlaier struct pf_pooladdr *pa; 1209126353Smlaier 1210126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1211126353Smlaier if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) 1212126353Smlaier err(1, "DIOCBEGINADDRS"); 1213126353Smlaier } 1214126353Smlaier 1215126353Smlaier pf->paddr.af = af; 1216126353Smlaier TAILQ_FOREACH(pa, &p->list, entries) { 1217126353Smlaier memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr)); 1218126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1219126353Smlaier if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) 1220126353Smlaier err(1, "DIOCADDADDR"); 1221126353Smlaier } 1222126353Smlaier } 1223126353Smlaier return (0); 1224126353Smlaier} 1225126353Smlaier 1226126353Smlaierint 1227145840Smlaierpfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call) 1228126353Smlaier{ 1229130617Smlaier u_int8_t rs_num; 1230171172Smlaier struct pf_rule *rule; 1231171172Smlaier struct pf_ruleset *rs; 1232171172Smlaier char *p; 1233126353Smlaier 1234171172Smlaier rs_num = pf_get_ruleset_number(r->action); 1235171172Smlaier if (rs_num == PF_RULESET_MAX) 1236145840Smlaier errx(1, "Invalid rule type %d", r->action); 1237126353Smlaier 1238171172Smlaier rs = &pf->anchor->ruleset; 1239145840Smlaier 1240171172Smlaier if (anchor_call[0] && r->anchor == NULL) { 1241171172Smlaier /* 1242171172Smlaier * Don't make non-brace anchors part of the main anchor pool. 1243145840Smlaier */ 1244171172Smlaier if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 1245171172Smlaier err(1, "pfctl_add_rule: calloc"); 1246171172Smlaier 1247171172Smlaier pf_init_ruleset(&r->anchor->ruleset); 1248171172Smlaier r->anchor->ruleset.anchor = r->anchor; 1249171172Smlaier if (strlcpy(r->anchor->path, anchor_call, 1250171172Smlaier sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 1251223637Sbz errx(1, "pfctl_add_rule: strlcpy"); 1252171172Smlaier if ((p = strrchr(anchor_call, '/')) != NULL) { 1253171172Smlaier if (!strlen(p)) 1254171172Smlaier err(1, "pfctl_add_rule: bad anchor name %s", 1255171172Smlaier anchor_call); 1256171172Smlaier } else 1257171172Smlaier p = (char *)anchor_call; 1258171172Smlaier if (strlcpy(r->anchor->name, p, 1259171172Smlaier sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 1260223637Sbz errx(1, "pfctl_add_rule: strlcpy"); 1261171172Smlaier } 1262145840Smlaier 1263171172Smlaier if ((rule = calloc(1, sizeof(*rule))) == NULL) 1264171172Smlaier err(1, "calloc"); 1265171172Smlaier bcopy(r, rule, sizeof(*rule)); 1266171172Smlaier TAILQ_INIT(&rule->rpool.list); 1267171172Smlaier pfctl_move_pool(&r->rpool, &rule->rpool); 1268145840Smlaier 1269171172Smlaier TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries); 1270171172Smlaier return (0); 1271171172Smlaier} 1272171172Smlaier 1273171172Smlaierint 1274171172Smlaierpfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a) 1275171172Smlaier{ 1276171172Smlaier int osize = pf->trans->pfrb_size; 1277171172Smlaier 1278171172Smlaier if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { 1279171172Smlaier if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || 1280171172Smlaier pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || 1281171172Smlaier pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) 1282171172Smlaier return (1); 1283171172Smlaier } 1284171172Smlaier if (a == pf->astack[0] && ((altqsupport && 1285223637Sbz (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) { 1286171172Smlaier if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path)) 1287171172Smlaier return (2); 1288171172Smlaier } 1289171172Smlaier if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) { 1290171172Smlaier if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) || 1291171172Smlaier pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path)) 1292171172Smlaier return (3); 1293171172Smlaier } 1294171172Smlaier if (pf->loadopt & PFCTL_FLAG_TABLE) 1295171172Smlaier if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path)) 1296171172Smlaier return (4); 1297171172Smlaier if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1298171172Smlaier return (5); 1299171172Smlaier 1300171172Smlaier return (0); 1301171172Smlaier} 1302171172Smlaier 1303171172Smlaierint 1304171172Smlaierpfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs, 1305171172Smlaier int rs_num, int depth) 1306171172Smlaier{ 1307171172Smlaier struct pf_rule *r; 1308171172Smlaier int error, len = strlen(path); 1309171172Smlaier int brace = 0; 1310171172Smlaier 1311171172Smlaier pf->anchor = rs->anchor; 1312171172Smlaier 1313171172Smlaier if (path[0]) 1314171172Smlaier snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name); 1315171172Smlaier else 1316171172Smlaier snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name); 1317171172Smlaier 1318171172Smlaier if (depth) { 1319171172Smlaier if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) { 1320171172Smlaier brace++; 1321171172Smlaier if (pf->opts & PF_OPT_VERBOSE) 1322171172Smlaier printf(" {\n"); 1323171172Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0 && 1324171172Smlaier (error = pfctl_ruleset_trans(pf, 1325171172Smlaier path, rs->anchor))) { 1326171172Smlaier printf("pfctl_load_rulesets: " 1327171172Smlaier "pfctl_ruleset_trans %d\n", error); 1328171172Smlaier goto error; 1329145840Smlaier } 1330171172Smlaier } else if (pf->opts & PF_OPT_VERBOSE) 1331171172Smlaier printf("\n"); 1332145840Smlaier 1333145840Smlaier } 1334145840Smlaier 1335171172Smlaier if (pf->optimize && rs_num == PF_RULESET_FILTER) 1336171172Smlaier pfctl_optimize_ruleset(pf, rs); 1337171172Smlaier 1338171172Smlaier while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) { 1339171172Smlaier TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries); 1340171172Smlaier if ((error = pfctl_load_rule(pf, path, r, depth))) 1341171172Smlaier goto error; 1342171172Smlaier if (r->anchor) { 1343171172Smlaier if ((error = pfctl_load_ruleset(pf, path, 1344171172Smlaier &r->anchor->ruleset, rs_num, depth + 1))) 1345171172Smlaier goto error; 1346171172Smlaier } else if (pf->opts & PF_OPT_VERBOSE) 1347171172Smlaier printf("\n"); 1348171172Smlaier free(r); 1349171172Smlaier } 1350171172Smlaier if (brace && pf->opts & PF_OPT_VERBOSE) { 1351171172Smlaier INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1352171172Smlaier printf("}\n"); 1353171172Smlaier } 1354171172Smlaier path[len] = '\0'; 1355171172Smlaier return (0); 1356171172Smlaier 1357171172Smlaier error: 1358171172Smlaier path[len] = '\0'; 1359171172Smlaier return (error); 1360171172Smlaier 1361171172Smlaier} 1362171172Smlaier 1363171172Smlaierint 1364171172Smlaierpfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) 1365171172Smlaier{ 1366171172Smlaier u_int8_t rs_num = pf_get_ruleset_number(r->action); 1367171172Smlaier char *name; 1368171172Smlaier struct pfioc_rule pr; 1369171172Smlaier int len = strlen(path); 1370171172Smlaier 1371171172Smlaier bzero(&pr, sizeof(pr)); 1372171172Smlaier /* set up anchor before adding to path for anchor_call */ 1373171172Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) 1374171172Smlaier pr.ticket = pfctl_get_ticket(pf->trans, rs_num, path); 1375171172Smlaier if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >= sizeof(pr.anchor)) 1376171172Smlaier errx(1, "pfctl_load_rule: strlcpy"); 1377171172Smlaier 1378171172Smlaier if (r->anchor) { 1379171172Smlaier if (r->anchor->match) { 1380171172Smlaier if (path[0]) 1381171172Smlaier snprintf(&path[len], MAXPATHLEN - len, 1382171172Smlaier "/%s", r->anchor->name); 1383171172Smlaier else 1384171172Smlaier snprintf(&path[len], MAXPATHLEN - len, 1385171172Smlaier "%s", r->anchor->name); 1386171172Smlaier name = path; 1387171172Smlaier } else 1388171172Smlaier name = r->anchor->path; 1389171172Smlaier } else 1390171172Smlaier name = ""; 1391171172Smlaier 1392126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1393126353Smlaier if (pfctl_add_pool(pf, &r->rpool, r->af)) 1394126353Smlaier return (1); 1395130617Smlaier pr.pool_ticket = pf->paddr.ticket; 1396130617Smlaier memcpy(&pr.rule, r, sizeof(pr.rule)); 1397171172Smlaier if (r->anchor && strlcpy(pr.anchor_call, name, 1398171172Smlaier sizeof(pr.anchor_call)) >= sizeof(pr.anchor_call)) 1399171172Smlaier errx(1, "pfctl_load_rule: strlcpy"); 1400130617Smlaier if (ioctl(pf->dev, DIOCADDRULE, &pr)) 1401126353Smlaier err(1, "DIOCADDRULE"); 1402126353Smlaier } 1403171172Smlaier 1404171172Smlaier if (pf->opts & PF_OPT_VERBOSE) { 1405171172Smlaier INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 1406171172Smlaier print_rule(r, r->anchor ? r->anchor->name : "", 1407223057Sbz pf->opts & PF_OPT_VERBOSE2, 1408223057Sbz pf->opts & PF_OPT_NUMERIC); 1409171172Smlaier } 1410171172Smlaier path[len] = '\0'; 1411126353Smlaier pfctl_clear_pool(&r->rpool); 1412126353Smlaier return (0); 1413126353Smlaier} 1414126353Smlaier 1415126353Smlaierint 1416126353Smlaierpfctl_add_altq(struct pfctl *pf, struct pf_altq *a) 1417126353Smlaier{ 1418126353Smlaier if (altqsupport && 1419126353Smlaier (loadopt & PFCTL_FLAG_ALTQ) != 0) { 1420126353Smlaier memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq)); 1421126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1422126353Smlaier if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) { 1423126353Smlaier if (errno == ENXIO) 1424126353Smlaier errx(1, "qtype not configured"); 1425126353Smlaier else if (errno == ENODEV) 1426126353Smlaier errx(1, "%s: driver does not support " 1427126353Smlaier "altq", a->ifname); 1428126353Smlaier else 1429126353Smlaier err(1, "DIOCADDALTQ"); 1430126353Smlaier } 1431126353Smlaier } 1432126353Smlaier pfaltq_store(&pf->paltq->altq); 1433126353Smlaier } 1434126353Smlaier return (0); 1435126353Smlaier} 1436126353Smlaier 1437126353Smlaierint 1438223637Sbzpfctl_rules(int dev, char *filename, int opts, int optimize, 1439171172Smlaier char *anchorname, struct pfr_buffer *trans) 1440126353Smlaier{ 1441126353Smlaier#define ERR(x) do { warn(x); goto _error; } while(0) 1442126353Smlaier#define ERRX(x) do { warnx(x); goto _error; } while(0) 1443126353Smlaier 1444130617Smlaier struct pfr_buffer *t, buf; 1445130617Smlaier struct pfioc_altq pa; 1446130617Smlaier struct pfctl pf; 1447171172Smlaier struct pf_ruleset *rs; 1448130617Smlaier struct pfr_table trs; 1449171172Smlaier char *path; 1450130617Smlaier int osize; 1451126353Smlaier 1452171172Smlaier RB_INIT(&pf_anchors); 1453171172Smlaier memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); 1454171172Smlaier pf_init_ruleset(&pf_main_anchor.ruleset); 1455171172Smlaier pf_main_anchor.ruleset.anchor = &pf_main_anchor; 1456130617Smlaier if (trans == NULL) { 1457171172Smlaier bzero(&buf, sizeof(buf)); 1458171172Smlaier buf.pfrb_type = PFRB_TRANS; 1459171172Smlaier t = &buf; 1460171172Smlaier osize = 0; 1461130617Smlaier } else { 1462171172Smlaier t = trans; 1463171172Smlaier osize = t->pfrb_size; 1464130617Smlaier } 1465130617Smlaier 1466126353Smlaier memset(&pa, 0, sizeof(pa)); 1467126353Smlaier memset(&pf, 0, sizeof(pf)); 1468126353Smlaier memset(&trs, 0, sizeof(trs)); 1469171172Smlaier if ((path = calloc(1, MAXPATHLEN)) == NULL) 1470171172Smlaier ERRX("pfctl_rules: calloc"); 1471126353Smlaier if (strlcpy(trs.pfrt_anchor, anchorname, 1472145840Smlaier sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) 1473126353Smlaier ERRX("pfctl_rules: strlcpy"); 1474126353Smlaier pf.dev = dev; 1475126353Smlaier pf.opts = opts; 1476171172Smlaier pf.optimize = optimize; 1477126353Smlaier pf.loadopt = loadopt; 1478171172Smlaier 1479171172Smlaier /* non-brace anchor, create without resolving the path */ 1480171172Smlaier if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) 1481171172Smlaier ERRX("pfctl_rules: calloc"); 1482171172Smlaier rs = &pf.anchor->ruleset; 1483171172Smlaier pf_init_ruleset(rs); 1484171172Smlaier rs->anchor = pf.anchor; 1485171172Smlaier if (strlcpy(pf.anchor->path, anchorname, 1486171172Smlaier sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 1487171172Smlaier errx(1, "pfctl_add_rule: strlcpy"); 1488171172Smlaier if (strlcpy(pf.anchor->name, anchorname, 1489171172Smlaier sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 1490171172Smlaier errx(1, "pfctl_add_rule: strlcpy"); 1491171172Smlaier 1492171172Smlaier 1493171172Smlaier pf.astack[0] = pf.anchor; 1494171172Smlaier pf.asd = 0; 1495130617Smlaier if (anchorname[0]) 1496130617Smlaier pf.loadopt &= ~PFCTL_FLAG_ALTQ; 1497126353Smlaier pf.paltq = &pa; 1498130617Smlaier pf.trans = t; 1499145840Smlaier pfctl_init_options(&pf); 1500130617Smlaier 1501130617Smlaier if ((opts & PF_OPT_NOACTION) == 0) { 1502171172Smlaier /* 1503171172Smlaier * XXX For the time being we need to open transactions for 1504171172Smlaier * the main ruleset before parsing, because tables are still 1505171172Smlaier * loaded at parse time. 1506171172Smlaier */ 1507171172Smlaier if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor)) 1508171172Smlaier ERRX("pfctl_rules"); 1509130617Smlaier if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) 1510171172Smlaier pa.ticket = 1511171172Smlaier pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname); 1512130617Smlaier if (pf.loadopt & PFCTL_FLAG_TABLE) 1513171172Smlaier pf.astack[0]->ruleset.tticket = 1514171172Smlaier pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname); 1515130617Smlaier } 1516171172Smlaier 1517223637Sbz if (parse_config(filename, &pf) < 0) { 1518126353Smlaier if ((opts & PF_OPT_NOACTION) == 0) 1519126353Smlaier ERRX("Syntax error in config file: " 1520126353Smlaier "pf rules not loaded"); 1521126353Smlaier else 1522126353Smlaier goto _error; 1523126353Smlaier } 1524333181Skp if (loadopt & PFCTL_FLAG_OPTION) 1525333181Skp pfctl_clear_skip_ifaces(&pf); 1526171172Smlaier 1527171172Smlaier if ((pf.loadopt & PFCTL_FLAG_FILTER && 1528171172Smlaier (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) || 1529171172Smlaier (pf.loadopt & PFCTL_FLAG_NAT && 1530171172Smlaier (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) || 1531171172Smlaier pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) || 1532171172Smlaier pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) || 1533171172Smlaier (pf.loadopt & PFCTL_FLAG_FILTER && 1534171172Smlaier pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) { 1535171172Smlaier if ((opts & PF_OPT_NOACTION) == 0) 1536171172Smlaier ERRX("Unable to load rules into kernel"); 1537171172Smlaier else 1538171172Smlaier goto _error; 1539145840Smlaier } 1540145840Smlaier 1541130617Smlaier if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0)) 1542126353Smlaier if (check_commit_altq(dev, opts) != 0) 1543126353Smlaier ERRX("errors in altq config"); 1544145840Smlaier 1545126353Smlaier /* process "load anchor" directives */ 1546145840Smlaier if (!anchorname[0]) 1547171172Smlaier if (pfctl_load_anchors(dev, &pf, t) == -1) 1548126353Smlaier ERRX("load anchors"); 1549126353Smlaier 1550145840Smlaier if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) { 1551145840Smlaier if (!anchorname[0]) 1552145840Smlaier if (pfctl_load_options(&pf)) 1553145840Smlaier goto _error; 1554171172Smlaier if (pfctl_trans(dev, t, DIOCXCOMMIT, osize)) 1555130617Smlaier ERR("DIOCXCOMMIT"); 1556145840Smlaier } 1557126353Smlaier return (0); 1558126353Smlaier 1559126353Smlaier_error: 1560130617Smlaier if (trans == NULL) { /* main ruleset */ 1561130617Smlaier if ((opts & PF_OPT_NOACTION) == 0) 1562171172Smlaier if (pfctl_trans(dev, t, DIOCXROLLBACK, osize)) 1563130617Smlaier err(1, "DIOCXROLLBACK"); 1564130617Smlaier exit(1); 1565145840Smlaier } else { /* sub ruleset */ 1566130617Smlaier return (-1); 1567145840Smlaier } 1568126353Smlaier 1569126353Smlaier#undef ERR 1570126353Smlaier#undef ERRX 1571126353Smlaier} 1572126353Smlaier 1573145840SmlaierFILE * 1574145840Smlaierpfctl_fopen(const char *name, const char *mode) 1575145840Smlaier{ 1576145840Smlaier struct stat st; 1577145840Smlaier FILE *fp; 1578145840Smlaier 1579145840Smlaier fp = fopen(name, mode); 1580145840Smlaier if (fp == NULL) 1581145840Smlaier return (NULL); 1582145840Smlaier if (fstat(fileno(fp), &st)) { 1583145840Smlaier fclose(fp); 1584145840Smlaier return (NULL); 1585145840Smlaier } 1586145840Smlaier if (S_ISDIR(st.st_mode)) { 1587145840Smlaier fclose(fp); 1588145840Smlaier errno = EISDIR; 1589145840Smlaier return (NULL); 1590145840Smlaier } 1591145840Smlaier return (fp); 1592145840Smlaier} 1593145840Smlaier 1594145840Smlaiervoid 1595145840Smlaierpfctl_init_options(struct pfctl *pf) 1596145840Smlaier{ 1597171172Smlaier 1598145840Smlaier pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 1599145840Smlaier pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; 1600145840Smlaier pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 1601145840Smlaier pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; 1602145840Smlaier pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; 1603145840Smlaier pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; 1604145840Smlaier pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; 1605145840Smlaier pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; 1606145840Smlaier pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; 1607145840Smlaier pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; 1608145840Smlaier pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; 1609145840Smlaier pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; 1610145840Smlaier pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; 1611145840Smlaier pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; 1612145840Smlaier pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; 1613145840Smlaier pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; 1614145840Smlaier pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; 1615145840Smlaier pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; 1616171172Smlaier pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; 1617171172Smlaier pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; 1618145840Smlaier 1619171172Smlaier pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; 1620171172Smlaier pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT; 1621171172Smlaier pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; 1622171172Smlaier pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; 1623145840Smlaier 1624145840Smlaier pf->debug = PF_DEBUG_URGENT; 1625145840Smlaier} 1626145840Smlaier 1627126353Smlaierint 1628145840Smlaierpfctl_load_options(struct pfctl *pf) 1629126353Smlaier{ 1630145840Smlaier int i, error = 0; 1631126353Smlaier 1632126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1633126353Smlaier return (0); 1634126353Smlaier 1635145840Smlaier /* load limits */ 1636145840Smlaier for (i = 0; i < PF_LIMIT_MAX; i++) { 1637145840Smlaier if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i]) 1638145840Smlaier continue; 1639145840Smlaier if (pfctl_load_limit(pf, i, pf->limit[i])) 1640145840Smlaier error = 1; 1641145840Smlaier } 1642145840Smlaier 1643171172Smlaier /* 1644223637Sbz * If we've set the limit, but haven't explicitly set adaptive 1645171172Smlaier * timeouts, do it now with a start of 60% and end of 120%. 1646171172Smlaier */ 1647171172Smlaier if (pf->limit_set[PF_LIMIT_STATES] && 1648171172Smlaier !pf->timeout_set[PFTM_ADAPTIVE_START] && 1649171172Smlaier !pf->timeout_set[PFTM_ADAPTIVE_END]) { 1650171172Smlaier pf->timeout[PFTM_ADAPTIVE_START] = 1651171172Smlaier (pf->limit[PF_LIMIT_STATES] / 10) * 6; 1652171172Smlaier pf->timeout_set[PFTM_ADAPTIVE_START] = 1; 1653171172Smlaier pf->timeout[PFTM_ADAPTIVE_END] = 1654171172Smlaier (pf->limit[PF_LIMIT_STATES] / 10) * 12; 1655171172Smlaier pf->timeout_set[PFTM_ADAPTIVE_END] = 1; 1656171172Smlaier } 1657171172Smlaier 1658145840Smlaier /* load timeouts */ 1659145840Smlaier for (i = 0; i < PFTM_MAX; i++) { 1660145840Smlaier if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i]) 1661145840Smlaier continue; 1662145840Smlaier if (pfctl_load_timeout(pf, i, pf->timeout[i])) 1663145840Smlaier error = 1; 1664145840Smlaier } 1665145840Smlaier 1666145840Smlaier /* load debug */ 1667145840Smlaier if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set) 1668145840Smlaier if (pfctl_load_debug(pf, pf->debug)) 1669145840Smlaier error = 1; 1670145840Smlaier 1671145840Smlaier /* load logif */ 1672145840Smlaier if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set) 1673145840Smlaier if (pfctl_load_logif(pf, pf->ifname)) 1674145840Smlaier error = 1; 1675145840Smlaier 1676145840Smlaier /* load hostid */ 1677145840Smlaier if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set) 1678145840Smlaier if (pfctl_load_hostid(pf, pf->hostid)) 1679145840Smlaier error = 1; 1680145840Smlaier 1681145840Smlaier return (error); 1682145840Smlaier} 1683145840Smlaier 1684145840Smlaierint 1685145840Smlaierpfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) 1686145840Smlaier{ 1687145840Smlaier int i; 1688145840Smlaier 1689145840Smlaier 1690126353Smlaier for (i = 0; pf_limits[i].name; i++) { 1691126353Smlaier if (strcasecmp(opt, pf_limits[i].name) == 0) { 1692145840Smlaier pf->limit[pf_limits[i].index] = limit; 1693145840Smlaier pf->limit_set[pf_limits[i].index] = 1; 1694126353Smlaier break; 1695126353Smlaier } 1696126353Smlaier } 1697126353Smlaier if (pf_limits[i].name == NULL) { 1698126353Smlaier warnx("Bad pool name."); 1699126353Smlaier return (1); 1700126353Smlaier } 1701126353Smlaier 1702126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 1703126353Smlaier printf("set limit %s %d\n", opt, limit); 1704126353Smlaier 1705126353Smlaier return (0); 1706126353Smlaier} 1707126353Smlaier 1708126353Smlaierint 1709145840Smlaierpfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) 1710145840Smlaier{ 1711145840Smlaier struct pfioc_limit pl; 1712145840Smlaier 1713145840Smlaier memset(&pl, 0, sizeof(pl)); 1714145840Smlaier pl.index = index; 1715145840Smlaier pl.limit = limit; 1716145840Smlaier if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) { 1717145840Smlaier if (errno == EBUSY) 1718145840Smlaier warnx("Current pool size exceeds requested hard limit"); 1719145840Smlaier else 1720145840Smlaier warnx("DIOCSETLIMIT"); 1721145840Smlaier return (1); 1722145840Smlaier } 1723145840Smlaier return (0); 1724145840Smlaier} 1725145840Smlaier 1726145840Smlaierint 1727126353Smlaierpfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 1728126353Smlaier{ 1729126353Smlaier int i; 1730126353Smlaier 1731126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1732126353Smlaier return (0); 1733126353Smlaier 1734126353Smlaier for (i = 0; pf_timeouts[i].name; i++) { 1735126353Smlaier if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 1736145840Smlaier pf->timeout[pf_timeouts[i].timeout] = seconds; 1737145840Smlaier pf->timeout_set[pf_timeouts[i].timeout] = 1; 1738126353Smlaier break; 1739126353Smlaier } 1740126353Smlaier } 1741126353Smlaier 1742126353Smlaier if (pf_timeouts[i].name == NULL) { 1743126353Smlaier warnx("Bad timeout name."); 1744126353Smlaier return (1); 1745126353Smlaier } 1746126353Smlaier 1747126353Smlaier 1748126353Smlaier if (pf->opts & PF_OPT_VERBOSE && ! quiet) 1749126353Smlaier printf("set timeout %s %d\n", opt, seconds); 1750126353Smlaier 1751126353Smlaier return (0); 1752126353Smlaier} 1753126353Smlaier 1754126353Smlaierint 1755145840Smlaierpfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) 1756145840Smlaier{ 1757145840Smlaier struct pfioc_tm pt; 1758145840Smlaier 1759145840Smlaier memset(&pt, 0, sizeof(pt)); 1760145840Smlaier pt.timeout = timeout; 1761145840Smlaier pt.seconds = seconds; 1762145840Smlaier if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) { 1763145840Smlaier warnx("DIOCSETTIMEOUT"); 1764145840Smlaier return (1); 1765145840Smlaier } 1766145840Smlaier return (0); 1767145840Smlaier} 1768145840Smlaier 1769145840Smlaierint 1770126353Smlaierpfctl_set_optimization(struct pfctl *pf, const char *opt) 1771126353Smlaier{ 1772126353Smlaier const struct pf_hint *hint; 1773126353Smlaier int i, r; 1774126353Smlaier 1775126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1776126353Smlaier return (0); 1777126353Smlaier 1778126353Smlaier for (i = 0; pf_hints[i].name; i++) 1779126353Smlaier if (strcasecmp(opt, pf_hints[i].name) == 0) 1780126353Smlaier break; 1781126353Smlaier 1782126353Smlaier hint = pf_hints[i].hint; 1783126353Smlaier if (hint == NULL) { 1784171172Smlaier warnx("invalid state timeouts optimization"); 1785126353Smlaier return (1); 1786126353Smlaier } 1787126353Smlaier 1788126353Smlaier for (i = 0; hint[i].name; i++) 1789126353Smlaier if ((r = pfctl_set_timeout(pf, hint[i].name, 1790126353Smlaier hint[i].timeout, 1))) 1791126353Smlaier return (r); 1792126353Smlaier 1793126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 1794126353Smlaier printf("set optimization %s\n", opt); 1795126353Smlaier 1796126353Smlaier return (0); 1797126353Smlaier} 1798126353Smlaier 1799126353Smlaierint 1800126353Smlaierpfctl_set_logif(struct pfctl *pf, char *ifname) 1801126353Smlaier{ 1802126353Smlaier 1803126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1804126353Smlaier return (0); 1805126353Smlaier 1806145840Smlaier if (!strcmp(ifname, "none")) { 1807145840Smlaier free(pf->ifname); 1808145840Smlaier pf->ifname = NULL; 1809145840Smlaier } else { 1810145840Smlaier pf->ifname = strdup(ifname); 1811145840Smlaier if (!pf->ifname) 1812145840Smlaier errx(1, "pfctl_set_logif: strdup"); 1813126353Smlaier } 1814145840Smlaier pf->ifname_set = 1; 1815126353Smlaier 1816126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 1817126353Smlaier printf("set loginterface %s\n", ifname); 1818126353Smlaier 1819126353Smlaier return (0); 1820126353Smlaier} 1821126353Smlaier 1822126353Smlaierint 1823145840Smlaierpfctl_load_logif(struct pfctl *pf, char *ifname) 1824145840Smlaier{ 1825145840Smlaier struct pfioc_if pi; 1826145840Smlaier 1827145840Smlaier memset(&pi, 0, sizeof(pi)); 1828145840Smlaier if (ifname && strlcpy(pi.ifname, ifname, 1829145840Smlaier sizeof(pi.ifname)) >= sizeof(pi.ifname)) { 1830171172Smlaier warnx("pfctl_load_logif: strlcpy"); 1831145840Smlaier return (1); 1832145840Smlaier } 1833145840Smlaier if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) { 1834145840Smlaier warnx("DIOCSETSTATUSIF"); 1835145840Smlaier return (1); 1836145840Smlaier } 1837145840Smlaier return (0); 1838145840Smlaier} 1839145840Smlaier 1840145840Smlaierint 1841130617Smlaierpfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 1842130617Smlaier{ 1843130617Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1844130617Smlaier return (0); 1845130617Smlaier 1846130617Smlaier HTONL(hostid); 1847130617Smlaier 1848145840Smlaier pf->hostid = hostid; 1849145840Smlaier pf->hostid_set = 1; 1850130617Smlaier 1851130617Smlaier if (pf->opts & PF_OPT_VERBOSE) 1852130617Smlaier printf("set hostid 0x%08x\n", ntohl(hostid)); 1853130617Smlaier 1854130617Smlaier return (0); 1855130617Smlaier} 1856130617Smlaier 1857130617Smlaierint 1858145840Smlaierpfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) 1859145840Smlaier{ 1860145840Smlaier if (ioctl(dev, DIOCSETHOSTID, &hostid)) { 1861145840Smlaier warnx("DIOCSETHOSTID"); 1862145840Smlaier return (1); 1863145840Smlaier } 1864145840Smlaier return (0); 1865145840Smlaier} 1866145840Smlaier 1867145840Smlaierint 1868130617Smlaierpfctl_set_debug(struct pfctl *pf, char *d) 1869130617Smlaier{ 1870130617Smlaier u_int32_t level; 1871130617Smlaier 1872130617Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1873130617Smlaier return (0); 1874130617Smlaier 1875130617Smlaier if (!strcmp(d, "none")) 1876145840Smlaier pf->debug = PF_DEBUG_NONE; 1877130617Smlaier else if (!strcmp(d, "urgent")) 1878145840Smlaier pf->debug = PF_DEBUG_URGENT; 1879130617Smlaier else if (!strcmp(d, "misc")) 1880145840Smlaier pf->debug = PF_DEBUG_MISC; 1881130617Smlaier else if (!strcmp(d, "loud")) 1882145840Smlaier pf->debug = PF_DEBUG_NOISY; 1883130617Smlaier else { 1884130617Smlaier warnx("unknown debug level \"%s\"", d); 1885130617Smlaier return (-1); 1886130617Smlaier } 1887130617Smlaier 1888145840Smlaier pf->debug_set = 1; 1889290236Skp level = pf->debug; 1890145840Smlaier 1891130617Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) 1892130617Smlaier if (ioctl(dev, DIOCSETDEBUG, &level)) 1893130617Smlaier err(1, "DIOCSETDEBUG"); 1894130617Smlaier 1895130617Smlaier if (pf->opts & PF_OPT_VERBOSE) 1896130617Smlaier printf("set debug %s\n", d); 1897130617Smlaier 1898130617Smlaier return (0); 1899130617Smlaier} 1900130617Smlaier 1901130617Smlaierint 1902145840Smlaierpfctl_load_debug(struct pfctl *pf, unsigned int level) 1903145840Smlaier{ 1904145840Smlaier if (ioctl(pf->dev, DIOCSETDEBUG, &level)) { 1905145840Smlaier warnx("DIOCSETDEBUG"); 1906145840Smlaier return (1); 1907145840Smlaier } 1908145840Smlaier return (0); 1909145840Smlaier} 1910145840Smlaier 1911145840Smlaierint 1912145840Smlaierpfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) 1913145840Smlaier{ 1914145840Smlaier struct pfioc_iface pi; 1915145840Smlaier 1916145840Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1917145840Smlaier return (0); 1918145840Smlaier 1919145840Smlaier bzero(&pi, sizeof(pi)); 1920145840Smlaier 1921145840Smlaier pi.pfiio_flags = flags; 1922145840Smlaier 1923145840Smlaier if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= 1924145840Smlaier sizeof(pi.pfiio_name)) 1925145840Smlaier errx(1, "pfctl_set_interface_flags: strlcpy"); 1926145840Smlaier 1927145840Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1928145840Smlaier if (how == 0) { 1929145840Smlaier if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi)) 1930145840Smlaier err(1, "DIOCCLRIFFLAG"); 1931145840Smlaier } else { 1932145840Smlaier if (ioctl(pf->dev, DIOCSETIFFLAG, &pi)) 1933145840Smlaier err(1, "DIOCSETIFFLAG"); 1934333181Skp pfctl_check_skip_ifaces(ifname); 1935145840Smlaier } 1936145840Smlaier } 1937145840Smlaier return (0); 1938145840Smlaier} 1939145840Smlaier 1940145840Smlaiervoid 1941126353Smlaierpfctl_debug(int dev, u_int32_t level, int opts) 1942126353Smlaier{ 1943126353Smlaier if (ioctl(dev, DIOCSETDEBUG, &level)) 1944126353Smlaier err(1, "DIOCSETDEBUG"); 1945126353Smlaier if ((opts & PF_OPT_QUIET) == 0) { 1946126353Smlaier fprintf(stderr, "debug level set to '"); 1947126353Smlaier switch (level) { 1948126353Smlaier case PF_DEBUG_NONE: 1949126353Smlaier fprintf(stderr, "none"); 1950126353Smlaier break; 1951126353Smlaier case PF_DEBUG_URGENT: 1952126353Smlaier fprintf(stderr, "urgent"); 1953126353Smlaier break; 1954126353Smlaier case PF_DEBUG_MISC: 1955126353Smlaier fprintf(stderr, "misc"); 1956126353Smlaier break; 1957126353Smlaier case PF_DEBUG_NOISY: 1958126353Smlaier fprintf(stderr, "loud"); 1959126353Smlaier break; 1960126353Smlaier default: 1961126353Smlaier fprintf(stderr, "<invalid>"); 1962126353Smlaier break; 1963126353Smlaier } 1964126353Smlaier fprintf(stderr, "'\n"); 1965126353Smlaier } 1966126353Smlaier} 1967126353Smlaier 1968126353Smlaierint 1969126353Smlaierpfctl_test_altqsupport(int dev, int opts) 1970126353Smlaier{ 1971126353Smlaier struct pfioc_altq pa; 1972126353Smlaier 1973126353Smlaier if (ioctl(dev, DIOCGETALTQS, &pa)) { 1974126353Smlaier if (errno == ENODEV) { 1975285730Sgnn if (opts & PF_OPT_VERBOSE) 1976126353Smlaier fprintf(stderr, "No ALTQ support in kernel\n" 1977126353Smlaier "ALTQ related functions disabled\n"); 1978126353Smlaier return (0); 1979126353Smlaier } else 1980126353Smlaier err(1, "DIOCGETALTQS"); 1981126353Smlaier } 1982126353Smlaier return (1); 1983126353Smlaier} 1984126353Smlaier 1985126353Smlaierint 1986126353Smlaierpfctl_show_anchors(int dev, int opts, char *anchorname) 1987126353Smlaier{ 1988145840Smlaier struct pfioc_ruleset pr; 1989145840Smlaier u_int32_t mnr, nr; 1990126353Smlaier 1991145840Smlaier memset(&pr, 0, sizeof(pr)); 1992145840Smlaier memcpy(pr.path, anchorname, sizeof(pr.path)); 1993145840Smlaier if (ioctl(dev, DIOCGETRULESETS, &pr)) { 1994145840Smlaier if (errno == EINVAL) 1995145840Smlaier fprintf(stderr, "Anchor '%s' not found.\n", 1996145840Smlaier anchorname); 1997145840Smlaier else 1998145840Smlaier err(1, "DIOCGETRULESETS"); 1999145840Smlaier return (-1); 2000145840Smlaier } 2001145840Smlaier mnr = pr.nr; 2002145840Smlaier for (nr = 0; nr < mnr; ++nr) { 2003145840Smlaier char sub[MAXPATHLEN]; 2004126353Smlaier 2005145840Smlaier pr.nr = nr; 2006145840Smlaier if (ioctl(dev, DIOCGETRULESET, &pr)) 2007145840Smlaier err(1, "DIOCGETRULESET"); 2008145840Smlaier if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) 2009145840Smlaier continue; 2010145840Smlaier sub[0] = 0; 2011145840Smlaier if (pr.path[0]) { 2012145840Smlaier strlcat(sub, pr.path, sizeof(sub)); 2013145840Smlaier strlcat(sub, "/", sizeof(sub)); 2014126353Smlaier } 2015145840Smlaier strlcat(sub, pr.name, sizeof(sub)); 2016171172Smlaier if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 2017171172Smlaier printf(" %s\n", sub); 2018171172Smlaier if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub)) 2019126353Smlaier return (-1); 2020126353Smlaier } 2021126353Smlaier return (0); 2022126353Smlaier} 2023126353Smlaier 2024126353Smlaierconst char * 2025126353Smlaierpfctl_lookup_option(char *cmd, const char **list) 2026126353Smlaier{ 2027126353Smlaier if (cmd != NULL && *cmd) 2028126353Smlaier for (; *list; list++) 2029126353Smlaier if (!strncmp(cmd, *list, strlen(cmd))) 2030126353Smlaier return (*list); 2031126353Smlaier return (NULL); 2032126353Smlaier} 2033126353Smlaier 2034126353Smlaierint 2035126353Smlaiermain(int argc, char *argv[]) 2036126353Smlaier{ 2037171172Smlaier int error = 0; 2038171172Smlaier int ch; 2039171172Smlaier int mode = O_RDONLY; 2040171172Smlaier int opts = 0; 2041223637Sbz int optimize = PF_OPTIMIZE_BASIC; 2042171172Smlaier char anchorname[MAXPATHLEN]; 2043171172Smlaier char *path; 2044126353Smlaier 2045126353Smlaier if (argc < 2) 2046126353Smlaier usage(); 2047126353Smlaier 2048130617Smlaier while ((ch = getopt(argc, argv, 2049223637Sbz "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:z")) != -1) { 2050126353Smlaier switch (ch) { 2051126353Smlaier case 'a': 2052126353Smlaier anchoropt = optarg; 2053126353Smlaier break; 2054126353Smlaier case 'd': 2055126353Smlaier opts |= PF_OPT_DISABLE; 2056126353Smlaier mode = O_RDWR; 2057126353Smlaier break; 2058126353Smlaier case 'D': 2059126353Smlaier if (pfctl_cmdline_symset(optarg) < 0) 2060126353Smlaier warnx("could not parse macro definition %s", 2061126353Smlaier optarg); 2062126353Smlaier break; 2063126353Smlaier case 'e': 2064126353Smlaier opts |= PF_OPT_ENABLE; 2065126353Smlaier mode = O_RDWR; 2066126353Smlaier break; 2067126353Smlaier case 'q': 2068126353Smlaier opts |= PF_OPT_QUIET; 2069126353Smlaier break; 2070126353Smlaier case 'F': 2071126353Smlaier clearopt = pfctl_lookup_option(optarg, clearopt_list); 2072126353Smlaier if (clearopt == NULL) { 2073126353Smlaier warnx("Unknown flush modifier '%s'", optarg); 2074126353Smlaier usage(); 2075126353Smlaier } 2076126353Smlaier mode = O_RDWR; 2077126353Smlaier break; 2078130617Smlaier case 'i': 2079130617Smlaier ifaceopt = optarg; 2080130617Smlaier break; 2081126353Smlaier case 'k': 2082126353Smlaier if (state_killers >= 2) { 2083126353Smlaier warnx("can only specify -k twice"); 2084126353Smlaier usage(); 2085126353Smlaier /* NOTREACHED */ 2086126353Smlaier } 2087126353Smlaier state_kill[state_killers++] = optarg; 2088126353Smlaier mode = O_RDWR; 2089126353Smlaier break; 2090171172Smlaier case 'K': 2091171172Smlaier if (src_node_killers >= 2) { 2092171172Smlaier warnx("can only specify -K twice"); 2093171172Smlaier usage(); 2094171172Smlaier /* NOTREACHED */ 2095171172Smlaier } 2096171172Smlaier src_node_kill[src_node_killers++] = optarg; 2097171172Smlaier mode = O_RDWR; 2098171172Smlaier break; 2099145840Smlaier case 'm': 2100145840Smlaier opts |= PF_OPT_MERGE; 2101145840Smlaier break; 2102126353Smlaier case 'n': 2103126353Smlaier opts |= PF_OPT_NOACTION; 2104126353Smlaier break; 2105126353Smlaier case 'N': 2106126353Smlaier loadopt |= PFCTL_FLAG_NAT; 2107126353Smlaier break; 2108126353Smlaier case 'r': 2109126353Smlaier opts |= PF_OPT_USEDNS; 2110126353Smlaier break; 2111126353Smlaier case 'f': 2112126353Smlaier rulesopt = optarg; 2113126353Smlaier mode = O_RDWR; 2114126353Smlaier break; 2115126353Smlaier case 'g': 2116126353Smlaier opts |= PF_OPT_DEBUG; 2117126353Smlaier break; 2118126353Smlaier case 'A': 2119126353Smlaier loadopt |= PFCTL_FLAG_ALTQ; 2120126353Smlaier break; 2121126353Smlaier case 'R': 2122126353Smlaier loadopt |= PFCTL_FLAG_FILTER; 2123126353Smlaier break; 2124145840Smlaier case 'o': 2125223637Sbz optiopt = pfctl_lookup_option(optarg, optiopt_list); 2126223637Sbz if (optiopt == NULL) { 2127223637Sbz warnx("Unknown optimization '%s'", optarg); 2128223637Sbz usage(); 2129171172Smlaier } 2130171172Smlaier opts |= PF_OPT_OPTIMIZE; 2131145840Smlaier break; 2132126353Smlaier case 'O': 2133126353Smlaier loadopt |= PFCTL_FLAG_OPTION; 2134126353Smlaier break; 2135130617Smlaier case 'p': 2136130617Smlaier pf_device = optarg; 2137130617Smlaier break; 2138223057Sbz case 'P': 2139223057Sbz opts |= PF_OPT_NUMERIC; 2140223057Sbz break; 2141126353Smlaier case 's': 2142126353Smlaier showopt = pfctl_lookup_option(optarg, showopt_list); 2143126353Smlaier if (showopt == NULL) { 2144126353Smlaier warnx("Unknown show modifier '%s'", optarg); 2145126353Smlaier usage(); 2146126353Smlaier } 2147126353Smlaier break; 2148126353Smlaier case 't': 2149126353Smlaier tableopt = optarg; 2150126353Smlaier break; 2151126353Smlaier case 'T': 2152126353Smlaier tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 2153126353Smlaier if (tblcmdopt == NULL) { 2154126353Smlaier warnx("Unknown table command '%s'", optarg); 2155126353Smlaier usage(); 2156126353Smlaier } 2157126353Smlaier break; 2158126353Smlaier case 'v': 2159126353Smlaier if (opts & PF_OPT_VERBOSE) 2160126353Smlaier opts |= PF_OPT_VERBOSE2; 2161126353Smlaier opts |= PF_OPT_VERBOSE; 2162126353Smlaier break; 2163126353Smlaier case 'x': 2164126353Smlaier debugopt = pfctl_lookup_option(optarg, debugopt_list); 2165126353Smlaier if (debugopt == NULL) { 2166126353Smlaier warnx("Unknown debug level '%s'", optarg); 2167126353Smlaier usage(); 2168126353Smlaier } 2169126353Smlaier mode = O_RDWR; 2170126353Smlaier break; 2171126353Smlaier case 'z': 2172126353Smlaier opts |= PF_OPT_CLRRULECTRS; 2173126353Smlaier mode = O_RDWR; 2174126353Smlaier break; 2175126353Smlaier case 'h': 2176126353Smlaier /* FALLTHROUGH */ 2177126353Smlaier default: 2178126353Smlaier usage(); 2179126353Smlaier /* NOTREACHED */ 2180126353Smlaier } 2181126353Smlaier } 2182126353Smlaier 2183126353Smlaier if (tblcmdopt != NULL) { 2184126353Smlaier argc -= optind; 2185126353Smlaier argv += optind; 2186126353Smlaier ch = *tblcmdopt; 2187126353Smlaier if (ch == 'l') { 2188126353Smlaier loadopt |= PFCTL_FLAG_TABLE; 2189126353Smlaier tblcmdopt = NULL; 2190130617Smlaier } else 2191171172Smlaier mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY; 2192126353Smlaier } else if (argc != optind) { 2193126353Smlaier warnx("unknown command line argument: %s ...", argv[optind]); 2194126353Smlaier usage(); 2195126353Smlaier /* NOTREACHED */ 2196126353Smlaier } 2197126353Smlaier if (loadopt == 0) 2198126353Smlaier loadopt = ~0; 2199126353Smlaier 2200171172Smlaier if ((path = calloc(1, MAXPATHLEN)) == NULL) 2201171172Smlaier errx(1, "pfctl: calloc"); 2202126353Smlaier memset(anchorname, 0, sizeof(anchorname)); 2203126353Smlaier if (anchoropt != NULL) { 2204171172Smlaier int len = strlen(anchoropt); 2205171172Smlaier 2206171172Smlaier if (anchoropt[len - 1] == '*') { 2207171172Smlaier if (len >= 2 && anchoropt[len - 2] == '/') 2208171172Smlaier anchoropt[len - 2] = '\0'; 2209171172Smlaier else 2210171172Smlaier anchoropt[len - 1] = '\0'; 2211171172Smlaier opts |= PF_OPT_RECURSE; 2212171172Smlaier } 2213145840Smlaier if (strlcpy(anchorname, anchoropt, 2214145840Smlaier sizeof(anchorname)) >= sizeof(anchorname)) 2215145840Smlaier errx(1, "anchor name '%s' too long", 2216145840Smlaier anchoropt); 2217126353Smlaier loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE; 2218126353Smlaier } 2219126353Smlaier 2220126353Smlaier if ((opts & PF_OPT_NOACTION) == 0) { 2221130617Smlaier dev = open(pf_device, mode); 2222126353Smlaier if (dev == -1) 2223130617Smlaier err(1, "%s", pf_device); 2224126353Smlaier altqsupport = pfctl_test_altqsupport(dev, opts); 2225126353Smlaier } else { 2226130617Smlaier dev = open(pf_device, O_RDONLY); 2227130617Smlaier if (dev >= 0) 2228130617Smlaier opts |= PF_OPT_DUMMYACTION; 2229126353Smlaier /* turn off options */ 2230126353Smlaier opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 2231126353Smlaier clearopt = showopt = debugopt = NULL; 2232258485Sglebius#if !defined(ENABLE_ALTQ) 2233126355Smlaier altqsupport = 0; 2234126355Smlaier#else 2235126353Smlaier altqsupport = 1; 2236126355Smlaier#endif 2237126353Smlaier } 2238126353Smlaier 2239126353Smlaier if (opts & PF_OPT_DISABLE) 2240126353Smlaier if (pfctl_disable(dev, opts)) 2241126353Smlaier error = 1; 2242126353Smlaier 2243126353Smlaier if (showopt != NULL) { 2244126353Smlaier switch (*showopt) { 2245126353Smlaier case 'A': 2246126353Smlaier pfctl_show_anchors(dev, opts, anchorname); 2247126353Smlaier break; 2248126353Smlaier case 'r': 2249126353Smlaier pfctl_load_fingerprints(dev, opts); 2250171172Smlaier pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 2251171172Smlaier anchorname, 0); 2252126353Smlaier break; 2253126353Smlaier case 'l': 2254126353Smlaier pfctl_load_fingerprints(dev, opts); 2255171172Smlaier pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 2256171172Smlaier anchorname, 0); 2257126353Smlaier break; 2258126353Smlaier case 'n': 2259126353Smlaier pfctl_load_fingerprints(dev, opts); 2260145840Smlaier pfctl_show_nat(dev, opts, anchorname); 2261126353Smlaier break; 2262126353Smlaier case 'q': 2263130617Smlaier pfctl_show_altq(dev, ifaceopt, opts, 2264130617Smlaier opts & PF_OPT_VERBOSE2); 2265126353Smlaier break; 2266126353Smlaier case 's': 2267130617Smlaier pfctl_show_states(dev, ifaceopt, opts); 2268126353Smlaier break; 2269130617Smlaier case 'S': 2270130617Smlaier pfctl_show_src_nodes(dev, opts); 2271130617Smlaier break; 2272126353Smlaier case 'i': 2273130617Smlaier pfctl_show_status(dev, opts); 2274126353Smlaier break; 2275126353Smlaier case 't': 2276130617Smlaier pfctl_show_timeouts(dev, opts); 2277126353Smlaier break; 2278126353Smlaier case 'm': 2279130617Smlaier pfctl_show_limits(dev, opts); 2280126353Smlaier break; 2281126353Smlaier case 'a': 2282130617Smlaier opts |= PF_OPT_SHOWALL; 2283126353Smlaier pfctl_load_fingerprints(dev, opts); 2284126353Smlaier 2285145840Smlaier pfctl_show_nat(dev, opts, anchorname); 2286171172Smlaier pfctl_show_rules(dev, path, opts, 0, anchorname, 0); 2287130617Smlaier pfctl_show_altq(dev, ifaceopt, opts, 0); 2288130617Smlaier pfctl_show_states(dev, ifaceopt, opts); 2289130617Smlaier pfctl_show_src_nodes(dev, opts); 2290130617Smlaier pfctl_show_status(dev, opts); 2291171172Smlaier pfctl_show_rules(dev, path, opts, 1, anchorname, 0); 2292130617Smlaier pfctl_show_timeouts(dev, opts); 2293130617Smlaier pfctl_show_limits(dev, opts); 2294145840Smlaier pfctl_show_tables(anchorname, opts); 2295126353Smlaier pfctl_show_fingerprints(opts); 2296126353Smlaier break; 2297126353Smlaier case 'T': 2298145840Smlaier pfctl_show_tables(anchorname, opts); 2299126353Smlaier break; 2300126353Smlaier case 'o': 2301126353Smlaier pfctl_load_fingerprints(dev, opts); 2302126353Smlaier pfctl_show_fingerprints(opts); 2303126353Smlaier break; 2304130617Smlaier case 'I': 2305130617Smlaier pfctl_show_ifaces(ifaceopt, opts); 2306130617Smlaier break; 2307126353Smlaier } 2308126353Smlaier } 2309126353Smlaier 2310171172Smlaier if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) 2311171172Smlaier pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 2312171172Smlaier anchorname, 0); 2313171172Smlaier 2314126353Smlaier if (clearopt != NULL) { 2315171172Smlaier if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 2316171172Smlaier errx(1, "anchor names beginning with '_' cannot " 2317171172Smlaier "be modified from the command line"); 2318171172Smlaier 2319126353Smlaier switch (*clearopt) { 2320126353Smlaier case 'r': 2321145840Smlaier pfctl_clear_rules(dev, opts, anchorname); 2322126353Smlaier break; 2323126353Smlaier case 'n': 2324145840Smlaier pfctl_clear_nat(dev, opts, anchorname); 2325126353Smlaier break; 2326126353Smlaier case 'q': 2327126353Smlaier pfctl_clear_altq(dev, opts); 2328126353Smlaier break; 2329126353Smlaier case 's': 2330130617Smlaier pfctl_clear_states(dev, ifaceopt, opts); 2331126353Smlaier break; 2332130617Smlaier case 'S': 2333130617Smlaier pfctl_clear_src_nodes(dev, opts); 2334130617Smlaier break; 2335126353Smlaier case 'i': 2336126353Smlaier pfctl_clear_stats(dev, opts); 2337126353Smlaier break; 2338126353Smlaier case 'a': 2339145840Smlaier pfctl_clear_rules(dev, opts, anchorname); 2340145840Smlaier pfctl_clear_nat(dev, opts, anchorname); 2341145840Smlaier pfctl_clear_tables(anchorname, opts); 2342145840Smlaier if (!*anchorname) { 2343130617Smlaier pfctl_clear_altq(dev, opts); 2344130617Smlaier pfctl_clear_states(dev, ifaceopt, opts); 2345130617Smlaier pfctl_clear_src_nodes(dev, opts); 2346130617Smlaier pfctl_clear_stats(dev, opts); 2347130617Smlaier pfctl_clear_fingerprints(dev, opts); 2348145840Smlaier pfctl_clear_interface_flags(dev, opts); 2349130617Smlaier } 2350126353Smlaier break; 2351126353Smlaier case 'o': 2352126353Smlaier pfctl_clear_fingerprints(dev, opts); 2353126353Smlaier break; 2354126353Smlaier case 'T': 2355145840Smlaier pfctl_clear_tables(anchorname, opts); 2356126353Smlaier break; 2357126353Smlaier } 2358126353Smlaier } 2359223637Sbz if (state_killers) { 2360223637Sbz if (!strcmp(state_kill[0], "label")) 2361223637Sbz pfctl_label_kill_states(dev, ifaceopt, opts); 2362223637Sbz else if (!strcmp(state_kill[0], "id")) 2363223637Sbz pfctl_id_kill_states(dev, ifaceopt, opts); 2364223637Sbz else 2365223637Sbz pfctl_net_kill_states(dev, ifaceopt, opts); 2366223637Sbz } 2367126353Smlaier 2368171172Smlaier if (src_node_killers) 2369171172Smlaier pfctl_kill_src_nodes(dev, ifaceopt, opts); 2370171172Smlaier 2371126353Smlaier if (tblcmdopt != NULL) { 2372126353Smlaier error = pfctl_command_tables(argc, argv, tableopt, 2373145840Smlaier tblcmdopt, rulesopt, anchorname, opts); 2374126353Smlaier rulesopt = NULL; 2375126353Smlaier } 2376171172Smlaier if (optiopt != NULL) { 2377171172Smlaier switch (*optiopt) { 2378171172Smlaier case 'n': 2379171172Smlaier optimize = 0; 2380171172Smlaier break; 2381171172Smlaier case 'b': 2382171172Smlaier optimize |= PF_OPTIMIZE_BASIC; 2383171172Smlaier break; 2384171172Smlaier case 'o': 2385171172Smlaier case 'p': 2386171172Smlaier optimize |= PF_OPTIMIZE_PROFILE; 2387171172Smlaier break; 2388171172Smlaier } 2389171172Smlaier } 2390126353Smlaier 2391171172Smlaier if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) && 2392171172Smlaier !anchorname[0]) 2393333181Skp if (pfctl_get_skip_ifaces()) 2394145840Smlaier error = 1; 2395145840Smlaier 2396145840Smlaier if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) && 2397145840Smlaier !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION)) 2398126353Smlaier if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 2399126353Smlaier error = 1; 2400126353Smlaier 2401126353Smlaier if (rulesopt != NULL) { 2402171172Smlaier if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 2403171172Smlaier errx(1, "anchor names beginning with '_' cannot " 2404171172Smlaier "be modified from the command line"); 2405223637Sbz if (pfctl_rules(dev, rulesopt, opts, optimize, 2406171172Smlaier anchorname, NULL)) 2407126353Smlaier error = 1; 2408126353Smlaier else if (!(opts & PF_OPT_NOACTION) && 2409126353Smlaier (loadopt & PFCTL_FLAG_TABLE)) 2410126353Smlaier warn_namespace_collision(NULL); 2411126353Smlaier } 2412126353Smlaier 2413126353Smlaier if (opts & PF_OPT_ENABLE) 2414126353Smlaier if (pfctl_enable(dev, opts)) 2415126353Smlaier error = 1; 2416126353Smlaier 2417126353Smlaier if (debugopt != NULL) { 2418126353Smlaier switch (*debugopt) { 2419126353Smlaier case 'n': 2420126353Smlaier pfctl_debug(dev, PF_DEBUG_NONE, opts); 2421126353Smlaier break; 2422126353Smlaier case 'u': 2423126353Smlaier pfctl_debug(dev, PF_DEBUG_URGENT, opts); 2424126353Smlaier break; 2425126353Smlaier case 'm': 2426126353Smlaier pfctl_debug(dev, PF_DEBUG_MISC, opts); 2427126353Smlaier break; 2428126353Smlaier case 'l': 2429126353Smlaier pfctl_debug(dev, PF_DEBUG_NOISY, opts); 2430126353Smlaier break; 2431126353Smlaier } 2432126353Smlaier } 2433126353Smlaier 2434126353Smlaier exit(error); 2435126353Smlaier} 2436