Home | History | Annotate | Line # | Download | only in pfctl
pfctl.c revision 1.1.1.2
      1  1.1.1.2    yamt /*	$OpenBSD: pfctl.c,v 1.222 2004/08/26 16:35:36 jaredy Exp $ */
      2      1.1  itojun 
      3      1.1  itojun /*
      4      1.1  itojun  * Copyright (c) 2001 Daniel Hartmeier
      5      1.1  itojun  * Copyright (c) 2002,2003 Henning Brauer
      6      1.1  itojun  * All rights reserved.
      7      1.1  itojun  *
      8      1.1  itojun  * Redistribution and use in source and binary forms, with or without
      9      1.1  itojun  * modification, are permitted provided that the following conditions
     10      1.1  itojun  * are met:
     11      1.1  itojun  *
     12      1.1  itojun  *    - Redistributions of source code must retain the above copyright
     13      1.1  itojun  *      notice, this list of conditions and the following disclaimer.
     14      1.1  itojun  *    - Redistributions in binary form must reproduce the above
     15      1.1  itojun  *      copyright notice, this list of conditions and the following
     16      1.1  itojun  *      disclaimer in the documentation and/or other materials provided
     17      1.1  itojun  *      with the distribution.
     18      1.1  itojun  *
     19      1.1  itojun  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20      1.1  itojun  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21      1.1  itojun  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     22      1.1  itojun  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     23      1.1  itojun  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     24      1.1  itojun  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     25      1.1  itojun  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     26      1.1  itojun  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     27      1.1  itojun  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     28      1.1  itojun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     29      1.1  itojun  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30      1.1  itojun  * POSSIBILITY OF SUCH DAMAGE.
     31      1.1  itojun  *
     32      1.1  itojun  */
     33      1.1  itojun 
     34      1.1  itojun #include <sys/types.h>
     35      1.1  itojun #include <sys/ioctl.h>
     36      1.1  itojun #include <sys/socket.h>
     37  1.1.1.2    yamt #include <sys/stat.h>
     38      1.1  itojun 
     39      1.1  itojun #include <net/if.h>
     40      1.1  itojun #include <netinet/in.h>
     41      1.1  itojun #include <net/pfvar.h>
     42      1.1  itojun #include <arpa/inet.h>
     43      1.1  itojun #include <altq/altq.h>
     44      1.1  itojun 
     45      1.1  itojun #include <err.h>
     46      1.1  itojun #include <errno.h>
     47      1.1  itojun #include <fcntl.h>
     48      1.1  itojun #include <limits.h>
     49      1.1  itojun #include <netdb.h>
     50      1.1  itojun #include <stdio.h>
     51      1.1  itojun #include <stdlib.h>
     52      1.1  itojun #include <string.h>
     53      1.1  itojun #include <unistd.h>
     54      1.1  itojun 
     55      1.1  itojun #include "pfctl_parser.h"
     56      1.1  itojun #include "pfctl.h"
     57      1.1  itojun 
     58      1.1  itojun void	 usage(void);
     59      1.1  itojun int	 pfctl_enable(int, int);
     60      1.1  itojun int	 pfctl_disable(int, int);
     61      1.1  itojun int	 pfctl_clear_stats(int, int);
     62  1.1.1.2    yamt int	 pfctl_clear_rules(int, int, char *);
     63  1.1.1.2    yamt int	 pfctl_clear_nat(int, int, char *);
     64      1.1  itojun int	 pfctl_clear_altq(int, int);
     65      1.1  itojun int	 pfctl_clear_src_nodes(int, int);
     66      1.1  itojun int	 pfctl_clear_states(int, const char *, int);
     67      1.1  itojun int	 pfctl_kill_states(int, const char *, int);
     68      1.1  itojun int	 pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int,
     69  1.1.1.2    yamt 	    char *);
     70      1.1  itojun void	 pfctl_print_rule_counters(struct pf_rule *, int);
     71  1.1.1.2    yamt int	 pfctl_show_rules(int, int, int, char *);
     72  1.1.1.2    yamt int	 pfctl_show_nat(int, int, char *);
     73      1.1  itojun int	 pfctl_show_src_nodes(int, int);
     74      1.1  itojun int	 pfctl_show_states(int, const char *, int);
     75      1.1  itojun int	 pfctl_show_status(int, int);
     76      1.1  itojun int	 pfctl_show_timeouts(int, int);
     77      1.1  itojun int	 pfctl_show_limits(int, int);
     78      1.1  itojun int	 pfctl_debug(int, u_int32_t, int);
     79      1.1  itojun int	 pfctl_clear_rule_counters(int, int);
     80      1.1  itojun int	 pfctl_test_altqsupport(int, int);
     81      1.1  itojun int	 pfctl_show_anchors(int, int, char *);
     82      1.1  itojun const char	*pfctl_lookup_option(char *, const char **);
     83      1.1  itojun 
     84      1.1  itojun const char	*clearopt;
     85      1.1  itojun char		*rulesopt;
     86      1.1  itojun const char	*showopt;
     87      1.1  itojun const char	*debugopt;
     88      1.1  itojun char		*anchoropt;
     89      1.1  itojun char		*pf_device = "/dev/pf";
     90      1.1  itojun char		*ifaceopt;
     91      1.1  itojun char		*tableopt;
     92      1.1  itojun const char	*tblcmdopt;
     93      1.1  itojun int		 state_killers;
     94      1.1  itojun char		*state_kill[2];
     95      1.1  itojun int		 loadopt;
     96      1.1  itojun int		 altqsupport;
     97      1.1  itojun 
     98      1.1  itojun int		 dev = -1;
     99      1.1  itojun int		 first_title = 1;
    100      1.1  itojun int		 labels = 0;
    101      1.1  itojun 
    102      1.1  itojun const char	*infile;
    103      1.1  itojun 
    104      1.1  itojun static const struct {
    105      1.1  itojun 	const char	*name;
    106      1.1  itojun 	int		index;
    107      1.1  itojun } pf_limits[] = {
    108      1.1  itojun 	{ "states",	PF_LIMIT_STATES },
    109      1.1  itojun 	{ "src-nodes",	PF_LIMIT_SRC_NODES },
    110      1.1  itojun 	{ "frags",	PF_LIMIT_FRAGS },
    111      1.1  itojun 	{ NULL,		0 }
    112      1.1  itojun };
    113      1.1  itojun 
    114      1.1  itojun struct pf_hint {
    115      1.1  itojun 	const char	*name;
    116      1.1  itojun 	int		timeout;
    117      1.1  itojun };
    118      1.1  itojun static const struct pf_hint pf_hint_normal[] = {
    119      1.1  itojun 	{ "tcp.first",		2 * 60 },
    120      1.1  itojun 	{ "tcp.opening",	30 },
    121      1.1  itojun 	{ "tcp.established",	24 * 60 * 60 },
    122      1.1  itojun 	{ "tcp.closing",	15 * 60 },
    123      1.1  itojun 	{ "tcp.finwait",	45 },
    124      1.1  itojun 	{ "tcp.closed",		90 },
    125  1.1.1.2    yamt 	{ "tcp.tsdiff",		30 },
    126      1.1  itojun 	{ NULL,			0 }
    127      1.1  itojun };
    128      1.1  itojun static const struct pf_hint pf_hint_satellite[] = {
    129      1.1  itojun 	{ "tcp.first",		3 * 60 },
    130      1.1  itojun 	{ "tcp.opening",	30 + 5 },
    131      1.1  itojun 	{ "tcp.established",	24 * 60 * 60 },
    132      1.1  itojun 	{ "tcp.closing",	15 * 60 + 5 },
    133      1.1  itojun 	{ "tcp.finwait",	45 + 5 },
    134      1.1  itojun 	{ "tcp.closed",		90 + 5 },
    135  1.1.1.2    yamt 	{ "tcp.tsdiff",		60 },
    136      1.1  itojun 	{ NULL,			0 }
    137      1.1  itojun };
    138      1.1  itojun static const struct pf_hint pf_hint_conservative[] = {
    139      1.1  itojun 	{ "tcp.first",		60 * 60 },
    140      1.1  itojun 	{ "tcp.opening",	15 * 60 },
    141      1.1  itojun 	{ "tcp.established",	5 * 24 * 60 * 60 },
    142      1.1  itojun 	{ "tcp.closing",	60 * 60 },
    143      1.1  itojun 	{ "tcp.finwait",	10 * 60 },
    144      1.1  itojun 	{ "tcp.closed",		3 * 60 },
    145  1.1.1.2    yamt 	{ "tcp.tsdiff",		60 },
    146      1.1  itojun 	{ NULL,			0 }
    147      1.1  itojun };
    148      1.1  itojun static const struct pf_hint pf_hint_aggressive[] = {
    149      1.1  itojun 	{ "tcp.first",		30 },
    150      1.1  itojun 	{ "tcp.opening",	5 },
    151      1.1  itojun 	{ "tcp.established",	5 * 60 * 60 },
    152      1.1  itojun 	{ "tcp.closing",	60 },
    153      1.1  itojun 	{ "tcp.finwait",	30 },
    154      1.1  itojun 	{ "tcp.closed",		30 },
    155  1.1.1.2    yamt 	{ "tcp.tsdiff",		10 },
    156      1.1  itojun 	{ NULL,			0 }
    157      1.1  itojun };
    158      1.1  itojun 
    159      1.1  itojun static const struct {
    160      1.1  itojun 	const char *name;
    161      1.1  itojun 	const struct pf_hint *hint;
    162      1.1  itojun } pf_hints[] = {
    163      1.1  itojun 	{ "normal",		pf_hint_normal },
    164      1.1  itojun 	{ "satellite",		pf_hint_satellite },
    165      1.1  itojun 	{ "high-latency",	pf_hint_satellite },
    166      1.1  itojun 	{ "conservative",	pf_hint_conservative },
    167      1.1  itojun 	{ "aggressive",		pf_hint_aggressive },
    168      1.1  itojun 	{ NULL,			NULL }
    169      1.1  itojun };
    170      1.1  itojun 
    171      1.1  itojun static const char *clearopt_list[] = {
    172      1.1  itojun 	"nat", "queue", "rules", "Sources",
    173      1.1  itojun 	"state", "info", "Tables", "osfp", "all", NULL
    174      1.1  itojun };
    175      1.1  itojun 
    176      1.1  itojun static const char *showopt_list[] = {
    177      1.1  itojun 	"nat", "queue", "rules", "Anchors", "Sources", "state", "info",
    178      1.1  itojun 	"Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
    179      1.1  itojun 	"all", NULL
    180      1.1  itojun };
    181      1.1  itojun 
    182      1.1  itojun static const char *tblcmdopt_list[] = {
    183      1.1  itojun 	"kill", "flush", "add", "delete", "load", "replace", "show",
    184      1.1  itojun 	"test", "zero", NULL
    185      1.1  itojun };
    186      1.1  itojun 
    187      1.1  itojun static const char *debugopt_list[] = {
    188      1.1  itojun 	"none", "urgent", "misc", "loud", NULL
    189      1.1  itojun };
    190      1.1  itojun 
    191      1.1  itojun 
    192      1.1  itojun void
    193      1.1  itojun usage(void)
    194      1.1  itojun {
    195      1.1  itojun 	extern char *__progname;
    196      1.1  itojun 
    197  1.1.1.2    yamt 	fprintf(stderr, "usage: %s [-AdeghNnOoqRrvz] ", __progname);
    198  1.1.1.2    yamt 	fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n");
    199      1.1  itojun 	fprintf(stderr, "             ");
    200  1.1.1.2    yamt 	fprintf(stderr, "[-f file] [-i interface] [-k host] ");
    201  1.1.1.2    yamt 	fprintf(stderr, "[-p device] [-s modifier]\n");
    202      1.1  itojun 	fprintf(stderr, "             ");
    203  1.1.1.2    yamt 	fprintf(stderr, "[-t table -T command [address ...]] ");
    204  1.1.1.2    yamt 	fprintf(stderr, "[-x level]\n");
    205      1.1  itojun 	exit(1);
    206      1.1  itojun }
    207      1.1  itojun 
    208      1.1  itojun int
    209      1.1  itojun pfctl_enable(int dev, int opts)
    210      1.1  itojun {
    211      1.1  itojun 	if (ioctl(dev, DIOCSTART)) {
    212      1.1  itojun 		if (errno == EEXIST)
    213      1.1  itojun 			errx(1, "pf already enabled");
    214      1.1  itojun 		else
    215      1.1  itojun 			err(1, "DIOCSTART");
    216      1.1  itojun 	}
    217      1.1  itojun 	if ((opts & PF_OPT_QUIET) == 0)
    218      1.1  itojun 		fprintf(stderr, "pf enabled\n");
    219      1.1  itojun 
    220      1.1  itojun 	if (altqsupport && ioctl(dev, DIOCSTARTALTQ))
    221      1.1  itojun 		if (errno != EEXIST)
    222      1.1  itojun 			err(1, "DIOCSTARTALTQ");
    223      1.1  itojun 
    224      1.1  itojun 	return (0);
    225      1.1  itojun }
    226      1.1  itojun 
    227      1.1  itojun int
    228      1.1  itojun pfctl_disable(int dev, int opts)
    229      1.1  itojun {
    230      1.1  itojun 	if (ioctl(dev, DIOCSTOP)) {
    231      1.1  itojun 		if (errno == ENOENT)
    232      1.1  itojun 			errx(1, "pf not enabled");
    233      1.1  itojun 		else
    234      1.1  itojun 			err(1, "DIOCSTOP");
    235      1.1  itojun 	}
    236      1.1  itojun 	if ((opts & PF_OPT_QUIET) == 0)
    237      1.1  itojun 		fprintf(stderr, "pf disabled\n");
    238      1.1  itojun 
    239      1.1  itojun 	if (altqsupport && ioctl(dev, DIOCSTOPALTQ))
    240      1.1  itojun 			if (errno != ENOENT)
    241      1.1  itojun 				err(1, "DIOCSTOPALTQ");
    242      1.1  itojun 
    243      1.1  itojun 	return (0);
    244      1.1  itojun }
    245      1.1  itojun 
    246      1.1  itojun int
    247      1.1  itojun pfctl_clear_stats(int dev, int opts)
    248      1.1  itojun {
    249      1.1  itojun 	if (ioctl(dev, DIOCCLRSTATUS))
    250      1.1  itojun 		err(1, "DIOCCLRSTATUS");
    251      1.1  itojun 	if ((opts & PF_OPT_QUIET) == 0)
    252      1.1  itojun 		fprintf(stderr, "pf: statistics cleared\n");
    253      1.1  itojun 	return (0);
    254      1.1  itojun }
    255      1.1  itojun 
    256      1.1  itojun int
    257  1.1.1.2    yamt pfctl_clear_rules(int dev, int opts, char *anchorname)
    258      1.1  itojun {
    259      1.1  itojun 	struct pfr_buffer t;
    260      1.1  itojun 
    261      1.1  itojun 	memset(&t, 0, sizeof(t));
    262      1.1  itojun 	t.pfrb_type = PFRB_TRANS;
    263  1.1.1.2    yamt 	if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname) ||
    264  1.1.1.2    yamt 	    pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) ||
    265      1.1  itojun 	    pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
    266      1.1  itojun 	    pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
    267      1.1  itojun 		err(1, "pfctl_clear_rules");
    268      1.1  itojun 	if ((opts & PF_OPT_QUIET) == 0)
    269      1.1  itojun 		fprintf(stderr, "rules cleared\n");
    270      1.1  itojun 	return (0);
    271      1.1  itojun }
    272      1.1  itojun 
    273      1.1  itojun int
    274  1.1.1.2    yamt pfctl_clear_nat(int dev, int opts, char *anchorname)
    275      1.1  itojun {
    276      1.1  itojun 	struct pfr_buffer t;
    277      1.1  itojun 
    278      1.1  itojun 	memset(&t, 0, sizeof(t));
    279      1.1  itojun 	t.pfrb_type = PFRB_TRANS;
    280  1.1.1.2    yamt 	if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname) ||
    281  1.1.1.2    yamt 	    pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname) ||
    282  1.1.1.2    yamt 	    pfctl_add_trans(&t, PF_RULESET_RDR, anchorname) ||
    283      1.1  itojun 	    pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
    284      1.1  itojun 	    pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
    285      1.1  itojun 		err(1, "pfctl_clear_nat");
    286      1.1  itojun 	if ((opts & PF_OPT_QUIET) == 0)
    287      1.1  itojun 		fprintf(stderr, "nat cleared\n");
    288      1.1  itojun 	return (0);
    289      1.1  itojun }
    290      1.1  itojun 
    291      1.1  itojun int
    292      1.1  itojun pfctl_clear_altq(int dev, int opts)
    293      1.1  itojun {
    294      1.1  itojun 	struct pfr_buffer t;
    295      1.1  itojun 
    296      1.1  itojun 	if (!altqsupport)
    297      1.1  itojun 		return (-1);
    298      1.1  itojun 	memset(&t, 0, sizeof(t));
    299      1.1  itojun 	t.pfrb_type = PFRB_TRANS;
    300  1.1.1.2    yamt 	if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") ||
    301      1.1  itojun 	    pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
    302      1.1  itojun 	    pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
    303      1.1  itojun 		err(1, "pfctl_clear_altq");
    304      1.1  itojun 	if ((opts & PF_OPT_QUIET) == 0)
    305      1.1  itojun 		fprintf(stderr, "altq cleared\n");
    306      1.1  itojun 	return (0);
    307      1.1  itojun }
    308      1.1  itojun 
    309      1.1  itojun int
    310      1.1  itojun pfctl_clear_src_nodes(int dev, int opts)
    311      1.1  itojun {
    312      1.1  itojun 	if (ioctl(dev, DIOCCLRSRCNODES))
    313      1.1  itojun 		err(1, "DIOCCLRSRCNODES");
    314      1.1  itojun 	if ((opts & PF_OPT_QUIET) == 0)
    315      1.1  itojun 		fprintf(stderr, "source tracking entries cleared\n");
    316      1.1  itojun 	return (0);
    317      1.1  itojun }
    318      1.1  itojun 
    319      1.1  itojun int
    320      1.1  itojun pfctl_clear_states(int dev, const char *iface, int opts)
    321      1.1  itojun {
    322      1.1  itojun 	struct pfioc_state_kill psk;
    323      1.1  itojun 
    324      1.1  itojun 	memset(&psk, 0, sizeof(psk));
    325      1.1  itojun 	if (iface != NULL && strlcpy(psk.psk_ifname, iface,
    326      1.1  itojun 	    sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
    327      1.1  itojun 		errx(1, "invalid interface: %s", iface);
    328      1.1  itojun 
    329      1.1  itojun 	if (ioctl(dev, DIOCCLRSTATES, &psk))
    330      1.1  itojun 		err(1, "DIOCCLRSTATES");
    331      1.1  itojun 	if ((opts & PF_OPT_QUIET) == 0)
    332      1.1  itojun 		fprintf(stderr, "%d states cleared\n", psk.psk_af);
    333      1.1  itojun 	return (0);
    334      1.1  itojun }
    335      1.1  itojun 
    336      1.1  itojun int
    337      1.1  itojun pfctl_kill_states(int dev, const char *iface, int opts)
    338      1.1  itojun {
    339      1.1  itojun 	struct pfioc_state_kill psk;
    340      1.1  itojun 	struct addrinfo *res[2], *resp[2];
    341      1.1  itojun 	struct sockaddr last_src, last_dst;
    342      1.1  itojun 	int killed, sources, dests;
    343      1.1  itojun 	int ret_ga;
    344      1.1  itojun 
    345      1.1  itojun 	killed = sources = dests = 0;
    346      1.1  itojun 
    347      1.1  itojun 	memset(&psk, 0, sizeof(psk));
    348      1.1  itojun 	memset(&psk.psk_src.addr.v.a.mask, 0xff,
    349      1.1  itojun 	    sizeof(psk.psk_src.addr.v.a.mask));
    350      1.1  itojun 	memset(&last_src, 0xff, sizeof(last_src));
    351      1.1  itojun 	memset(&last_dst, 0xff, sizeof(last_dst));
    352      1.1  itojun 	if (iface != NULL && strlcpy(psk.psk_ifname, iface,
    353      1.1  itojun 	    sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
    354      1.1  itojun 		errx(1, "invalid interface: %s", iface);
    355      1.1  itojun 
    356      1.1  itojun 	if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) {
    357      1.1  itojun 		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
    358      1.1  itojun 		/* NOTREACHED */
    359      1.1  itojun 	}
    360      1.1  itojun 	for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
    361      1.1  itojun 		if (resp[0]->ai_addr == NULL)
    362      1.1  itojun 			continue;
    363      1.1  itojun 		/* We get lots of duplicates.  Catch the easy ones */
    364      1.1  itojun 		if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
    365      1.1  itojun 			continue;
    366      1.1  itojun 		last_src = *(struct sockaddr *)resp[0]->ai_addr;
    367      1.1  itojun 
    368      1.1  itojun 		psk.psk_af = resp[0]->ai_family;
    369      1.1  itojun 		sources++;
    370      1.1  itojun 
    371      1.1  itojun 		if (psk.psk_af == AF_INET)
    372      1.1  itojun 			psk.psk_src.addr.v.a.addr.v4 =
    373      1.1  itojun 			    ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
    374      1.1  itojun 		else if (psk.psk_af == AF_INET6)
    375      1.1  itojun 			psk.psk_src.addr.v.a.addr.v6 =
    376      1.1  itojun 			    ((struct sockaddr_in6 *)resp[0]->ai_addr)->
    377      1.1  itojun 			    sin6_addr;
    378      1.1  itojun 		else
    379      1.1  itojun 			errx(1, "Unknown address family %d", psk.psk_af);
    380      1.1  itojun 
    381      1.1  itojun 		if (state_killers > 1) {
    382      1.1  itojun 			dests = 0;
    383      1.1  itojun 			memset(&psk.psk_dst.addr.v.a.mask, 0xff,
    384      1.1  itojun 			    sizeof(psk.psk_dst.addr.v.a.mask));
    385      1.1  itojun 			memset(&last_dst, 0xff, sizeof(last_dst));
    386      1.1  itojun 			if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL,
    387      1.1  itojun 			    &res[1]))) {
    388      1.1  itojun 				errx(1, "getaddrinfo: %s",
    389      1.1  itojun 				    gai_strerror(ret_ga));
    390      1.1  itojun 				/* NOTREACHED */
    391      1.1  itojun 			}
    392      1.1  itojun 			for (resp[1] = res[1]; resp[1];
    393      1.1  itojun 			    resp[1] = resp[1]->ai_next) {
    394      1.1  itojun 				if (resp[1]->ai_addr == NULL)
    395      1.1  itojun 					continue;
    396      1.1  itojun 				if (psk.psk_af != resp[1]->ai_family)
    397      1.1  itojun 					continue;
    398      1.1  itojun 
    399      1.1  itojun 				if (memcmp(&last_dst, resp[1]->ai_addr,
    400      1.1  itojun 				    sizeof(last_dst)) == 0)
    401      1.1  itojun 					continue;
    402      1.1  itojun 				last_dst = *(struct sockaddr *)resp[1]->ai_addr;
    403      1.1  itojun 
    404      1.1  itojun 				dests++;
    405      1.1  itojun 
    406      1.1  itojun 				if (psk.psk_af == AF_INET)
    407      1.1  itojun 					psk.psk_dst.addr.v.a.addr.v4 =
    408      1.1  itojun 					    ((struct sockaddr_in *)resp[1]->
    409      1.1  itojun 					    ai_addr)->sin_addr;
    410      1.1  itojun 				else if (psk.psk_af == AF_INET6)
    411      1.1  itojun 					psk.psk_dst.addr.v.a.addr.v6 =
    412      1.1  itojun 					    ((struct sockaddr_in6 *)resp[1]->
    413      1.1  itojun 					    ai_addr)->sin6_addr;
    414      1.1  itojun 				else
    415      1.1  itojun 					errx(1, "Unknown address family %d",
    416      1.1  itojun 					    psk.psk_af);
    417      1.1  itojun 
    418      1.1  itojun 				if (ioctl(dev, DIOCKILLSTATES, &psk))
    419      1.1  itojun 					err(1, "DIOCKILLSTATES");
    420      1.1  itojun 				killed += psk.psk_af;
    421      1.1  itojun 				/* fixup psk.psk_af */
    422      1.1  itojun 				psk.psk_af = resp[1]->ai_family;
    423      1.1  itojun 			}
    424      1.1  itojun 			freeaddrinfo(res[1]);
    425      1.1  itojun 		} else {
    426      1.1  itojun 			if (ioctl(dev, DIOCKILLSTATES, &psk))
    427      1.1  itojun 				err(1, "DIOCKILLSTATES");
    428      1.1  itojun 			killed += psk.psk_af;
    429      1.1  itojun 			/* fixup psk.psk_af */
    430      1.1  itojun 			psk.psk_af = res[0]->ai_family;
    431      1.1  itojun 		}
    432      1.1  itojun 	}
    433      1.1  itojun 
    434      1.1  itojun 	freeaddrinfo(res[0]);
    435      1.1  itojun 
    436      1.1  itojun 	if ((opts & PF_OPT_QUIET) == 0)
    437      1.1  itojun 		fprintf(stderr, "killed %d states from %d sources and %d "
    438      1.1  itojun 		    "destinations\n", killed, sources, dests);
    439      1.1  itojun 	return (0);
    440      1.1  itojun }
    441      1.1  itojun 
    442      1.1  itojun int
    443      1.1  itojun pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr,
    444  1.1.1.2    yamt     u_int32_t ticket, int r_action, char *anchorname)
    445      1.1  itojun {
    446      1.1  itojun 	struct pfioc_pooladdr pp;
    447      1.1  itojun 	struct pf_pooladdr *pa;
    448      1.1  itojun 	u_int32_t pnr, mpnr;
    449      1.1  itojun 
    450      1.1  itojun 	memset(&pp, 0, sizeof(pp));
    451      1.1  itojun 	memcpy(pp.anchor, anchorname, sizeof(pp.anchor));
    452      1.1  itojun 	pp.r_action = r_action;
    453      1.1  itojun 	pp.r_num = nr;
    454      1.1  itojun 	pp.ticket = ticket;
    455      1.1  itojun 	if (ioctl(dev, DIOCGETADDRS, &pp)) {
    456      1.1  itojun 		warn("DIOCGETADDRS");
    457      1.1  itojun 		return (-1);
    458      1.1  itojun 	}
    459      1.1  itojun 	mpnr = pp.nr;
    460      1.1  itojun 	TAILQ_INIT(&pool->list);
    461      1.1  itojun 	for (pnr = 0; pnr < mpnr; ++pnr) {
    462      1.1  itojun 		pp.nr = pnr;
    463      1.1  itojun 		if (ioctl(dev, DIOCGETADDR, &pp)) {
    464      1.1  itojun 			warn("DIOCGETADDR");
    465      1.1  itojun 			return (-1);
    466      1.1  itojun 		}
    467      1.1  itojun 		pa = calloc(1, sizeof(struct pf_pooladdr));
    468      1.1  itojun 		if (pa == NULL)
    469      1.1  itojun 			err(1, "calloc");
    470      1.1  itojun 		bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr));
    471      1.1  itojun 		TAILQ_INSERT_TAIL(&pool->list, pa, entries);
    472      1.1  itojun 	}
    473      1.1  itojun 
    474      1.1  itojun 	return (0);
    475      1.1  itojun }
    476      1.1  itojun 
    477      1.1  itojun void
    478      1.1  itojun pfctl_clear_pool(struct pf_pool *pool)
    479      1.1  itojun {
    480      1.1  itojun 	struct pf_pooladdr *pa;
    481      1.1  itojun 
    482      1.1  itojun 	while ((pa = TAILQ_FIRST(&pool->list)) != NULL) {
    483      1.1  itojun 		TAILQ_REMOVE(&pool->list, pa, entries);
    484      1.1  itojun 		free(pa);
    485      1.1  itojun 	}
    486      1.1  itojun }
    487      1.1  itojun 
    488      1.1  itojun void
    489      1.1  itojun pfctl_print_rule_counters(struct pf_rule *rule, int opts)
    490      1.1  itojun {
    491      1.1  itojun 	if (opts & PF_OPT_DEBUG) {
    492      1.1  itojun 		const char *t[PF_SKIP_COUNT] = { "i", "d", "f",
    493      1.1  itojun 		    "p", "sa", "sp", "da", "dp" };
    494      1.1  itojun 		int i;
    495      1.1  itojun 
    496      1.1  itojun 		printf("  [ Skip steps: ");
    497      1.1  itojun 		for (i = 0; i < PF_SKIP_COUNT; ++i) {
    498      1.1  itojun 			if (rule->skip[i].nr == rule->nr + 1)
    499      1.1  itojun 				continue;
    500      1.1  itojun 			printf("%s=", t[i]);
    501      1.1  itojun 			if (rule->skip[i].nr == -1)
    502      1.1  itojun 				printf("end ");
    503      1.1  itojun 			else
    504      1.1  itojun 				printf("%u ", rule->skip[i].nr);
    505      1.1  itojun 		}
    506      1.1  itojun 		printf("]\n");
    507      1.1  itojun 
    508      1.1  itojun 		printf("  [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
    509      1.1  itojun 		    rule->qname, rule->qid, rule->pqname, rule->pqid);
    510      1.1  itojun 	}
    511      1.1  itojun 	if (opts & PF_OPT_VERBOSE)
    512      1.1  itojun 		printf("  [ Evaluations: %-8llu  Packets: %-8llu  "
    513      1.1  itojun 			    "Bytes: %-10llu  States: %-6u]\n",
    514      1.1  itojun 			    (unsigned long long)rule->evaluations,
    515      1.1  itojun 			    (unsigned long long)rule->packets,
    516      1.1  itojun 			    (unsigned long long)rule->bytes, rule->states);
    517      1.1  itojun }
    518      1.1  itojun 
    519      1.1  itojun void
    520      1.1  itojun pfctl_print_title(char *title)
    521      1.1  itojun {
    522      1.1  itojun 	if (!first_title)
    523      1.1  itojun 		printf("\n");
    524      1.1  itojun 	first_title = 0;
    525      1.1  itojun 	printf("%s\n", title);
    526      1.1  itojun }
    527      1.1  itojun 
    528      1.1  itojun int
    529  1.1.1.2    yamt pfctl_show_rules(int dev, int opts, int format, char *anchorname)
    530      1.1  itojun {
    531      1.1  itojun 	struct pfioc_rule pr;
    532      1.1  itojun 	u_int32_t nr, mnr, header = 0;
    533      1.1  itojun 	int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
    534      1.1  itojun 
    535      1.1  itojun 	memset(&pr, 0, sizeof(pr));
    536      1.1  itojun 	memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
    537      1.1  itojun 	if (opts & PF_OPT_SHOWALL) {
    538      1.1  itojun 		pr.rule.action = PF_PASS;
    539      1.1  itojun 		if (ioctl(dev, DIOCGETRULES, &pr)) {
    540      1.1  itojun 			warn("DIOCGETRULES");
    541      1.1  itojun 			return (-1);
    542      1.1  itojun 		}
    543      1.1  itojun 		header++;
    544      1.1  itojun 	}
    545      1.1  itojun 	pr.rule.action = PF_SCRUB;
    546      1.1  itojun 	if (ioctl(dev, DIOCGETRULES, &pr)) {
    547      1.1  itojun 		warn("DIOCGETRULES");
    548      1.1  itojun 		return (-1);
    549      1.1  itojun 	}
    550      1.1  itojun 	if (opts & PF_OPT_SHOWALL) {
    551      1.1  itojun 		if (format == 0 && (pr.nr > 0 || header))
    552      1.1  itojun 			pfctl_print_title("FILTER RULES:");
    553      1.1  itojun 		else if (format == 1 && labels)
    554      1.1  itojun 			pfctl_print_title("LABEL COUNTERS:");
    555      1.1  itojun 	}
    556      1.1  itojun 	mnr = pr.nr;
    557      1.1  itojun 	for (nr = 0; nr < mnr; ++nr) {
    558      1.1  itojun 		pr.nr = nr;
    559      1.1  itojun 		if (ioctl(dev, DIOCGETRULE, &pr)) {
    560      1.1  itojun 			warn("DIOCGETRULE");
    561      1.1  itojun 			return (-1);
    562      1.1  itojun 		}
    563      1.1  itojun 
    564      1.1  itojun 		if (pfctl_get_pool(dev, &pr.rule.rpool,
    565  1.1.1.2    yamt 		    nr, pr.ticket, PF_SCRUB, anchorname) != 0)
    566      1.1  itojun 			return (-1);
    567      1.1  itojun 
    568      1.1  itojun 		switch (format) {
    569      1.1  itojun 		case 1:
    570      1.1  itojun 			if (pr.rule.label[0]) {
    571      1.1  itojun 				printf("%s ", pr.rule.label);
    572      1.1  itojun 				printf("%llu %llu %llu\n",
    573      1.1  itojun 				    (unsigned long long)pr.rule.evaluations,
    574      1.1  itojun 				    (unsigned long long)pr.rule.packets,
    575      1.1  itojun 				    (unsigned long long)pr.rule.bytes);
    576      1.1  itojun 			}
    577      1.1  itojun 			break;
    578      1.1  itojun 		default:
    579      1.1  itojun 			if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
    580      1.1  itojun 				labels = 1;
    581  1.1.1.2    yamt 			print_rule(&pr.rule, pr.anchor_call, rule_numbers);
    582      1.1  itojun 			pfctl_print_rule_counters(&pr.rule, opts);
    583      1.1  itojun 		}
    584      1.1  itojun 		pfctl_clear_pool(&pr.rule.rpool);
    585      1.1  itojun 	}
    586      1.1  itojun 	pr.rule.action = PF_PASS;
    587      1.1  itojun 	if (ioctl(dev, DIOCGETRULES, &pr)) {
    588      1.1  itojun 		warn("DIOCGETRULES");
    589      1.1  itojun 		return (-1);
    590      1.1  itojun 	}
    591      1.1  itojun 	mnr = pr.nr;
    592      1.1  itojun 	for (nr = 0; nr < mnr; ++nr) {
    593      1.1  itojun 		pr.nr = nr;
    594      1.1  itojun 		if (ioctl(dev, DIOCGETRULE, &pr)) {
    595      1.1  itojun 			warn("DIOCGETRULE");
    596      1.1  itojun 			return (-1);
    597      1.1  itojun 		}
    598      1.1  itojun 
    599      1.1  itojun 		if (pfctl_get_pool(dev, &pr.rule.rpool,
    600  1.1.1.2    yamt 		    nr, pr.ticket, PF_PASS, anchorname) != 0)
    601      1.1  itojun 			return (-1);
    602      1.1  itojun 
    603      1.1  itojun 		switch (format) {
    604      1.1  itojun 		case 1:
    605      1.1  itojun 			if (pr.rule.label[0]) {
    606      1.1  itojun 				printf("%s ", pr.rule.label);
    607      1.1  itojun 				printf("%llu %llu %llu\n",
    608      1.1  itojun 				    (unsigned long long)pr.rule.evaluations,
    609      1.1  itojun 				    (unsigned long long)pr.rule.packets,
    610      1.1  itojun 				    (unsigned long long)pr.rule.bytes);
    611      1.1  itojun 			}
    612      1.1  itojun 			break;
    613      1.1  itojun 		default:
    614      1.1  itojun 			if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
    615      1.1  itojun 				labels = 1;
    616  1.1.1.2    yamt 			print_rule(&pr.rule, pr.anchor_call, rule_numbers);
    617      1.1  itojun 			pfctl_print_rule_counters(&pr.rule, opts);
    618      1.1  itojun 		}
    619      1.1  itojun 		pfctl_clear_pool(&pr.rule.rpool);
    620      1.1  itojun 	}
    621      1.1  itojun 	return (0);
    622      1.1  itojun }
    623      1.1  itojun 
    624      1.1  itojun int
    625  1.1.1.2    yamt pfctl_show_nat(int dev, int opts, char *anchorname)
    626      1.1  itojun {
    627      1.1  itojun 	struct pfioc_rule pr;
    628      1.1  itojun 	u_int32_t mnr, nr;
    629      1.1  itojun 	static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT };
    630      1.1  itojun 	int i, dotitle = opts & PF_OPT_SHOWALL;
    631      1.1  itojun 
    632      1.1  itojun 	memset(&pr, 0, sizeof(pr));
    633      1.1  itojun 	memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
    634      1.1  itojun 	for (i = 0; i < 3; i++) {
    635      1.1  itojun 		pr.rule.action = nattype[i];
    636      1.1  itojun 		if (ioctl(dev, DIOCGETRULES, &pr)) {
    637      1.1  itojun 			warn("DIOCGETRULES");
    638      1.1  itojun 			return (-1);
    639      1.1  itojun 		}
    640      1.1  itojun 		mnr = pr.nr;
    641      1.1  itojun 		for (nr = 0; nr < mnr; ++nr) {
    642      1.1  itojun 			pr.nr = nr;
    643      1.1  itojun 			if (ioctl(dev, DIOCGETRULE, &pr)) {
    644      1.1  itojun 				warn("DIOCGETRULE");
    645      1.1  itojun 				return (-1);
    646      1.1  itojun 			}
    647      1.1  itojun 			if (pfctl_get_pool(dev, &pr.rule.rpool, nr,
    648  1.1.1.2    yamt 			    pr.ticket, nattype[i], anchorname) != 0)
    649      1.1  itojun 				return (-1);
    650      1.1  itojun 			if (dotitle) {
    651      1.1  itojun 				pfctl_print_title("TRANSLATION RULES:");
    652      1.1  itojun 				dotitle = 0;
    653      1.1  itojun 			}
    654  1.1.1.2    yamt 			print_rule(&pr.rule, pr.anchor_call,
    655  1.1.1.2    yamt 			    opts & PF_OPT_VERBOSE2);
    656      1.1  itojun 			pfctl_print_rule_counters(&pr.rule, opts);
    657      1.1  itojun 			pfctl_clear_pool(&pr.rule.rpool);
    658      1.1  itojun 		}
    659      1.1  itojun 	}
    660      1.1  itojun 	return (0);
    661      1.1  itojun }
    662      1.1  itojun 
    663      1.1  itojun int
    664      1.1  itojun pfctl_show_src_nodes(int dev, int opts)
    665      1.1  itojun {
    666      1.1  itojun 	struct pfioc_src_nodes psn;
    667      1.1  itojun 	struct pf_src_node *p;
    668      1.1  itojun 	char *inbuf = NULL, *newinbuf = NULL;
    669      1.1  itojun 	unsigned len = 0;
    670      1.1  itojun 	int i;
    671      1.1  itojun 
    672      1.1  itojun 	memset(&psn, 0, sizeof(psn));
    673      1.1  itojun 	for (;;) {
    674      1.1  itojun 		psn.psn_len = len;
    675      1.1  itojun 		if (len) {
    676      1.1  itojun 			newinbuf = realloc(inbuf, len);
    677      1.1  itojun 			if (newinbuf == NULL)
    678      1.1  itojun 				err(1, "realloc");
    679      1.1  itojun 			psn.psn_buf = inbuf = newinbuf;
    680      1.1  itojun 		}
    681      1.1  itojun 		if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) {
    682      1.1  itojun 			warn("DIOCGETSRCNODES");
    683      1.1  itojun 			return (-1);
    684      1.1  itojun 		}
    685      1.1  itojun 		if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len)
    686      1.1  itojun 			break;
    687      1.1  itojun 		if (len == 0 && psn.psn_len == 0)
    688      1.1  itojun 			return (0);
    689      1.1  itojun 		if (len == 0 && psn.psn_len != 0)
    690      1.1  itojun 			len = psn.psn_len;
    691      1.1  itojun 		if (psn.psn_len == 0)
    692      1.1  itojun 			return (0);	/* no src_nodes */
    693      1.1  itojun 		len *= 2;
    694      1.1  itojun 	}
    695      1.1  itojun 	p = psn.psn_src_nodes;
    696      1.1  itojun 	if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL))
    697      1.1  itojun 		pfctl_print_title("SOURCE TRACKING NODES:");
    698      1.1  itojun 	for (i = 0; i < psn.psn_len; i += sizeof(*p)) {
    699      1.1  itojun 		print_src_node(p, opts);
    700      1.1  itojun 		p++;
    701      1.1  itojun 	}
    702      1.1  itojun 	return (0);
    703      1.1  itojun }
    704      1.1  itojun 
    705      1.1  itojun int
    706      1.1  itojun pfctl_show_states(int dev, const char *iface, int opts)
    707      1.1  itojun {
    708      1.1  itojun 	struct pfioc_states ps;
    709      1.1  itojun 	struct pf_state *p;
    710      1.1  itojun 	char *inbuf = NULL, *newinbuf = NULL;
    711      1.1  itojun 	unsigned len = 0;
    712      1.1  itojun 	int i, dotitle = (opts & PF_OPT_SHOWALL);
    713      1.1  itojun 
    714      1.1  itojun 	memset(&ps, 0, sizeof(ps));
    715      1.1  itojun 	for (;;) {
    716      1.1  itojun 		ps.ps_len = len;
    717      1.1  itojun 		if (len) {
    718      1.1  itojun 			newinbuf = realloc(inbuf, len);
    719      1.1  itojun 			if (newinbuf == NULL)
    720      1.1  itojun 				err(1, "realloc");
    721      1.1  itojun 			ps.ps_buf = inbuf = newinbuf;
    722      1.1  itojun 		}
    723      1.1  itojun 		if (ioctl(dev, DIOCGETSTATES, &ps) < 0) {
    724      1.1  itojun 			warn("DIOCGETSTATES");
    725      1.1  itojun 			return (-1);
    726      1.1  itojun 		}
    727      1.1  itojun 		if (ps.ps_len + sizeof(struct pfioc_states) < len)
    728      1.1  itojun 			break;
    729      1.1  itojun 		if (len == 0 && ps.ps_len == 0)
    730      1.1  itojun 			return (0);
    731      1.1  itojun 		if (len == 0 && ps.ps_len != 0)
    732      1.1  itojun 			len = ps.ps_len;
    733      1.1  itojun 		if (ps.ps_len == 0)
    734      1.1  itojun 			return (0);	/* no states */
    735      1.1  itojun 		len *= 2;
    736      1.1  itojun 	}
    737      1.1  itojun 	p = ps.ps_states;
    738      1.1  itojun 	for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) {
    739      1.1  itojun 		if (iface != NULL && strcmp(p->u.ifname, iface))
    740      1.1  itojun 			continue;
    741      1.1  itojun 		if (dotitle) {
    742      1.1  itojun 			pfctl_print_title("STATES:");
    743      1.1  itojun 			dotitle = 0;
    744      1.1  itojun 		}
    745      1.1  itojun 		print_state(p, opts);
    746      1.1  itojun 	}
    747      1.1  itojun 	return (0);
    748      1.1  itojun }
    749      1.1  itojun 
    750      1.1  itojun int
    751      1.1  itojun pfctl_show_status(int dev, int opts)
    752      1.1  itojun {
    753      1.1  itojun 	struct pf_status status;
    754      1.1  itojun 
    755      1.1  itojun 	if (ioctl(dev, DIOCGETSTATUS, &status)) {
    756      1.1  itojun 		warn("DIOCGETSTATUS");
    757      1.1  itojun 		return (-1);
    758      1.1  itojun 	}
    759      1.1  itojun 	if (opts & PF_OPT_SHOWALL)
    760      1.1  itojun 		pfctl_print_title("INFO:");
    761      1.1  itojun 	print_status(&status, opts);
    762      1.1  itojun 	return (0);
    763      1.1  itojun }
    764      1.1  itojun 
    765      1.1  itojun int
    766      1.1  itojun pfctl_show_timeouts(int dev, int opts)
    767      1.1  itojun {
    768      1.1  itojun 	struct pfioc_tm pt;
    769      1.1  itojun 	int i;
    770      1.1  itojun 
    771      1.1  itojun 	if (opts & PF_OPT_SHOWALL)
    772      1.1  itojun 		pfctl_print_title("TIMEOUTS:");
    773      1.1  itojun 	memset(&pt, 0, sizeof(pt));
    774      1.1  itojun 	for (i = 0; pf_timeouts[i].name; i++) {
    775      1.1  itojun 		pt.timeout = pf_timeouts[i].timeout;
    776      1.1  itojun 		if (ioctl(dev, DIOCGETTIMEOUT, &pt))
    777      1.1  itojun 			err(1, "DIOCGETTIMEOUT");
    778      1.1  itojun 		printf("%-20s %10d", pf_timeouts[i].name, pt.seconds);
    779  1.1.1.2    yamt 		if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START &&
    780  1.1.1.2    yamt 		    pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END)
    781      1.1  itojun 			printf(" states");
    782      1.1  itojun 		else
    783      1.1  itojun 			printf("s");
    784      1.1  itojun 		printf("\n");
    785      1.1  itojun 	}
    786      1.1  itojun 	return (0);
    787      1.1  itojun 
    788      1.1  itojun }
    789      1.1  itojun 
    790      1.1  itojun int
    791      1.1  itojun pfctl_show_limits(int dev, int opts)
    792      1.1  itojun {
    793      1.1  itojun 	struct pfioc_limit pl;
    794      1.1  itojun 	int i;
    795      1.1  itojun 
    796      1.1  itojun 	if (opts & PF_OPT_SHOWALL)
    797      1.1  itojun 		pfctl_print_title("LIMITS:");
    798      1.1  itojun 	memset(&pl, 0, sizeof(pl));
    799      1.1  itojun 	for (i = 0; pf_limits[i].name; i++) {
    800      1.1  itojun 		pl.index = pf_limits[i].index;
    801      1.1  itojun 		if (ioctl(dev, DIOCGETLIMIT, &pl))
    802      1.1  itojun 			err(1, "DIOCGETLIMIT");
    803      1.1  itojun 		printf("%-10s ", pf_limits[i].name);
    804      1.1  itojun 		if (pl.limit == UINT_MAX)
    805      1.1  itojun 			printf("unlimited\n");
    806      1.1  itojun 		else
    807      1.1  itojun 			printf("hard limit %6u\n", pl.limit);
    808      1.1  itojun 	}
    809      1.1  itojun 	return (0);
    810      1.1  itojun }
    811      1.1  itojun 
    812      1.1  itojun /* callbacks for rule/nat/rdr/addr */
    813      1.1  itojun int
    814      1.1  itojun pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af)
    815      1.1  itojun {
    816      1.1  itojun 	struct pf_pooladdr *pa;
    817      1.1  itojun 
    818      1.1  itojun 	if ((pf->opts & PF_OPT_NOACTION) == 0) {
    819      1.1  itojun 		if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr))
    820      1.1  itojun 			err(1, "DIOCBEGINADDRS");
    821      1.1  itojun 	}
    822      1.1  itojun 
    823      1.1  itojun 	pf->paddr.af = af;
    824      1.1  itojun 	TAILQ_FOREACH(pa, &p->list, entries) {
    825      1.1  itojun 		memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr));
    826      1.1  itojun 		if ((pf->opts & PF_OPT_NOACTION) == 0) {
    827      1.1  itojun 			if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr))
    828      1.1  itojun 				err(1, "DIOCADDADDR");
    829      1.1  itojun 		}
    830      1.1  itojun 	}
    831      1.1  itojun 	return (0);
    832      1.1  itojun }
    833      1.1  itojun 
    834      1.1  itojun int
    835  1.1.1.2    yamt pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
    836      1.1  itojun {
    837      1.1  itojun 	u_int8_t		rs_num;
    838      1.1  itojun 	struct pfioc_rule	pr;
    839      1.1  itojun 
    840      1.1  itojun 	switch (r->action) {
    841      1.1  itojun 	case PF_SCRUB:
    842      1.1  itojun 		if ((loadopt & PFCTL_FLAG_FILTER) == 0)
    843      1.1  itojun 			return (0);
    844      1.1  itojun 		rs_num = PF_RULESET_SCRUB;
    845      1.1  itojun 		break;
    846      1.1  itojun 	case PF_DROP:
    847      1.1  itojun 	case PF_PASS:
    848      1.1  itojun 		if ((loadopt & PFCTL_FLAG_FILTER) == 0)
    849      1.1  itojun 			return (0);
    850      1.1  itojun 		rs_num = PF_RULESET_FILTER;
    851      1.1  itojun 		break;
    852      1.1  itojun 	case PF_NAT:
    853      1.1  itojun 	case PF_NONAT:
    854      1.1  itojun 		if ((loadopt & PFCTL_FLAG_NAT) == 0)
    855      1.1  itojun 			return (0);
    856      1.1  itojun 		rs_num = PF_RULESET_NAT;
    857      1.1  itojun 		break;
    858      1.1  itojun 	case PF_RDR:
    859      1.1  itojun 	case PF_NORDR:
    860      1.1  itojun 		if ((loadopt & PFCTL_FLAG_NAT) == 0)
    861      1.1  itojun 			return (0);
    862      1.1  itojun 		rs_num = PF_RULESET_RDR;
    863      1.1  itojun 		break;
    864      1.1  itojun 	case PF_BINAT:
    865      1.1  itojun 	case PF_NOBINAT:
    866      1.1  itojun 		if ((loadopt & PFCTL_FLAG_NAT) == 0)
    867      1.1  itojun 			return (0);
    868      1.1  itojun 		rs_num = PF_RULESET_BINAT;
    869      1.1  itojun 		break;
    870      1.1  itojun 	default:
    871  1.1.1.2    yamt 		errx(1, "Invalid rule type %d", r->action);
    872      1.1  itojun 		break;
    873      1.1  itojun 	}
    874      1.1  itojun 
    875  1.1.1.2    yamt 
    876  1.1.1.2    yamt 	if ((pf->opts & PF_OPT_OPTIMIZE) && rs_num == PF_RULESET_FILTER) {
    877  1.1.1.2    yamt 		/*
    878  1.1.1.2    yamt 		 * We'll do an optimization post-pass before finally adding the
    879  1.1.1.2    yamt 		 * rules.  Then we'll disable the optimization flag and feed
    880  1.1.1.2    yamt 		 * the rules right back into this function.
    881  1.1.1.2    yamt 		 */
    882  1.1.1.2    yamt 		struct pf_opt_rule *pfr;
    883  1.1.1.2    yamt 		struct pf_pooladdr *pa;
    884  1.1.1.2    yamt 
    885  1.1.1.2    yamt 		if ((pfr = calloc(1, sizeof(*pfr))) == NULL)
    886  1.1.1.2    yamt 			err(1, "calloc");
    887  1.1.1.2    yamt 		memcpy(&pfr->por_rule, r, sizeof(*r));
    888  1.1.1.2    yamt 		if (strlcpy(pfr->por_anchor, anchor_call,
    889  1.1.1.2    yamt 		    sizeof(pfr->por_anchor)) >= sizeof(pfr->por_anchor))
    890  1.1.1.2    yamt 			errx(1, "pfctl_add_rule: strlcpy");
    891  1.1.1.2    yamt 		TAILQ_INSERT_TAIL(&pf->opt_queue, pfr, por_entry);
    892  1.1.1.2    yamt 
    893  1.1.1.2    yamt 		if (TAILQ_FIRST(&r->rpool.list) != NULL)  {
    894  1.1.1.2    yamt 			TAILQ_INIT(&pfr->por_rule.rpool.list);
    895  1.1.1.2    yamt 			while ((pa = TAILQ_FIRST(&r->rpool.list)) != NULL) {
    896  1.1.1.2    yamt 				TAILQ_REMOVE(&r->rpool.list, pa, entries);
    897  1.1.1.2    yamt 				TAILQ_INSERT_TAIL(&pfr->por_rule.rpool.list, pa,
    898  1.1.1.2    yamt 			    	entries);
    899  1.1.1.2    yamt 			}
    900  1.1.1.2    yamt 		} else {
    901  1.1.1.2    yamt 			memset(&pfr->por_rule.rpool, 0,
    902  1.1.1.2    yamt 			    sizeof(pfr->por_rule.rpool));
    903  1.1.1.2    yamt 
    904  1.1.1.2    yamt 		}
    905  1.1.1.2    yamt 		return (0);
    906  1.1.1.2    yamt 	}
    907  1.1.1.2    yamt 
    908      1.1  itojun 	if ((pf->opts & PF_OPT_NOACTION) == 0) {
    909      1.1  itojun 		bzero(&pr, sizeof(pr));
    910      1.1  itojun 		if (strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor)) >=
    911  1.1.1.2    yamt 		    sizeof(pr.anchor))
    912      1.1  itojun 			errx(1, "pfctl_add_rule: strlcpy");
    913      1.1  itojun 		if (pfctl_add_pool(pf, &r->rpool, r->af))
    914      1.1  itojun 			return (1);
    915  1.1.1.2    yamt 		pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor);
    916      1.1  itojun 		pr.pool_ticket = pf->paddr.ticket;
    917      1.1  itojun 		memcpy(&pr.rule, r, sizeof(pr.rule));
    918  1.1.1.2    yamt 		strlcpy(pr.anchor_call, anchor_call, sizeof(pr.anchor_call));
    919      1.1  itojun 		if (ioctl(pf->dev, DIOCADDRULE, &pr))
    920      1.1  itojun 			err(1, "DIOCADDRULE");
    921      1.1  itojun 	}
    922      1.1  itojun 	if (pf->opts & PF_OPT_VERBOSE)
    923  1.1.1.2    yamt 		print_rule(r, anchor_call, pf->opts & PF_OPT_VERBOSE2);
    924      1.1  itojun 	pfctl_clear_pool(&r->rpool);
    925      1.1  itojun 	return (0);
    926      1.1  itojun }
    927      1.1  itojun 
    928      1.1  itojun int
    929      1.1  itojun pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
    930      1.1  itojun {
    931      1.1  itojun 	if (altqsupport &&
    932      1.1  itojun 	    (loadopt & PFCTL_FLAG_ALTQ) != 0) {
    933      1.1  itojun 		memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq));
    934      1.1  itojun 		if ((pf->opts & PF_OPT_NOACTION) == 0) {
    935      1.1  itojun 			if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) {
    936      1.1  itojun 				if (errno == ENXIO)
    937      1.1  itojun 					errx(1, "qtype not configured");
    938      1.1  itojun 				else if (errno == ENODEV)
    939      1.1  itojun 					errx(1, "%s: driver does not support "
    940      1.1  itojun 					    "altq", a->ifname);
    941      1.1  itojun 				else
    942      1.1  itojun 					err(1, "DIOCADDALTQ");
    943      1.1  itojun 			}
    944      1.1  itojun 		}
    945      1.1  itojun 		pfaltq_store(&pf->paltq->altq);
    946      1.1  itojun 	}
    947      1.1  itojun 	return (0);
    948      1.1  itojun }
    949      1.1  itojun 
    950      1.1  itojun int
    951      1.1  itojun pfctl_rules(int dev, char *filename, int opts, char *anchorname,
    952  1.1.1.2    yamt     struct pfr_buffer *trans)
    953      1.1  itojun {
    954      1.1  itojun #define ERR(x) do { warn(x); goto _error; } while(0)
    955      1.1  itojun #define ERRX(x) do { warnx(x); goto _error; } while(0)
    956      1.1  itojun 
    957      1.1  itojun 	FILE			*fin;
    958      1.1  itojun 	struct pfr_buffer	*t, buf;
    959      1.1  itojun 	struct pfioc_altq	 pa;
    960      1.1  itojun 	struct pfctl		 pf;
    961      1.1  itojun 	struct pfr_table	 trs;
    962      1.1  itojun 	int			 osize;
    963      1.1  itojun 
    964      1.1  itojun 	if (trans == NULL) {
    965      1.1  itojun 	    bzero(&buf, sizeof(buf));
    966      1.1  itojun 	    buf.pfrb_type = PFRB_TRANS;
    967      1.1  itojun 	    t = &buf;
    968      1.1  itojun 	    osize = 0;
    969      1.1  itojun 	} else {
    970      1.1  itojun 	    t = trans;
    971      1.1  itojun 	    osize = t->pfrb_size;
    972      1.1  itojun 	}
    973      1.1  itojun 
    974      1.1  itojun 	memset(&pa, 0, sizeof(pa));
    975      1.1  itojun 	memset(&pf, 0, sizeof(pf));
    976      1.1  itojun 	memset(&trs, 0, sizeof(trs));
    977      1.1  itojun 	if (strlcpy(trs.pfrt_anchor, anchorname,
    978  1.1.1.2    yamt 	    sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor))
    979      1.1  itojun 		ERRX("pfctl_rules: strlcpy");
    980      1.1  itojun 	if (strcmp(filename, "-") == 0) {
    981      1.1  itojun 		fin = stdin;
    982      1.1  itojun 		infile = "stdin";
    983      1.1  itojun 	} else {
    984  1.1.1.2    yamt 		if ((fin = pfctl_fopen(filename, "r")) == NULL) {
    985      1.1  itojun 			warn("%s", filename);
    986      1.1  itojun 			return (1);
    987      1.1  itojun 		}
    988      1.1  itojun 		infile = filename;
    989      1.1  itojun 	}
    990      1.1  itojun 	pf.dev = dev;
    991      1.1  itojun 	pf.opts = opts;
    992      1.1  itojun 	pf.loadopt = loadopt;
    993      1.1  itojun 	if (anchorname[0])
    994      1.1  itojun 		pf.loadopt &= ~PFCTL_FLAG_ALTQ;
    995      1.1  itojun 	pf.paltq = &pa;
    996      1.1  itojun 	pf.trans = t;
    997      1.1  itojun 	pf.rule_nr = 0;
    998      1.1  itojun 	pf.anchor = anchorname;
    999  1.1.1.2    yamt 	TAILQ_INIT(&pf.opt_queue);
   1000      1.1  itojun 
   1001      1.1  itojun 	if ((opts & PF_OPT_NOACTION) == 0) {
   1002      1.1  itojun 		if ((pf.loadopt & PFCTL_FLAG_NAT) != 0) {
   1003  1.1.1.2    yamt 			if (pfctl_add_trans(t, PF_RULESET_NAT, anchorname) ||
   1004  1.1.1.2    yamt 			    pfctl_add_trans(t, PF_RULESET_BINAT, anchorname) ||
   1005  1.1.1.2    yamt 			    pfctl_add_trans(t, PF_RULESET_RDR, anchorname))
   1006      1.1  itojun 				ERR("pfctl_rules");
   1007      1.1  itojun 		}
   1008      1.1  itojun 		if (((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))) {
   1009  1.1.1.2    yamt 			if (pfctl_add_trans(t, PF_RULESET_ALTQ, anchorname))
   1010      1.1  itojun 				ERR("pfctl_rules");
   1011      1.1  itojun 		}
   1012      1.1  itojun 		if ((pf.loadopt & PFCTL_FLAG_FILTER) != 0) {
   1013  1.1.1.2    yamt 			if (pfctl_add_trans(t, PF_RULESET_SCRUB, anchorname) ||
   1014  1.1.1.2    yamt 			    pfctl_add_trans(t, PF_RULESET_FILTER, anchorname))
   1015      1.1  itojun 				ERR("pfctl_rules");
   1016      1.1  itojun 		}
   1017      1.1  itojun 		if (pf.loadopt & PFCTL_FLAG_TABLE) {
   1018  1.1.1.2    yamt 			if (pfctl_add_trans(t, PF_RULESET_TABLE, anchorname))
   1019      1.1  itojun 				ERR("pfctl_rules");
   1020      1.1  itojun 		}
   1021      1.1  itojun 		if (pfctl_trans(dev, t, DIOCXBEGIN, osize))
   1022      1.1  itojun 			ERR("DIOCXBEGIN");
   1023      1.1  itojun 		if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ))
   1024      1.1  itojun 			pa.ticket = pfctl_get_ticket(t, PF_RULESET_ALTQ,
   1025  1.1.1.2    yamt 			    anchorname);
   1026      1.1  itojun 		if (pf.loadopt & PFCTL_FLAG_TABLE)
   1027      1.1  itojun 			pf.tticket = pfctl_get_ticket(t, PF_RULESET_TABLE,
   1028  1.1.1.2    yamt 			    anchorname);
   1029      1.1  itojun 	}
   1030      1.1  itojun 	if (parse_rules(fin, &pf) < 0) {
   1031      1.1  itojun 		if ((opts & PF_OPT_NOACTION) == 0)
   1032      1.1  itojun 			ERRX("Syntax error in config file: "
   1033      1.1  itojun 			    "pf rules not loaded");
   1034      1.1  itojun 		else
   1035      1.1  itojun 			goto _error;
   1036      1.1  itojun 	}
   1037  1.1.1.2    yamt 	if (pf.opts & PF_OPT_OPTIMIZE) {
   1038  1.1.1.2    yamt 		if (pfctl_optimize_rules(&pf))
   1039  1.1.1.2    yamt 			ERRX("Failed to optimize ruleset: pf rules not loaded");
   1040  1.1.1.2    yamt 	}
   1041  1.1.1.2    yamt 
   1042      1.1  itojun 	if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))
   1043      1.1  itojun 		if (check_commit_altq(dev, opts) != 0)
   1044      1.1  itojun 			ERRX("errors in altq config");
   1045      1.1  itojun 	if (fin != stdin)
   1046      1.1  itojun 		fclose(fin);
   1047      1.1  itojun 
   1048      1.1  itojun 	/* process "load anchor" directives */
   1049  1.1.1.2    yamt 	if (!anchorname[0])
   1050      1.1  itojun 		if (pfctl_load_anchors(dev, opts, t) == -1)
   1051      1.1  itojun 			ERRX("load anchors");
   1052      1.1  itojun 
   1053      1.1  itojun 	if (trans == NULL && (opts & PF_OPT_NOACTION) == 0)
   1054      1.1  itojun 		if (pfctl_trans(dev, t, DIOCXCOMMIT, 0))
   1055      1.1  itojun 			ERR("DIOCXCOMMIT");
   1056      1.1  itojun 	return (0);
   1057      1.1  itojun 
   1058      1.1  itojun _error:
   1059      1.1  itojun 	if (trans == NULL) {	/* main ruleset */
   1060      1.1  itojun 		if ((opts & PF_OPT_NOACTION) == 0)
   1061      1.1  itojun 			if (pfctl_trans(dev, t, DIOCXROLLBACK, 0))
   1062      1.1  itojun 				err(1, "DIOCXROLLBACK");
   1063      1.1  itojun 		exit(1);
   1064      1.1  itojun 	} else			/* sub ruleset */
   1065      1.1  itojun 		return (-1);
   1066      1.1  itojun 
   1067      1.1  itojun #undef ERR
   1068      1.1  itojun #undef ERRX
   1069      1.1  itojun }
   1070      1.1  itojun 
   1071  1.1.1.2    yamt FILE *
   1072  1.1.1.2    yamt pfctl_fopen(const char *name, const char *mode)
   1073  1.1.1.2    yamt {
   1074  1.1.1.2    yamt 	struct stat	 st;
   1075  1.1.1.2    yamt 	FILE		*fp;
   1076  1.1.1.2    yamt 
   1077  1.1.1.2    yamt 	fp = fopen(name, mode);
   1078  1.1.1.2    yamt 	if (fp == NULL)
   1079  1.1.1.2    yamt 		return (NULL);
   1080  1.1.1.2    yamt 	if (fstat(fileno(fp), &st)) {
   1081  1.1.1.2    yamt 		fclose(fp);
   1082  1.1.1.2    yamt 		return (NULL);
   1083  1.1.1.2    yamt 	}
   1084  1.1.1.2    yamt 	if (S_ISDIR(st.st_mode)) {
   1085  1.1.1.2    yamt 		fclose(fp);
   1086  1.1.1.2    yamt 		errno = EISDIR;
   1087  1.1.1.2    yamt 		return (NULL);
   1088  1.1.1.2    yamt 	}
   1089  1.1.1.2    yamt 	return (fp);
   1090  1.1.1.2    yamt }
   1091  1.1.1.2    yamt 
   1092      1.1  itojun int
   1093      1.1  itojun pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
   1094      1.1  itojun {
   1095      1.1  itojun 	struct pfioc_limit pl;
   1096      1.1  itojun 	int i;
   1097      1.1  itojun 
   1098      1.1  itojun 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
   1099      1.1  itojun 		return (0);
   1100      1.1  itojun 
   1101      1.1  itojun 	memset(&pl, 0, sizeof(pl));
   1102      1.1  itojun 	for (i = 0; pf_limits[i].name; i++) {
   1103      1.1  itojun 		if (strcasecmp(opt, pf_limits[i].name) == 0) {
   1104      1.1  itojun 			pl.index = pf_limits[i].index;
   1105      1.1  itojun 			pl.limit = limit;
   1106      1.1  itojun 			if ((pf->opts & PF_OPT_NOACTION) == 0) {
   1107      1.1  itojun 				if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) {
   1108      1.1  itojun 					if (errno == EBUSY) {
   1109      1.1  itojun 						warnx("Current pool "
   1110      1.1  itojun 						    "size exceeds requested "
   1111      1.1  itojun 						    "hard limit");
   1112      1.1  itojun 						return (1);
   1113      1.1  itojun 					} else
   1114      1.1  itojun 						err(1, "DIOCSETLIMIT");
   1115      1.1  itojun 				}
   1116      1.1  itojun 			}
   1117      1.1  itojun 			break;
   1118      1.1  itojun 		}
   1119      1.1  itojun 	}
   1120      1.1  itojun 	if (pf_limits[i].name == NULL) {
   1121      1.1  itojun 		warnx("Bad pool name.");
   1122      1.1  itojun 		return (1);
   1123      1.1  itojun 	}
   1124      1.1  itojun 
   1125      1.1  itojun 	if (pf->opts & PF_OPT_VERBOSE)
   1126      1.1  itojun 		printf("set limit %s %d\n", opt, limit);
   1127      1.1  itojun 
   1128      1.1  itojun 	return (0);
   1129      1.1  itojun }
   1130      1.1  itojun 
   1131      1.1  itojun int
   1132      1.1  itojun pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
   1133      1.1  itojun {
   1134      1.1  itojun 	struct pfioc_tm pt;
   1135      1.1  itojun 	int i;
   1136      1.1  itojun 
   1137      1.1  itojun 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
   1138      1.1  itojun 		return (0);
   1139      1.1  itojun 
   1140      1.1  itojun 	memset(&pt, 0, sizeof(pt));
   1141      1.1  itojun 	for (i = 0; pf_timeouts[i].name; i++) {
   1142      1.1  itojun 		if (strcasecmp(opt, pf_timeouts[i].name) == 0) {
   1143      1.1  itojun 			pt.timeout = pf_timeouts[i].timeout;
   1144      1.1  itojun 			break;
   1145      1.1  itojun 		}
   1146      1.1  itojun 	}
   1147      1.1  itojun 
   1148      1.1  itojun 	if (pf_timeouts[i].name == NULL) {
   1149      1.1  itojun 		warnx("Bad timeout name.");
   1150      1.1  itojun 		return (1);
   1151      1.1  itojun 	}
   1152      1.1  itojun 
   1153      1.1  itojun 	pt.seconds = seconds;
   1154      1.1  itojun 	if ((pf->opts & PF_OPT_NOACTION) == 0) {
   1155      1.1  itojun 		if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt))
   1156      1.1  itojun 			err(1, "DIOCSETTIMEOUT");
   1157      1.1  itojun 	}
   1158      1.1  itojun 
   1159      1.1  itojun 	if (pf->opts & PF_OPT_VERBOSE && ! quiet)
   1160      1.1  itojun 		printf("set timeout %s %d\n", opt, seconds);
   1161      1.1  itojun 
   1162      1.1  itojun 	return (0);
   1163      1.1  itojun }
   1164      1.1  itojun 
   1165      1.1  itojun int
   1166      1.1  itojun pfctl_set_optimization(struct pfctl *pf, const char *opt)
   1167      1.1  itojun {
   1168      1.1  itojun 	const struct pf_hint *hint;
   1169      1.1  itojun 	int i, r;
   1170      1.1  itojun 
   1171      1.1  itojun 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
   1172      1.1  itojun 		return (0);
   1173      1.1  itojun 
   1174      1.1  itojun 	for (i = 0; pf_hints[i].name; i++)
   1175      1.1  itojun 		if (strcasecmp(opt, pf_hints[i].name) == 0)
   1176      1.1  itojun 			break;
   1177      1.1  itojun 
   1178      1.1  itojun 	hint = pf_hints[i].hint;
   1179      1.1  itojun 	if (hint == NULL) {
   1180      1.1  itojun 		warnx("Bad hint name.");
   1181      1.1  itojun 		return (1);
   1182      1.1  itojun 	}
   1183      1.1  itojun 
   1184      1.1  itojun 	for (i = 0; hint[i].name; i++)
   1185      1.1  itojun 		if ((r = pfctl_set_timeout(pf, hint[i].name,
   1186      1.1  itojun 		    hint[i].timeout, 1)))
   1187      1.1  itojun 			return (r);
   1188      1.1  itojun 
   1189      1.1  itojun 	if (pf->opts & PF_OPT_VERBOSE)
   1190      1.1  itojun 		printf("set optimization %s\n", opt);
   1191      1.1  itojun 
   1192      1.1  itojun 	return (0);
   1193      1.1  itojun }
   1194      1.1  itojun 
   1195      1.1  itojun int
   1196      1.1  itojun pfctl_set_logif(struct pfctl *pf, char *ifname)
   1197      1.1  itojun {
   1198      1.1  itojun 	struct pfioc_if pi;
   1199      1.1  itojun 
   1200      1.1  itojun 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
   1201      1.1  itojun 		return (0);
   1202      1.1  itojun 
   1203      1.1  itojun 	memset(&pi, 0, sizeof(pi));
   1204      1.1  itojun 	if ((pf->opts & PF_OPT_NOACTION) == 0) {
   1205      1.1  itojun 		if (!strcmp(ifname, "none"))
   1206      1.1  itojun 			bzero(pi.ifname, sizeof(pi.ifname));
   1207      1.1  itojun 		else {
   1208      1.1  itojun 			if (strlcpy(pi.ifname, ifname,
   1209      1.1  itojun 			    sizeof(pi.ifname)) >= sizeof(pi.ifname))
   1210      1.1  itojun 				errx(1, "pfctl_set_logif: strlcpy");
   1211      1.1  itojun 		}
   1212      1.1  itojun 		if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi))
   1213      1.1  itojun 			err(1, "DIOCSETSTATUSIF");
   1214      1.1  itojun 	}
   1215      1.1  itojun 
   1216      1.1  itojun 	if (pf->opts & PF_OPT_VERBOSE)
   1217      1.1  itojun 		printf("set loginterface %s\n", ifname);
   1218      1.1  itojun 
   1219      1.1  itojun 	return (0);
   1220      1.1  itojun }
   1221      1.1  itojun 
   1222      1.1  itojun int
   1223      1.1  itojun pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
   1224      1.1  itojun {
   1225      1.1  itojun 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
   1226      1.1  itojun 		return (0);
   1227      1.1  itojun 
   1228      1.1  itojun 	HTONL(hostid);
   1229      1.1  itojun 
   1230      1.1  itojun 	if ((pf->opts & PF_OPT_NOACTION) == 0)
   1231      1.1  itojun 		if (ioctl(dev, DIOCSETHOSTID, &hostid))
   1232      1.1  itojun 			err(1, "DIOCSETHOSTID");
   1233      1.1  itojun 
   1234      1.1  itojun 	if (pf->opts & PF_OPT_VERBOSE)
   1235      1.1  itojun 		printf("set hostid 0x%08x\n", ntohl(hostid));
   1236      1.1  itojun 
   1237      1.1  itojun 	return (0);
   1238      1.1  itojun }
   1239      1.1  itojun 
   1240      1.1  itojun int
   1241      1.1  itojun pfctl_set_debug(struct pfctl *pf, char *d)
   1242      1.1  itojun {
   1243      1.1  itojun 	u_int32_t	level;
   1244      1.1  itojun 
   1245      1.1  itojun 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
   1246      1.1  itojun 		return (0);
   1247      1.1  itojun 
   1248      1.1  itojun 	if (!strcmp(d, "none"))
   1249      1.1  itojun 		level = PF_DEBUG_NONE;
   1250      1.1  itojun 	else if (!strcmp(d, "urgent"))
   1251      1.1  itojun 		level = PF_DEBUG_URGENT;
   1252      1.1  itojun 	else if (!strcmp(d, "misc"))
   1253      1.1  itojun 		level = PF_DEBUG_MISC;
   1254      1.1  itojun 	else if (!strcmp(d, "loud"))
   1255      1.1  itojun 		level = PF_DEBUG_NOISY;
   1256      1.1  itojun 	else {
   1257      1.1  itojun 		warnx("unknown debug level \"%s\"", d);
   1258      1.1  itojun 		return (-1);
   1259      1.1  itojun 	}
   1260      1.1  itojun 
   1261      1.1  itojun 	if ((pf->opts & PF_OPT_NOACTION) == 0)
   1262      1.1  itojun 		if (ioctl(dev, DIOCSETDEBUG, &level))
   1263      1.1  itojun 			err(1, "DIOCSETDEBUG");
   1264      1.1  itojun 
   1265      1.1  itojun 	if (pf->opts & PF_OPT_VERBOSE)
   1266      1.1  itojun 		printf("set debug %s\n", d);
   1267      1.1  itojun 
   1268      1.1  itojun 	return (0);
   1269      1.1  itojun }
   1270      1.1  itojun 
   1271      1.1  itojun int
   1272      1.1  itojun pfctl_debug(int dev, u_int32_t level, int opts)
   1273      1.1  itojun {
   1274      1.1  itojun 	if (ioctl(dev, DIOCSETDEBUG, &level))
   1275      1.1  itojun 		err(1, "DIOCSETDEBUG");
   1276      1.1  itojun 	if ((opts & PF_OPT_QUIET) == 0) {
   1277      1.1  itojun 		fprintf(stderr, "debug level set to '");
   1278      1.1  itojun 		switch (level) {
   1279      1.1  itojun 		case PF_DEBUG_NONE:
   1280      1.1  itojun 			fprintf(stderr, "none");
   1281      1.1  itojun 			break;
   1282      1.1  itojun 		case PF_DEBUG_URGENT:
   1283      1.1  itojun 			fprintf(stderr, "urgent");
   1284      1.1  itojun 			break;
   1285      1.1  itojun 		case PF_DEBUG_MISC:
   1286      1.1  itojun 			fprintf(stderr, "misc");
   1287      1.1  itojun 			break;
   1288      1.1  itojun 		case PF_DEBUG_NOISY:
   1289      1.1  itojun 			fprintf(stderr, "loud");
   1290      1.1  itojun 			break;
   1291      1.1  itojun 		default:
   1292      1.1  itojun 			fprintf(stderr, "<invalid>");
   1293      1.1  itojun 			break;
   1294      1.1  itojun 		}
   1295      1.1  itojun 		fprintf(stderr, "'\n");
   1296      1.1  itojun 	}
   1297      1.1  itojun 	return (0);
   1298      1.1  itojun }
   1299      1.1  itojun 
   1300      1.1  itojun int
   1301      1.1  itojun pfctl_clear_rule_counters(int dev, int opts)
   1302      1.1  itojun {
   1303      1.1  itojun 	if (ioctl(dev, DIOCCLRRULECTRS))
   1304      1.1  itojun 		err(1, "DIOCCLRRULECTRS");
   1305      1.1  itojun 	if ((opts & PF_OPT_QUIET) == 0)
   1306      1.1  itojun 		fprintf(stderr, "pf: rule counters cleared\n");
   1307      1.1  itojun 	return (0);
   1308      1.1  itojun }
   1309      1.1  itojun 
   1310      1.1  itojun int
   1311      1.1  itojun pfctl_test_altqsupport(int dev, int opts)
   1312      1.1  itojun {
   1313      1.1  itojun 	struct pfioc_altq pa;
   1314      1.1  itojun 
   1315      1.1  itojun 	if (ioctl(dev, DIOCGETALTQS, &pa)) {
   1316      1.1  itojun 		if (errno == ENODEV) {
   1317      1.1  itojun 			if (!(opts & PF_OPT_QUIET))
   1318      1.1  itojun 				fprintf(stderr, "No ALTQ support in kernel\n"
   1319      1.1  itojun 				    "ALTQ related functions disabled\n");
   1320      1.1  itojun 			return (0);
   1321      1.1  itojun 		} else
   1322      1.1  itojun 			err(1, "DIOCGETALTQS");
   1323      1.1  itojun 	}
   1324      1.1  itojun 	return (1);
   1325      1.1  itojun }
   1326      1.1  itojun 
   1327      1.1  itojun int
   1328      1.1  itojun pfctl_show_anchors(int dev, int opts, char *anchorname)
   1329      1.1  itojun {
   1330  1.1.1.2    yamt 	struct pfioc_ruleset	 pr;
   1331  1.1.1.2    yamt 	u_int32_t		 mnr, nr;
   1332      1.1  itojun 
   1333  1.1.1.2    yamt 	memset(&pr, 0, sizeof(pr));
   1334  1.1.1.2    yamt 	memcpy(pr.path, anchorname, sizeof(pr.path));
   1335  1.1.1.2    yamt 	if (ioctl(dev, DIOCGETRULESETS, &pr)) {
   1336  1.1.1.2    yamt 		if (errno == EINVAL)
   1337  1.1.1.2    yamt 			fprintf(stderr, "Anchor '%s' not found.\n",
   1338  1.1.1.2    yamt 			    anchorname);
   1339  1.1.1.2    yamt 		else
   1340  1.1.1.2    yamt 			err(1, "DIOCGETRULESETS");
   1341  1.1.1.2    yamt 		return (-1);
   1342  1.1.1.2    yamt 	}
   1343  1.1.1.2    yamt 	mnr = pr.nr;
   1344  1.1.1.2    yamt 	for (nr = 0; nr < mnr; ++nr) {
   1345  1.1.1.2    yamt 		char sub[MAXPATHLEN];
   1346      1.1  itojun 
   1347  1.1.1.2    yamt 		pr.nr = nr;
   1348  1.1.1.2    yamt 		if (ioctl(dev, DIOCGETRULESET, &pr))
   1349  1.1.1.2    yamt 			err(1, "DIOCGETRULESET");
   1350  1.1.1.2    yamt 		if (!strcmp(pr.name, PF_RESERVED_ANCHOR))
   1351  1.1.1.2    yamt 			continue;
   1352  1.1.1.2    yamt 		sub[0] = 0;
   1353  1.1.1.2    yamt 		if (pr.path[0]) {
   1354  1.1.1.2    yamt 			strlcat(sub, pr.path, sizeof(sub));
   1355  1.1.1.2    yamt 			strlcat(sub, "/", sizeof(sub));
   1356  1.1.1.2    yamt 		}
   1357  1.1.1.2    yamt 		strlcat(sub, pr.name, sizeof(sub));
   1358  1.1.1.2    yamt 		printf("  %s\n", sub);
   1359  1.1.1.2    yamt 		if (opts & PF_OPT_VERBOSE && pfctl_show_anchors(dev, opts, sub))
   1360      1.1  itojun 			return (-1);
   1361      1.1  itojun 	}
   1362      1.1  itojun 	return (0);
   1363      1.1  itojun }
   1364      1.1  itojun 
   1365      1.1  itojun const char *
   1366      1.1  itojun pfctl_lookup_option(char *cmd, const char **list)
   1367      1.1  itojun {
   1368      1.1  itojun 	if (cmd != NULL && *cmd)
   1369      1.1  itojun 		for (; *list; list++)
   1370      1.1  itojun 			if (!strncmp(cmd, *list, strlen(cmd)))
   1371      1.1  itojun 				return (*list);
   1372      1.1  itojun 	return (NULL);
   1373      1.1  itojun }
   1374      1.1  itojun 
   1375      1.1  itojun int
   1376      1.1  itojun main(int argc, char *argv[])
   1377      1.1  itojun {
   1378      1.1  itojun 	int	error = 0;
   1379      1.1  itojun 	int	ch;
   1380      1.1  itojun 	int	mode = O_RDONLY;
   1381      1.1  itojun 	int	opts = 0;
   1382  1.1.1.2    yamt 	char	anchorname[MAXPATHLEN];
   1383      1.1  itojun 
   1384      1.1  itojun 	if (argc < 2)
   1385      1.1  itojun 		usage();
   1386      1.1  itojun 
   1387      1.1  itojun 	while ((ch = getopt(argc, argv,
   1388  1.1.1.2    yamt 	    "a:AdD:eqf:F:ghi:k:nNOop:rRs:t:T:vx:z")) != -1) {
   1389      1.1  itojun 		switch (ch) {
   1390      1.1  itojun 		case 'a':
   1391      1.1  itojun 			anchoropt = optarg;
   1392      1.1  itojun 			break;
   1393      1.1  itojun 		case 'd':
   1394      1.1  itojun 			opts |= PF_OPT_DISABLE;
   1395      1.1  itojun 			mode = O_RDWR;
   1396      1.1  itojun 			break;
   1397      1.1  itojun 		case 'D':
   1398      1.1  itojun 			if (pfctl_cmdline_symset(optarg) < 0)
   1399      1.1  itojun 				warnx("could not parse macro definition %s",
   1400      1.1  itojun 				    optarg);
   1401      1.1  itojun 			break;
   1402      1.1  itojun 		case 'e':
   1403      1.1  itojun 			opts |= PF_OPT_ENABLE;
   1404      1.1  itojun 			mode = O_RDWR;
   1405      1.1  itojun 			break;
   1406      1.1  itojun 		case 'q':
   1407      1.1  itojun 			opts |= PF_OPT_QUIET;
   1408      1.1  itojun 			break;
   1409      1.1  itojun 		case 'F':
   1410      1.1  itojun 			clearopt = pfctl_lookup_option(optarg, clearopt_list);
   1411      1.1  itojun 			if (clearopt == NULL) {
   1412      1.1  itojun 				warnx("Unknown flush modifier '%s'", optarg);
   1413      1.1  itojun 				usage();
   1414      1.1  itojun 			}
   1415      1.1  itojun 			mode = O_RDWR;
   1416      1.1  itojun 			break;
   1417      1.1  itojun 		case 'i':
   1418      1.1  itojun 			ifaceopt = optarg;
   1419      1.1  itojun 			break;
   1420      1.1  itojun 		case 'k':
   1421      1.1  itojun 			if (state_killers >= 2) {
   1422      1.1  itojun 				warnx("can only specify -k twice");
   1423      1.1  itojun 				usage();
   1424      1.1  itojun 				/* NOTREACHED */
   1425      1.1  itojun 			}
   1426      1.1  itojun 			state_kill[state_killers++] = optarg;
   1427      1.1  itojun 			mode = O_RDWR;
   1428      1.1  itojun 			break;
   1429      1.1  itojun 		case 'n':
   1430      1.1  itojun 			opts |= PF_OPT_NOACTION;
   1431      1.1  itojun 			break;
   1432      1.1  itojun 		case 'N':
   1433      1.1  itojun 			loadopt |= PFCTL_FLAG_NAT;
   1434      1.1  itojun 			break;
   1435      1.1  itojun 		case 'r':
   1436      1.1  itojun 			opts |= PF_OPT_USEDNS;
   1437      1.1  itojun 			break;
   1438      1.1  itojun 		case 'f':
   1439      1.1  itojun 			rulesopt = optarg;
   1440      1.1  itojun 			mode = O_RDWR;
   1441      1.1  itojun 			break;
   1442      1.1  itojun 		case 'g':
   1443      1.1  itojun 			opts |= PF_OPT_DEBUG;
   1444      1.1  itojun 			break;
   1445      1.1  itojun 		case 'A':
   1446      1.1  itojun 			loadopt |= PFCTL_FLAG_ALTQ;
   1447      1.1  itojun 			break;
   1448      1.1  itojun 		case 'R':
   1449      1.1  itojun 			loadopt |= PFCTL_FLAG_FILTER;
   1450      1.1  itojun 			break;
   1451  1.1.1.2    yamt 		case 'o':
   1452  1.1.1.2    yamt 			if (opts & PF_OPT_OPTIMIZE)
   1453  1.1.1.2    yamt 				opts |= PF_OPT_OPTIMIZE_PROFILE;
   1454  1.1.1.2    yamt 			else
   1455  1.1.1.2    yamt 				opts |= PF_OPT_OPTIMIZE;
   1456  1.1.1.2    yamt 			break;
   1457      1.1  itojun 		case 'O':
   1458      1.1  itojun 			loadopt |= PFCTL_FLAG_OPTION;
   1459      1.1  itojun 			break;
   1460      1.1  itojun 		case 'p':
   1461      1.1  itojun 			pf_device = optarg;
   1462      1.1  itojun 			break;
   1463      1.1  itojun 		case 's':
   1464      1.1  itojun 			showopt = pfctl_lookup_option(optarg, showopt_list);
   1465      1.1  itojun 			if (showopt == NULL) {
   1466      1.1  itojun 				warnx("Unknown show modifier '%s'", optarg);
   1467      1.1  itojun 				usage();
   1468      1.1  itojun 			}
   1469      1.1  itojun 			break;
   1470      1.1  itojun 		case 't':
   1471      1.1  itojun 			tableopt = optarg;
   1472      1.1  itojun 			break;
   1473      1.1  itojun 		case 'T':
   1474      1.1  itojun 			tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list);
   1475      1.1  itojun 			if (tblcmdopt == NULL) {
   1476      1.1  itojun 				warnx("Unknown table command '%s'", optarg);
   1477      1.1  itojun 				usage();
   1478      1.1  itojun 			}
   1479      1.1  itojun 			break;
   1480      1.1  itojun 		case 'v':
   1481      1.1  itojun 			if (opts & PF_OPT_VERBOSE)
   1482      1.1  itojun 				opts |= PF_OPT_VERBOSE2;
   1483      1.1  itojun 			opts |= PF_OPT_VERBOSE;
   1484      1.1  itojun 			break;
   1485      1.1  itojun 		case 'x':
   1486      1.1  itojun 			debugopt = pfctl_lookup_option(optarg, debugopt_list);
   1487      1.1  itojun 			if (debugopt == NULL) {
   1488      1.1  itojun 				warnx("Unknown debug level '%s'", optarg);
   1489      1.1  itojun 				usage();
   1490      1.1  itojun 			}
   1491      1.1  itojun 			mode = O_RDWR;
   1492      1.1  itojun 			break;
   1493      1.1  itojun 		case 'z':
   1494      1.1  itojun 			opts |= PF_OPT_CLRRULECTRS;
   1495      1.1  itojun 			mode = O_RDWR;
   1496      1.1  itojun 			break;
   1497      1.1  itojun 		case 'h':
   1498      1.1  itojun 			/* FALLTHROUGH */
   1499      1.1  itojun 		default:
   1500      1.1  itojun 			usage();
   1501      1.1  itojun 			/* NOTREACHED */
   1502      1.1  itojun 		}
   1503      1.1  itojun 	}
   1504      1.1  itojun 
   1505      1.1  itojun 	if (tblcmdopt != NULL) {
   1506      1.1  itojun 		argc -= optind;
   1507      1.1  itojun 		argv += optind;
   1508      1.1  itojun 		ch = *tblcmdopt;
   1509      1.1  itojun 		if (ch == 'l') {
   1510      1.1  itojun 			loadopt |= PFCTL_FLAG_TABLE;
   1511      1.1  itojun 			tblcmdopt = NULL;
   1512      1.1  itojun 		} else
   1513      1.1  itojun 			mode = strchr("acdfkrz", ch) ? O_RDWR : O_RDONLY;
   1514      1.1  itojun 	} else if (argc != optind) {
   1515      1.1  itojun 		warnx("unknown command line argument: %s ...", argv[optind]);
   1516      1.1  itojun 		usage();
   1517      1.1  itojun 		/* NOTREACHED */
   1518      1.1  itojun 	}
   1519      1.1  itojun 	if (loadopt == 0)
   1520      1.1  itojun 		loadopt = ~0;
   1521      1.1  itojun 
   1522      1.1  itojun 	memset(anchorname, 0, sizeof(anchorname));
   1523      1.1  itojun 	if (anchoropt != NULL) {
   1524  1.1.1.2    yamt 		if (strlcpy(anchorname, anchoropt,
   1525  1.1.1.2    yamt 		    sizeof(anchorname)) >= sizeof(anchorname))
   1526  1.1.1.2    yamt 			errx(1, "anchor name '%s' too long",
   1527  1.1.1.2    yamt 			    anchoropt);
   1528      1.1  itojun 		loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE;
   1529      1.1  itojun 	}
   1530      1.1  itojun 
   1531      1.1  itojun 	if ((opts & PF_OPT_NOACTION) == 0) {
   1532      1.1  itojun 		dev = open(pf_device, mode);
   1533      1.1  itojun 		if (dev == -1)
   1534      1.1  itojun 			err(1, "%s", pf_device);
   1535      1.1  itojun 		altqsupport = pfctl_test_altqsupport(dev, opts);
   1536      1.1  itojun 	} else {
   1537      1.1  itojun 		dev = open(pf_device, O_RDONLY);
   1538      1.1  itojun 		if (dev >= 0)
   1539      1.1  itojun 			opts |= PF_OPT_DUMMYACTION;
   1540      1.1  itojun 		/* turn off options */
   1541      1.1  itojun 		opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE);
   1542      1.1  itojun 		clearopt = showopt = debugopt = NULL;
   1543      1.1  itojun 		altqsupport = 1;
   1544      1.1  itojun 	}
   1545      1.1  itojun 
   1546      1.1  itojun 	if (opts & PF_OPT_DISABLE)
   1547      1.1  itojun 		if (pfctl_disable(dev, opts))
   1548      1.1  itojun 			error = 1;
   1549      1.1  itojun 
   1550      1.1  itojun 	if (showopt != NULL) {
   1551      1.1  itojun 		switch (*showopt) {
   1552      1.1  itojun 		case 'A':
   1553      1.1  itojun 			pfctl_show_anchors(dev, opts, anchorname);
   1554      1.1  itojun 			break;
   1555      1.1  itojun 		case 'r':
   1556      1.1  itojun 			pfctl_load_fingerprints(dev, opts);
   1557  1.1.1.2    yamt 			pfctl_show_rules(dev, opts, 0, anchorname);
   1558      1.1  itojun 			break;
   1559      1.1  itojun 		case 'l':
   1560      1.1  itojun 			pfctl_load_fingerprints(dev, opts);
   1561  1.1.1.2    yamt 			pfctl_show_rules(dev, opts, 1, anchorname);
   1562      1.1  itojun 			break;
   1563      1.1  itojun 		case 'n':
   1564      1.1  itojun 			pfctl_load_fingerprints(dev, opts);
   1565  1.1.1.2    yamt 			pfctl_show_nat(dev, opts, anchorname);
   1566      1.1  itojun 			break;
   1567      1.1  itojun 		case 'q':
   1568      1.1  itojun 			pfctl_show_altq(dev, ifaceopt, opts,
   1569      1.1  itojun 			    opts & PF_OPT_VERBOSE2);
   1570      1.1  itojun 			break;
   1571      1.1  itojun 		case 's':
   1572      1.1  itojun 			pfctl_show_states(dev, ifaceopt, opts);
   1573      1.1  itojun 			break;
   1574      1.1  itojun 		case 'S':
   1575      1.1  itojun 			pfctl_show_src_nodes(dev, opts);
   1576      1.1  itojun 			break;
   1577      1.1  itojun 		case 'i':
   1578      1.1  itojun 			pfctl_show_status(dev, opts);
   1579      1.1  itojun 			break;
   1580      1.1  itojun 		case 't':
   1581      1.1  itojun 			pfctl_show_timeouts(dev, opts);
   1582      1.1  itojun 			break;
   1583      1.1  itojun 		case 'm':
   1584      1.1  itojun 			pfctl_show_limits(dev, opts);
   1585      1.1  itojun 			break;
   1586      1.1  itojun 		case 'a':
   1587      1.1  itojun 			opts |= PF_OPT_SHOWALL;
   1588      1.1  itojun 			pfctl_load_fingerprints(dev, opts);
   1589      1.1  itojun 
   1590  1.1.1.2    yamt 			pfctl_show_nat(dev, opts, anchorname);
   1591  1.1.1.2    yamt 			pfctl_show_rules(dev, opts, 0, anchorname);
   1592      1.1  itojun 			pfctl_show_altq(dev, ifaceopt, opts, 0);
   1593      1.1  itojun 			pfctl_show_states(dev, ifaceopt, opts);
   1594      1.1  itojun 			pfctl_show_src_nodes(dev, opts);
   1595      1.1  itojun 			pfctl_show_status(dev, opts);
   1596  1.1.1.2    yamt 			pfctl_show_rules(dev, opts, 1, anchorname);
   1597      1.1  itojun 			pfctl_show_timeouts(dev, opts);
   1598      1.1  itojun 			pfctl_show_limits(dev, opts);
   1599  1.1.1.2    yamt 			pfctl_show_tables(anchorname, opts);
   1600      1.1  itojun 			pfctl_show_fingerprints(opts);
   1601      1.1  itojun 			break;
   1602      1.1  itojun 		case 'T':
   1603  1.1.1.2    yamt 			pfctl_show_tables(anchorname, opts);
   1604      1.1  itojun 			break;
   1605      1.1  itojun 		case 'o':
   1606      1.1  itojun 			pfctl_load_fingerprints(dev, opts);
   1607      1.1  itojun 			pfctl_show_fingerprints(opts);
   1608      1.1  itojun 			break;
   1609      1.1  itojun 		case 'I':
   1610      1.1  itojun 			pfctl_show_ifaces(ifaceopt, opts);
   1611      1.1  itojun 			break;
   1612      1.1  itojun 		}
   1613      1.1  itojun 	}
   1614      1.1  itojun 
   1615      1.1  itojun 	if (clearopt != NULL) {
   1616      1.1  itojun 		switch (*clearopt) {
   1617      1.1  itojun 		case 'r':
   1618  1.1.1.2    yamt 			pfctl_clear_rules(dev, opts, anchorname);
   1619      1.1  itojun 			break;
   1620      1.1  itojun 		case 'n':
   1621  1.1.1.2    yamt 			pfctl_clear_nat(dev, opts, anchorname);
   1622      1.1  itojun 			break;
   1623      1.1  itojun 		case 'q':
   1624      1.1  itojun 			pfctl_clear_altq(dev, opts);
   1625      1.1  itojun 			break;
   1626      1.1  itojun 		case 's':
   1627      1.1  itojun 			pfctl_clear_states(dev, ifaceopt, opts);
   1628      1.1  itojun 			break;
   1629      1.1  itojun 		case 'S':
   1630      1.1  itojun 			pfctl_clear_src_nodes(dev, opts);
   1631      1.1  itojun 			break;
   1632      1.1  itojun 		case 'i':
   1633      1.1  itojun 			pfctl_clear_stats(dev, opts);
   1634      1.1  itojun 			break;
   1635      1.1  itojun 		case 'a':
   1636  1.1.1.2    yamt 			pfctl_clear_rules(dev, opts, anchorname);
   1637  1.1.1.2    yamt 			pfctl_clear_nat(dev, opts, anchorname);
   1638  1.1.1.2    yamt 			pfctl_clear_tables(anchorname, opts);
   1639  1.1.1.2    yamt 			if (!*anchorname) {
   1640      1.1  itojun 				pfctl_clear_altq(dev, opts);
   1641      1.1  itojun 				pfctl_clear_states(dev, ifaceopt, opts);
   1642      1.1  itojun 				pfctl_clear_src_nodes(dev, opts);
   1643      1.1  itojun 				pfctl_clear_stats(dev, opts);
   1644      1.1  itojun 				pfctl_clear_fingerprints(dev, opts);
   1645      1.1  itojun 			}
   1646      1.1  itojun 			break;
   1647      1.1  itojun 		case 'o':
   1648      1.1  itojun 			pfctl_clear_fingerprints(dev, opts);
   1649      1.1  itojun 			break;
   1650      1.1  itojun 		case 'T':
   1651  1.1.1.2    yamt 			pfctl_clear_tables(anchorname, opts);
   1652      1.1  itojun 			break;
   1653      1.1  itojun 		}
   1654      1.1  itojun 	}
   1655      1.1  itojun 	if (state_killers)
   1656      1.1  itojun 		pfctl_kill_states(dev, ifaceopt, opts);
   1657      1.1  itojun 
   1658      1.1  itojun 	if (tblcmdopt != NULL) {
   1659      1.1  itojun 		error = pfctl_command_tables(argc, argv, tableopt,
   1660  1.1.1.2    yamt 		    tblcmdopt, rulesopt, anchorname, opts);
   1661      1.1  itojun 		rulesopt = NULL;
   1662      1.1  itojun 	}
   1663      1.1  itojun 
   1664      1.1  itojun 	if (rulesopt != NULL)
   1665      1.1  itojun 		if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE))
   1666      1.1  itojun 			error = 1;
   1667      1.1  itojun 
   1668      1.1  itojun 	if (rulesopt != NULL) {
   1669  1.1.1.2    yamt 		if (pfctl_rules(dev, rulesopt, opts, anchorname, NULL))
   1670      1.1  itojun 			error = 1;
   1671      1.1  itojun 		else if (!(opts & PF_OPT_NOACTION) &&
   1672      1.1  itojun 		    (loadopt & PFCTL_FLAG_TABLE))
   1673      1.1  itojun 			warn_namespace_collision(NULL);
   1674      1.1  itojun 	}
   1675      1.1  itojun 
   1676      1.1  itojun 	if (opts & PF_OPT_ENABLE)
   1677      1.1  itojun 		if (pfctl_enable(dev, opts))
   1678      1.1  itojun 			error = 1;
   1679      1.1  itojun 
   1680      1.1  itojun 	if (debugopt != NULL) {
   1681      1.1  itojun 		switch (*debugopt) {
   1682      1.1  itojun 		case 'n':
   1683      1.1  itojun 			pfctl_debug(dev, PF_DEBUG_NONE, opts);
   1684      1.1  itojun 			break;
   1685      1.1  itojun 		case 'u':
   1686      1.1  itojun 			pfctl_debug(dev, PF_DEBUG_URGENT, opts);
   1687      1.1  itojun 			break;
   1688      1.1  itojun 		case 'm':
   1689      1.1  itojun 			pfctl_debug(dev, PF_DEBUG_MISC, opts);
   1690      1.1  itojun 			break;
   1691      1.1  itojun 		case 'l':
   1692      1.1  itojun 			pfctl_debug(dev, PF_DEBUG_NOISY, opts);
   1693      1.1  itojun 			break;
   1694      1.1  itojun 		}
   1695      1.1  itojun 	}
   1696      1.1  itojun 
   1697      1.1  itojun 	if (opts & PF_OPT_CLRRULECTRS) {
   1698      1.1  itojun 		if (pfctl_clear_rule_counters(dev, opts))
   1699      1.1  itojun 			error = 1;
   1700      1.1  itojun 	}
   1701      1.1  itojun 	exit(error);
   1702      1.1  itojun }
   1703