xref: /freebsd-src/sbin/pfctl/pfctl.c (revision 0972294ef034d92f59857b8312dd2e1e3a7adc9c)
13b3a8eb9SGleb Smirnoff /*	$OpenBSD: pfctl.c,v 1.278 2008/08/31 20:18:17 jmc Exp $ */
23b3a8eb9SGleb Smirnoff 
31de7b4b8SPedro F. Giffuni /*-
41de7b4b8SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause
51de7b4b8SPedro F. Giffuni  *
63b3a8eb9SGleb Smirnoff  * Copyright (c) 2001 Daniel Hartmeier
73b3a8eb9SGleb Smirnoff  * Copyright (c) 2002,2003 Henning Brauer
83b3a8eb9SGleb Smirnoff  * All rights reserved.
93b3a8eb9SGleb Smirnoff  *
103b3a8eb9SGleb Smirnoff  * Redistribution and use in source and binary forms, with or without
113b3a8eb9SGleb Smirnoff  * modification, are permitted provided that the following conditions
123b3a8eb9SGleb Smirnoff  * are met:
133b3a8eb9SGleb Smirnoff  *
143b3a8eb9SGleb Smirnoff  *    - Redistributions of source code must retain the above copyright
153b3a8eb9SGleb Smirnoff  *      notice, this list of conditions and the following disclaimer.
163b3a8eb9SGleb Smirnoff  *    - Redistributions in binary form must reproduce the above
173b3a8eb9SGleb Smirnoff  *      copyright notice, this list of conditions and the following
183b3a8eb9SGleb Smirnoff  *      disclaimer in the documentation and/or other materials provided
193b3a8eb9SGleb Smirnoff  *      with the distribution.
203b3a8eb9SGleb Smirnoff  *
213b3a8eb9SGleb Smirnoff  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
223b3a8eb9SGleb Smirnoff  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
233b3a8eb9SGleb Smirnoff  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
243b3a8eb9SGleb Smirnoff  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
253b3a8eb9SGleb Smirnoff  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
263b3a8eb9SGleb Smirnoff  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
273b3a8eb9SGleb Smirnoff  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
283b3a8eb9SGleb Smirnoff  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
293b3a8eb9SGleb Smirnoff  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
303b3a8eb9SGleb Smirnoff  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
313b3a8eb9SGleb Smirnoff  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
323b3a8eb9SGleb Smirnoff  * POSSIBILITY OF SUCH DAMAGE.
333b3a8eb9SGleb Smirnoff  *
343b3a8eb9SGleb Smirnoff  */
353b3a8eb9SGleb Smirnoff 
363b3a8eb9SGleb Smirnoff #include <sys/cdefs.h>
37249cc75fSPatrick Kelsey #define PFIOC_USE_LATEST
38249cc75fSPatrick Kelsey 
393b3a8eb9SGleb Smirnoff #include <sys/types.h>
403b3a8eb9SGleb Smirnoff #include <sys/ioctl.h>
413b3a8eb9SGleb Smirnoff #include <sys/socket.h>
423b3a8eb9SGleb Smirnoff #include <sys/stat.h>
433b3a8eb9SGleb Smirnoff #include <sys/endian.h>
443b3a8eb9SGleb Smirnoff 
453b3a8eb9SGleb Smirnoff #include <net/if.h>
463b3a8eb9SGleb Smirnoff #include <netinet/in.h>
473b3a8eb9SGleb Smirnoff #include <net/pfvar.h>
483b3a8eb9SGleb Smirnoff #include <arpa/inet.h>
49772e66a6SGleb Smirnoff #include <net/altq/altq.h>
503b3a8eb9SGleb Smirnoff 
513b3a8eb9SGleb Smirnoff #include <err.h>
523b3a8eb9SGleb Smirnoff #include <errno.h>
533b3a8eb9SGleb Smirnoff #include <fcntl.h>
540d71f9f3SKristof Provost #include <libpfctl.h>
553b3a8eb9SGleb Smirnoff #include <limits.h>
563b3a8eb9SGleb Smirnoff #include <netdb.h>
575a9ab487SGleb Smirnoff #include <stdint.h>
583b3a8eb9SGleb Smirnoff #include <stdio.h>
593b3a8eb9SGleb Smirnoff #include <stdlib.h>
603b3a8eb9SGleb Smirnoff #include <string.h>
613b3a8eb9SGleb Smirnoff #include <unistd.h>
623b3a8eb9SGleb Smirnoff 
633b3a8eb9SGleb Smirnoff #include "pfctl_parser.h"
643b3a8eb9SGleb Smirnoff #include "pfctl.h"
653b3a8eb9SGleb Smirnoff 
663b3a8eb9SGleb Smirnoff void	 usage(void);
673b3a8eb9SGleb Smirnoff int	 pfctl_enable(int, int);
683b3a8eb9SGleb Smirnoff int	 pfctl_disable(int, int);
699dbbe68bSKristof Provost int	 pfctl_clear_stats(struct pfctl_handle *, int);
70c5e10565SKristof Provost int	 pfctl_get_skip_ifaces(void);
71c5e10565SKristof Provost int	 pfctl_check_skip_ifaces(char *);
727a831fecSKristof Provost int	 pfctl_adjust_skip_ifaces(struct pfctl *);
733b3a8eb9SGleb Smirnoff int	 pfctl_clear_interface_flags(int, int);
74f0c334e4SKristof Provost int	 pfctl_flush_eth_rules(int, int, char *);
75f0c334e4SKristof Provost int	 pfctl_flush_rules(int, int, char *);
76f0c334e4SKristof Provost int	 pfctl_flush_nat(int, int, char *);
773b3a8eb9SGleb Smirnoff int	 pfctl_clear_altq(int, int);
783b3a8eb9SGleb Smirnoff int	 pfctl_clear_src_nodes(int, int);
7953714a58SKristof Provost int	 pfctl_clear_iface_states(int, const char *, int);
803b3a8eb9SGleb Smirnoff void	 pfctl_addrprefix(char *, struct pf_addr *);
813b3a8eb9SGleb Smirnoff int	 pfctl_kill_src_nodes(int, const char *, int);
823b3a8eb9SGleb Smirnoff int	 pfctl_net_kill_states(int, const char *, int);
83abbcba9cSKristof Provost int	 pfctl_gateway_kill_states(int, const char *, int);
843b3a8eb9SGleb Smirnoff int	 pfctl_label_kill_states(int, const char *, int);
853b3a8eb9SGleb Smirnoff int	 pfctl_id_kill_states(int, const char *, int);
863b3a8eb9SGleb Smirnoff void	 pfctl_init_options(struct pfctl *);
873b3a8eb9SGleb Smirnoff int	 pfctl_load_options(struct pfctl *);
883b3a8eb9SGleb Smirnoff int	 pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
893b3a8eb9SGleb Smirnoff int	 pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int);
903b3a8eb9SGleb Smirnoff int	 pfctl_load_debug(struct pfctl *, unsigned int);
913b3a8eb9SGleb Smirnoff int	 pfctl_load_logif(struct pfctl *, char *);
929a5e33beSKristof Provost int	 pfctl_load_hostid(struct pfctl *, u_int32_t);
9339282ef3SKajetan Staszkiewicz int	 pfctl_load_reassembly(struct pfctl *, u_int32_t);
94c69121c4SKristof Provost int	 pfctl_load_syncookies(struct pfctl *, u_int8_t);
95600bd6ceSKurosawa Takahiro int	 pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int,
96aa69fdf1SKristof Provost 	    char *, int);
972b29ceb8SKristof Provost void	 pfctl_print_eth_rule_counters(struct pfctl_eth_rule *, int);
98e9eb0941SKristof Provost void	 pfctl_print_rule_counters(struct pfctl_rule *, int);
99cfa1a130SKristof Provost int	 pfctl_show_eth_rules(int, char *, int, enum pfctl_show, char *, int, int);
100585a5ed0SKristof Provost int	 pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int);
1018ddd0359SKristof Provost int	 pfctl_show_nat(int, char *, int, char *, int, int);
1023b3a8eb9SGleb Smirnoff int	 pfctl_show_src_nodes(int, int);
1033b3a8eb9SGleb Smirnoff int	 pfctl_show_states(int, const char *, int);
1043b3a8eb9SGleb Smirnoff int	 pfctl_show_status(int, int);
105fa1d4439SKristof Provost int	 pfctl_show_running(int);
1063b3a8eb9SGleb Smirnoff int	 pfctl_show_timeouts(int, int);
1073b3a8eb9SGleb Smirnoff int	 pfctl_show_limits(int, int);
1083b3a8eb9SGleb Smirnoff void	 pfctl_debug(int, u_int32_t, int);
1093b3a8eb9SGleb Smirnoff int	 pfctl_test_altqsupport(int, int);
1103b3a8eb9SGleb Smirnoff int	 pfctl_show_anchors(int, int, char *);
1119bb06778SKristof Provost int	 pfctl_show_eth_anchors(int, int, char *);
112c5131afeSKristof Provost int	 pfctl_ruleset_trans(struct pfctl *, char *, struct pfctl_anchor *, bool);
113c5131afeSKristof Provost int	 pfctl_eth_ruleset_trans(struct pfctl *, char *,
114c5131afeSKristof Provost 	    struct pfctl_eth_anchor *);
115c5131afeSKristof Provost int	 pfctl_load_eth_ruleset(struct pfctl *, char *,
116c5131afeSKristof Provost 	    struct pfctl_eth_ruleset *, int);
117c5131afeSKristof Provost int	 pfctl_load_eth_rule(struct pfctl *, char *, struct pfctl_eth_rule *,
118c5131afeSKristof Provost 	    int);
1193b3a8eb9SGleb Smirnoff int	 pfctl_load_ruleset(struct pfctl *, char *,
120e9eb0941SKristof Provost 		struct pfctl_ruleset *, int, int);
121e9eb0941SKristof Provost int	 pfctl_load_rule(struct pfctl *, char *, struct pfctl_rule *, int);
12272a3cf0fSKristof Provost const char	*pfctl_lookup_option(char *, const char * const *);
1233b3a8eb9SGleb Smirnoff 
124e9eb0941SKristof Provost static struct pfctl_anchor_global	 pf_anchors;
125c5131afeSKristof Provost struct pfctl_anchor	 pf_main_anchor;
126c5131afeSKristof Provost struct pfctl_eth_anchor	 pf_eth_main_anchor;
127c5e10565SKristof Provost static struct pfr_buffer skip_b;
1283b3a8eb9SGleb Smirnoff 
12913cfafabSKristof Provost static const char	*clearopt;
13013cfafabSKristof Provost static char		*rulesopt;
13113cfafabSKristof Provost static const char	*showopt;
13213cfafabSKristof Provost static const char	*debugopt;
13313cfafabSKristof Provost static char		*anchoropt;
13413cfafabSKristof Provost static const char	*optiopt = NULL;
13566cacc14SKristof Provost static const char	*pf_device = PF_DEVICE;
13613cfafabSKristof Provost static char		*ifaceopt;
13713cfafabSKristof Provost static char		*tableopt;
13813cfafabSKristof Provost static const char	*tblcmdopt;
13913cfafabSKristof Provost static int		 src_node_killers;
14013cfafabSKristof Provost static char		*src_node_kill[2];
14113cfafabSKristof Provost static int		 state_killers;
14213cfafabSKristof Provost static char		*state_kill[2];
1433b3a8eb9SGleb Smirnoff int			 loadopt;
1443b3a8eb9SGleb Smirnoff int			 altqsupport;
1453b3a8eb9SGleb Smirnoff 
1463b3a8eb9SGleb Smirnoff int			 dev = -1;
14766cacc14SKristof Provost struct pfctl_handle	*pfh = NULL;
14813cfafabSKristof Provost static int		 first_title = 1;
14913cfafabSKristof Provost static int		 labels = 0;
1503b3a8eb9SGleb Smirnoff 
1513b3a8eb9SGleb Smirnoff #define INDENT(d, o)	do {						\
1523b3a8eb9SGleb Smirnoff 				if (o) {				\
1533b3a8eb9SGleb Smirnoff 					int i;				\
1543b3a8eb9SGleb Smirnoff 					for (i=0; i < d; i++)		\
1553b3a8eb9SGleb Smirnoff 						printf("  ");		\
1563b3a8eb9SGleb Smirnoff 				}					\
1573b3a8eb9SGleb Smirnoff 			} while (0);					\
1583b3a8eb9SGleb Smirnoff 
1593b3a8eb9SGleb Smirnoff 
1603b3a8eb9SGleb Smirnoff static const struct {
1613b3a8eb9SGleb Smirnoff 	const char	*name;
1623b3a8eb9SGleb Smirnoff 	int		index;
1633b3a8eb9SGleb Smirnoff } pf_limits[] = {
1643b3a8eb9SGleb Smirnoff 	{ "states",		PF_LIMIT_STATES },
1653b3a8eb9SGleb Smirnoff 	{ "src-nodes",		PF_LIMIT_SRC_NODES },
1663b3a8eb9SGleb Smirnoff 	{ "frags",		PF_LIMIT_FRAGS },
1673b3a8eb9SGleb Smirnoff 	{ "table-entries",	PF_LIMIT_TABLE_ENTRIES },
1683b3a8eb9SGleb Smirnoff 	{ NULL,			0 }
1693b3a8eb9SGleb Smirnoff };
1703b3a8eb9SGleb Smirnoff 
1713b3a8eb9SGleb Smirnoff struct pf_hint {
1723b3a8eb9SGleb Smirnoff 	const char	*name;
1733b3a8eb9SGleb Smirnoff 	int		timeout;
1743b3a8eb9SGleb Smirnoff };
1753b3a8eb9SGleb Smirnoff static const struct pf_hint pf_hint_normal[] = {
1763b3a8eb9SGleb Smirnoff 	{ "tcp.first",		2 * 60 },
1773b3a8eb9SGleb Smirnoff 	{ "tcp.opening",	30 },
1783b3a8eb9SGleb Smirnoff 	{ "tcp.established",	24 * 60 * 60 },
1793b3a8eb9SGleb Smirnoff 	{ "tcp.closing",	15 * 60 },
1803b3a8eb9SGleb Smirnoff 	{ "tcp.finwait",	45 },
1813b3a8eb9SGleb Smirnoff 	{ "tcp.closed",		90 },
1823b3a8eb9SGleb Smirnoff 	{ "tcp.tsdiff",		30 },
1833b3a8eb9SGleb Smirnoff 	{ NULL,			0 }
1843b3a8eb9SGleb Smirnoff };
1853b3a8eb9SGleb Smirnoff static const struct pf_hint pf_hint_satellite[] = {
1863b3a8eb9SGleb Smirnoff 	{ "tcp.first",		3 * 60 },
1873b3a8eb9SGleb Smirnoff 	{ "tcp.opening",	30 + 5 },
1883b3a8eb9SGleb Smirnoff 	{ "tcp.established",	24 * 60 * 60 },
1893b3a8eb9SGleb Smirnoff 	{ "tcp.closing",	15 * 60 + 5 },
1903b3a8eb9SGleb Smirnoff 	{ "tcp.finwait",	45 + 5 },
1913b3a8eb9SGleb Smirnoff 	{ "tcp.closed",		90 + 5 },
1923b3a8eb9SGleb Smirnoff 	{ "tcp.tsdiff",		60 },
1933b3a8eb9SGleb Smirnoff 	{ NULL,			0 }
1943b3a8eb9SGleb Smirnoff };
1953b3a8eb9SGleb Smirnoff static const struct pf_hint pf_hint_conservative[] = {
1963b3a8eb9SGleb Smirnoff 	{ "tcp.first",		60 * 60 },
1973b3a8eb9SGleb Smirnoff 	{ "tcp.opening",	15 * 60 },
1983b3a8eb9SGleb Smirnoff 	{ "tcp.established",	5 * 24 * 60 * 60 },
1993b3a8eb9SGleb Smirnoff 	{ "tcp.closing",	60 * 60 },
2003b3a8eb9SGleb Smirnoff 	{ "tcp.finwait",	10 * 60 },
2013b3a8eb9SGleb Smirnoff 	{ "tcp.closed",		3 * 60 },
2023b3a8eb9SGleb Smirnoff 	{ "tcp.tsdiff",		60 },
2033b3a8eb9SGleb Smirnoff 	{ NULL,			0 }
2043b3a8eb9SGleb Smirnoff };
2053b3a8eb9SGleb Smirnoff static const struct pf_hint pf_hint_aggressive[] = {
2063b3a8eb9SGleb Smirnoff 	{ "tcp.first",		30 },
2073b3a8eb9SGleb Smirnoff 	{ "tcp.opening",	5 },
2083b3a8eb9SGleb Smirnoff 	{ "tcp.established",	5 * 60 * 60 },
2093b3a8eb9SGleb Smirnoff 	{ "tcp.closing",	60 },
2103b3a8eb9SGleb Smirnoff 	{ "tcp.finwait",	30 },
2113b3a8eb9SGleb Smirnoff 	{ "tcp.closed",		30 },
2123b3a8eb9SGleb Smirnoff 	{ "tcp.tsdiff",		10 },
2133b3a8eb9SGleb Smirnoff 	{ NULL,			0 }
2143b3a8eb9SGleb Smirnoff };
2153b3a8eb9SGleb Smirnoff 
2163b3a8eb9SGleb Smirnoff static const struct {
2173b3a8eb9SGleb Smirnoff 	const char *name;
2183b3a8eb9SGleb Smirnoff 	const struct pf_hint *hint;
2193b3a8eb9SGleb Smirnoff } pf_hints[] = {
2203b3a8eb9SGleb Smirnoff 	{ "normal",		pf_hint_normal },
2213b3a8eb9SGleb Smirnoff 	{ "satellite",		pf_hint_satellite },
2223b3a8eb9SGleb Smirnoff 	{ "high-latency",	pf_hint_satellite },
2233b3a8eb9SGleb Smirnoff 	{ "conservative",	pf_hint_conservative },
2243b3a8eb9SGleb Smirnoff 	{ "aggressive",		pf_hint_aggressive },
2253b3a8eb9SGleb Smirnoff 	{ NULL,			NULL }
2263b3a8eb9SGleb Smirnoff };
2273b3a8eb9SGleb Smirnoff 
22872a3cf0fSKristof Provost static const char * const clearopt_list[] = {
2293b3a8eb9SGleb Smirnoff 	"nat", "queue", "rules", "Sources",
2306ea1c3cfSKristof Provost 	"states", "info", "Tables", "osfp", "all",
2316ea1c3cfSKristof Provost 	"ethernet", NULL
2323b3a8eb9SGleb Smirnoff };
2333b3a8eb9SGleb Smirnoff 
23472a3cf0fSKristof Provost static const char * const showopt_list[] = {
2352b29ceb8SKristof Provost 	"ether", "nat", "queue", "rules", "Anchors", "Sources", "states",
2362b29ceb8SKristof Provost 	"info", "Interfaces", "labels", "timeouts", "memory", "Tables",
237a7191e5dSKristof Provost 	"osfp", "Running", "all", "creatorids", NULL
2383b3a8eb9SGleb Smirnoff };
2393b3a8eb9SGleb Smirnoff 
24072a3cf0fSKristof Provost static const char * const tblcmdopt_list[] = {
2413b3a8eb9SGleb Smirnoff 	"kill", "flush", "add", "delete", "load", "replace", "show",
2425b59b0c6SLeonid Evdokimov 	"test", "zero", "expire", "reset", NULL
2433b3a8eb9SGleb Smirnoff };
2443b3a8eb9SGleb Smirnoff 
24572a3cf0fSKristof Provost static const char * const debugopt_list[] = {
2463b3a8eb9SGleb Smirnoff 	"none", "urgent", "misc", "loud", NULL
2473b3a8eb9SGleb Smirnoff };
2483b3a8eb9SGleb Smirnoff 
24972a3cf0fSKristof Provost static const char * const optiopt_list[] = {
2503b3a8eb9SGleb Smirnoff 	"none", "basic", "profile", NULL
2513b3a8eb9SGleb Smirnoff };
2523b3a8eb9SGleb Smirnoff 
2533b3a8eb9SGleb Smirnoff void
2543b3a8eb9SGleb Smirnoff usage(void)
2553b3a8eb9SGleb Smirnoff {
2563b3a8eb9SGleb Smirnoff 	extern char *__progname;
2573b3a8eb9SGleb Smirnoff 
2580c46447bSGleb Smirnoff 	fprintf(stderr,
25993abcf17SKristof Provost "usage: %s [-AdeghMmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n"
2600c46447bSGleb Smirnoff 	"\t[-f file] [-i interface] [-K host | network]\n"
261abbcba9cSKristof Provost 	"\t[-k host | network | gateway | label | id] [-o level] [-p device]\n"
2620c46447bSGleb Smirnoff 	"\t[-s modifier] [-t table -T command [address ...]] [-x level]\n",
2630c46447bSGleb Smirnoff 	    __progname);
2640c46447bSGleb Smirnoff 
2653b3a8eb9SGleb Smirnoff 	exit(1);
2663b3a8eb9SGleb Smirnoff }
2673b3a8eb9SGleb Smirnoff 
268858937beSMateusz Guzik /*
269858937beSMateusz Guzik  * Cache protocol number to name translations.
270858937beSMateusz Guzik  *
271858937beSMateusz Guzik  * Translation is performed a lot e.g., when dumping states and
272858937beSMateusz Guzik  * getprotobynumber is incredibly expensive.
273858937beSMateusz Guzik  *
274858937beSMateusz Guzik  * Note from the getprotobynumber(3) manpage:
275858937beSMateusz Guzik  * <quote>
276858937beSMateusz Guzik  * These functions use a thread-specific data space; if the data is needed
277858937beSMateusz Guzik  * for future use, it should be copied before any subsequent calls overwrite
278858937beSMateusz Guzik  * it.  Only the Internet protocols are currently understood.
279858937beSMateusz Guzik  * </quote>
280858937beSMateusz Guzik  *
281858937beSMateusz Guzik  * Consequently we only cache the name and strdup it for safety.
282858937beSMateusz Guzik  *
283858937beSMateusz Guzik  * At the time of writing this comment the last entry in /etc/protocols is:
284858937beSMateusz Guzik  * divert  258     DIVERT          # Divert pseudo-protocol [non IANA]
285858937beSMateusz Guzik  */
286858937beSMateusz Guzik const char *
287858937beSMateusz Guzik pfctl_proto2name(int proto)
288858937beSMateusz Guzik {
289858937beSMateusz Guzik 	static const char *pfctl_proto_cache[259];
290858937beSMateusz Guzik 	struct protoent *p;
291858937beSMateusz Guzik 
292858937beSMateusz Guzik 	if (proto >= nitems(pfctl_proto_cache)) {
293858937beSMateusz Guzik 		p = getprotobynumber(proto);
294858937beSMateusz Guzik 		if (p == NULL) {
295858937beSMateusz Guzik 			return (NULL);
296858937beSMateusz Guzik 		}
297858937beSMateusz Guzik 		return (p->p_name);
298858937beSMateusz Guzik 	}
299858937beSMateusz Guzik 
300858937beSMateusz Guzik 	if (pfctl_proto_cache[proto] == NULL) {
301858937beSMateusz Guzik 		p = getprotobynumber(proto);
302858937beSMateusz Guzik 		if (p == NULL) {
303858937beSMateusz Guzik 			return (NULL);
304858937beSMateusz Guzik 		}
305858937beSMateusz Guzik 		pfctl_proto_cache[proto] = strdup(p->p_name);
306858937beSMateusz Guzik 	}
307858937beSMateusz Guzik 
308858937beSMateusz Guzik 	return (pfctl_proto_cache[proto]);
309858937beSMateusz Guzik }
310858937beSMateusz Guzik 
3113b3a8eb9SGleb Smirnoff int
3123b3a8eb9SGleb Smirnoff pfctl_enable(int dev, int opts)
3133b3a8eb9SGleb Smirnoff {
31481647eb6SKristof Provost 	int ret;
31581647eb6SKristof Provost 
31666cacc14SKristof Provost 	if ((ret = pfctl_startstop(pfh, 1)) != 0) {
31781647eb6SKristof Provost 		if (ret == EEXIST)
3183b3a8eb9SGleb Smirnoff 			errx(1, "pf already enabled");
31981647eb6SKristof Provost 		else if (ret == ESRCH)
3203b3a8eb9SGleb Smirnoff 			errx(1, "pfil registeration failed");
3213b3a8eb9SGleb Smirnoff 		else
322375aaa29SKristof Provost 			errc(1, ret, "DIOCSTART");
3233b3a8eb9SGleb Smirnoff 	}
3243b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0)
3253b3a8eb9SGleb Smirnoff 		fprintf(stderr, "pf enabled\n");
3263b3a8eb9SGleb Smirnoff 
3273b3a8eb9SGleb Smirnoff 	if (altqsupport && ioctl(dev, DIOCSTARTALTQ))
3283b3a8eb9SGleb Smirnoff 		if (errno != EEXIST)
3293b3a8eb9SGleb Smirnoff 			err(1, "DIOCSTARTALTQ");
3303b3a8eb9SGleb Smirnoff 
3313b3a8eb9SGleb Smirnoff 	return (0);
3323b3a8eb9SGleb Smirnoff }
3333b3a8eb9SGleb Smirnoff 
3343b3a8eb9SGleb Smirnoff int
3353b3a8eb9SGleb Smirnoff pfctl_disable(int dev, int opts)
3363b3a8eb9SGleb Smirnoff {
33781647eb6SKristof Provost 	int ret;
33881647eb6SKristof Provost 
33966cacc14SKristof Provost 	if ((ret = pfctl_startstop(pfh, 0)) != 0) {
34081647eb6SKristof Provost 		if (ret == ENOENT)
3413b3a8eb9SGleb Smirnoff 			errx(1, "pf not enabled");
3423b3a8eb9SGleb Smirnoff 		else
343375aaa29SKristof Provost 			errc(1, ret, "DIOCSTOP");
3443b3a8eb9SGleb Smirnoff 	}
3453b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0)
3463b3a8eb9SGleb Smirnoff 		fprintf(stderr, "pf disabled\n");
3473b3a8eb9SGleb Smirnoff 
3483b3a8eb9SGleb Smirnoff 	if (altqsupport && ioctl(dev, DIOCSTOPALTQ))
3493b3a8eb9SGleb Smirnoff 			if (errno != ENOENT)
3503b3a8eb9SGleb Smirnoff 				err(1, "DIOCSTOPALTQ");
3513b3a8eb9SGleb Smirnoff 
3523b3a8eb9SGleb Smirnoff 	return (0);
3533b3a8eb9SGleb Smirnoff }
3543b3a8eb9SGleb Smirnoff 
3553b3a8eb9SGleb Smirnoff int
3569dbbe68bSKristof Provost pfctl_clear_stats(struct pfctl_handle *h, int opts)
3573b3a8eb9SGleb Smirnoff {
358375aaa29SKristof Provost 	int ret;
359375aaa29SKristof Provost 	if ((ret = pfctl_clear_status(h)) != 0)
360375aaa29SKristof Provost 		errc(1, ret, "DIOCCLRSTATUS");
3613b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0)
3623b3a8eb9SGleb Smirnoff 		fprintf(stderr, "pf: statistics cleared\n");
3633b3a8eb9SGleb Smirnoff 	return (0);
3643b3a8eb9SGleb Smirnoff }
3653b3a8eb9SGleb Smirnoff 
3663b3a8eb9SGleb Smirnoff int
367c5e10565SKristof Provost pfctl_get_skip_ifaces(void)
368c5e10565SKristof Provost {
369c5e10565SKristof Provost 	bzero(&skip_b, sizeof(skip_b));
370c5e10565SKristof Provost 	skip_b.pfrb_type = PFRB_IFACES;
371c5e10565SKristof Provost 	for (;;) {
372c5e10565SKristof Provost 		pfr_buf_grow(&skip_b, skip_b.pfrb_size);
373c5e10565SKristof Provost 		skip_b.pfrb_size = skip_b.pfrb_msize;
374c5e10565SKristof Provost 		if (pfi_get_ifaces(NULL, skip_b.pfrb_caddr, &skip_b.pfrb_size))
375c5e10565SKristof Provost 			err(1, "pfi_get_ifaces");
376c5e10565SKristof Provost 		if (skip_b.pfrb_size <= skip_b.pfrb_msize)
377c5e10565SKristof Provost 			break;
378c5e10565SKristof Provost 	}
379c5e10565SKristof Provost 	return (0);
380c5e10565SKristof Provost }
381c5e10565SKristof Provost 
382c5e10565SKristof Provost int
383c5e10565SKristof Provost pfctl_check_skip_ifaces(char *ifname)
384c5e10565SKristof Provost {
385c5e10565SKristof Provost 	struct pfi_kif		*p;
3867a831fecSKristof Provost 	struct node_host	*h = NULL, *n = NULL;
387c5e10565SKristof Provost 
3887a831fecSKristof Provost 	PFRB_FOREACH(p, &skip_b) {
3897a831fecSKristof Provost 		if (!strcmp(ifname, p->pfik_name) &&
3907a831fecSKristof Provost 		    (p->pfik_flags & PFI_IFLAG_SKIP))
391c5e10565SKristof Provost 			p->pfik_flags &= ~PFI_IFLAG_SKIP;
3927a831fecSKristof Provost 		if (!strcmp(ifname, p->pfik_name) && p->pfik_group != NULL) {
3937a831fecSKristof Provost 			if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL)
3947a831fecSKristof Provost 				continue;
3957a831fecSKristof Provost 
3967a831fecSKristof Provost 			for (n = h; n != NULL; n = n->next) {
3977a831fecSKristof Provost 				if (strncmp(p->pfik_name, ifname, IFNAMSIZ))
3987a831fecSKristof Provost 					continue;
3997a831fecSKristof Provost 
4007a831fecSKristof Provost 				p->pfik_flags &= ~PFI_IFLAG_SKIP;
4017a831fecSKristof Provost 			}
4027a831fecSKristof Provost 		}
4037a831fecSKristof Provost 	}
404c5e10565SKristof Provost 	return (0);
405c5e10565SKristof Provost }
406c5e10565SKristof Provost 
4077a831fecSKristof Provost int
4087a831fecSKristof Provost pfctl_adjust_skip_ifaces(struct pfctl *pf)
4097a831fecSKristof Provost {
4107a831fecSKristof Provost 	struct pfi_kif		*p, *pp;
4117a831fecSKristof Provost 	struct node_host	*h = NULL, *n = NULL;
4127a831fecSKristof Provost 
4137a831fecSKristof Provost 	PFRB_FOREACH(p, &skip_b) {
4147a831fecSKristof Provost 		if (p->pfik_group == NULL || !(p->pfik_flags & PFI_IFLAG_SKIP))
4157a831fecSKristof Provost 			continue;
4167a831fecSKristof Provost 
417c5e10565SKristof Provost 		pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0);
4187a831fecSKristof Provost 		if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL)
4197a831fecSKristof Provost 			continue;
4207a831fecSKristof Provost 
4217a831fecSKristof Provost 		for (n = h; n != NULL; n = n->next)
4227a831fecSKristof Provost 			PFRB_FOREACH(pp, &skip_b) {
4237a831fecSKristof Provost 				if (strncmp(pp->pfik_name, n->ifname, IFNAMSIZ))
4247a831fecSKristof Provost 					continue;
4257a831fecSKristof Provost 
4267a831fecSKristof Provost 				if (!(pp->pfik_flags & PFI_IFLAG_SKIP))
4277a831fecSKristof Provost 					pfctl_set_interface_flags(pf,
4287a831fecSKristof Provost 					    pp->pfik_name, PFI_IFLAG_SKIP, 1);
4297a831fecSKristof Provost 				if (pp->pfik_flags & PFI_IFLAG_SKIP)
4307a831fecSKristof Provost 					pp->pfik_flags &= ~PFI_IFLAG_SKIP;
4317a831fecSKristof Provost 			}
4327a831fecSKristof Provost 	}
4337a831fecSKristof Provost 
4347a831fecSKristof Provost 	PFRB_FOREACH(p, &skip_b) {
4356a88e227SKristof Provost 		if (! (p->pfik_flags & PFI_IFLAG_SKIP))
4367a831fecSKristof Provost 			continue;
4377a831fecSKristof Provost 
4387a831fecSKristof Provost 		pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0);
4397a831fecSKristof Provost 	}
4407a831fecSKristof Provost 
441c5e10565SKristof Provost 	return (0);
442c5e10565SKristof Provost }
443c5e10565SKristof Provost 
444c5e10565SKristof Provost int
4453b3a8eb9SGleb Smirnoff pfctl_clear_interface_flags(int dev, int opts)
4463b3a8eb9SGleb Smirnoff {
4473b3a8eb9SGleb Smirnoff 	struct pfioc_iface	pi;
4483b3a8eb9SGleb Smirnoff 
4493b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_NOACTION) == 0) {
4503b3a8eb9SGleb Smirnoff 		bzero(&pi, sizeof(pi));
4513b3a8eb9SGleb Smirnoff 		pi.pfiio_flags = PFI_IFLAG_SKIP;
4523b3a8eb9SGleb Smirnoff 
4533b3a8eb9SGleb Smirnoff 		if (ioctl(dev, DIOCCLRIFFLAG, &pi))
4543b3a8eb9SGleb Smirnoff 			err(1, "DIOCCLRIFFLAG");
4553b3a8eb9SGleb Smirnoff 		if ((opts & PF_OPT_QUIET) == 0)
4563b3a8eb9SGleb Smirnoff 			fprintf(stderr, "pf: interface flags reset\n");
4573b3a8eb9SGleb Smirnoff 	}
4583b3a8eb9SGleb Smirnoff 	return (0);
4593b3a8eb9SGleb Smirnoff }
4603b3a8eb9SGleb Smirnoff 
4613b3a8eb9SGleb Smirnoff int
462f0c334e4SKristof Provost pfctl_flush_eth_rules(int dev, int opts, char *anchorname)
4636ea1c3cfSKristof Provost {
464f0c334e4SKristof Provost 	int ret;
4656ea1c3cfSKristof Provost 
466f0c334e4SKristof Provost 	ret = pfctl_clear_eth_rules(dev, anchorname);
467f0c334e4SKristof Provost 	if (ret != 0)
4686ea1c3cfSKristof Provost 		err(1, "pfctl_clear_eth_rules");
469f0c334e4SKristof Provost 
4706ea1c3cfSKristof Provost 	if ((opts & PF_OPT_QUIET) == 0)
4716ea1c3cfSKristof Provost 		fprintf(stderr, "Ethernet rules cleared\n");
472f0c334e4SKristof Provost 
473f0c334e4SKristof Provost 	return (ret);
4746ea1c3cfSKristof Provost }
4756ea1c3cfSKristof Provost 
4766ea1c3cfSKristof Provost int
477f0c334e4SKristof Provost pfctl_flush_rules(int dev, int opts, char *anchorname)
4783b3a8eb9SGleb Smirnoff {
479f0c334e4SKristof Provost 	int ret;
4803b3a8eb9SGleb Smirnoff 
481f0c334e4SKristof Provost 	ret = pfctl_clear_rules(dev, anchorname);
482f0c334e4SKristof Provost 	if (ret != 0)
4833b3a8eb9SGleb Smirnoff 		err(1, "pfctl_clear_rules");
4843b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0)
4853b3a8eb9SGleb Smirnoff 		fprintf(stderr, "rules cleared\n");
4863b3a8eb9SGleb Smirnoff 	return (0);
4873b3a8eb9SGleb Smirnoff }
4883b3a8eb9SGleb Smirnoff 
4893b3a8eb9SGleb Smirnoff int
490f0c334e4SKristof Provost pfctl_flush_nat(int dev, int opts, char *anchorname)
4913b3a8eb9SGleb Smirnoff {
492f0c334e4SKristof Provost 	int ret;
4933b3a8eb9SGleb Smirnoff 
494f0c334e4SKristof Provost 	ret = pfctl_clear_nat(dev, anchorname);
495f0c334e4SKristof Provost 	if (ret != 0)
4963b3a8eb9SGleb Smirnoff 		err(1, "pfctl_clear_nat");
4973b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0)
4983b3a8eb9SGleb Smirnoff 		fprintf(stderr, "nat cleared\n");
4993b3a8eb9SGleb Smirnoff 	return (0);
5003b3a8eb9SGleb Smirnoff }
5013b3a8eb9SGleb Smirnoff 
5023b3a8eb9SGleb Smirnoff int
5033b3a8eb9SGleb Smirnoff pfctl_clear_altq(int dev, int opts)
5043b3a8eb9SGleb Smirnoff {
5053b3a8eb9SGleb Smirnoff 	struct pfr_buffer t;
5063b3a8eb9SGleb Smirnoff 
5073b3a8eb9SGleb Smirnoff 	if (!altqsupport)
5083b3a8eb9SGleb Smirnoff 		return (-1);
5093b3a8eb9SGleb Smirnoff 	memset(&t, 0, sizeof(t));
5103b3a8eb9SGleb Smirnoff 	t.pfrb_type = PFRB_TRANS;
5113b3a8eb9SGleb Smirnoff 	if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") ||
5123b3a8eb9SGleb Smirnoff 	    pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
5133b3a8eb9SGleb Smirnoff 	    pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
5143b3a8eb9SGleb Smirnoff 		err(1, "pfctl_clear_altq");
5153b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0)
5163b3a8eb9SGleb Smirnoff 		fprintf(stderr, "altq cleared\n");
5173b3a8eb9SGleb Smirnoff 	return (0);
5183b3a8eb9SGleb Smirnoff }
5193b3a8eb9SGleb Smirnoff 
5203b3a8eb9SGleb Smirnoff int
5213b3a8eb9SGleb Smirnoff pfctl_clear_src_nodes(int dev, int opts)
5223b3a8eb9SGleb Smirnoff {
5233b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCCLRSRCNODES))
5243b3a8eb9SGleb Smirnoff 		err(1, "DIOCCLRSRCNODES");
5253b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0)
5263b3a8eb9SGleb Smirnoff 		fprintf(stderr, "source tracking entries cleared\n");
5273b3a8eb9SGleb Smirnoff 	return (0);
5283b3a8eb9SGleb Smirnoff }
5293b3a8eb9SGleb Smirnoff 
5303b3a8eb9SGleb Smirnoff int
53153714a58SKristof Provost pfctl_clear_iface_states(int dev, const char *iface, int opts)
5323b3a8eb9SGleb Smirnoff {
53353714a58SKristof Provost 	struct pfctl_kill kill;
53453714a58SKristof Provost 	unsigned int killed;
535375aaa29SKristof Provost 	int ret;
5363b3a8eb9SGleb Smirnoff 
53753714a58SKristof Provost 	memset(&kill, 0, sizeof(kill));
53853714a58SKristof Provost 	if (iface != NULL && strlcpy(kill.ifname, iface,
53953714a58SKristof Provost 	    sizeof(kill.ifname)) >= sizeof(kill.ifname))
5403b3a8eb9SGleb Smirnoff 		errx(1, "invalid interface: %s", iface);
5413b3a8eb9SGleb Smirnoff 
54293abcf17SKristof Provost 	if (opts & PF_OPT_KILLMATCH)
54393abcf17SKristof Provost 		kill.kill_match = true;
54493abcf17SKristof Provost 
545375aaa29SKristof Provost 	if ((ret = pfctl_clear_states_h(pfh, &kill, &killed)) != 0)
546375aaa29SKristof Provost 		errc(1, ret, "DIOCCLRSTATES");
5473b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0)
54853714a58SKristof Provost 		fprintf(stderr, "%d states cleared\n", killed);
5493b3a8eb9SGleb Smirnoff 	return (0);
5503b3a8eb9SGleb Smirnoff }
5513b3a8eb9SGleb Smirnoff 
5523b3a8eb9SGleb Smirnoff void
5533b3a8eb9SGleb Smirnoff pfctl_addrprefix(char *addr, struct pf_addr *mask)
5543b3a8eb9SGleb Smirnoff {
5553b3a8eb9SGleb Smirnoff 	char *p;
5563b3a8eb9SGleb Smirnoff 	const char *errstr;
5573b3a8eb9SGleb Smirnoff 	int prefix, ret_ga, q, r;
5583b3a8eb9SGleb Smirnoff 	struct addrinfo hints, *res;
5593b3a8eb9SGleb Smirnoff 
5603b3a8eb9SGleb Smirnoff 	if ((p = strchr(addr, '/')) == NULL)
5613b3a8eb9SGleb Smirnoff 		return;
5623b3a8eb9SGleb Smirnoff 
5633b3a8eb9SGleb Smirnoff 	*p++ = '\0';
5643b3a8eb9SGleb Smirnoff 	prefix = strtonum(p, 0, 128, &errstr);
5653b3a8eb9SGleb Smirnoff 	if (errstr)
5663b3a8eb9SGleb Smirnoff 		errx(1, "prefix is %s: %s", errstr, p);
5673b3a8eb9SGleb Smirnoff 
5683b3a8eb9SGleb Smirnoff 	bzero(&hints, sizeof(hints));
5693b3a8eb9SGleb Smirnoff 	/* prefix only with numeric addresses */
5703b3a8eb9SGleb Smirnoff 	hints.ai_flags |= AI_NUMERICHOST;
5713b3a8eb9SGleb Smirnoff 
5723b3a8eb9SGleb Smirnoff 	if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) {
5733b3a8eb9SGleb Smirnoff 		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
5743b3a8eb9SGleb Smirnoff 		/* NOTREACHED */
5753b3a8eb9SGleb Smirnoff 	}
5763b3a8eb9SGleb Smirnoff 
5773b3a8eb9SGleb Smirnoff 	if (res->ai_family == AF_INET && prefix > 32)
5783b3a8eb9SGleb Smirnoff 		errx(1, "prefix too long for AF_INET");
5793b3a8eb9SGleb Smirnoff 	else if (res->ai_family == AF_INET6 && prefix > 128)
5803b3a8eb9SGleb Smirnoff 		errx(1, "prefix too long for AF_INET6");
5813b3a8eb9SGleb Smirnoff 
5823b3a8eb9SGleb Smirnoff 	q = prefix >> 3;
5833b3a8eb9SGleb Smirnoff 	r = prefix & 7;
5843b3a8eb9SGleb Smirnoff 	switch (res->ai_family) {
5853b3a8eb9SGleb Smirnoff 	case AF_INET:
5863b3a8eb9SGleb Smirnoff 		bzero(&mask->v4, sizeof(mask->v4));
5873b3a8eb9SGleb Smirnoff 		mask->v4.s_addr = htonl((u_int32_t)
5883b3a8eb9SGleb Smirnoff 		    (0xffffffffffULL << (32 - prefix)));
5893b3a8eb9SGleb Smirnoff 		break;
5903b3a8eb9SGleb Smirnoff 	case AF_INET6:
5913b3a8eb9SGleb Smirnoff 		bzero(&mask->v6, sizeof(mask->v6));
5923b3a8eb9SGleb Smirnoff 		if (q > 0)
5933b3a8eb9SGleb Smirnoff 			memset((void *)&mask->v6, 0xff, q);
5943b3a8eb9SGleb Smirnoff 		if (r > 0)
5953b3a8eb9SGleb Smirnoff 			*((u_char *)&mask->v6 + q) =
5963b3a8eb9SGleb Smirnoff 			    (0xff00 >> r) & 0xff;
5973b3a8eb9SGleb Smirnoff 		break;
5983b3a8eb9SGleb Smirnoff 	}
5993b3a8eb9SGleb Smirnoff 	freeaddrinfo(res);
6003b3a8eb9SGleb Smirnoff }
6013b3a8eb9SGleb Smirnoff 
6023b3a8eb9SGleb Smirnoff int
6033b3a8eb9SGleb Smirnoff pfctl_kill_src_nodes(int dev, const char *iface, int opts)
6043b3a8eb9SGleb Smirnoff {
6053b3a8eb9SGleb Smirnoff 	struct pfioc_src_node_kill psnk;
6063b3a8eb9SGleb Smirnoff 	struct addrinfo *res[2], *resp[2];
6073b3a8eb9SGleb Smirnoff 	struct sockaddr last_src, last_dst;
6083b3a8eb9SGleb Smirnoff 	int killed, sources, dests;
6093b3a8eb9SGleb Smirnoff 	int ret_ga;
6103b3a8eb9SGleb Smirnoff 
6113b3a8eb9SGleb Smirnoff 	killed = sources = dests = 0;
6123b3a8eb9SGleb Smirnoff 
6133b3a8eb9SGleb Smirnoff 	memset(&psnk, 0, sizeof(psnk));
6143b3a8eb9SGleb Smirnoff 	memset(&psnk.psnk_src.addr.v.a.mask, 0xff,
6153b3a8eb9SGleb Smirnoff 	    sizeof(psnk.psnk_src.addr.v.a.mask));
6163b3a8eb9SGleb Smirnoff 	memset(&last_src, 0xff, sizeof(last_src));
6173b3a8eb9SGleb Smirnoff 	memset(&last_dst, 0xff, sizeof(last_dst));
6183b3a8eb9SGleb Smirnoff 
6193b3a8eb9SGleb Smirnoff 	pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask);
6203b3a8eb9SGleb Smirnoff 
6213b3a8eb9SGleb Smirnoff 	if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) {
6223b3a8eb9SGleb Smirnoff 		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
6233b3a8eb9SGleb Smirnoff 		/* NOTREACHED */
6243b3a8eb9SGleb Smirnoff 	}
6253b3a8eb9SGleb Smirnoff 	for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
6263b3a8eb9SGleb Smirnoff 		if (resp[0]->ai_addr == NULL)
6273b3a8eb9SGleb Smirnoff 			continue;
6283b3a8eb9SGleb Smirnoff 		/* We get lots of duplicates.  Catch the easy ones */
6293b3a8eb9SGleb Smirnoff 		if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
6303b3a8eb9SGleb Smirnoff 			continue;
6313b3a8eb9SGleb Smirnoff 		last_src = *(struct sockaddr *)resp[0]->ai_addr;
6323b3a8eb9SGleb Smirnoff 
6333b3a8eb9SGleb Smirnoff 		psnk.psnk_af = resp[0]->ai_family;
6343b3a8eb9SGleb Smirnoff 		sources++;
6353b3a8eb9SGleb Smirnoff 
6363b3a8eb9SGleb Smirnoff 		if (psnk.psnk_af == AF_INET)
6373b3a8eb9SGleb Smirnoff 			psnk.psnk_src.addr.v.a.addr.v4 =
6383b3a8eb9SGleb Smirnoff 			    ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
6393b3a8eb9SGleb Smirnoff 		else if (psnk.psnk_af == AF_INET6)
6403b3a8eb9SGleb Smirnoff 			psnk.psnk_src.addr.v.a.addr.v6 =
6413b3a8eb9SGleb Smirnoff 			    ((struct sockaddr_in6 *)resp[0]->ai_addr)->
6423b3a8eb9SGleb Smirnoff 			    sin6_addr;
6433b3a8eb9SGleb Smirnoff 		else
6443b3a8eb9SGleb Smirnoff 			errx(1, "Unknown address family %d", psnk.psnk_af);
6453b3a8eb9SGleb Smirnoff 
6463b3a8eb9SGleb Smirnoff 		if (src_node_killers > 1) {
6473b3a8eb9SGleb Smirnoff 			dests = 0;
6483b3a8eb9SGleb Smirnoff 			memset(&psnk.psnk_dst.addr.v.a.mask, 0xff,
6493b3a8eb9SGleb Smirnoff 			    sizeof(psnk.psnk_dst.addr.v.a.mask));
6503b3a8eb9SGleb Smirnoff 			memset(&last_dst, 0xff, sizeof(last_dst));
6513b3a8eb9SGleb Smirnoff 			pfctl_addrprefix(src_node_kill[1],
6523b3a8eb9SGleb Smirnoff 			    &psnk.psnk_dst.addr.v.a.mask);
6533b3a8eb9SGleb Smirnoff 			if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL,
6543b3a8eb9SGleb Smirnoff 			    &res[1]))) {
6553b3a8eb9SGleb Smirnoff 				errx(1, "getaddrinfo: %s",
6563b3a8eb9SGleb Smirnoff 				    gai_strerror(ret_ga));
6573b3a8eb9SGleb Smirnoff 				/* NOTREACHED */
6583b3a8eb9SGleb Smirnoff 			}
6593b3a8eb9SGleb Smirnoff 			for (resp[1] = res[1]; resp[1];
6603b3a8eb9SGleb Smirnoff 			    resp[1] = resp[1]->ai_next) {
6613b3a8eb9SGleb Smirnoff 				if (resp[1]->ai_addr == NULL)
6623b3a8eb9SGleb Smirnoff 					continue;
6633b3a8eb9SGleb Smirnoff 				if (psnk.psnk_af != resp[1]->ai_family)
6643b3a8eb9SGleb Smirnoff 					continue;
6653b3a8eb9SGleb Smirnoff 
6663b3a8eb9SGleb Smirnoff 				if (memcmp(&last_dst, resp[1]->ai_addr,
6673b3a8eb9SGleb Smirnoff 				    sizeof(last_dst)) == 0)
6683b3a8eb9SGleb Smirnoff 					continue;
6693b3a8eb9SGleb Smirnoff 				last_dst = *(struct sockaddr *)resp[1]->ai_addr;
6703b3a8eb9SGleb Smirnoff 
6713b3a8eb9SGleb Smirnoff 				dests++;
6723b3a8eb9SGleb Smirnoff 
6733b3a8eb9SGleb Smirnoff 				if (psnk.psnk_af == AF_INET)
6743b3a8eb9SGleb Smirnoff 					psnk.psnk_dst.addr.v.a.addr.v4 =
6753b3a8eb9SGleb Smirnoff 					    ((struct sockaddr_in *)resp[1]->
6763b3a8eb9SGleb Smirnoff 					    ai_addr)->sin_addr;
6773b3a8eb9SGleb Smirnoff 				else if (psnk.psnk_af == AF_INET6)
6783b3a8eb9SGleb Smirnoff 					psnk.psnk_dst.addr.v.a.addr.v6 =
6793b3a8eb9SGleb Smirnoff 					    ((struct sockaddr_in6 *)resp[1]->
6803b3a8eb9SGleb Smirnoff 					    ai_addr)->sin6_addr;
6813b3a8eb9SGleb Smirnoff 				else
6823b3a8eb9SGleb Smirnoff 					errx(1, "Unknown address family %d",
6833b3a8eb9SGleb Smirnoff 					    psnk.psnk_af);
6843b3a8eb9SGleb Smirnoff 
6853b3a8eb9SGleb Smirnoff 				if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
6863b3a8eb9SGleb Smirnoff 					err(1, "DIOCKILLSRCNODES");
6873b3a8eb9SGleb Smirnoff 				killed += psnk.psnk_killed;
6883b3a8eb9SGleb Smirnoff 			}
6893b3a8eb9SGleb Smirnoff 			freeaddrinfo(res[1]);
6903b3a8eb9SGleb Smirnoff 		} else {
6913b3a8eb9SGleb Smirnoff 			if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
6923b3a8eb9SGleb Smirnoff 				err(1, "DIOCKILLSRCNODES");
6933b3a8eb9SGleb Smirnoff 			killed += psnk.psnk_killed;
6943b3a8eb9SGleb Smirnoff 		}
6953b3a8eb9SGleb Smirnoff 	}
6963b3a8eb9SGleb Smirnoff 
6973b3a8eb9SGleb Smirnoff 	freeaddrinfo(res[0]);
6983b3a8eb9SGleb Smirnoff 
6993b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0)
7003b3a8eb9SGleb Smirnoff 		fprintf(stderr, "killed %d src nodes from %d sources and %d "
7013b3a8eb9SGleb Smirnoff 		    "destinations\n", killed, sources, dests);
7023b3a8eb9SGleb Smirnoff 	return (0);
7033b3a8eb9SGleb Smirnoff }
7043b3a8eb9SGleb Smirnoff 
7053b3a8eb9SGleb Smirnoff int
7063b3a8eb9SGleb Smirnoff pfctl_net_kill_states(int dev, const char *iface, int opts)
7073b3a8eb9SGleb Smirnoff {
7082a00c4dbSKristof Provost 	struct pfctl_kill kill;
7093b3a8eb9SGleb Smirnoff 	struct addrinfo *res[2], *resp[2];
7103b3a8eb9SGleb Smirnoff 	struct sockaddr last_src, last_dst;
7112a00c4dbSKristof Provost 	unsigned int newkilled;
7123b3a8eb9SGleb Smirnoff 	int killed, sources, dests;
713375aaa29SKristof Provost 	int ret_ga, ret;
7143b3a8eb9SGleb Smirnoff 
7153b3a8eb9SGleb Smirnoff 	killed = sources = dests = 0;
7163b3a8eb9SGleb Smirnoff 
7172a00c4dbSKristof Provost 	memset(&kill, 0, sizeof(kill));
7182a00c4dbSKristof Provost 	memset(&kill.src.addr.v.a.mask, 0xff,
7192a00c4dbSKristof Provost 	    sizeof(kill.src.addr.v.a.mask));
7203b3a8eb9SGleb Smirnoff 	memset(&last_src, 0xff, sizeof(last_src));
7213b3a8eb9SGleb Smirnoff 	memset(&last_dst, 0xff, sizeof(last_dst));
7222a00c4dbSKristof Provost 	if (iface != NULL && strlcpy(kill.ifname, iface,
7232a00c4dbSKristof Provost 	    sizeof(kill.ifname)) >= sizeof(kill.ifname))
7243b3a8eb9SGleb Smirnoff 		errx(1, "invalid interface: %s", iface);
7253b3a8eb9SGleb Smirnoff 
7264f337550SKristof Provost 	if (state_killers == 2 && (strcmp(state_kill[0], "nat") == 0)) {
7274f337550SKristof Provost 		kill.nat = true;
7284f337550SKristof Provost 		state_kill[0] = state_kill[1];
7294f337550SKristof Provost 		state_killers = 1;
7304f337550SKristof Provost 	}
7314f337550SKristof Provost 
7322a00c4dbSKristof Provost 	pfctl_addrprefix(state_kill[0], &kill.src.addr.v.a.mask);
7333b3a8eb9SGleb Smirnoff 
73493abcf17SKristof Provost 	if (opts & PF_OPT_KILLMATCH)
73593abcf17SKristof Provost 		kill.kill_match = true;
73693abcf17SKristof Provost 
7373b3a8eb9SGleb Smirnoff 	if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) {
7383b3a8eb9SGleb Smirnoff 		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
7393b3a8eb9SGleb Smirnoff 		/* NOTREACHED */
7403b3a8eb9SGleb Smirnoff 	}
7413b3a8eb9SGleb Smirnoff 	for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
7423b3a8eb9SGleb Smirnoff 		if (resp[0]->ai_addr == NULL)
7433b3a8eb9SGleb Smirnoff 			continue;
7443b3a8eb9SGleb Smirnoff 		/* We get lots of duplicates.  Catch the easy ones */
7453b3a8eb9SGleb Smirnoff 		if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
7463b3a8eb9SGleb Smirnoff 			continue;
7473b3a8eb9SGleb Smirnoff 		last_src = *(struct sockaddr *)resp[0]->ai_addr;
7483b3a8eb9SGleb Smirnoff 
7492a00c4dbSKristof Provost 		kill.af = resp[0]->ai_family;
7503b3a8eb9SGleb Smirnoff 		sources++;
7513b3a8eb9SGleb Smirnoff 
7522a00c4dbSKristof Provost 		if (kill.af == AF_INET)
7532a00c4dbSKristof Provost 			kill.src.addr.v.a.addr.v4 =
7543b3a8eb9SGleb Smirnoff 			    ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
7552a00c4dbSKristof Provost 		else if (kill.af == AF_INET6)
7562a00c4dbSKristof Provost 			kill.src.addr.v.a.addr.v6 =
7573b3a8eb9SGleb Smirnoff 			    ((struct sockaddr_in6 *)resp[0]->ai_addr)->
7583b3a8eb9SGleb Smirnoff 			    sin6_addr;
7593b3a8eb9SGleb Smirnoff 		else
7602a00c4dbSKristof Provost 			errx(1, "Unknown address family %d", kill.af);
7613b3a8eb9SGleb Smirnoff 
7623b3a8eb9SGleb Smirnoff 		if (state_killers > 1) {
7633b3a8eb9SGleb Smirnoff 			dests = 0;
7642a00c4dbSKristof Provost 			memset(&kill.dst.addr.v.a.mask, 0xff,
7652a00c4dbSKristof Provost 			    sizeof(kill.dst.addr.v.a.mask));
7663b3a8eb9SGleb Smirnoff 			memset(&last_dst, 0xff, sizeof(last_dst));
7673b3a8eb9SGleb Smirnoff 			pfctl_addrprefix(state_kill[1],
7682a00c4dbSKristof Provost 			    &kill.dst.addr.v.a.mask);
7693b3a8eb9SGleb Smirnoff 			if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL,
7703b3a8eb9SGleb Smirnoff 			    &res[1]))) {
7713b3a8eb9SGleb Smirnoff 				errx(1, "getaddrinfo: %s",
7723b3a8eb9SGleb Smirnoff 				    gai_strerror(ret_ga));
7733b3a8eb9SGleb Smirnoff 				/* NOTREACHED */
7743b3a8eb9SGleb Smirnoff 			}
7753b3a8eb9SGleb Smirnoff 			for (resp[1] = res[1]; resp[1];
7763b3a8eb9SGleb Smirnoff 			    resp[1] = resp[1]->ai_next) {
7773b3a8eb9SGleb Smirnoff 				if (resp[1]->ai_addr == NULL)
7783b3a8eb9SGleb Smirnoff 					continue;
7792a00c4dbSKristof Provost 				if (kill.af != resp[1]->ai_family)
7803b3a8eb9SGleb Smirnoff 					continue;
7813b3a8eb9SGleb Smirnoff 
7823b3a8eb9SGleb Smirnoff 				if (memcmp(&last_dst, resp[1]->ai_addr,
7833b3a8eb9SGleb Smirnoff 				    sizeof(last_dst)) == 0)
7843b3a8eb9SGleb Smirnoff 					continue;
7853b3a8eb9SGleb Smirnoff 				last_dst = *(struct sockaddr *)resp[1]->ai_addr;
7863b3a8eb9SGleb Smirnoff 
7873b3a8eb9SGleb Smirnoff 				dests++;
7883b3a8eb9SGleb Smirnoff 
7892a00c4dbSKristof Provost 				if (kill.af == AF_INET)
7902a00c4dbSKristof Provost 					kill.dst.addr.v.a.addr.v4 =
7913b3a8eb9SGleb Smirnoff 					    ((struct sockaddr_in *)resp[1]->
7923b3a8eb9SGleb Smirnoff 					    ai_addr)->sin_addr;
7932a00c4dbSKristof Provost 				else if (kill.af == AF_INET6)
7942a00c4dbSKristof Provost 					kill.dst.addr.v.a.addr.v6 =
7953b3a8eb9SGleb Smirnoff 					    ((struct sockaddr_in6 *)resp[1]->
7963b3a8eb9SGleb Smirnoff 					    ai_addr)->sin6_addr;
7973b3a8eb9SGleb Smirnoff 				else
7983b3a8eb9SGleb Smirnoff 					errx(1, "Unknown address family %d",
7992a00c4dbSKristof Provost 					    kill.af);
8003b3a8eb9SGleb Smirnoff 
801375aaa29SKristof Provost 				if ((ret = pfctl_kill_states_h(pfh, &kill, &newkilled)) != 0)
802375aaa29SKristof Provost 					errc(1, ret, "DIOCKILLSTATES");
8032a00c4dbSKristof Provost 				killed += newkilled;
8043b3a8eb9SGleb Smirnoff 			}
8053b3a8eb9SGleb Smirnoff 			freeaddrinfo(res[1]);
8063b3a8eb9SGleb Smirnoff 		} else {
807375aaa29SKristof Provost 			if ((ret = pfctl_kill_states_h(pfh, &kill, &newkilled)) != 0)
808375aaa29SKristof Provost 				errc(1, ret, "DIOCKILLSTATES");
8092a00c4dbSKristof Provost 			killed += newkilled;
8103b3a8eb9SGleb Smirnoff 		}
8113b3a8eb9SGleb Smirnoff 	}
8123b3a8eb9SGleb Smirnoff 
8133b3a8eb9SGleb Smirnoff 	freeaddrinfo(res[0]);
8143b3a8eb9SGleb Smirnoff 
8153b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0)
8163b3a8eb9SGleb Smirnoff 		fprintf(stderr, "killed %d states from %d sources and %d "
8173b3a8eb9SGleb Smirnoff 		    "destinations\n", killed, sources, dests);
8183b3a8eb9SGleb Smirnoff 	return (0);
8193b3a8eb9SGleb Smirnoff }
8203b3a8eb9SGleb Smirnoff 
8213b3a8eb9SGleb Smirnoff int
822abbcba9cSKristof Provost pfctl_gateway_kill_states(int dev, const char *iface, int opts)
823abbcba9cSKristof Provost {
824abbcba9cSKristof Provost 	struct pfctl_kill kill;
825abbcba9cSKristof Provost 	struct addrinfo *res, *resp;
826abbcba9cSKristof Provost 	struct sockaddr last_src;
827abbcba9cSKristof Provost 	unsigned int newkilled;
828abbcba9cSKristof Provost 	int killed = 0;
829abbcba9cSKristof Provost 	int ret_ga;
830abbcba9cSKristof Provost 
831abbcba9cSKristof Provost 	if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
832abbcba9cSKristof Provost 		warnx("no gateway specified");
833abbcba9cSKristof Provost 		usage();
834abbcba9cSKristof Provost 	}
835abbcba9cSKristof Provost 
836abbcba9cSKristof Provost 	memset(&kill, 0, sizeof(kill));
837abbcba9cSKristof Provost 	memset(&kill.rt_addr.addr.v.a.mask, 0xff,
838abbcba9cSKristof Provost 	    sizeof(kill.rt_addr.addr.v.a.mask));
839abbcba9cSKristof Provost 	memset(&last_src, 0xff, sizeof(last_src));
840abbcba9cSKristof Provost 	if (iface != NULL && strlcpy(kill.ifname, iface,
841abbcba9cSKristof Provost 	    sizeof(kill.ifname)) >= sizeof(kill.ifname))
842abbcba9cSKristof Provost 		errx(1, "invalid interface: %s", iface);
843abbcba9cSKristof Provost 
84493abcf17SKristof Provost 	if (opts & PF_OPT_KILLMATCH)
84593abcf17SKristof Provost 		kill.kill_match = true;
84693abcf17SKristof Provost 
847abbcba9cSKristof Provost 	pfctl_addrprefix(state_kill[1], &kill.rt_addr.addr.v.a.mask);
848abbcba9cSKristof Provost 
849abbcba9cSKristof Provost 	if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, &res))) {
850abbcba9cSKristof Provost 		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
851abbcba9cSKristof Provost 		/* NOTREACHED */
852abbcba9cSKristof Provost 	}
853abbcba9cSKristof Provost 	for (resp = res; resp; resp = resp->ai_next) {
854abbcba9cSKristof Provost 		if (resp->ai_addr == NULL)
855abbcba9cSKristof Provost 			continue;
856abbcba9cSKristof Provost 		/* We get lots of duplicates.  Catch the easy ones */
857abbcba9cSKristof Provost 		if (memcmp(&last_src, resp->ai_addr, sizeof(last_src)) == 0)
858abbcba9cSKristof Provost 			continue;
859abbcba9cSKristof Provost 		last_src = *(struct sockaddr *)resp->ai_addr;
860abbcba9cSKristof Provost 
861abbcba9cSKristof Provost 		kill.af = resp->ai_family;
862abbcba9cSKristof Provost 
863abbcba9cSKristof Provost 		if (kill.af == AF_INET)
864abbcba9cSKristof Provost 			kill.rt_addr.addr.v.a.addr.v4 =
865abbcba9cSKristof Provost 			    ((struct sockaddr_in *)resp->ai_addr)->sin_addr;
866abbcba9cSKristof Provost 		else if (kill.af == AF_INET6)
867abbcba9cSKristof Provost 			kill.rt_addr.addr.v.a.addr.v6 =
868abbcba9cSKristof Provost 			    ((struct sockaddr_in6 *)resp->ai_addr)->
869abbcba9cSKristof Provost 			    sin6_addr;
870abbcba9cSKristof Provost 		else
871abbcba9cSKristof Provost 			errx(1, "Unknown address family %d", kill.af);
872abbcba9cSKristof Provost 
873706d465dSKristof Provost 		if (pfctl_kill_states_h(pfh, &kill, &newkilled))
874abbcba9cSKristof Provost 			err(1, "DIOCKILLSTATES");
875abbcba9cSKristof Provost 		killed += newkilled;
876abbcba9cSKristof Provost 	}
877abbcba9cSKristof Provost 
878abbcba9cSKristof Provost 	freeaddrinfo(res);
879abbcba9cSKristof Provost 
880abbcba9cSKristof Provost 	if ((opts & PF_OPT_QUIET) == 0)
881abbcba9cSKristof Provost 		fprintf(stderr, "killed %d states\n", killed);
882abbcba9cSKristof Provost 	return (0);
883abbcba9cSKristof Provost }
884abbcba9cSKristof Provost 
885abbcba9cSKristof Provost int
8863b3a8eb9SGleb Smirnoff pfctl_label_kill_states(int dev, const char *iface, int opts)
8873b3a8eb9SGleb Smirnoff {
8882a00c4dbSKristof Provost 	struct pfctl_kill kill;
8892a00c4dbSKristof Provost 	unsigned int killed;
890375aaa29SKristof Provost 	int ret;
8913b3a8eb9SGleb Smirnoff 
8923b3a8eb9SGleb Smirnoff 	if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
8933b3a8eb9SGleb Smirnoff 		warnx("no label specified");
8943b3a8eb9SGleb Smirnoff 		usage();
8953b3a8eb9SGleb Smirnoff 	}
8962a00c4dbSKristof Provost 	memset(&kill, 0, sizeof(kill));
8972a00c4dbSKristof Provost 	if (iface != NULL && strlcpy(kill.ifname, iface,
8982a00c4dbSKristof Provost 	    sizeof(kill.ifname)) >= sizeof(kill.ifname))
8993b3a8eb9SGleb Smirnoff 		errx(1, "invalid interface: %s", iface);
9003b3a8eb9SGleb Smirnoff 
90193abcf17SKristof Provost 	if (opts & PF_OPT_KILLMATCH)
90293abcf17SKristof Provost 		kill.kill_match = true;
90393abcf17SKristof Provost 
9042a00c4dbSKristof Provost 	if (strlcpy(kill.label, state_kill[1], sizeof(kill.label)) >=
9052a00c4dbSKristof Provost 	    sizeof(kill.label))
9063b3a8eb9SGleb Smirnoff 		errx(1, "label too long: %s", state_kill[1]);
9073b3a8eb9SGleb Smirnoff 
908375aaa29SKristof Provost 	if ((ret = pfctl_kill_states_h(pfh, &kill, &killed)) != 0)
909375aaa29SKristof Provost 		errc(1, ret, "DIOCKILLSTATES");
9103b3a8eb9SGleb Smirnoff 
9113b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0)
9122a00c4dbSKristof Provost 		fprintf(stderr, "killed %d states\n", killed);
9133b3a8eb9SGleb Smirnoff 
9143b3a8eb9SGleb Smirnoff 	return (0);
9153b3a8eb9SGleb Smirnoff }
9163b3a8eb9SGleb Smirnoff 
9173b3a8eb9SGleb Smirnoff int
9183b3a8eb9SGleb Smirnoff pfctl_id_kill_states(int dev, const char *iface, int opts)
9193b3a8eb9SGleb Smirnoff {
9202a00c4dbSKristof Provost 	struct pfctl_kill kill;
9212a00c4dbSKristof Provost 	unsigned int killed;
922375aaa29SKristof Provost 	int ret;
9233b3a8eb9SGleb Smirnoff 
9243b3a8eb9SGleb Smirnoff 	if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
9253b3a8eb9SGleb Smirnoff 		warnx("no id specified");
9263b3a8eb9SGleb Smirnoff 		usage();
9273b3a8eb9SGleb Smirnoff 	}
9283b3a8eb9SGleb Smirnoff 
9292a00c4dbSKristof Provost 	memset(&kill, 0, sizeof(kill));
93093abcf17SKristof Provost 
93193abcf17SKristof Provost 	if (opts & PF_OPT_KILLMATCH)
93293abcf17SKristof Provost 		kill.kill_match = true;
93393abcf17SKristof Provost 
9343b3a8eb9SGleb Smirnoff 	if ((sscanf(state_kill[1], "%jx/%x",
9359ce32082SKristof Provost 	    &kill.cmp.id, &kill.cmp.creatorid)) == 2) {
9369ce32082SKristof Provost 	}
9372a00c4dbSKristof Provost 	else if ((sscanf(state_kill[1], "%jx", &kill.cmp.id)) == 1) {
9382a00c4dbSKristof Provost 		kill.cmp.creatorid = 0;
9393b3a8eb9SGleb Smirnoff 	} else {
9403b3a8eb9SGleb Smirnoff 		warnx("wrong id format specified");
9413b3a8eb9SGleb Smirnoff 		usage();
9423b3a8eb9SGleb Smirnoff 	}
9432a00c4dbSKristof Provost 	if (kill.cmp.id == 0) {
9443b3a8eb9SGleb Smirnoff 		warnx("cannot kill id 0");
9453b3a8eb9SGleb Smirnoff 		usage();
9463b3a8eb9SGleb Smirnoff 	}
9473b3a8eb9SGleb Smirnoff 
948375aaa29SKristof Provost 	if ((ret = pfctl_kill_states_h(pfh, &kill, &killed)) != 0)
949375aaa29SKristof Provost 		errc(1, ret, "DIOCKILLSTATES");
9503b3a8eb9SGleb Smirnoff 
9513b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0)
9522a00c4dbSKristof Provost 		fprintf(stderr, "killed %d states\n", killed);
9533b3a8eb9SGleb Smirnoff 
9543b3a8eb9SGleb Smirnoff 	return (0);
9553b3a8eb9SGleb Smirnoff }
9563b3a8eb9SGleb Smirnoff 
9573b3a8eb9SGleb Smirnoff int
958600bd6ceSKurosawa Takahiro pfctl_get_pool(int dev, struct pfctl_pool *pool, u_int32_t nr,
959aa69fdf1SKristof Provost     u_int32_t ticket, int r_action, char *anchorname, int which)
9603b3a8eb9SGleb Smirnoff {
9613b3a8eb9SGleb Smirnoff 	struct pfioc_pooladdr pp;
9623b3a8eb9SGleb Smirnoff 	struct pf_pooladdr *pa;
9633b3a8eb9SGleb Smirnoff 	u_int32_t pnr, mpnr;
964375aaa29SKristof Provost 	int ret;
9653b3a8eb9SGleb Smirnoff 
9663b3a8eb9SGleb Smirnoff 	memset(&pp, 0, sizeof(pp));
967aa69fdf1SKristof Provost 	if ((ret = pfctl_get_addrs(pfh, ticket, nr, r_action, anchorname, &mpnr, which)) != 0) {
968375aaa29SKristof Provost 		warnc(ret, "DIOCGETADDRS");
9693b3a8eb9SGleb Smirnoff 		return (-1);
9703b3a8eb9SGleb Smirnoff 	}
9719ae91f59SKristof Provost 
9723b3a8eb9SGleb Smirnoff 	TAILQ_INIT(&pool->list);
9733b3a8eb9SGleb Smirnoff 	for (pnr = 0; pnr < mpnr; ++pnr) {
974aa69fdf1SKristof Provost 		if ((ret = pfctl_get_addr(pfh, ticket, nr, r_action, anchorname, pnr, &pp, which)) != 0) {
975375aaa29SKristof Provost 			warnc(ret, "DIOCGETADDR");
9763b3a8eb9SGleb Smirnoff 			return (-1);
9773b3a8eb9SGleb Smirnoff 		}
9783b3a8eb9SGleb Smirnoff 		pa = calloc(1, sizeof(struct pf_pooladdr));
9793b3a8eb9SGleb Smirnoff 		if (pa == NULL)
9803b3a8eb9SGleb Smirnoff 			err(1, "calloc");
9813b3a8eb9SGleb Smirnoff 		bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr));
9823b3a8eb9SGleb Smirnoff 		TAILQ_INSERT_TAIL(&pool->list, pa, entries);
9833b3a8eb9SGleb Smirnoff 	}
9843b3a8eb9SGleb Smirnoff 
9853b3a8eb9SGleb Smirnoff 	return (0);
9863b3a8eb9SGleb Smirnoff }
9873b3a8eb9SGleb Smirnoff 
9883b3a8eb9SGleb Smirnoff void
989600bd6ceSKurosawa Takahiro pfctl_move_pool(struct pfctl_pool *src, struct pfctl_pool *dst)
9903b3a8eb9SGleb Smirnoff {
9913b3a8eb9SGleb Smirnoff 	struct pf_pooladdr *pa;
9923b3a8eb9SGleb Smirnoff 
9933b3a8eb9SGleb Smirnoff 	while ((pa = TAILQ_FIRST(&src->list)) != NULL) {
9943b3a8eb9SGleb Smirnoff 		TAILQ_REMOVE(&src->list, pa, entries);
9953b3a8eb9SGleb Smirnoff 		TAILQ_INSERT_TAIL(&dst->list, pa, entries);
9963b3a8eb9SGleb Smirnoff 	}
9973b3a8eb9SGleb Smirnoff }
9983b3a8eb9SGleb Smirnoff 
9993b3a8eb9SGleb Smirnoff void
1000600bd6ceSKurosawa Takahiro pfctl_clear_pool(struct pfctl_pool *pool)
10013b3a8eb9SGleb Smirnoff {
10023b3a8eb9SGleb Smirnoff 	struct pf_pooladdr *pa;
10033b3a8eb9SGleb Smirnoff 
10043b3a8eb9SGleb Smirnoff 	while ((pa = TAILQ_FIRST(&pool->list)) != NULL) {
10053b3a8eb9SGleb Smirnoff 		TAILQ_REMOVE(&pool->list, pa, entries);
10063b3a8eb9SGleb Smirnoff 		free(pa);
10073b3a8eb9SGleb Smirnoff 	}
10083b3a8eb9SGleb Smirnoff }
10093b3a8eb9SGleb Smirnoff 
10103b3a8eb9SGleb Smirnoff void
10112b29ceb8SKristof Provost pfctl_print_eth_rule_counters(struct pfctl_eth_rule *rule, int opts)
10122b29ceb8SKristof Provost {
10132b29ceb8SKristof Provost 	if (opts & PF_OPT_VERBOSE) {
10142b29ceb8SKristof Provost 		printf("  [ Evaluations: %-8llu  Packets: %-8llu  "
10152b29ceb8SKristof Provost 			    "Bytes: %-10llu]\n",
10162b29ceb8SKristof Provost 			    (unsigned long long)rule->evaluations,
10172b29ceb8SKristof Provost 			    (unsigned long long)(rule->packets[0] +
10182b29ceb8SKristof Provost 			    rule->packets[1]),
10192b29ceb8SKristof Provost 			    (unsigned long long)(rule->bytes[0] +
10202b29ceb8SKristof Provost 			    rule->bytes[1]));
10212b29ceb8SKristof Provost 	}
10220abcc1d2SReid Linnemann 	if (opts & PF_OPT_VERBOSE2) {
10230abcc1d2SReid Linnemann 		char timestr[30];
10240abcc1d2SReid Linnemann 
10250abcc1d2SReid Linnemann 		if (rule->last_active_timestamp != 0) {
10261d090028SKristof Provost 			bcopy(ctime(&rule->last_active_timestamp), timestr,
10271d090028SKristof Provost 			    sizeof(timestr));
10280abcc1d2SReid Linnemann 			*strchr(timestr, '\n') = '\0';
10290abcc1d2SReid Linnemann 		} else {
10300abcc1d2SReid Linnemann 			snprintf(timestr, sizeof(timestr), "N/A");
10310abcc1d2SReid Linnemann 		}
10320abcc1d2SReid Linnemann 		printf("  [ Last Active Time: %s ]\n", timestr);
10330abcc1d2SReid Linnemann 	}
10342b29ceb8SKristof Provost }
10352b29ceb8SKristof Provost 
10362b29ceb8SKristof Provost void
1037e9eb0941SKristof Provost pfctl_print_rule_counters(struct pfctl_rule *rule, int opts)
10383b3a8eb9SGleb Smirnoff {
10393b3a8eb9SGleb Smirnoff 	if (opts & PF_OPT_DEBUG) {
10403b3a8eb9SGleb Smirnoff 		const char *t[PF_SKIP_COUNT] = { "i", "d", "f",
1041ee9f418cSKristof Provost 		    "p", "sa", "da", "sp", "dp" };
10423b3a8eb9SGleb Smirnoff 		int i;
10433b3a8eb9SGleb Smirnoff 
10443b3a8eb9SGleb Smirnoff 		printf("  [ Skip steps: ");
10453b3a8eb9SGleb Smirnoff 		for (i = 0; i < PF_SKIP_COUNT; ++i) {
10463b3a8eb9SGleb Smirnoff 			if (rule->skip[i].nr == rule->nr + 1)
10473b3a8eb9SGleb Smirnoff 				continue;
10483b3a8eb9SGleb Smirnoff 			printf("%s=", t[i]);
10493b3a8eb9SGleb Smirnoff 			if (rule->skip[i].nr == -1)
10503b3a8eb9SGleb Smirnoff 				printf("end ");
10513b3a8eb9SGleb Smirnoff 			else
10523b3a8eb9SGleb Smirnoff 				printf("%u ", rule->skip[i].nr);
10533b3a8eb9SGleb Smirnoff 		}
10543b3a8eb9SGleb Smirnoff 		printf("]\n");
10553b3a8eb9SGleb Smirnoff 
10563b3a8eb9SGleb Smirnoff 		printf("  [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
10573b3a8eb9SGleb Smirnoff 		    rule->qname, rule->qid, rule->pqname, rule->pqid);
10583b3a8eb9SGleb Smirnoff 	}
10593b3a8eb9SGleb Smirnoff 	if (opts & PF_OPT_VERBOSE) {
10603b3a8eb9SGleb Smirnoff 		printf("  [ Evaluations: %-8llu  Packets: %-8llu  "
10615a9ab487SGleb Smirnoff 			    "Bytes: %-10llu  States: %-6ju]\n",
10623b3a8eb9SGleb Smirnoff 			    (unsigned long long)rule->evaluations,
10633b3a8eb9SGleb Smirnoff 			    (unsigned long long)(rule->packets[0] +
10643b3a8eb9SGleb Smirnoff 			    rule->packets[1]),
10653b3a8eb9SGleb Smirnoff 			    (unsigned long long)(rule->bytes[0] +
1066ab5707a5SKristof Provost 			    rule->bytes[1]), (uintmax_t)rule->states_cur);
10673b3a8eb9SGleb Smirnoff 		if (!(opts & PF_OPT_DEBUG))
10683b3a8eb9SGleb Smirnoff 			printf("  [ Inserted: uid %u pid %u "
10695a9ab487SGleb Smirnoff 			    "State Creations: %-6ju]\n",
10703b3a8eb9SGleb Smirnoff 			    (unsigned)rule->cuid, (unsigned)rule->cpid,
1071ab5707a5SKristof Provost 			    (uintmax_t)rule->states_tot);
10723b3a8eb9SGleb Smirnoff 	}
10730abcc1d2SReid Linnemann 	if (opts & PF_OPT_VERBOSE2) {
10740abcc1d2SReid Linnemann 		char timestr[30];
10750abcc1d2SReid Linnemann 		if (rule->last_active_timestamp != 0) {
10761d090028SKristof Provost 			bcopy(ctime(&rule->last_active_timestamp), timestr,
10771d090028SKristof Provost 			    sizeof(timestr));
10780abcc1d2SReid Linnemann 			*strchr(timestr, '\n') = '\0';
10790abcc1d2SReid Linnemann 		} else {
10800abcc1d2SReid Linnemann 			snprintf(timestr, sizeof(timestr), "N/A");
10810abcc1d2SReid Linnemann 		}
10820abcc1d2SReid Linnemann 		printf("  [ Last Active Time: %s ]\n", timestr);
10830abcc1d2SReid Linnemann 	}
10843b3a8eb9SGleb Smirnoff }
10853b3a8eb9SGleb Smirnoff 
10863b3a8eb9SGleb Smirnoff void
10873b3a8eb9SGleb Smirnoff pfctl_print_title(char *title)
10883b3a8eb9SGleb Smirnoff {
10893b3a8eb9SGleb Smirnoff 	if (!first_title)
10903b3a8eb9SGleb Smirnoff 		printf("\n");
10913b3a8eb9SGleb Smirnoff 	first_title = 0;
10923b3a8eb9SGleb Smirnoff 	printf("%s\n", title);
10933b3a8eb9SGleb Smirnoff }
10943b3a8eb9SGleb Smirnoff 
10953b3a8eb9SGleb Smirnoff int
1096c5131afeSKristof Provost pfctl_show_eth_rules(int dev, char *path, int opts, enum pfctl_show format,
1097cfa1a130SKristof Provost     char *anchorname, int depth, int wildcard)
10982b29ceb8SKristof Provost {
1099c5131afeSKristof Provost 	char anchor_call[MAXPATHLEN];
11002b29ceb8SKristof Provost 	struct pfctl_eth_rules_info info;
11012b29ceb8SKristof Provost 	struct pfctl_eth_rule rule;
1102cfa1a130SKristof Provost 	int brace;
11032b29ceb8SKristof Provost 	int dotitle = opts & PF_OPT_SHOWALL;
1104c5131afeSKristof Provost 	int len = strlen(path);
1105375aaa29SKristof Provost 	int ret;
1106cfa1a130SKristof Provost 	char *npath, *p;
11072b29ceb8SKristof Provost 
1108cfa1a130SKristof Provost 	/*
1109cfa1a130SKristof Provost 	 * Truncate a trailing / and * on an anchorname before searching for
1110cfa1a130SKristof Provost 	 * the ruleset, this is syntactic sugar that doesn't actually make it
1111cfa1a130SKristof Provost 	 * to the kernel.
1112cfa1a130SKristof Provost 	 */
1113cfa1a130SKristof Provost 	if ((p = strrchr(anchorname, '/')) != NULL &&
1114cfa1a130SKristof Provost 			p[1] == '*' && p[2] == '\0') {
1115cfa1a130SKristof Provost 		p[0] = '\0';
1116cfa1a130SKristof Provost 	}
1117cfa1a130SKristof Provost 
1118cfa1a130SKristof Provost 	if (anchorname[0] == '/') {
1119cfa1a130SKristof Provost 		if ((npath = calloc(1, MAXPATHLEN)) == NULL)
1120cfa1a130SKristof Provost 			errx(1, "pfctl_rules: calloc");
1121cfa1a130SKristof Provost 		snprintf(npath, MAXPATHLEN, "%s", anchorname);
1122cfa1a130SKristof Provost 	} else {
1123c5131afeSKristof Provost 		if (path[0])
1124c5131afeSKristof Provost 			snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
1125c5131afeSKristof Provost 		else
1126c5131afeSKristof Provost 			snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
1127cfa1a130SKristof Provost 		npath = path;
1128cfa1a130SKristof Provost 	}
1129cfa1a130SKristof Provost 
1130cfa1a130SKristof Provost 	/*
1131cfa1a130SKristof Provost 	 * If this anchor was called with a wildcard path, go through
1132cfa1a130SKristof Provost 	 * the rulesets in the anchor rather than the rules.
1133cfa1a130SKristof Provost 	 */
1134cfa1a130SKristof Provost 	if (wildcard && (opts & PF_OPT_RECURSE)) {
1135cfa1a130SKristof Provost 		struct pfctl_eth_rulesets_info	ri;
1136cfa1a130SKristof Provost 		u_int32_t                mnr, nr;
1137cfa1a130SKristof Provost 
1138375aaa29SKristof Provost 		if ((ret = pfctl_get_eth_rulesets_info(dev, &ri, npath)) != 0) {
1139375aaa29SKristof Provost 			if (ret == EINVAL) {
1140cfa1a130SKristof Provost 				fprintf(stderr, "Anchor '%s' "
1141cfa1a130SKristof Provost 						"not found.\n", anchorname);
1142cfa1a130SKristof Provost 			} else {
1143375aaa29SKristof Provost 				warnc(ret, "DIOCGETETHRULESETS");
1144cfa1a130SKristof Provost 				return (-1);
1145cfa1a130SKristof Provost 			}
1146cfa1a130SKristof Provost 		}
1147cfa1a130SKristof Provost 		mnr = ri.nr;
1148cfa1a130SKristof Provost 
1149cfa1a130SKristof Provost 		pfctl_print_eth_rule_counters(&rule, opts);
1150cfa1a130SKristof Provost 		for (nr = 0; nr < mnr; ++nr) {
1151cfa1a130SKristof Provost 			struct pfctl_eth_ruleset_info	rs;
1152cfa1a130SKristof Provost 
1153375aaa29SKristof Provost 			if ((ret = pfctl_get_eth_ruleset(dev, npath, nr, &rs)) != 0)
1154375aaa29SKristof Provost 				errc(1, ret, "DIOCGETETHRULESET");
1155cfa1a130SKristof Provost 			INDENT(depth, !(opts & PF_OPT_VERBOSE));
1156cfa1a130SKristof Provost 			printf("anchor \"%s\" all {\n", rs.name);
1157cfa1a130SKristof Provost 			pfctl_show_eth_rules(dev, npath, opts,
1158cfa1a130SKristof Provost 					format, rs.name, depth + 1, 0);
1159cfa1a130SKristof Provost 			INDENT(depth, !(opts & PF_OPT_VERBOSE));
1160cfa1a130SKristof Provost 			printf("}\n");
1161cfa1a130SKristof Provost 		}
1162cfa1a130SKristof Provost 		path[len] = '\0';
1163cfa1a130SKristof Provost 		return (0);
1164cfa1a130SKristof Provost 	}
1165c5131afeSKristof Provost 
1166375aaa29SKristof Provost 	if ((ret = pfctl_get_eth_rules_info(dev, &info, path)) != 0) {
1167375aaa29SKristof Provost 		warnc(ret, "DIOCGETETHRULES");
11682b29ceb8SKristof Provost 		return (-1);
11692b29ceb8SKristof Provost 	}
11702b29ceb8SKristof Provost 	for (int nr = 0; nr < info.nr; nr++) {
1171c5131afeSKristof Provost 		brace = 0;
1172c5131afeSKristof Provost 		INDENT(depth, !(opts & PF_OPT_VERBOSE));
1173375aaa29SKristof Provost 		if ((ret = pfctl_get_eth_rule(dev, nr, info.ticket, path, &rule,
1174375aaa29SKristof Provost 		    opts & PF_OPT_CLRRULECTRS, anchor_call)) != 0) {
1175375aaa29SKristof Provost 			warnc(ret, "DIOCGETETHRULE");
11762b29ceb8SKristof Provost 			return (-1);
11772b29ceb8SKristof Provost 		}
1178c5131afeSKristof Provost 		if (anchor_call[0] &&
1179c5131afeSKristof Provost 		   ((((p = strrchr(anchor_call, '_')) != NULL) &&
1180c5131afeSKristof Provost 		   (p == anchor_call ||
1181c5131afeSKristof Provost 		   *(--p) == '/')) || (opts & PF_OPT_RECURSE))) {
1182c5131afeSKristof Provost 			brace++;
1183ed5eb77eSKristof Provost 			int aclen = strlen(anchor_call);
1184ed5eb77eSKristof Provost 			if (anchor_call[aclen - 1] == '*')
1185ed5eb77eSKristof Provost 				anchor_call[aclen - 2] = '\0';
1186ed5eb77eSKristof Provost 		}
1187c5131afeSKristof Provost 		p = &anchor_call[0];
11882b29ceb8SKristof Provost 		if (dotitle) {
11892b29ceb8SKristof Provost 			pfctl_print_title("ETH RULES:");
11902b29ceb8SKristof Provost 			dotitle = 0;
11912b29ceb8SKristof Provost 		}
1192c5131afeSKristof Provost 		print_eth_rule(&rule, anchor_call,
1193c5131afeSKristof Provost 		    opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG));
1194c5131afeSKristof Provost 		if (brace)
1195c5131afeSKristof Provost 			printf(" {\n");
1196c5131afeSKristof Provost 		else
11972b29ceb8SKristof Provost 			printf("\n");
11982b29ceb8SKristof Provost 		pfctl_print_eth_rule_counters(&rule, opts);
1199c5131afeSKristof Provost 		if (brace) {
1200c5131afeSKristof Provost 			pfctl_show_eth_rules(dev, path, opts, format,
1201cfa1a130SKristof Provost 			    p, depth + 1, rule.anchor_wildcard);
1202c5131afeSKristof Provost 			INDENT(depth, !(opts & PF_OPT_VERBOSE));
1203c5131afeSKristof Provost 			printf("}\n");
1204c5131afeSKristof Provost 		}
12052b29ceb8SKristof Provost 	}
12062b29ceb8SKristof Provost 
1207c5131afeSKristof Provost 	path[len] = '\0';
12082b29ceb8SKristof Provost 	return (0);
12092b29ceb8SKristof Provost }
12102b29ceb8SKristof Provost 
12112b29ceb8SKristof Provost int
12123b3a8eb9SGleb Smirnoff pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
1213585a5ed0SKristof Provost     char *anchorname, int depth, int wildcard)
12143b3a8eb9SGleb Smirnoff {
12158c1400b0SKristof Provost 	struct pfctl_rules_info ri;
1216e9eb0941SKristof Provost 	struct pfctl_rule rule;
12178c1400b0SKristof Provost 	char anchor_call[MAXPATHLEN];
12188c1400b0SKristof Provost 	u_int32_t nr, header = 0;
12193b3a8eb9SGleb Smirnoff 	int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
12203b3a8eb9SGleb Smirnoff 	int numeric = opts & PF_OPT_NUMERIC;
1221585a5ed0SKristof Provost 	int len = strlen(path), ret = 0;
1222585a5ed0SKristof Provost 	char *npath, *p;
12233b3a8eb9SGleb Smirnoff 
1224585a5ed0SKristof Provost 	/*
1225585a5ed0SKristof Provost 	 * Truncate a trailing / and * on an anchorname before searching for
1226585a5ed0SKristof Provost 	 * the ruleset, this is syntactic sugar that doesn't actually make it
1227585a5ed0SKristof Provost 	 * to the kernel.
1228585a5ed0SKristof Provost 	 */
1229585a5ed0SKristof Provost 	if ((p = strrchr(anchorname, '/')) != NULL &&
1230585a5ed0SKristof Provost 	    p[1] == '*' && p[2] == '\0') {
1231585a5ed0SKristof Provost 		p[0] = '\0';
1232585a5ed0SKristof Provost 	}
1233585a5ed0SKristof Provost 
1234585a5ed0SKristof Provost 	if (anchorname[0] == '/') {
1235585a5ed0SKristof Provost 		if ((npath = calloc(1, MAXPATHLEN)) == NULL)
1236585a5ed0SKristof Provost 			errx(1, "pfctl_rules: calloc");
1237a8136ab4SKristof Provost 		strlcpy(npath, anchorname, MAXPATHLEN);
1238585a5ed0SKristof Provost 	} else {
12393b3a8eb9SGleb Smirnoff 		if (path[0])
12403b3a8eb9SGleb Smirnoff 			snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
12413b3a8eb9SGleb Smirnoff 		else
12423b3a8eb9SGleb Smirnoff 			snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
1243585a5ed0SKristof Provost 		npath = path;
1244585a5ed0SKristof Provost 	}
1245585a5ed0SKristof Provost 
1246585a5ed0SKristof Provost 	/*
1247585a5ed0SKristof Provost 	 * If this anchor was called with a wildcard path, go through
1248585a5ed0SKristof Provost 	 * the rulesets in the anchor rather than the rules.
1249585a5ed0SKristof Provost 	 */
1250585a5ed0SKristof Provost 	if (wildcard && (opts & PF_OPT_RECURSE)) {
1251585a5ed0SKristof Provost 		struct pfioc_ruleset     prs;
1252585a5ed0SKristof Provost 		u_int32_t                mnr, nr;
1253585a5ed0SKristof Provost 
1254585a5ed0SKristof Provost 		memset(&prs, 0, sizeof(prs));
125525e0f8f9SKristof Provost 		if ((ret = pfctl_get_rulesets(pfh, npath, &mnr)) != 0) {
125625e0f8f9SKristof Provost 			if (ret == EINVAL)
1257585a5ed0SKristof Provost 				fprintf(stderr, "Anchor '%s' "
1258585a5ed0SKristof Provost 				    "not found.\n", anchorname);
1259585a5ed0SKristof Provost 			else
126025e0f8f9SKristof Provost 				errc(1, ret, "DIOCGETRULESETS");
1261585a5ed0SKristof Provost 		}
1262585a5ed0SKristof Provost 
1263585a5ed0SKristof Provost 		pfctl_print_rule_counters(&rule, opts);
1264585a5ed0SKristof Provost 		for (nr = 0; nr < mnr; ++nr) {
126548f5bf8bSKristof Provost 			if ((ret = pfctl_get_ruleset(pfh, npath, nr, &prs)) != 0)
126648f5bf8bSKristof Provost 				errc(1, ret, "DIOCGETRULESET");
1267585a5ed0SKristof Provost 			INDENT(depth, !(opts & PF_OPT_VERBOSE));
1268585a5ed0SKristof Provost 			printf("anchor \"%s\" all {\n", prs.name);
1269585a5ed0SKristof Provost 			pfctl_show_rules(dev, npath, opts,
1270585a5ed0SKristof Provost 			    format, prs.name, depth + 1, 0);
1271585a5ed0SKristof Provost 			INDENT(depth, !(opts & PF_OPT_VERBOSE));
1272585a5ed0SKristof Provost 			printf("}\n");
1273585a5ed0SKristof Provost 		}
1274585a5ed0SKristof Provost 		path[len] = '\0';
1275585a5ed0SKristof Provost 		return (0);
1276585a5ed0SKristof Provost 	}
12773b3a8eb9SGleb Smirnoff 
12783b3a8eb9SGleb Smirnoff 	if (opts & PF_OPT_SHOWALL) {
1279f1612e70SKristof Provost 		ret = pfctl_get_rules_info_h(pfh, &ri, PF_PASS, path);
12808c1400b0SKristof Provost 		if (ret != 0) {
1281375aaa29SKristof Provost 			warnc(ret, "DIOCGETRULES");
12823b3a8eb9SGleb Smirnoff 			goto error;
12833b3a8eb9SGleb Smirnoff 		}
12843b3a8eb9SGleb Smirnoff 		header++;
12853b3a8eb9SGleb Smirnoff 	}
1286f1612e70SKristof Provost 	ret = pfctl_get_rules_info_h(pfh, &ri, PF_SCRUB, path);
12878c1400b0SKristof Provost 	if (ret != 0) {
1288375aaa29SKristof Provost 		warnc(ret, "DIOCGETRULES");
12893b3a8eb9SGleb Smirnoff 		goto error;
12903b3a8eb9SGleb Smirnoff 	}
12913b3a8eb9SGleb Smirnoff 	if (opts & PF_OPT_SHOWALL) {
12928c1400b0SKristof Provost 		if (format == PFCTL_SHOW_RULES && (ri.nr > 0 || header))
12933b3a8eb9SGleb Smirnoff 			pfctl_print_title("FILTER RULES:");
12943b3a8eb9SGleb Smirnoff 		else if (format == PFCTL_SHOW_LABELS && labels)
12953b3a8eb9SGleb Smirnoff 			pfctl_print_title("LABEL COUNTERS:");
12963b3a8eb9SGleb Smirnoff 	}
12973b3a8eb9SGleb Smirnoff 
12988c1400b0SKristof Provost 	for (nr = 0; nr < ri.nr; ++nr) {
1299375aaa29SKristof Provost 		if ((ret = pfctl_get_clear_rule_h(pfh, nr, ri.ticket, path, PF_SCRUB,
1300375aaa29SKristof Provost 		    &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) != 0) {
1301375aaa29SKristof Provost 			warnc(ret, "DIOCGETRULENV");
13023b3a8eb9SGleb Smirnoff 			goto error;
13033b3a8eb9SGleb Smirnoff 		}
13043b3a8eb9SGleb Smirnoff 
1305096efeb6SKristof Provost 		if (pfctl_get_pool(dev, &rule.rdr,
1306aa69fdf1SKristof Provost 		    nr, ri.ticket, PF_SCRUB, path, PF_RDR) != 0)
1307aa69fdf1SKristof Provost 			goto error;
1308aa69fdf1SKristof Provost 
1309aa69fdf1SKristof Provost 		if (pfctl_get_pool(dev, &rule.nat,
1310aa69fdf1SKristof Provost 		    nr, ri.ticket, PF_SCRUB, path, PF_NAT) != 0)
13113b3a8eb9SGleb Smirnoff 			goto error;
13123b3a8eb9SGleb Smirnoff 
1313*0972294eSKristof Provost 		if (pfctl_get_pool(dev, &rule.route,
1314*0972294eSKristof Provost 		    nr, ri.ticket, PF_SCRUB, path, PF_RT) != 0)
1315*0972294eSKristof Provost 			goto error;
1316*0972294eSKristof Provost 
13173b3a8eb9SGleb Smirnoff 		switch (format) {
13183b3a8eb9SGleb Smirnoff 		case PFCTL_SHOW_LABELS:
13193b3a8eb9SGleb Smirnoff 			break;
13203b3a8eb9SGleb Smirnoff 		case PFCTL_SHOW_RULES:
1321cd80c52cSKristof Provost 			if (rule.label[0][0] && (opts & PF_OPT_SHOWALL))
13223b3a8eb9SGleb Smirnoff 				labels = 1;
13238c1400b0SKristof Provost 			print_rule(&rule, anchor_call, rule_numbers, numeric);
13243b3a8eb9SGleb Smirnoff 			printf("\n");
1325e9eb0941SKristof Provost 			pfctl_print_rule_counters(&rule, opts);
13263b3a8eb9SGleb Smirnoff 			break;
13273b3a8eb9SGleb Smirnoff 		case PFCTL_SHOW_NOTHING:
13283b3a8eb9SGleb Smirnoff 			break;
13293b3a8eb9SGleb Smirnoff 		}
1330096efeb6SKristof Provost 		pfctl_clear_pool(&rule.rdr);
13315cb08fddSKristof Provost 		pfctl_clear_pool(&rule.nat);
1332*0972294eSKristof Provost 		pfctl_clear_pool(&rule.route);
13333b3a8eb9SGleb Smirnoff 	}
1334f1612e70SKristof Provost 	ret = pfctl_get_rules_info_h(pfh, &ri, PF_PASS, path);
13358c1400b0SKristof Provost 	if (ret != 0) {
1336375aaa29SKristof Provost 		warnc(ret, "DIOCGETRULES");
13373b3a8eb9SGleb Smirnoff 		goto error;
13383b3a8eb9SGleb Smirnoff 	}
13398c1400b0SKristof Provost 	for (nr = 0; nr < ri.nr; ++nr) {
1340375aaa29SKristof Provost 		if ((ret = pfctl_get_clear_rule_h(pfh, nr, ri.ticket, path, PF_PASS,
1341375aaa29SKristof Provost 		    &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) != 0) {
1342375aaa29SKristof Provost 			warnc(ret, "DIOCGETRULE");
13433b3a8eb9SGleb Smirnoff 			goto error;
13443b3a8eb9SGleb Smirnoff 		}
13453b3a8eb9SGleb Smirnoff 
1346096efeb6SKristof Provost 		if (pfctl_get_pool(dev, &rule.rdr,
1347aa69fdf1SKristof Provost 		    nr, ri.ticket, PF_PASS, path, PF_RDR) != 0)
1348aa69fdf1SKristof Provost 			goto error;
1349aa69fdf1SKristof Provost 
1350aa69fdf1SKristof Provost 		if (pfctl_get_pool(dev, &rule.nat,
1351aa69fdf1SKristof Provost 		    nr, ri.ticket, PF_PASS, path, PF_NAT) != 0)
13523b3a8eb9SGleb Smirnoff 			goto error;
13533b3a8eb9SGleb Smirnoff 
1354*0972294eSKristof Provost 		if (pfctl_get_pool(dev, &rule.route,
1355*0972294eSKristof Provost 		    nr, ri.ticket, PF_PASS, path, PF_RT) != 0)
1356*0972294eSKristof Provost 			goto error;
1357*0972294eSKristof Provost 
13583b3a8eb9SGleb Smirnoff 		switch (format) {
13596fcc8e04SKristof Provost 		case PFCTL_SHOW_LABELS: {
13606fcc8e04SKristof Provost 			bool show = false;
13616fcc8e04SKristof Provost 			int i = 0;
13626fcc8e04SKristof Provost 
13636fcc8e04SKristof Provost 			while (rule.label[i][0]) {
13646fcc8e04SKristof Provost 				printf("%s ", rule.label[i++]);
13656fcc8e04SKristof Provost 				show = true;
13666fcc8e04SKristof Provost 			}
13676fcc8e04SKristof Provost 
13686fcc8e04SKristof Provost 			if (show) {
13696fcc8e04SKristof Provost 				printf("%llu %llu %llu %llu"
13705a9ab487SGleb Smirnoff 				    " %llu %llu %llu %ju\n",
1371e9eb0941SKristof Provost 				    (unsigned long long)rule.evaluations,
1372e9eb0941SKristof Provost 				    (unsigned long long)(rule.packets[0] +
1373e9eb0941SKristof Provost 				    rule.packets[1]),
1374e9eb0941SKristof Provost 				    (unsigned long long)(rule.bytes[0] +
1375e9eb0941SKristof Provost 				    rule.bytes[1]),
1376e9eb0941SKristof Provost 				    (unsigned long long)rule.packets[0],
1377e9eb0941SKristof Provost 				    (unsigned long long)rule.bytes[0],
1378e9eb0941SKristof Provost 				    (unsigned long long)rule.packets[1],
1379e9eb0941SKristof Provost 				    (unsigned long long)rule.bytes[1],
1380ab5707a5SKristof Provost 				    (uintmax_t)rule.states_tot);
13813b3a8eb9SGleb Smirnoff 			}
13820187875aSLuiz Amaral 
13830187875aSLuiz Amaral 			if (anchor_call[0] &&
13840187875aSLuiz Amaral 			    (((p = strrchr(anchor_call, '/')) ?
13850187875aSLuiz Amaral 			      p[1] == '_' : anchor_call[0] == '_') ||
13860187875aSLuiz Amaral 			     opts & PF_OPT_RECURSE)) {
13870187875aSLuiz Amaral 				pfctl_show_rules(dev, npath, opts, format,
13880187875aSLuiz Amaral 				    anchor_call, depth, rule.anchor_wildcard);
13890187875aSLuiz Amaral 			}
13903b3a8eb9SGleb Smirnoff 			break;
13916fcc8e04SKristof Provost 		}
13923b3a8eb9SGleb Smirnoff 		case PFCTL_SHOW_RULES:
1393cd80c52cSKristof Provost 			if (rule.label[0][0] && (opts & PF_OPT_SHOWALL))
13943b3a8eb9SGleb Smirnoff 				labels = 1;
13953b3a8eb9SGleb Smirnoff 			INDENT(depth, !(opts & PF_OPT_VERBOSE));
1396585a5ed0SKristof Provost 			print_rule(&rule, anchor_call, rule_numbers, numeric);
13973b3a8eb9SGleb Smirnoff 
1398585a5ed0SKristof Provost 			/*
1399585a5ed0SKristof Provost 			 * If this is a 'unnamed' brace notation
1400585a5ed0SKristof Provost 			 * anchor, OR the user has explicitly requested
1401585a5ed0SKristof Provost 			 * recursion, print it recursively.
1402585a5ed0SKristof Provost 			 */
1403585a5ed0SKristof Provost 			if (anchor_call[0] &&
1404585a5ed0SKristof Provost 			    (((p = strrchr(anchor_call, '/')) ?
1405585a5ed0SKristof Provost 			      p[1] == '_' : anchor_call[0] == '_') ||
1406585a5ed0SKristof Provost 			     opts & PF_OPT_RECURSE)) {
14073b3a8eb9SGleb Smirnoff 				printf(" {\n");
1408e9eb0941SKristof Provost 				pfctl_print_rule_counters(&rule, opts);
1409585a5ed0SKristof Provost 				pfctl_show_rules(dev, npath, opts, format,
1410585a5ed0SKristof Provost 				    anchor_call, depth + 1,
1411585a5ed0SKristof Provost 				    rule.anchor_wildcard);
14123b3a8eb9SGleb Smirnoff 				INDENT(depth, !(opts & PF_OPT_VERBOSE));
14133b3a8eb9SGleb Smirnoff 				printf("}\n");
1414585a5ed0SKristof Provost 			} else {
1415585a5ed0SKristof Provost 				printf("\n");
1416585a5ed0SKristof Provost 				pfctl_print_rule_counters(&rule, opts);
14173b3a8eb9SGleb Smirnoff 			}
14183b3a8eb9SGleb Smirnoff 			break;
14193b3a8eb9SGleb Smirnoff 		case PFCTL_SHOW_NOTHING:
14203b3a8eb9SGleb Smirnoff 			break;
14213b3a8eb9SGleb Smirnoff 		}
1422096efeb6SKristof Provost 		pfctl_clear_pool(&rule.rdr);
14235cb08fddSKristof Provost 		pfctl_clear_pool(&rule.nat);
14243b3a8eb9SGleb Smirnoff 	}
14253b3a8eb9SGleb Smirnoff 
14263b3a8eb9SGleb Smirnoff  error:
14273b3a8eb9SGleb Smirnoff 	path[len] = '\0';
1428585a5ed0SKristof Provost 	return (ret);
14293b3a8eb9SGleb Smirnoff }
14303b3a8eb9SGleb Smirnoff 
14313b3a8eb9SGleb Smirnoff int
14328ddd0359SKristof Provost pfctl_show_nat(int dev, char *path, int opts, char *anchorname, int depth,
14338ddd0359SKristof Provost     int wildcard)
14343b3a8eb9SGleb Smirnoff {
14358c1400b0SKristof Provost 	struct pfctl_rules_info ri;
1436e9eb0941SKristof Provost 	struct pfctl_rule rule;
14378c1400b0SKristof Provost 	char anchor_call[MAXPATHLEN];
14388c1400b0SKristof Provost 	u_int32_t nr;
14393b3a8eb9SGleb Smirnoff 	static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT };
14403b3a8eb9SGleb Smirnoff 	int i, dotitle = opts & PF_OPT_SHOWALL;
14418ddd0359SKristof Provost 	int ret;
1442a632d9e3SKristof Provost 	int len = strlen(path);
14438ddd0359SKristof Provost 	char *npath, *p;
14443b3a8eb9SGleb Smirnoff 
14458ddd0359SKristof Provost 	/*
14468ddd0359SKristof Provost 	 * Truncate a trailing / and * on an anchorname before searching for
14478ddd0359SKristof Provost 	 * the ruleset, this is syntactic sugar that doesn't actually make it
14488ddd0359SKristof Provost 	 * to the kernel.
14498ddd0359SKristof Provost 	 */
14508ddd0359SKristof Provost 	if ((p = strrchr(anchorname, '/')) != NULL &&
14518ddd0359SKristof Provost 	    p[1] == '*' && p[2] == '\0') {
14528ddd0359SKristof Provost 		p[0] = '\0';
14538ddd0359SKristof Provost 	}
14548ddd0359SKristof Provost 
14558ddd0359SKristof Provost 	if (anchorname[0] == '/') {
14568ddd0359SKristof Provost 		if ((npath = calloc(1, MAXPATHLEN)) == NULL)
14578ddd0359SKristof Provost 			errx(1, "pfctl_rules: calloc");
14588ddd0359SKristof Provost 		snprintf(npath, MAXPATHLEN, "%s", anchorname);
14598ddd0359SKristof Provost 	} else {
1460a632d9e3SKristof Provost 		if (path[0])
1461a632d9e3SKristof Provost 			snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
1462a632d9e3SKristof Provost 		else
1463a632d9e3SKristof Provost 			snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
14648ddd0359SKristof Provost 		npath = path;
14658ddd0359SKristof Provost 	}
14668ddd0359SKristof Provost 
14678ddd0359SKristof Provost 	/*
14688ddd0359SKristof Provost 	 * If this anchor was called with a wildcard path, go through
14698ddd0359SKristof Provost 	 * the rulesets in the anchor rather than the rules.
14708ddd0359SKristof Provost 	 */
14718ddd0359SKristof Provost 	if (wildcard && (opts & PF_OPT_RECURSE)) {
14728ddd0359SKristof Provost 		struct pfioc_ruleset     prs;
14738ddd0359SKristof Provost 		u_int32_t                mnr, nr;
14748ddd0359SKristof Provost 		memset(&prs, 0, sizeof(prs));
147525e0f8f9SKristof Provost 		if ((ret = pfctl_get_rulesets(pfh, npath, &mnr)) != 0) {
147625e0f8f9SKristof Provost 			if (ret == EINVAL)
14778ddd0359SKristof Provost 				fprintf(stderr, "NAT anchor '%s' "
14788ddd0359SKristof Provost 				    "not found.\n", anchorname);
14798ddd0359SKristof Provost 			else
148025e0f8f9SKristof Provost 				errc(1, ret, "DIOCGETRULESETS");
14818ddd0359SKristof Provost 		}
14828ddd0359SKristof Provost 
14838ddd0359SKristof Provost 		pfctl_print_rule_counters(&rule, opts);
14848ddd0359SKristof Provost 		for (nr = 0; nr < mnr; ++nr) {
148548f5bf8bSKristof Provost 			if ((ret = pfctl_get_ruleset(pfh, npath, nr, &prs)) != 0)
148648f5bf8bSKristof Provost 				errc(1, ret, "DIOCGETRULESET");
14878ddd0359SKristof Provost 			INDENT(depth, !(opts & PF_OPT_VERBOSE));
14888ddd0359SKristof Provost 			printf("nat-anchor \"%s\" all {\n", prs.name);
14898ddd0359SKristof Provost 			pfctl_show_nat(dev, npath, opts,
14908ddd0359SKristof Provost 			    prs.name, depth + 1, 0);
14918ddd0359SKristof Provost 			INDENT(depth, !(opts & PF_OPT_VERBOSE));
14928ddd0359SKristof Provost 			printf("}\n");
14938ddd0359SKristof Provost 		}
14948ddd0359SKristof Provost 		path[len] = '\0';
14958ddd0359SKristof Provost 		return (0);
14968ddd0359SKristof Provost 	}
1497a632d9e3SKristof Provost 
1498a20773c8SKristof Provost 	for (i = 0; i < 3; i++) {
1499f1612e70SKristof Provost 		ret = pfctl_get_rules_info_h(pfh, &ri, nattype[i], path);
15008c1400b0SKristof Provost 		if (ret != 0) {
1501375aaa29SKristof Provost 			warnc(ret, "DIOCGETRULES");
15023b3a8eb9SGleb Smirnoff 			return (-1);
15033b3a8eb9SGleb Smirnoff 		}
15048c1400b0SKristof Provost 		for (nr = 0; nr < ri.nr; ++nr) {
1505a20773c8SKristof Provost 			INDENT(depth, !(opts & PF_OPT_VERBOSE));
1506a20773c8SKristof Provost 
1507375aaa29SKristof Provost 			if ((ret = pfctl_get_rule_h(pfh, nr, ri.ticket, path,
1508375aaa29SKristof Provost 			    nattype[i], &rule, anchor_call)) != 0) {
1509375aaa29SKristof Provost 				warnc(ret, "DIOCGETRULE");
15103b3a8eb9SGleb Smirnoff 				return (-1);
15113b3a8eb9SGleb Smirnoff 			}
1512096efeb6SKristof Provost 			if (pfctl_get_pool(dev, &rule.rdr, nr,
1513aa69fdf1SKristof Provost 			    ri.ticket, nattype[i], path, PF_RDR) != 0)
1514aa69fdf1SKristof Provost 				return (-1);
1515aa69fdf1SKristof Provost 			if (pfctl_get_pool(dev, &rule.nat, nr,
1516aa69fdf1SKristof Provost 			    ri.ticket, nattype[i], path, PF_NAT) != 0)
15173b3a8eb9SGleb Smirnoff 				return (-1);
1518*0972294eSKristof Provost 			if (pfctl_get_pool(dev, &rule.route, nr,
1519*0972294eSKristof Provost 			    ri.ticket, nattype[i], path, PF_RT) != 0)
1520*0972294eSKristof Provost 				return (-1);
1521a20773c8SKristof Provost 
15223b3a8eb9SGleb Smirnoff 			if (dotitle) {
15233b3a8eb9SGleb Smirnoff 				pfctl_print_title("TRANSLATION RULES:");
15243b3a8eb9SGleb Smirnoff 				dotitle = 0;
15253b3a8eb9SGleb Smirnoff 			}
15268c1400b0SKristof Provost 			print_rule(&rule, anchor_call,
15273b3a8eb9SGleb Smirnoff 			    opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC);
15288ddd0359SKristof Provost 			if (anchor_call[0] &&
15298ddd0359SKristof Provost 			    (((p = strrchr(anchor_call, '/')) ?
15308ddd0359SKristof Provost 			      p[1] == '_' : anchor_call[0] == '_') ||
15318ddd0359SKristof Provost 			     opts & PF_OPT_RECURSE)) {
1532a20773c8SKristof Provost 				printf(" {\n");
1533e9eb0941SKristof Provost 				pfctl_print_rule_counters(&rule, opts);
15348ddd0359SKristof Provost 				pfctl_show_nat(dev, npath, opts, anchor_call,
15358ddd0359SKristof Provost 				    depth + 1, rule.anchor_wildcard);
1536a20773c8SKristof Provost 				INDENT(depth, !(opts & PF_OPT_VERBOSE));
1537a20773c8SKristof Provost 				printf("}\n");
15388ddd0359SKristof Provost 			} else {
15398ddd0359SKristof Provost 				printf("\n");
15408ddd0359SKristof Provost 				pfctl_print_rule_counters(&rule, opts);
1541a20773c8SKristof Provost 			}
15423b3a8eb9SGleb Smirnoff 		}
15433b3a8eb9SGleb Smirnoff 	}
15443b3a8eb9SGleb Smirnoff 	return (0);
15453b3a8eb9SGleb Smirnoff }
15463b3a8eb9SGleb Smirnoff 
15479c125336SKristof Provost static int
15489c125336SKristof Provost pfctl_print_src_node(struct pfctl_src_node *sn, void *arg)
15499c125336SKristof Provost {
15509c125336SKristof Provost 	int *opts = (int *)arg;
15519c125336SKristof Provost 
15529c125336SKristof Provost 	if (*opts & PF_OPT_SHOWALL) {
15539c125336SKristof Provost 		pfctl_print_title("SOURCE TRACKING NODES:");
15549c125336SKristof Provost 		*opts &= ~PF_OPT_SHOWALL;
15559c125336SKristof Provost 	}
15569c125336SKristof Provost 
15579c125336SKristof Provost 	print_src_node(sn, *opts);
15589c125336SKristof Provost 
15599c125336SKristof Provost 	return (0);
15609c125336SKristof Provost }
15619c125336SKristof Provost 
15623b3a8eb9SGleb Smirnoff int
15633b3a8eb9SGleb Smirnoff pfctl_show_src_nodes(int dev, int opts)
15643b3a8eb9SGleb Smirnoff {
15659c125336SKristof Provost 	int error;
15663b3a8eb9SGleb Smirnoff 
15679c125336SKristof Provost 	error = pfctl_get_srcnodes(pfh, pfctl_print_src_node, &opts);
15689c125336SKristof Provost 
15699c125336SKristof Provost 	return (error);
15703b3a8eb9SGleb Smirnoff }
15713b3a8eb9SGleb Smirnoff 
1572f218b851SKristof Provost struct pfctl_show_state_arg {
1573f218b851SKristof Provost 	int opts;
1574f218b851SKristof Provost 	int dotitle;
1575f218b851SKristof Provost 	const char *iface;
1576f218b851SKristof Provost };
1577f218b851SKristof Provost 
1578f218b851SKristof Provost static int
1579f218b851SKristof Provost pfctl_show_state(struct pfctl_state *s, void *arg)
1580f218b851SKristof Provost {
1581f218b851SKristof Provost 	struct pfctl_show_state_arg *a = (struct pfctl_show_state_arg *)arg;
1582f218b851SKristof Provost 
1583f218b851SKristof Provost 	if (a->dotitle) {
1584f218b851SKristof Provost 		pfctl_print_title("STATES:");
1585f218b851SKristof Provost 		a->dotitle = 0;
1586f218b851SKristof Provost 	}
1587f218b851SKristof Provost 	print_state(s, a->opts);
1588f218b851SKristof Provost 
1589f218b851SKristof Provost 	return (0);
1590f218b851SKristof Provost }
1591f218b851SKristof Provost 
15923b3a8eb9SGleb Smirnoff int
15933b3a8eb9SGleb Smirnoff pfctl_show_states(int dev, const char *iface, int opts)
15943b3a8eb9SGleb Smirnoff {
1595f218b851SKristof Provost 	struct pfctl_show_state_arg arg;
1596044eef6aSKristof Provost 	struct pfctl_state_filter filter = {};
1597044eef6aSKristof Provost 
1598044eef6aSKristof Provost 	if (iface != NULL)
1599044eef6aSKristof Provost 		strncpy(filter.ifname, iface, IFNAMSIZ);
16003b3a8eb9SGleb Smirnoff 
1601f218b851SKristof Provost 	arg.opts = opts;
1602f218b851SKristof Provost 	arg.dotitle = opts & PF_OPT_SHOWALL;
1603f218b851SKristof Provost 	arg.iface = iface;
1604bc941291SKristof Provost 
1605044eef6aSKristof Provost 	if (pfctl_get_filtered_states_iter(&filter, pfctl_show_state, &arg))
16063b3a8eb9SGleb Smirnoff 		return (-1);
1607bc941291SKristof Provost 
16083b3a8eb9SGleb Smirnoff 	return (0);
16093b3a8eb9SGleb Smirnoff }
16103b3a8eb9SGleb Smirnoff 
16113b3a8eb9SGleb Smirnoff int
16123b3a8eb9SGleb Smirnoff pfctl_show_status(int dev, int opts)
16133b3a8eb9SGleb Smirnoff {
161480078d9dSKristof Provost 	struct pfctl_status	*status;
1615c69121c4SKristof Provost 	struct pfctl_syncookies	cookies;
1616375aaa29SKristof Provost 	int ret;
16173b3a8eb9SGleb Smirnoff 
16185824df8dSKristof Provost 	if ((status = pfctl_get_status_h(pfh)) == NULL) {
16193b3a8eb9SGleb Smirnoff 		warn("DIOCGETSTATUS");
16203b3a8eb9SGleb Smirnoff 		return (-1);
16213b3a8eb9SGleb Smirnoff 	}
1622375aaa29SKristof Provost 	if ((ret = pfctl_get_syncookies(dev, &cookies)) != 0) {
162380078d9dSKristof Provost 		pfctl_free_status(status);
1624375aaa29SKristof Provost 		warnc(ret, "DIOCGETSYNCOOKIES");
1625c69121c4SKristof Provost 		return (-1);
1626c69121c4SKristof Provost 	}
16273b3a8eb9SGleb Smirnoff 	if (opts & PF_OPT_SHOWALL)
16283b3a8eb9SGleb Smirnoff 		pfctl_print_title("INFO:");
162980078d9dSKristof Provost 	print_status(status, &cookies, opts);
163080078d9dSKristof Provost 	pfctl_free_status(status);
16313b3a8eb9SGleb Smirnoff 	return (0);
16323b3a8eb9SGleb Smirnoff }
16333b3a8eb9SGleb Smirnoff 
16343b3a8eb9SGleb Smirnoff int
1635fa1d4439SKristof Provost pfctl_show_running(int dev)
1636fa1d4439SKristof Provost {
163780078d9dSKristof Provost 	struct pfctl_status *status;
163880078d9dSKristof Provost 	int running;
1639fa1d4439SKristof Provost 
16405824df8dSKristof Provost 	if ((status = pfctl_get_status_h(pfh)) == NULL) {
1641fa1d4439SKristof Provost 		warn("DIOCGETSTATUS");
1642fa1d4439SKristof Provost 		return (-1);
1643fa1d4439SKristof Provost 	}
1644fa1d4439SKristof Provost 
164580078d9dSKristof Provost 	running = status->running;
164680078d9dSKristof Provost 
164780078d9dSKristof Provost 	print_running(status);
164880078d9dSKristof Provost 	pfctl_free_status(status);
164980078d9dSKristof Provost 	return (!running);
1650fa1d4439SKristof Provost }
1651fa1d4439SKristof Provost 
1652fa1d4439SKristof Provost int
16533b3a8eb9SGleb Smirnoff pfctl_show_timeouts(int dev, int opts)
16543b3a8eb9SGleb Smirnoff {
165530bad751SKristof Provost 	uint32_t seconds;
16563b3a8eb9SGleb Smirnoff 	int i;
1657375aaa29SKristof Provost 	int ret;
16583b3a8eb9SGleb Smirnoff 
16593b3a8eb9SGleb Smirnoff 	if (opts & PF_OPT_SHOWALL)
16603b3a8eb9SGleb Smirnoff 		pfctl_print_title("TIMEOUTS:");
16613b3a8eb9SGleb Smirnoff 	for (i = 0; pf_timeouts[i].name; i++) {
1662375aaa29SKristof Provost 		if ((ret = pfctl_get_timeout(pfh, pf_timeouts[i].timeout, &seconds)) != 0)
1663375aaa29SKristof Provost 			errc(1, ret, "DIOCGETTIMEOUT");
166430bad751SKristof Provost 		printf("%-20s %10d", pf_timeouts[i].name, seconds);
16653b3a8eb9SGleb Smirnoff 		if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START &&
16663b3a8eb9SGleb Smirnoff 		    pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END)
16673b3a8eb9SGleb Smirnoff 			printf(" states");
16683b3a8eb9SGleb Smirnoff 		else
16693b3a8eb9SGleb Smirnoff 			printf("s");
16703b3a8eb9SGleb Smirnoff 		printf("\n");
16713b3a8eb9SGleb Smirnoff 	}
16723b3a8eb9SGleb Smirnoff 	return (0);
16733b3a8eb9SGleb Smirnoff 
16743b3a8eb9SGleb Smirnoff }
16753b3a8eb9SGleb Smirnoff 
16763b3a8eb9SGleb Smirnoff int
16773b3a8eb9SGleb Smirnoff pfctl_show_limits(int dev, int opts)
16783b3a8eb9SGleb Smirnoff {
1679d9ab8999SKristof Provost 	unsigned int limit;
16803b3a8eb9SGleb Smirnoff 	int i;
1681375aaa29SKristof Provost 	int ret;
16823b3a8eb9SGleb Smirnoff 
16833b3a8eb9SGleb Smirnoff 	if (opts & PF_OPT_SHOWALL)
16843b3a8eb9SGleb Smirnoff 		pfctl_print_title("LIMITS:");
16853b3a8eb9SGleb Smirnoff 	for (i = 0; pf_limits[i].name; i++) {
1686375aaa29SKristof Provost 		if ((ret = pfctl_get_limit(pfh, pf_limits[i].index, &limit)) != 0)
1687375aaa29SKristof Provost 			errc(1, ret, "DIOCGETLIMIT");
16883b3a8eb9SGleb Smirnoff 		printf("%-13s ", pf_limits[i].name);
1689d9ab8999SKristof Provost 		if (limit == UINT_MAX)
16903b3a8eb9SGleb Smirnoff 			printf("unlimited\n");
16913b3a8eb9SGleb Smirnoff 		else
1692d9ab8999SKristof Provost 			printf("hard limit %8u\n", limit);
16933b3a8eb9SGleb Smirnoff 	}
16943b3a8eb9SGleb Smirnoff 	return (0);
16953b3a8eb9SGleb Smirnoff }
16963b3a8eb9SGleb Smirnoff 
1697a7191e5dSKristof Provost void
1698a7191e5dSKristof Provost pfctl_show_creators(int opts)
1699a7191e5dSKristof Provost {
1700a7191e5dSKristof Provost 	int ret;
1701a7191e5dSKristof Provost 	uint32_t creators[16];
1702a7191e5dSKristof Provost 	size_t count = nitems(creators);
1703a7191e5dSKristof Provost 
170466cacc14SKristof Provost 	ret = pfctl_get_creatorids(pfh, creators, &count);
1705a7191e5dSKristof Provost 	if (ret != 0)
1706a7191e5dSKristof Provost 		errx(ret, "Failed to retrieve creators");
1707a7191e5dSKristof Provost 
1708a7191e5dSKristof Provost 	printf("Creator IDs:\n");
1709a7191e5dSKristof Provost 	for (size_t i = 0; i < count; i++)
1710a7191e5dSKristof Provost 		printf("%08x\n", creators[i]);
1711a7191e5dSKristof Provost }
1712a7191e5dSKristof Provost 
17133b3a8eb9SGleb Smirnoff /* callbacks for rule/nat/rdr/addr */
17143b3a8eb9SGleb Smirnoff int
1715e11dacbfSKristof Provost pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af, int which)
17163b3a8eb9SGleb Smirnoff {
17173b3a8eb9SGleb Smirnoff 	struct pf_pooladdr *pa;
1718375aaa29SKristof Provost 	int ret;
17193b3a8eb9SGleb Smirnoff 
17203b3a8eb9SGleb Smirnoff 	pf->paddr.af = af;
17213b3a8eb9SGleb Smirnoff 	TAILQ_FOREACH(pa, &p->list, entries) {
17223b3a8eb9SGleb Smirnoff 		memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr));
17233b3a8eb9SGleb Smirnoff 		if ((pf->opts & PF_OPT_NOACTION) == 0) {
1724e11dacbfSKristof Provost 			if ((ret = pfctl_add_addr(pf->h, &pf->paddr, which)) != 0)
1725375aaa29SKristof Provost 				errc(1, ret, "DIOCADDADDR");
17263b3a8eb9SGleb Smirnoff 		}
17273b3a8eb9SGleb Smirnoff 	}
17283b3a8eb9SGleb Smirnoff 	return (0);
17293b3a8eb9SGleb Smirnoff }
17303b3a8eb9SGleb Smirnoff 
17313b3a8eb9SGleb Smirnoff int
1732e9eb0941SKristof Provost pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r,
1733e9eb0941SKristof Provost     const char *anchor_call)
17343b3a8eb9SGleb Smirnoff {
17353b3a8eb9SGleb Smirnoff 	u_int8_t		rs_num;
1736e9eb0941SKristof Provost 	struct pfctl_rule	*rule;
1737e9eb0941SKristof Provost 	struct pfctl_ruleset	*rs;
17383b3a8eb9SGleb Smirnoff 	char 			*p;
17393b3a8eb9SGleb Smirnoff 
17403b3a8eb9SGleb Smirnoff 	rs_num = pf_get_ruleset_number(r->action);
17413b3a8eb9SGleb Smirnoff 	if (rs_num == PF_RULESET_MAX)
17423b3a8eb9SGleb Smirnoff 		errx(1, "Invalid rule type %d", r->action);
17433b3a8eb9SGleb Smirnoff 
17443b3a8eb9SGleb Smirnoff 	rs = &pf->anchor->ruleset;
17453b3a8eb9SGleb Smirnoff 
17463b3a8eb9SGleb Smirnoff 	if (anchor_call[0] && r->anchor == NULL) {
17473b3a8eb9SGleb Smirnoff 		/*
17483b3a8eb9SGleb Smirnoff 		 * Don't make non-brace anchors part of the main anchor pool.
17493b3a8eb9SGleb Smirnoff 		 */
17503b3a8eb9SGleb Smirnoff 		if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL)
17510d71f9f3SKristof Provost 			err(1, "pfctl_append_rule: calloc");
17523b3a8eb9SGleb Smirnoff 
17533b3a8eb9SGleb Smirnoff 		pf_init_ruleset(&r->anchor->ruleset);
17543b3a8eb9SGleb Smirnoff 		r->anchor->ruleset.anchor = r->anchor;
17553b3a8eb9SGleb Smirnoff 		if (strlcpy(r->anchor->path, anchor_call,
17563b3a8eb9SGleb Smirnoff 		    sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
17570d71f9f3SKristof Provost 			errx(1, "pfctl_append_rule: strlcpy");
17583b3a8eb9SGleb Smirnoff 		if ((p = strrchr(anchor_call, '/')) != NULL) {
17593b3a8eb9SGleb Smirnoff 			if (!strlen(p))
17600d71f9f3SKristof Provost 				err(1, "pfctl_append_rule: bad anchor name %s",
17613b3a8eb9SGleb Smirnoff 				    anchor_call);
17623b3a8eb9SGleb Smirnoff 		} else
17633b3a8eb9SGleb Smirnoff 			p = (char *)anchor_call;
17643b3a8eb9SGleb Smirnoff 		if (strlcpy(r->anchor->name, p,
17653b3a8eb9SGleb Smirnoff 		    sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
17660d71f9f3SKristof Provost 			errx(1, "pfctl_append_rule: strlcpy");
17673b3a8eb9SGleb Smirnoff 	}
17683b3a8eb9SGleb Smirnoff 
17693b3a8eb9SGleb Smirnoff 	if ((rule = calloc(1, sizeof(*rule))) == NULL)
17703b3a8eb9SGleb Smirnoff 		err(1, "calloc");
17713b3a8eb9SGleb Smirnoff 	bcopy(r, rule, sizeof(*rule));
1772096efeb6SKristof Provost 	TAILQ_INIT(&rule->rdr.list);
1773096efeb6SKristof Provost 	pfctl_move_pool(&r->rdr, &rule->rdr);
17745cb08fddSKristof Provost 	TAILQ_INIT(&rule->nat.list);
17755cb08fddSKristof Provost 	pfctl_move_pool(&r->nat, &rule->nat);
1776*0972294eSKristof Provost 	TAILQ_INIT(&rule->route.list);
1777*0972294eSKristof Provost 	pfctl_move_pool(&r->route, &rule->route);
17783b3a8eb9SGleb Smirnoff 
17793b3a8eb9SGleb Smirnoff 	TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries);
17803b3a8eb9SGleb Smirnoff 	return (0);
17813b3a8eb9SGleb Smirnoff }
17823b3a8eb9SGleb Smirnoff 
17833b3a8eb9SGleb Smirnoff int
1784c5131afeSKristof Provost pfctl_append_eth_rule(struct pfctl *pf, struct pfctl_eth_rule *r,
1785c5131afeSKristof Provost     const char *anchor_call)
1786c5131afeSKristof Provost {
1787c5131afeSKristof Provost 	struct pfctl_eth_rule		*rule;
1788c5131afeSKristof Provost 	struct pfctl_eth_ruleset	*rs;
1789c5131afeSKristof Provost 	char 				*p;
1790c5131afeSKristof Provost 
1791c5131afeSKristof Provost 	rs = &pf->eanchor->ruleset;
1792c5131afeSKristof Provost 
1793c5131afeSKristof Provost 	if (anchor_call[0] && r->anchor == NULL) {
1794c5131afeSKristof Provost 		/*
1795c5131afeSKristof Provost 		 * Don't make non-brace anchors part of the main anchor pool.
1796c5131afeSKristof Provost 		 */
1797c5131afeSKristof Provost 		if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL)
1798c5131afeSKristof Provost 			err(1, "pfctl_append_rule: calloc");
1799c5131afeSKristof Provost 
1800c5131afeSKristof Provost 		pf_init_eth_ruleset(&r->anchor->ruleset);
1801c5131afeSKristof Provost 		r->anchor->ruleset.anchor = r->anchor;
1802c5131afeSKristof Provost 		if (strlcpy(r->anchor->path, anchor_call,
1803c5131afeSKristof Provost 		    sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
1804c5131afeSKristof Provost 			errx(1, "pfctl_append_rule: strlcpy");
1805c5131afeSKristof Provost 		if ((p = strrchr(anchor_call, '/')) != NULL) {
1806c5131afeSKristof Provost 			if (!strlen(p))
1807c5131afeSKristof Provost 				err(1, "pfctl_append_eth_rule: bad anchor name %s",
1808c5131afeSKristof Provost 				    anchor_call);
1809c5131afeSKristof Provost 		} else
1810c5131afeSKristof Provost 			p = (char *)anchor_call;
1811c5131afeSKristof Provost 		if (strlcpy(r->anchor->name, p,
1812c5131afeSKristof Provost 		    sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
1813c5131afeSKristof Provost 			errx(1, "pfctl_append_eth_rule: strlcpy");
1814c5131afeSKristof Provost 	}
1815c5131afeSKristof Provost 
1816c5131afeSKristof Provost 	if ((rule = calloc(1, sizeof(*rule))) == NULL)
1817c5131afeSKristof Provost 		err(1, "calloc");
1818c5131afeSKristof Provost 	bcopy(r, rule, sizeof(*rule));
1819c5131afeSKristof Provost 
1820c5131afeSKristof Provost 	TAILQ_INSERT_TAIL(&rs->rules, rule, entries);
1821c5131afeSKristof Provost 	return (0);
1822c5131afeSKristof Provost }
1823c5131afeSKristof Provost 
1824c5131afeSKristof Provost int
1825c5131afeSKristof Provost pfctl_eth_ruleset_trans(struct pfctl *pf, char *path,
1826c5131afeSKristof Provost     struct pfctl_eth_anchor *a)
18273b3a8eb9SGleb Smirnoff {
18283b3a8eb9SGleb Smirnoff 	int osize = pf->trans->pfrb_size;
18293b3a8eb9SGleb Smirnoff 
18302b29ceb8SKristof Provost 	if ((pf->loadopt & PFCTL_FLAG_ETH) != 0) {
18312b29ceb8SKristof Provost 		if (pfctl_add_trans(pf->trans, PF_RULESET_ETH, path))
18322b29ceb8SKristof Provost 			return (1);
18332b29ceb8SKristof Provost 	}
1834c5131afeSKristof Provost 	if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize))
1835c5131afeSKristof Provost 		return (5);
1836c5131afeSKristof Provost 
1837c5131afeSKristof Provost 	return (0);
1838c5131afeSKristof Provost }
1839c5131afeSKristof Provost 
1840c5131afeSKristof Provost int
1841c5131afeSKristof Provost pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pfctl_anchor *a, bool do_eth)
1842c5131afeSKristof Provost {
1843c5131afeSKristof Provost 	int osize = pf->trans->pfrb_size;
1844c5131afeSKristof Provost 
1845c5131afeSKristof Provost 	if ((pf->loadopt & PFCTL_FLAG_ETH) != 0 && do_eth) {
1846c5131afeSKristof Provost 		if (pfctl_add_trans(pf->trans, PF_RULESET_ETH, path))
1847c5131afeSKristof Provost 			return (1);
18482b29ceb8SKristof Provost 	}
18493b3a8eb9SGleb Smirnoff 	if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) {
18503b3a8eb9SGleb Smirnoff 		if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) ||
18513b3a8eb9SGleb Smirnoff 		    pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) ||
18523b3a8eb9SGleb Smirnoff 		    pfctl_add_trans(pf->trans, PF_RULESET_RDR, path))
18533b3a8eb9SGleb Smirnoff 			return (1);
18543b3a8eb9SGleb Smirnoff 	}
18553b3a8eb9SGleb Smirnoff 	if (a == pf->astack[0] && ((altqsupport &&
18563b3a8eb9SGleb Smirnoff 	    (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) {
18573b3a8eb9SGleb Smirnoff 		if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path))
18583b3a8eb9SGleb Smirnoff 			return (2);
18593b3a8eb9SGleb Smirnoff 	}
18603b3a8eb9SGleb Smirnoff 	if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) {
18613b3a8eb9SGleb Smirnoff 		if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) ||
18623b3a8eb9SGleb Smirnoff 		    pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path))
18633b3a8eb9SGleb Smirnoff 			return (3);
18643b3a8eb9SGleb Smirnoff 	}
18653b3a8eb9SGleb Smirnoff 	if (pf->loadopt & PFCTL_FLAG_TABLE)
18663b3a8eb9SGleb Smirnoff 		if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path))
18673b3a8eb9SGleb Smirnoff 			return (4);
18683b3a8eb9SGleb Smirnoff 	if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize))
18693b3a8eb9SGleb Smirnoff 		return (5);
18703b3a8eb9SGleb Smirnoff 
18713b3a8eb9SGleb Smirnoff 	return (0);
18723b3a8eb9SGleb Smirnoff }
18733b3a8eb9SGleb Smirnoff 
18743b3a8eb9SGleb Smirnoff int
1875c5131afeSKristof Provost pfctl_load_eth_ruleset(struct pfctl *pf, char *path,
1876c5131afeSKristof Provost     struct pfctl_eth_ruleset *rs, int depth)
18772b29ceb8SKristof Provost {
18782b29ceb8SKristof Provost 	struct pfctl_eth_rule	*r;
1879c5131afeSKristof Provost 	int	error, len = strlen(path);
1880c5131afeSKristof Provost 	int	brace = 0;
18812b29ceb8SKristof Provost 
1882c5131afeSKristof Provost 	pf->eanchor = rs->anchor;
1883c5131afeSKristof Provost 	if (path[0])
1884c5131afeSKristof Provost 		snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->eanchor->name);
1885c5131afeSKristof Provost 	else
1886c5131afeSKristof Provost 		snprintf(&path[len], MAXPATHLEN - len, "%s", pf->eanchor->name);
18872b29ceb8SKristof Provost 
1888c5131afeSKristof Provost 	if (depth) {
1889c5131afeSKristof Provost 		if (TAILQ_FIRST(&rs->rules) != NULL) {
1890c5131afeSKristof Provost 			brace++;
1891c5131afeSKristof Provost 			if (pf->opts & PF_OPT_VERBOSE)
1892c5131afeSKristof Provost 				printf(" {\n");
1893c5131afeSKristof Provost 			if ((pf->opts & PF_OPT_NOACTION) == 0 &&
1894c5131afeSKristof Provost 			    (error = pfctl_eth_ruleset_trans(pf,
1895c5131afeSKristof Provost 			    path, rs->anchor))) {
1896c5131afeSKristof Provost 				printf("pfctl_load_eth_rulesets: "
1897c5131afeSKristof Provost 				    "pfctl_eth_ruleset_trans %d\n", error);
1898c5131afeSKristof Provost 				goto error;
1899c5131afeSKristof Provost 			}
1900c5131afeSKristof Provost 		} else if (pf->opts & PF_OPT_VERBOSE)
1901c5131afeSKristof Provost 			printf("\n");
1902c5131afeSKristof Provost 	}
1903c5131afeSKristof Provost 
1904c5131afeSKristof Provost 	while ((r = TAILQ_FIRST(&rs->rules)) != NULL) {
1905c5131afeSKristof Provost 		TAILQ_REMOVE(&rs->rules, r, entries);
1906c5131afeSKristof Provost 
1907c5131afeSKristof Provost 		error = pfctl_load_eth_rule(pf, path, r, depth);
19082b29ceb8SKristof Provost 		if (error)
19092b29ceb8SKristof Provost 			return (error);
1910c5131afeSKristof Provost 
1911c5131afeSKristof Provost 		if (r->anchor) {
1912c5131afeSKristof Provost 			if ((error = pfctl_load_eth_ruleset(pf, path,
1913c5131afeSKristof Provost 			    &r->anchor->ruleset, depth + 1)))
1914c5131afeSKristof Provost 				return (error);
1915c32cd180SKristof Provost 		} else if (pf->opts & PF_OPT_VERBOSE)
1916c32cd180SKristof Provost 			printf("\n");
1917c5131afeSKristof Provost 		free(r);
1918c5131afeSKristof Provost 	}
1919c5131afeSKristof Provost 	if (brace && pf->opts & PF_OPT_VERBOSE) {
1920c5131afeSKristof Provost 		INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE));
1921c5131afeSKristof Provost 		printf("}\n");
1922c5131afeSKristof Provost 	}
1923c5131afeSKristof Provost 	path[len] = '\0';
1924c5131afeSKristof Provost 
1925c5131afeSKristof Provost 	return (0);
1926c5131afeSKristof Provost error:
1927c5131afeSKristof Provost 	path[len] = '\0';
1928c5131afeSKristof Provost 	return (error);
19292b29ceb8SKristof Provost }
19302b29ceb8SKristof Provost 
1931c5131afeSKristof Provost int
1932c5131afeSKristof Provost pfctl_load_eth_rule(struct pfctl *pf, char *path, struct pfctl_eth_rule *r,
1933c5131afeSKristof Provost     int depth)
1934c5131afeSKristof Provost {
1935c5131afeSKristof Provost 	char			*name;
1936c5131afeSKristof Provost 	char			anchor[PF_ANCHOR_NAME_SIZE];
1937c5131afeSKristof Provost 	int			len = strlen(path);
1938375aaa29SKristof Provost 	int			ret;
1939c5131afeSKristof Provost 
1940c5131afeSKristof Provost 	if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor))
1941c5131afeSKristof Provost 		errx(1, "pfctl_load_eth_rule: strlcpy");
1942c5131afeSKristof Provost 
1943c5131afeSKristof Provost 	if (r->anchor) {
1944c5131afeSKristof Provost 		if (r->anchor->match) {
1945c5131afeSKristof Provost 			if (path[0])
1946c5131afeSKristof Provost 				snprintf(&path[len], MAXPATHLEN - len,
1947c5131afeSKristof Provost 				    "/%s", r->anchor->name);
1948c5131afeSKristof Provost 			else
1949c5131afeSKristof Provost 				snprintf(&path[len], MAXPATHLEN - len,
1950c5131afeSKristof Provost 				    "%s", r->anchor->name);
1951c5131afeSKristof Provost 			name = r->anchor->name;
1952c5131afeSKristof Provost 		} else
1953c5131afeSKristof Provost 			name = r->anchor->path;
1954c5131afeSKristof Provost 	} else
1955c5131afeSKristof Provost 		name = "";
1956c5131afeSKristof Provost 
1957c5131afeSKristof Provost 	if ((pf->opts & PF_OPT_NOACTION) == 0)
1958375aaa29SKristof Provost 		if ((ret = pfctl_add_eth_rule(pf->dev, r, anchor, name,
1959375aaa29SKristof Provost 		    pf->eth_ticket)) != 0)
1960375aaa29SKristof Provost 			errc(1, ret, "DIOCADDETHRULENV");
1961c5131afeSKristof Provost 
1962c32cd180SKristof Provost 	if (pf->opts & PF_OPT_VERBOSE) {
1963c32cd180SKristof Provost 		INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2));
1964c32cd180SKristof Provost 		print_eth_rule(r, r->anchor ? r->anchor->name : "",
1965c32cd180SKristof Provost 		    pf->opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG));
1966c32cd180SKristof Provost 	}
1967c32cd180SKristof Provost 
1968c5131afeSKristof Provost 	path[len] = '\0';
19692b29ceb8SKristof Provost 
19702b29ceb8SKristof Provost 	return (0);
19712b29ceb8SKristof Provost }
19722b29ceb8SKristof Provost 
19732b29ceb8SKristof Provost int
1974e9eb0941SKristof Provost pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs,
19753b3a8eb9SGleb Smirnoff     int rs_num, int depth)
19763b3a8eb9SGleb Smirnoff {
1977e9eb0941SKristof Provost 	struct pfctl_rule *r;
19783b3a8eb9SGleb Smirnoff 	int		error, len = strlen(path);
19793b3a8eb9SGleb Smirnoff 	int		brace = 0;
19803b3a8eb9SGleb Smirnoff 
19813b3a8eb9SGleb Smirnoff 	pf->anchor = rs->anchor;
19823b3a8eb9SGleb Smirnoff 
19833b3a8eb9SGleb Smirnoff 	if (path[0])
19843b3a8eb9SGleb Smirnoff 		snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name);
19853b3a8eb9SGleb Smirnoff 	else
19863b3a8eb9SGleb Smirnoff 		snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name);
19873b3a8eb9SGleb Smirnoff 
19883b3a8eb9SGleb Smirnoff 	if (depth) {
19893b3a8eb9SGleb Smirnoff 		if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) {
19903b3a8eb9SGleb Smirnoff 			brace++;
19913b3a8eb9SGleb Smirnoff 			if (pf->opts & PF_OPT_VERBOSE)
19923b3a8eb9SGleb Smirnoff 				printf(" {\n");
19933b3a8eb9SGleb Smirnoff 			if ((pf->opts & PF_OPT_NOACTION) == 0 &&
19943b3a8eb9SGleb Smirnoff 			    (error = pfctl_ruleset_trans(pf,
1995c5131afeSKristof Provost 			    path, rs->anchor, false))) {
19963b3a8eb9SGleb Smirnoff 				printf("pfctl_load_rulesets: "
19973b3a8eb9SGleb Smirnoff 				    "pfctl_ruleset_trans %d\n", error);
19983b3a8eb9SGleb Smirnoff 				goto error;
19993b3a8eb9SGleb Smirnoff 			}
20003b3a8eb9SGleb Smirnoff 		} else if (pf->opts & PF_OPT_VERBOSE)
20013b3a8eb9SGleb Smirnoff 			printf("\n");
20023b3a8eb9SGleb Smirnoff 
20033b3a8eb9SGleb Smirnoff 	}
20043b3a8eb9SGleb Smirnoff 
20053b3a8eb9SGleb Smirnoff 	if (pf->optimize && rs_num == PF_RULESET_FILTER)
20063b3a8eb9SGleb Smirnoff 		pfctl_optimize_ruleset(pf, rs);
20073b3a8eb9SGleb Smirnoff 
20083b3a8eb9SGleb Smirnoff 	while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) {
20093b3a8eb9SGleb Smirnoff 		TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries);
201009c7f238SKristof Provost 
201109c7f238SKristof Provost 		for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
201209c7f238SKristof Provost 			expand_label(r->label[i], PF_RULE_LABEL_SIZE, r);
201309c7f238SKristof Provost 		expand_label(r->tagname, PF_TAG_NAME_SIZE, r);
201409c7f238SKristof Provost 		expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r);
201509c7f238SKristof Provost 
20163b3a8eb9SGleb Smirnoff 		if ((error = pfctl_load_rule(pf, path, r, depth)))
20173b3a8eb9SGleb Smirnoff 			goto error;
20183b3a8eb9SGleb Smirnoff 		if (r->anchor) {
20193b3a8eb9SGleb Smirnoff 			if ((error = pfctl_load_ruleset(pf, path,
20203b3a8eb9SGleb Smirnoff 			    &r->anchor->ruleset, rs_num, depth + 1)))
20213b3a8eb9SGleb Smirnoff 				goto error;
20223b3a8eb9SGleb Smirnoff 		} else if (pf->opts & PF_OPT_VERBOSE)
20233b3a8eb9SGleb Smirnoff 			printf("\n");
20243b3a8eb9SGleb Smirnoff 		free(r);
20253b3a8eb9SGleb Smirnoff 	}
20263b3a8eb9SGleb Smirnoff 	if (brace && pf->opts & PF_OPT_VERBOSE) {
20273b3a8eb9SGleb Smirnoff 		INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE));
20283b3a8eb9SGleb Smirnoff 		printf("}\n");
20293b3a8eb9SGleb Smirnoff 	}
20303b3a8eb9SGleb Smirnoff 	path[len] = '\0';
20313b3a8eb9SGleb Smirnoff 	return (0);
20323b3a8eb9SGleb Smirnoff 
20333b3a8eb9SGleb Smirnoff  error:
20343b3a8eb9SGleb Smirnoff 	path[len] = '\0';
20353b3a8eb9SGleb Smirnoff 	return (error);
20363b3a8eb9SGleb Smirnoff 
20373b3a8eb9SGleb Smirnoff }
20383b3a8eb9SGleb Smirnoff 
20393b3a8eb9SGleb Smirnoff int
2040e9eb0941SKristof Provost pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth)
20413b3a8eb9SGleb Smirnoff {
20423b3a8eb9SGleb Smirnoff 	u_int8_t		rs_num = pf_get_ruleset_number(r->action);
20433b3a8eb9SGleb Smirnoff 	char			*name;
20445c11c5a3SKristof Provost 	u_int32_t		ticket;
20455c11c5a3SKristof Provost 	char			anchor[PF_ANCHOR_NAME_SIZE];
20463b3a8eb9SGleb Smirnoff 	int			len = strlen(path);
2047c4a08ef2SMateusz Guzik 	int			error;
2048c4a08ef2SMateusz Guzik 	bool			was_present;
20493b3a8eb9SGleb Smirnoff 
20503b3a8eb9SGleb Smirnoff 	/* set up anchor before adding to path for anchor_call */
20513b3a8eb9SGleb Smirnoff 	if ((pf->opts & PF_OPT_NOACTION) == 0)
20525c11c5a3SKristof Provost 		ticket = pfctl_get_ticket(pf->trans, rs_num, path);
20535c11c5a3SKristof Provost 	if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor))
20543b3a8eb9SGleb Smirnoff 		errx(1, "pfctl_load_rule: strlcpy");
20553b3a8eb9SGleb Smirnoff 
20563b3a8eb9SGleb Smirnoff 	if (r->anchor) {
20573b3a8eb9SGleb Smirnoff 		if (r->anchor->match) {
20583b3a8eb9SGleb Smirnoff 			if (path[0])
20593b3a8eb9SGleb Smirnoff 				snprintf(&path[len], MAXPATHLEN - len,
20603b3a8eb9SGleb Smirnoff 				    "/%s", r->anchor->name);
20613b3a8eb9SGleb Smirnoff 			else
20623b3a8eb9SGleb Smirnoff 				snprintf(&path[len], MAXPATHLEN - len,
20633b3a8eb9SGleb Smirnoff 				    "%s", r->anchor->name);
20642fd47deaSKristof Provost 			name = r->anchor->name;
20653b3a8eb9SGleb Smirnoff 		} else
20663b3a8eb9SGleb Smirnoff 			name = r->anchor->path;
20673b3a8eb9SGleb Smirnoff 	} else
20683b3a8eb9SGleb Smirnoff 		name = "";
20693b3a8eb9SGleb Smirnoff 
2070c4a08ef2SMateusz Guzik 	was_present = false;
20713b3a8eb9SGleb Smirnoff 	if ((pf->opts & PF_OPT_NOACTION) == 0) {
2072aa69fdf1SKristof Provost 		if ((pf->opts & PF_OPT_NOACTION) == 0) {
2073aa69fdf1SKristof Provost 			if ((error = pfctl_begin_addrs(pf->h,
2074aa69fdf1SKristof Provost 			    &pf->paddr.ticket)) != 0)
2075aa69fdf1SKristof Provost 				errc(1, error, "DIOCBEGINADDRS");
2076aa69fdf1SKristof Provost 		}
2077aa69fdf1SKristof Provost 
2078096efeb6SKristof Provost 		if (pfctl_add_pool(pf, &r->rdr, r->af, PF_RDR))
20793b3a8eb9SGleb Smirnoff 			return (1);
2080aa69fdf1SKristof Provost 		if (pfctl_add_pool(pf, &r->nat, r->naf ? r->naf : r->af, PF_NAT))
2081aa69fdf1SKristof Provost 			return (1);
2082*0972294eSKristof Provost 		if (pfctl_add_pool(pf, &r->route, r->af, PF_RT))
2083*0972294eSKristof Provost 			return (1);
208476bc4a77SKristof Provost 		error = pfctl_add_rule_h(pf->h, r, anchor, name, ticket,
2085c4a08ef2SMateusz Guzik 		    pf->paddr.ticket);
2086c4a08ef2SMateusz Guzik 		switch (error) {
2087c4a08ef2SMateusz Guzik 		case 0:
2088c4a08ef2SMateusz Guzik 			/* things worked, do nothing */
2089c4a08ef2SMateusz Guzik 			break;
2090c4a08ef2SMateusz Guzik 		case EEXIST:
2091c4a08ef2SMateusz Guzik 			/* an identical rule is already present */
2092c4a08ef2SMateusz Guzik 			was_present = true;
2093c4a08ef2SMateusz Guzik 			break;
2094c4a08ef2SMateusz Guzik 		default:
2095375aaa29SKristof Provost 			errc(1, error, "DIOCADDRULE");
20963b3a8eb9SGleb Smirnoff 		}
2097c4a08ef2SMateusz Guzik 	}
20983b3a8eb9SGleb Smirnoff 
20993b3a8eb9SGleb Smirnoff 	if (pf->opts & PF_OPT_VERBOSE) {
21003b3a8eb9SGleb Smirnoff 		INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2));
2101585a5ed0SKristof Provost 		print_rule(r, name,
21023b3a8eb9SGleb Smirnoff 		    pf->opts & PF_OPT_VERBOSE2,
21033b3a8eb9SGleb Smirnoff 		    pf->opts & PF_OPT_NUMERIC);
2104c4a08ef2SMateusz Guzik 		if (was_present)
2105c4a08ef2SMateusz Guzik 			printf(" -- rule was already present");
21063b3a8eb9SGleb Smirnoff 	}
21073b3a8eb9SGleb Smirnoff 	path[len] = '\0';
2108096efeb6SKristof Provost 	pfctl_clear_pool(&r->rdr);
21095cb08fddSKristof Provost 	pfctl_clear_pool(&r->nat);
21103b3a8eb9SGleb Smirnoff 	return (0);
21113b3a8eb9SGleb Smirnoff }
21123b3a8eb9SGleb Smirnoff 
21133b3a8eb9SGleb Smirnoff int
21143b3a8eb9SGleb Smirnoff pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
21153b3a8eb9SGleb Smirnoff {
21163b3a8eb9SGleb Smirnoff 	if (altqsupport &&
21173b3a8eb9SGleb Smirnoff 	    (loadopt & PFCTL_FLAG_ALTQ) != 0) {
21183b3a8eb9SGleb Smirnoff 		memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq));
21193b3a8eb9SGleb Smirnoff 		if ((pf->opts & PF_OPT_NOACTION) == 0) {
21203b3a8eb9SGleb Smirnoff 			if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) {
21213b3a8eb9SGleb Smirnoff 				if (errno == ENXIO)
21223b3a8eb9SGleb Smirnoff 					errx(1, "qtype not configured");
21233b3a8eb9SGleb Smirnoff 				else if (errno == ENODEV)
21243b3a8eb9SGleb Smirnoff 					errx(1, "%s: driver does not support "
21253b3a8eb9SGleb Smirnoff 					    "altq", a->ifname);
21263b3a8eb9SGleb Smirnoff 				else
21273b3a8eb9SGleb Smirnoff 					err(1, "DIOCADDALTQ");
21283b3a8eb9SGleb Smirnoff 			}
21293b3a8eb9SGleb Smirnoff 		}
21303b3a8eb9SGleb Smirnoff 		pfaltq_store(&pf->paltq->altq);
21313b3a8eb9SGleb Smirnoff 	}
21323b3a8eb9SGleb Smirnoff 	return (0);
21333b3a8eb9SGleb Smirnoff }
21343b3a8eb9SGleb Smirnoff 
21353b3a8eb9SGleb Smirnoff int
21363b3a8eb9SGleb Smirnoff pfctl_rules(int dev, char *filename, int opts, int optimize,
21373b3a8eb9SGleb Smirnoff     char *anchorname, struct pfr_buffer *trans)
21383b3a8eb9SGleb Smirnoff {
21393b3a8eb9SGleb Smirnoff #define ERR(x) do { warn(x); goto _error; } while(0)
21403b3a8eb9SGleb Smirnoff #define ERRX(x) do { warnx(x); goto _error; } while(0)
21413b3a8eb9SGleb Smirnoff 
21423b3a8eb9SGleb Smirnoff 	struct pfr_buffer	*t, buf;
21433b3a8eb9SGleb Smirnoff 	struct pfioc_altq	 pa;
21443b3a8eb9SGleb Smirnoff 	struct pfctl		 pf;
2145e9eb0941SKristof Provost 	struct pfctl_ruleset	*rs;
2146c5131afeSKristof Provost 	struct pfctl_eth_ruleset	*ethrs;
21473b3a8eb9SGleb Smirnoff 	struct pfr_table	 trs;
21483b3a8eb9SGleb Smirnoff 	char			*path;
21493b3a8eb9SGleb Smirnoff 	int			 osize;
21503b3a8eb9SGleb Smirnoff 
21513b3a8eb9SGleb Smirnoff 	RB_INIT(&pf_anchors);
21523b3a8eb9SGleb Smirnoff 	memset(&pf_main_anchor, 0, sizeof(pf_main_anchor));
21533b3a8eb9SGleb Smirnoff 	pf_init_ruleset(&pf_main_anchor.ruleset);
21543b3a8eb9SGleb Smirnoff 	pf_main_anchor.ruleset.anchor = &pf_main_anchor;
2155c5131afeSKristof Provost 
2156c5131afeSKristof Provost 	memset(&pf_eth_main_anchor, 0, sizeof(pf_eth_main_anchor));
2157c5131afeSKristof Provost 	pf_init_eth_ruleset(&pf_eth_main_anchor.ruleset);
2158c5131afeSKristof Provost 	pf_eth_main_anchor.ruleset.anchor = &pf_eth_main_anchor;
2159c5131afeSKristof Provost 
21603b3a8eb9SGleb Smirnoff 	if (trans == NULL) {
21613b3a8eb9SGleb Smirnoff 		bzero(&buf, sizeof(buf));
21623b3a8eb9SGleb Smirnoff 		buf.pfrb_type = PFRB_TRANS;
21633b3a8eb9SGleb Smirnoff 		t = &buf;
21643b3a8eb9SGleb Smirnoff 		osize = 0;
21653b3a8eb9SGleb Smirnoff 	} else {
21663b3a8eb9SGleb Smirnoff 		t = trans;
21673b3a8eb9SGleb Smirnoff 		osize = t->pfrb_size;
21683b3a8eb9SGleb Smirnoff 	}
21693b3a8eb9SGleb Smirnoff 
21703b3a8eb9SGleb Smirnoff 	memset(&pa, 0, sizeof(pa));
2171249cc75fSPatrick Kelsey 	pa.version = PFIOC_ALTQ_VERSION;
21723b3a8eb9SGleb Smirnoff 	memset(&pf, 0, sizeof(pf));
21733b3a8eb9SGleb Smirnoff 	memset(&trs, 0, sizeof(trs));
21743b3a8eb9SGleb Smirnoff 	if ((path = calloc(1, MAXPATHLEN)) == NULL)
21753b3a8eb9SGleb Smirnoff 		ERRX("pfctl_rules: calloc");
21763b3a8eb9SGleb Smirnoff 	if (strlcpy(trs.pfrt_anchor, anchorname,
21773b3a8eb9SGleb Smirnoff 	    sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor))
21783b3a8eb9SGleb Smirnoff 		ERRX("pfctl_rules: strlcpy");
21793b3a8eb9SGleb Smirnoff 	pf.dev = dev;
2180f1612e70SKristof Provost 	pf.h = pfh;
21813b3a8eb9SGleb Smirnoff 	pf.opts = opts;
21823b3a8eb9SGleb Smirnoff 	pf.optimize = optimize;
21833b3a8eb9SGleb Smirnoff 	pf.loadopt = loadopt;
21843b3a8eb9SGleb Smirnoff 
21853b3a8eb9SGleb Smirnoff 	/* non-brace anchor, create without resolving the path */
21863b3a8eb9SGleb Smirnoff 	if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL)
21873b3a8eb9SGleb Smirnoff 		ERRX("pfctl_rules: calloc");
21883b3a8eb9SGleb Smirnoff 	rs = &pf.anchor->ruleset;
21893b3a8eb9SGleb Smirnoff 	pf_init_ruleset(rs);
21903b3a8eb9SGleb Smirnoff 	rs->anchor = pf.anchor;
21913b3a8eb9SGleb Smirnoff 	if (strlcpy(pf.anchor->path, anchorname,
21923b3a8eb9SGleb Smirnoff 	    sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path))
2193c5131afeSKristof Provost 		errx(1, "pfctl_rules: strlcpy");
21943b3a8eb9SGleb Smirnoff 	if (strlcpy(pf.anchor->name, anchorname,
21953b3a8eb9SGleb Smirnoff 	    sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name))
2196c5131afeSKristof Provost 		errx(1, "pfctl_rules: strlcpy");
21973b3a8eb9SGleb Smirnoff 
21983b3a8eb9SGleb Smirnoff 
21993b3a8eb9SGleb Smirnoff 	pf.astack[0] = pf.anchor;
22003b3a8eb9SGleb Smirnoff 	pf.asd = 0;
22013b3a8eb9SGleb Smirnoff 	if (anchorname[0])
22023b3a8eb9SGleb Smirnoff 		pf.loadopt &= ~PFCTL_FLAG_ALTQ;
22033b3a8eb9SGleb Smirnoff 	pf.paltq = &pa;
22043b3a8eb9SGleb Smirnoff 	pf.trans = t;
22053b3a8eb9SGleb Smirnoff 	pfctl_init_options(&pf);
22063b3a8eb9SGleb Smirnoff 
2207c5131afeSKristof Provost 	/* Set up ethernet anchor */
2208c5131afeSKristof Provost 	if ((pf.eanchor = calloc(1, sizeof(*pf.eanchor))) == NULL)
2209c5131afeSKristof Provost 		ERRX("pfctl_rules: calloc");
2210c5131afeSKristof Provost 
2211c5131afeSKristof Provost 	if (strlcpy(pf.eanchor->path, anchorname,
2212c5131afeSKristof Provost 	    sizeof(pf.eanchor->path)) >= sizeof(pf.eanchor->path))
2213c5131afeSKristof Provost 		errx(1, "pfctl_rules: strlcpy");
2214c5131afeSKristof Provost 	if (strlcpy(pf.eanchor->name, anchorname,
2215c5131afeSKristof Provost 	    sizeof(pf.eanchor->name)) >= sizeof(pf.eanchor->name))
2216c5131afeSKristof Provost 		errx(1, "pfctl_rules: strlcpy");
2217c5131afeSKristof Provost 
2218c5131afeSKristof Provost 	ethrs = &pf.eanchor->ruleset;
2219c5131afeSKristof Provost 	pf_init_eth_ruleset(ethrs);
2220c5131afeSKristof Provost 	ethrs->anchor = pf.eanchor;
2221c5131afeSKristof Provost 	pf.eastack[0] = pf.eanchor;
2222c5131afeSKristof Provost 
22233b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_NOACTION) == 0) {
22243b3a8eb9SGleb Smirnoff 		/*
22253b3a8eb9SGleb Smirnoff 		 * XXX For the time being we need to open transactions for
22263b3a8eb9SGleb Smirnoff 		 * the main ruleset before parsing, because tables are still
22273b3a8eb9SGleb Smirnoff 		 * loaded at parse time.
22283b3a8eb9SGleb Smirnoff 		 */
2229c5131afeSKristof Provost 		if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor, true))
22303b3a8eb9SGleb Smirnoff 			ERRX("pfctl_rules");
22312b29ceb8SKristof Provost 		if (pf.loadopt & PFCTL_FLAG_ETH)
22322b29ceb8SKristof Provost 			pf.eth_ticket = pfctl_get_ticket(t, PF_RULESET_ETH, anchorname);
22333b3a8eb9SGleb Smirnoff 		if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ))
22343b3a8eb9SGleb Smirnoff 			pa.ticket =
22353b3a8eb9SGleb Smirnoff 			    pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname);
22363b3a8eb9SGleb Smirnoff 		if (pf.loadopt & PFCTL_FLAG_TABLE)
22373b3a8eb9SGleb Smirnoff 			pf.astack[0]->ruleset.tticket =
22383b3a8eb9SGleb Smirnoff 			    pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname);
22393b3a8eb9SGleb Smirnoff 	}
22403b3a8eb9SGleb Smirnoff 
22413b3a8eb9SGleb Smirnoff 	if (parse_config(filename, &pf) < 0) {
22423b3a8eb9SGleb Smirnoff 		if ((opts & PF_OPT_NOACTION) == 0)
22433b3a8eb9SGleb Smirnoff 			ERRX("Syntax error in config file: "
22443b3a8eb9SGleb Smirnoff 			    "pf rules not loaded");
22453b3a8eb9SGleb Smirnoff 		else
22463b3a8eb9SGleb Smirnoff 			goto _error;
22473b3a8eb9SGleb Smirnoff 	}
2248c5e10565SKristof Provost 	if (loadopt & PFCTL_FLAG_OPTION)
22497a831fecSKristof Provost 		pfctl_adjust_skip_ifaces(&pf);
22503b3a8eb9SGleb Smirnoff 
22513b3a8eb9SGleb Smirnoff 	if ((pf.loadopt & PFCTL_FLAG_FILTER &&
22523b3a8eb9SGleb Smirnoff 	    (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) ||
22532b29ceb8SKristof Provost 	    (pf.loadopt & PFCTL_FLAG_ETH &&
2254c5131afeSKristof Provost 	    (pfctl_load_eth_ruleset(&pf, path, ethrs, 0))) ||
22553b3a8eb9SGleb Smirnoff 	    (pf.loadopt & PFCTL_FLAG_NAT &&
22563b3a8eb9SGleb Smirnoff 	    (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) ||
22573b3a8eb9SGleb Smirnoff 	    pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) ||
22583b3a8eb9SGleb Smirnoff 	    pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) ||
22593b3a8eb9SGleb Smirnoff 	    (pf.loadopt & PFCTL_FLAG_FILTER &&
22603b3a8eb9SGleb Smirnoff 	    pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) {
22613b3a8eb9SGleb Smirnoff 		if ((opts & PF_OPT_NOACTION) == 0)
22623b3a8eb9SGleb Smirnoff 			ERRX("Unable to load rules into kernel");
22633b3a8eb9SGleb Smirnoff 		else
22643b3a8eb9SGleb Smirnoff 			goto _error;
22653b3a8eb9SGleb Smirnoff 	}
22663b3a8eb9SGleb Smirnoff 
22673b3a8eb9SGleb Smirnoff 	if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))
22683b3a8eb9SGleb Smirnoff 		if (check_commit_altq(dev, opts) != 0)
22693b3a8eb9SGleb Smirnoff 			ERRX("errors in altq config");
22703b3a8eb9SGleb Smirnoff 
22713b3a8eb9SGleb Smirnoff 	/* process "load anchor" directives */
22723b3a8eb9SGleb Smirnoff 	if (!anchorname[0])
22733b3a8eb9SGleb Smirnoff 		if (pfctl_load_anchors(dev, &pf, t) == -1)
22743b3a8eb9SGleb Smirnoff 			ERRX("load anchors");
22753b3a8eb9SGleb Smirnoff 
22763b3a8eb9SGleb Smirnoff 	if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) {
22773b3a8eb9SGleb Smirnoff 		if (!anchorname[0])
22783b3a8eb9SGleb Smirnoff 			if (pfctl_load_options(&pf))
22793b3a8eb9SGleb Smirnoff 				goto _error;
22803b3a8eb9SGleb Smirnoff 		if (pfctl_trans(dev, t, DIOCXCOMMIT, osize))
22813b3a8eb9SGleb Smirnoff 			ERR("DIOCXCOMMIT");
22823b3a8eb9SGleb Smirnoff 	}
228307695000SWarner Losh 	free(path);
22843b3a8eb9SGleb Smirnoff 	return (0);
22853b3a8eb9SGleb Smirnoff 
22863b3a8eb9SGleb Smirnoff _error:
22873b3a8eb9SGleb Smirnoff 	if (trans == NULL) {	/* main ruleset */
22883b3a8eb9SGleb Smirnoff 		if ((opts & PF_OPT_NOACTION) == 0)
22893b3a8eb9SGleb Smirnoff 			if (pfctl_trans(dev, t, DIOCXROLLBACK, osize))
22903b3a8eb9SGleb Smirnoff 				err(1, "DIOCXROLLBACK");
22913b3a8eb9SGleb Smirnoff 		exit(1);
22923b3a8eb9SGleb Smirnoff 	} else {		/* sub ruleset */
229307695000SWarner Losh 		free(path);
22943b3a8eb9SGleb Smirnoff 		return (-1);
22953b3a8eb9SGleb Smirnoff 	}
22963b3a8eb9SGleb Smirnoff 
22973b3a8eb9SGleb Smirnoff #undef ERR
22983b3a8eb9SGleb Smirnoff #undef ERRX
22993b3a8eb9SGleb Smirnoff }
23003b3a8eb9SGleb Smirnoff 
23013b3a8eb9SGleb Smirnoff FILE *
23023b3a8eb9SGleb Smirnoff pfctl_fopen(const char *name, const char *mode)
23033b3a8eb9SGleb Smirnoff {
23043b3a8eb9SGleb Smirnoff 	struct stat	 st;
23053b3a8eb9SGleb Smirnoff 	FILE		*fp;
23063b3a8eb9SGleb Smirnoff 
23073b3a8eb9SGleb Smirnoff 	fp = fopen(name, mode);
23083b3a8eb9SGleb Smirnoff 	if (fp == NULL)
23093b3a8eb9SGleb Smirnoff 		return (NULL);
23103b3a8eb9SGleb Smirnoff 	if (fstat(fileno(fp), &st)) {
23113b3a8eb9SGleb Smirnoff 		fclose(fp);
23123b3a8eb9SGleb Smirnoff 		return (NULL);
23133b3a8eb9SGleb Smirnoff 	}
23143b3a8eb9SGleb Smirnoff 	if (S_ISDIR(st.st_mode)) {
23153b3a8eb9SGleb Smirnoff 		fclose(fp);
23163b3a8eb9SGleb Smirnoff 		errno = EISDIR;
23173b3a8eb9SGleb Smirnoff 		return (NULL);
23183b3a8eb9SGleb Smirnoff 	}
23193b3a8eb9SGleb Smirnoff 	return (fp);
23203b3a8eb9SGleb Smirnoff }
23213b3a8eb9SGleb Smirnoff 
23223b3a8eb9SGleb Smirnoff void
23233b3a8eb9SGleb Smirnoff pfctl_init_options(struct pfctl *pf)
23243b3a8eb9SGleb Smirnoff {
23253b3a8eb9SGleb Smirnoff 
23263b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
23273b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
23283b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
23293b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
23303b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
23313b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
2332ca9dbde8SKristof Provost 	pf->timeout[PFTM_SCTP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
2333ca9dbde8SKristof Provost 	pf->timeout[PFTM_SCTP_OPENING] = PFTM_TCP_OPENING_VAL;
2334ca9dbde8SKristof Provost 	pf->timeout[PFTM_SCTP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
2335ca9dbde8SKristof Provost 	pf->timeout[PFTM_SCTP_CLOSING] = PFTM_TCP_CLOSING_VAL;
2336ca9dbde8SKristof Provost 	pf->timeout[PFTM_SCTP_CLOSED] = PFTM_TCP_CLOSED_VAL;
23373b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
23383b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
23393b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
23403b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
23413b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
23423b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
23433b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
23443b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
23453b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
23463b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
23473b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
23483b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
23493b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START;
23503b3a8eb9SGleb Smirnoff 	pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
23513b3a8eb9SGleb Smirnoff 
23523b3a8eb9SGleb Smirnoff 	pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT;
23533b3a8eb9SGleb Smirnoff 	pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT;
23543b3a8eb9SGleb Smirnoff 	pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT;
23553b3a8eb9SGleb Smirnoff 	pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
23563b3a8eb9SGleb Smirnoff 
23573b3a8eb9SGleb Smirnoff 	pf->debug = PF_DEBUG_URGENT;
235839282ef3SKajetan Staszkiewicz 	pf->reassemble = 0;
23595062afffSKristof Provost 
23605062afffSKristof Provost 	pf->syncookies = false;
23615062afffSKristof Provost 	pf->syncookieswat[0] = PF_SYNCOOKIES_LOWATPCT;
23625062afffSKristof Provost 	pf->syncookieswat[1] = PF_SYNCOOKIES_HIWATPCT;
23633b3a8eb9SGleb Smirnoff }
23643b3a8eb9SGleb Smirnoff 
23653b3a8eb9SGleb Smirnoff int
23663b3a8eb9SGleb Smirnoff pfctl_load_options(struct pfctl *pf)
23673b3a8eb9SGleb Smirnoff {
23683b3a8eb9SGleb Smirnoff 	int i, error = 0;
23693b3a8eb9SGleb Smirnoff 
23703b3a8eb9SGleb Smirnoff 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
23713b3a8eb9SGleb Smirnoff 		return (0);
23723b3a8eb9SGleb Smirnoff 
23733b3a8eb9SGleb Smirnoff 	/* load limits */
23743b3a8eb9SGleb Smirnoff 	for (i = 0; i < PF_LIMIT_MAX; i++) {
23753b3a8eb9SGleb Smirnoff 		if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i])
23763b3a8eb9SGleb Smirnoff 			continue;
23773b3a8eb9SGleb Smirnoff 		if (pfctl_load_limit(pf, i, pf->limit[i]))
23783b3a8eb9SGleb Smirnoff 			error = 1;
23793b3a8eb9SGleb Smirnoff 	}
23803b3a8eb9SGleb Smirnoff 
23813b3a8eb9SGleb Smirnoff 	/*
23823b3a8eb9SGleb Smirnoff 	 * If we've set the limit, but haven't explicitly set adaptive
23833b3a8eb9SGleb Smirnoff 	 * timeouts, do it now with a start of 60% and end of 120%.
23843b3a8eb9SGleb Smirnoff 	 */
23853b3a8eb9SGleb Smirnoff 	if (pf->limit_set[PF_LIMIT_STATES] &&
23863b3a8eb9SGleb Smirnoff 	    !pf->timeout_set[PFTM_ADAPTIVE_START] &&
23873b3a8eb9SGleb Smirnoff 	    !pf->timeout_set[PFTM_ADAPTIVE_END]) {
23883b3a8eb9SGleb Smirnoff 		pf->timeout[PFTM_ADAPTIVE_START] =
23893b3a8eb9SGleb Smirnoff 			(pf->limit[PF_LIMIT_STATES] / 10) * 6;
23903b3a8eb9SGleb Smirnoff 		pf->timeout_set[PFTM_ADAPTIVE_START] = 1;
23913b3a8eb9SGleb Smirnoff 		pf->timeout[PFTM_ADAPTIVE_END] =
23923b3a8eb9SGleb Smirnoff 			(pf->limit[PF_LIMIT_STATES] / 10) * 12;
23933b3a8eb9SGleb Smirnoff 		pf->timeout_set[PFTM_ADAPTIVE_END] = 1;
23943b3a8eb9SGleb Smirnoff 	}
23953b3a8eb9SGleb Smirnoff 
23963b3a8eb9SGleb Smirnoff 	/* load timeouts */
23973b3a8eb9SGleb Smirnoff 	for (i = 0; i < PFTM_MAX; i++) {
23983b3a8eb9SGleb Smirnoff 		if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i])
23993b3a8eb9SGleb Smirnoff 			continue;
24003b3a8eb9SGleb Smirnoff 		if (pfctl_load_timeout(pf, i, pf->timeout[i]))
24013b3a8eb9SGleb Smirnoff 			error = 1;
24023b3a8eb9SGleb Smirnoff 	}
24033b3a8eb9SGleb Smirnoff 
24043b3a8eb9SGleb Smirnoff 	/* load debug */
24053b3a8eb9SGleb Smirnoff 	if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set)
24063b3a8eb9SGleb Smirnoff 		if (pfctl_load_debug(pf, pf->debug))
24073b3a8eb9SGleb Smirnoff 			error = 1;
24083b3a8eb9SGleb Smirnoff 
24093b3a8eb9SGleb Smirnoff 	/* load logif */
24103b3a8eb9SGleb Smirnoff 	if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set)
24113b3a8eb9SGleb Smirnoff 		if (pfctl_load_logif(pf, pf->ifname))
24123b3a8eb9SGleb Smirnoff 			error = 1;
24133b3a8eb9SGleb Smirnoff 
24143b3a8eb9SGleb Smirnoff 	/* load hostid */
24153b3a8eb9SGleb Smirnoff 	if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set)
24163b3a8eb9SGleb Smirnoff 		if (pfctl_load_hostid(pf, pf->hostid))
24173b3a8eb9SGleb Smirnoff 			error = 1;
24183b3a8eb9SGleb Smirnoff 
241939282ef3SKajetan Staszkiewicz 	/* load reassembly settings */
242039282ef3SKajetan Staszkiewicz 	if (!(pf->opts & PF_OPT_MERGE) || pf->reass_set)
242139282ef3SKajetan Staszkiewicz 		if (pfctl_load_reassembly(pf, pf->reassemble))
242239282ef3SKajetan Staszkiewicz 			error = 1;
242339282ef3SKajetan Staszkiewicz 
242442ec75f8SKristof Provost 	/* load keepcounters */
242542ec75f8SKristof Provost 	if (pfctl_set_keepcounters(pf->dev, pf->keep_counters))
242642ec75f8SKristof Provost 		error = 1;
242742ec75f8SKristof Provost 
2428c69121c4SKristof Provost 	/* load syncookies settings */
2429c69121c4SKristof Provost 	if (pfctl_load_syncookies(pf, pf->syncookies))
2430c69121c4SKristof Provost 		error = 1;
2431c69121c4SKristof Provost 
24323b3a8eb9SGleb Smirnoff 	return (error);
24333b3a8eb9SGleb Smirnoff }
24343b3a8eb9SGleb Smirnoff 
24353b3a8eb9SGleb Smirnoff int
2436d9ab8999SKristof Provost pfctl_apply_limit(struct pfctl *pf, const char *opt, unsigned int limit)
24373b3a8eb9SGleb Smirnoff {
24383b3a8eb9SGleb Smirnoff 	int i;
24393b3a8eb9SGleb Smirnoff 
24403b3a8eb9SGleb Smirnoff 
24413b3a8eb9SGleb Smirnoff 	for (i = 0; pf_limits[i].name; i++) {
24423b3a8eb9SGleb Smirnoff 		if (strcasecmp(opt, pf_limits[i].name) == 0) {
24433b3a8eb9SGleb Smirnoff 			pf->limit[pf_limits[i].index] = limit;
24443b3a8eb9SGleb Smirnoff 			pf->limit_set[pf_limits[i].index] = 1;
24453b3a8eb9SGleb Smirnoff 			break;
24463b3a8eb9SGleb Smirnoff 		}
24473b3a8eb9SGleb Smirnoff 	}
24483b3a8eb9SGleb Smirnoff 	if (pf_limits[i].name == NULL) {
24493b3a8eb9SGleb Smirnoff 		warnx("Bad pool name.");
24503b3a8eb9SGleb Smirnoff 		return (1);
24513b3a8eb9SGleb Smirnoff 	}
24523b3a8eb9SGleb Smirnoff 
24533b3a8eb9SGleb Smirnoff 	if (pf->opts & PF_OPT_VERBOSE)
24543b3a8eb9SGleb Smirnoff 		printf("set limit %s %d\n", opt, limit);
24553b3a8eb9SGleb Smirnoff 
24563b3a8eb9SGleb Smirnoff 	return (0);
24573b3a8eb9SGleb Smirnoff }
24583b3a8eb9SGleb Smirnoff 
24593b3a8eb9SGleb Smirnoff int
24603b3a8eb9SGleb Smirnoff pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit)
24613b3a8eb9SGleb Smirnoff {
2462d9ab8999SKristof Provost 	if (pfctl_set_limit(pf->h, index, limit)) {
24633b3a8eb9SGleb Smirnoff 		if (errno == EBUSY)
24643b3a8eb9SGleb Smirnoff 			warnx("Current pool size exceeds requested hard limit");
24653b3a8eb9SGleb Smirnoff 		else
24663b3a8eb9SGleb Smirnoff 			warnx("DIOCSETLIMIT");
24673b3a8eb9SGleb Smirnoff 		return (1);
24683b3a8eb9SGleb Smirnoff 	}
24693b3a8eb9SGleb Smirnoff 	return (0);
24703b3a8eb9SGleb Smirnoff }
24713b3a8eb9SGleb Smirnoff 
24723b3a8eb9SGleb Smirnoff int
247330bad751SKristof Provost pfctl_apply_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
24743b3a8eb9SGleb Smirnoff {
24753b3a8eb9SGleb Smirnoff 	int i;
24763b3a8eb9SGleb Smirnoff 
24773b3a8eb9SGleb Smirnoff 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
24783b3a8eb9SGleb Smirnoff 		return (0);
24793b3a8eb9SGleb Smirnoff 
24803b3a8eb9SGleb Smirnoff 	for (i = 0; pf_timeouts[i].name; i++) {
24813b3a8eb9SGleb Smirnoff 		if (strcasecmp(opt, pf_timeouts[i].name) == 0) {
24823b3a8eb9SGleb Smirnoff 			pf->timeout[pf_timeouts[i].timeout] = seconds;
24833b3a8eb9SGleb Smirnoff 			pf->timeout_set[pf_timeouts[i].timeout] = 1;
24843b3a8eb9SGleb Smirnoff 			break;
24853b3a8eb9SGleb Smirnoff 		}
24863b3a8eb9SGleb Smirnoff 	}
24873b3a8eb9SGleb Smirnoff 
24883b3a8eb9SGleb Smirnoff 	if (pf_timeouts[i].name == NULL) {
24893b3a8eb9SGleb Smirnoff 		warnx("Bad timeout name.");
24903b3a8eb9SGleb Smirnoff 		return (1);
24913b3a8eb9SGleb Smirnoff 	}
24923b3a8eb9SGleb Smirnoff 
24933b3a8eb9SGleb Smirnoff 
24943b3a8eb9SGleb Smirnoff 	if (pf->opts & PF_OPT_VERBOSE && ! quiet)
24953b3a8eb9SGleb Smirnoff 		printf("set timeout %s %d\n", opt, seconds);
24963b3a8eb9SGleb Smirnoff 
24973b3a8eb9SGleb Smirnoff 	return (0);
24983b3a8eb9SGleb Smirnoff }
24993b3a8eb9SGleb Smirnoff 
25003b3a8eb9SGleb Smirnoff int
25013b3a8eb9SGleb Smirnoff pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds)
25023b3a8eb9SGleb Smirnoff {
250330bad751SKristof Provost 	if (pfctl_set_timeout(pf->h, timeout, seconds)) {
25043b3a8eb9SGleb Smirnoff 		warnx("DIOCSETTIMEOUT");
25053b3a8eb9SGleb Smirnoff 		return (1);
25063b3a8eb9SGleb Smirnoff 	}
25073b3a8eb9SGleb Smirnoff 	return (0);
25083b3a8eb9SGleb Smirnoff }
25093b3a8eb9SGleb Smirnoff 
25103b3a8eb9SGleb Smirnoff int
251139282ef3SKajetan Staszkiewicz pfctl_set_reassembly(struct pfctl *pf, int on, int nodf)
251239282ef3SKajetan Staszkiewicz {
251339282ef3SKajetan Staszkiewicz 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
251439282ef3SKajetan Staszkiewicz 		return (0);
251539282ef3SKajetan Staszkiewicz 
251639282ef3SKajetan Staszkiewicz 	pf->reass_set = 1;
251739282ef3SKajetan Staszkiewicz 	if (on) {
251839282ef3SKajetan Staszkiewicz 		pf->reassemble = PF_REASS_ENABLED;
251939282ef3SKajetan Staszkiewicz 		if (nodf)
252039282ef3SKajetan Staszkiewicz 			pf->reassemble |= PF_REASS_NODF;
252139282ef3SKajetan Staszkiewicz 	} else {
252239282ef3SKajetan Staszkiewicz 		pf->reassemble = 0;
252339282ef3SKajetan Staszkiewicz 	}
252439282ef3SKajetan Staszkiewicz 
252539282ef3SKajetan Staszkiewicz 	if (pf->opts & PF_OPT_VERBOSE)
252639282ef3SKajetan Staszkiewicz 		printf("set reassemble %s %s\n", on ? "yes" : "no",
252739282ef3SKajetan Staszkiewicz 		    nodf ? "no-df" : "");
252839282ef3SKajetan Staszkiewicz 
252939282ef3SKajetan Staszkiewicz 	return (0);
253039282ef3SKajetan Staszkiewicz }
253139282ef3SKajetan Staszkiewicz 
253239282ef3SKajetan Staszkiewicz int
25333b3a8eb9SGleb Smirnoff pfctl_set_optimization(struct pfctl *pf, const char *opt)
25343b3a8eb9SGleb Smirnoff {
25353b3a8eb9SGleb Smirnoff 	const struct pf_hint *hint;
25363b3a8eb9SGleb Smirnoff 	int i, r;
25373b3a8eb9SGleb Smirnoff 
25383b3a8eb9SGleb Smirnoff 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
25393b3a8eb9SGleb Smirnoff 		return (0);
25403b3a8eb9SGleb Smirnoff 
25413b3a8eb9SGleb Smirnoff 	for (i = 0; pf_hints[i].name; i++)
25423b3a8eb9SGleb Smirnoff 		if (strcasecmp(opt, pf_hints[i].name) == 0)
25433b3a8eb9SGleb Smirnoff 			break;
25443b3a8eb9SGleb Smirnoff 
25453b3a8eb9SGleb Smirnoff 	hint = pf_hints[i].hint;
25463b3a8eb9SGleb Smirnoff 	if (hint == NULL) {
25473b3a8eb9SGleb Smirnoff 		warnx("invalid state timeouts optimization");
25483b3a8eb9SGleb Smirnoff 		return (1);
25493b3a8eb9SGleb Smirnoff 	}
25503b3a8eb9SGleb Smirnoff 
25513b3a8eb9SGleb Smirnoff 	for (i = 0; hint[i].name; i++)
255230bad751SKristof Provost 		if ((r = pfctl_apply_timeout(pf, hint[i].name,
25533b3a8eb9SGleb Smirnoff 		    hint[i].timeout, 1)))
25543b3a8eb9SGleb Smirnoff 			return (r);
25553b3a8eb9SGleb Smirnoff 
25563b3a8eb9SGleb Smirnoff 	if (pf->opts & PF_OPT_VERBOSE)
25573b3a8eb9SGleb Smirnoff 		printf("set optimization %s\n", opt);
25583b3a8eb9SGleb Smirnoff 
25593b3a8eb9SGleb Smirnoff 	return (0);
25603b3a8eb9SGleb Smirnoff }
25613b3a8eb9SGleb Smirnoff 
25623b3a8eb9SGleb Smirnoff int
25633b3a8eb9SGleb Smirnoff pfctl_set_logif(struct pfctl *pf, char *ifname)
25643b3a8eb9SGleb Smirnoff {
25653b3a8eb9SGleb Smirnoff 
25663b3a8eb9SGleb Smirnoff 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
25673b3a8eb9SGleb Smirnoff 		return (0);
25683b3a8eb9SGleb Smirnoff 
25693b3a8eb9SGleb Smirnoff 	if (!strcmp(ifname, "none")) {
25703b3a8eb9SGleb Smirnoff 		free(pf->ifname);
25713b3a8eb9SGleb Smirnoff 		pf->ifname = NULL;
25723b3a8eb9SGleb Smirnoff 	} else {
25733b3a8eb9SGleb Smirnoff 		pf->ifname = strdup(ifname);
25743b3a8eb9SGleb Smirnoff 		if (!pf->ifname)
25753b3a8eb9SGleb Smirnoff 			errx(1, "pfctl_set_logif: strdup");
25763b3a8eb9SGleb Smirnoff 	}
25773b3a8eb9SGleb Smirnoff 	pf->ifname_set = 1;
25783b3a8eb9SGleb Smirnoff 
25793b3a8eb9SGleb Smirnoff 	if (pf->opts & PF_OPT_VERBOSE)
25803b3a8eb9SGleb Smirnoff 		printf("set loginterface %s\n", ifname);
25813b3a8eb9SGleb Smirnoff 
25823b3a8eb9SGleb Smirnoff 	return (0);
25833b3a8eb9SGleb Smirnoff }
25843b3a8eb9SGleb Smirnoff 
25853b3a8eb9SGleb Smirnoff int
25863b3a8eb9SGleb Smirnoff pfctl_load_logif(struct pfctl *pf, char *ifname)
25873b3a8eb9SGleb Smirnoff {
2588470a2b33SKristof Provost 	if (ifname != NULL && strlen(ifname) >= IFNAMSIZ) {
25893b3a8eb9SGleb Smirnoff 		warnx("pfctl_load_logif: strlcpy");
25903b3a8eb9SGleb Smirnoff 		return (1);
25913b3a8eb9SGleb Smirnoff 	}
2592470a2b33SKristof Provost 	return (pfctl_set_statusif(pfh, ifname ? ifname : ""));
25933b3a8eb9SGleb Smirnoff }
25943b3a8eb9SGleb Smirnoff 
25954aafc73dSKristof Provost void
25963b3a8eb9SGleb Smirnoff pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
25973b3a8eb9SGleb Smirnoff {
25983b3a8eb9SGleb Smirnoff 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
25994aafc73dSKristof Provost 		return;
26003b3a8eb9SGleb Smirnoff 
26013b3a8eb9SGleb Smirnoff 	HTONL(hostid);
26023b3a8eb9SGleb Smirnoff 
26033b3a8eb9SGleb Smirnoff 	pf->hostid = hostid;
26043b3a8eb9SGleb Smirnoff 	pf->hostid_set = 1;
26053b3a8eb9SGleb Smirnoff 
26063b3a8eb9SGleb Smirnoff 	if (pf->opts & PF_OPT_VERBOSE)
26073b3a8eb9SGleb Smirnoff 		printf("set hostid 0x%08x\n", ntohl(hostid));
26083b3a8eb9SGleb Smirnoff }
26093b3a8eb9SGleb Smirnoff 
26103b3a8eb9SGleb Smirnoff int
26113b3a8eb9SGleb Smirnoff pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid)
26123b3a8eb9SGleb Smirnoff {
26133b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCSETHOSTID, &hostid)) {
26143b3a8eb9SGleb Smirnoff 		warnx("DIOCSETHOSTID");
26153b3a8eb9SGleb Smirnoff 		return (1);
26163b3a8eb9SGleb Smirnoff 	}
26173b3a8eb9SGleb Smirnoff 	return (0);
26183b3a8eb9SGleb Smirnoff }
26193b3a8eb9SGleb Smirnoff 
26203b3a8eb9SGleb Smirnoff int
262139282ef3SKajetan Staszkiewicz pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly)
262239282ef3SKajetan Staszkiewicz {
262339282ef3SKajetan Staszkiewicz 	if (ioctl(dev, DIOCSETREASS, &reassembly)) {
262439282ef3SKajetan Staszkiewicz 		warnx("DIOCSETREASS");
262539282ef3SKajetan Staszkiewicz 		return (1);
262639282ef3SKajetan Staszkiewicz 	}
262739282ef3SKajetan Staszkiewicz 	return (0);
262839282ef3SKajetan Staszkiewicz }
262939282ef3SKajetan Staszkiewicz 
263039282ef3SKajetan Staszkiewicz int
2631c69121c4SKristof Provost pfctl_load_syncookies(struct pfctl *pf, u_int8_t val)
2632c69121c4SKristof Provost {
2633c69121c4SKristof Provost 	struct pfctl_syncookies	cookies;
2634c69121c4SKristof Provost 
2635c69121c4SKristof Provost 	bzero(&cookies, sizeof(cookies));
2636c69121c4SKristof Provost 
26375062afffSKristof Provost 	cookies.mode = val;
26385062afffSKristof Provost 	cookies.lowwater = pf->syncookieswat[0];
26395062afffSKristof Provost 	cookies.highwater = pf->syncookieswat[1];
2640c69121c4SKristof Provost 
2641c69121c4SKristof Provost 	if (pfctl_set_syncookies(dev, &cookies)) {
2642c69121c4SKristof Provost 		warnx("DIOCSETSYNCOOKIES");
2643c69121c4SKristof Provost 		return (1);
2644c69121c4SKristof Provost 	}
2645c69121c4SKristof Provost 	return (0);
2646c69121c4SKristof Provost }
2647c69121c4SKristof Provost 
2648c69121c4SKristof Provost int
26495062afffSKristof Provost pfctl_cfg_syncookies(struct pfctl *pf, uint8_t val, struct pfctl_watermarks *w)
26505062afffSKristof Provost {
26515062afffSKristof Provost 	if (val != PF_SYNCOOKIES_ADAPTIVE && w != NULL) {
26525062afffSKristof Provost 		warnx("syncookies start/end only apply to adaptive");
26535062afffSKristof Provost 		return (1);
26545062afffSKristof Provost 	}
26555062afffSKristof Provost 	if (val == PF_SYNCOOKIES_ADAPTIVE && w != NULL) {
26565062afffSKristof Provost 		if (!w->hi)
26575062afffSKristof Provost 			w->hi = PF_SYNCOOKIES_HIWATPCT;
26585062afffSKristof Provost 		if (!w->lo)
26595062afffSKristof Provost 			w->lo = w->hi / 2;
26605062afffSKristof Provost 		if (w->lo >= w->hi) {
26615062afffSKristof Provost 			warnx("start must be higher than end");
26625062afffSKristof Provost 			return (1);
26635062afffSKristof Provost 		}
26645062afffSKristof Provost 		pf->syncookieswat[0] = w->lo;
26655062afffSKristof Provost 		pf->syncookieswat[1] = w->hi;
26665062afffSKristof Provost 		pf->syncookieswat_set = 1;
26675062afffSKristof Provost 	}
26685062afffSKristof Provost 
26695062afffSKristof Provost 	if (pf->opts & PF_OPT_VERBOSE) {
26705062afffSKristof Provost 		if (val == PF_SYNCOOKIES_NEVER)
26715062afffSKristof Provost 			printf("set syncookies never\n");
26725062afffSKristof Provost 		else if (val == PF_SYNCOOKIES_ALWAYS)
26735062afffSKristof Provost 			printf("set syncookies always\n");
26745062afffSKristof Provost 		else if (val == PF_SYNCOOKIES_ADAPTIVE) {
26755062afffSKristof Provost 			if (pf->syncookieswat_set)
26765062afffSKristof Provost 				printf("set syncookies adaptive (start %u%%, "
26775062afffSKristof Provost 				    "end %u%%)\n", pf->syncookieswat[1],
26785062afffSKristof Provost 				    pf->syncookieswat[0]);
26795062afffSKristof Provost 			else
26805062afffSKristof Provost 				printf("set syncookies adaptive\n");
26815062afffSKristof Provost 		} else {        /* cannot happen */
26825062afffSKristof Provost 			warnx("king bula ate all syncookies");
26835062afffSKristof Provost 			return (1);
26845062afffSKristof Provost 		}
26855062afffSKristof Provost 	}
26865062afffSKristof Provost 
26875062afffSKristof Provost 	pf->syncookies = val;
26885062afffSKristof Provost 	return (0);
26895062afffSKristof Provost }
26905062afffSKristof Provost 
26915062afffSKristof Provost int
2692c36c90a2SKristof Provost pfctl_do_set_debug(struct pfctl *pf, char *d)
26933b3a8eb9SGleb Smirnoff {
26943b3a8eb9SGleb Smirnoff 	u_int32_t	level;
2695375aaa29SKristof Provost 	int		ret;
26963b3a8eb9SGleb Smirnoff 
26973b3a8eb9SGleb Smirnoff 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
26983b3a8eb9SGleb Smirnoff 		return (0);
26993b3a8eb9SGleb Smirnoff 
27003b3a8eb9SGleb Smirnoff 	if (!strcmp(d, "none"))
27013b3a8eb9SGleb Smirnoff 		pf->debug = PF_DEBUG_NONE;
27023b3a8eb9SGleb Smirnoff 	else if (!strcmp(d, "urgent"))
27033b3a8eb9SGleb Smirnoff 		pf->debug = PF_DEBUG_URGENT;
27043b3a8eb9SGleb Smirnoff 	else if (!strcmp(d, "misc"))
27053b3a8eb9SGleb Smirnoff 		pf->debug = PF_DEBUG_MISC;
27063b3a8eb9SGleb Smirnoff 	else if (!strcmp(d, "loud"))
27073b3a8eb9SGleb Smirnoff 		pf->debug = PF_DEBUG_NOISY;
27083b3a8eb9SGleb Smirnoff 	else {
27093b3a8eb9SGleb Smirnoff 		warnx("unknown debug level \"%s\"", d);
27103b3a8eb9SGleb Smirnoff 		return (-1);
27113b3a8eb9SGleb Smirnoff 	}
27123b3a8eb9SGleb Smirnoff 
27133b3a8eb9SGleb Smirnoff 	pf->debug_set = 1;
27143e768368SKristof Provost 	level = pf->debug;
27153b3a8eb9SGleb Smirnoff 
27163b3a8eb9SGleb Smirnoff 	if ((pf->opts & PF_OPT_NOACTION) == 0)
2717375aaa29SKristof Provost 		if ((ret = pfctl_set_debug(pfh, level)) != 0)
2718375aaa29SKristof Provost 			errc(1, ret, "DIOCSETDEBUG");
27193b3a8eb9SGleb Smirnoff 
27203b3a8eb9SGleb Smirnoff 	if (pf->opts & PF_OPT_VERBOSE)
27213b3a8eb9SGleb Smirnoff 		printf("set debug %s\n", d);
27223b3a8eb9SGleb Smirnoff 
27233b3a8eb9SGleb Smirnoff 	return (0);
27243b3a8eb9SGleb Smirnoff }
27253b3a8eb9SGleb Smirnoff 
27263b3a8eb9SGleb Smirnoff int
27273b3a8eb9SGleb Smirnoff pfctl_load_debug(struct pfctl *pf, unsigned int level)
27283b3a8eb9SGleb Smirnoff {
2729c36c90a2SKristof Provost 	if (pfctl_set_debug(pf->h, level)) {
27303b3a8eb9SGleb Smirnoff 		warnx("DIOCSETDEBUG");
27313b3a8eb9SGleb Smirnoff 		return (1);
27323b3a8eb9SGleb Smirnoff 	}
27333b3a8eb9SGleb Smirnoff 	return (0);
27343b3a8eb9SGleb Smirnoff }
27353b3a8eb9SGleb Smirnoff 
27363b3a8eb9SGleb Smirnoff int
27373b3a8eb9SGleb Smirnoff pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how)
27383b3a8eb9SGleb Smirnoff {
27393b3a8eb9SGleb Smirnoff 	struct pfioc_iface	pi;
2740b1f3ab00SKristof Provost 	struct node_host	*h = NULL, *n = NULL;
27413b3a8eb9SGleb Smirnoff 
27423b3a8eb9SGleb Smirnoff 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
27433b3a8eb9SGleb Smirnoff 		return (0);
27443b3a8eb9SGleb Smirnoff 
27453b3a8eb9SGleb Smirnoff 	bzero(&pi, sizeof(pi));
27463b3a8eb9SGleb Smirnoff 
27473b3a8eb9SGleb Smirnoff 	pi.pfiio_flags = flags;
27483b3a8eb9SGleb Smirnoff 
2749b1f3ab00SKristof Provost 	/* Make sure our cache matches the kernel. If we set or clear the flag
2750b1f3ab00SKristof Provost 	 * for a group this applies to all members. */
2751b1f3ab00SKristof Provost 	h = ifa_grouplookup(ifname, 0);
2752b1f3ab00SKristof Provost 	for (n = h; n != NULL; n = n->next)
2753b1f3ab00SKristof Provost 		pfctl_set_interface_flags(pf, n->ifname, flags, how);
2754b1f3ab00SKristof Provost 
27553b3a8eb9SGleb Smirnoff 	if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >=
27563b3a8eb9SGleb Smirnoff 	    sizeof(pi.pfiio_name))
27573b3a8eb9SGleb Smirnoff 		errx(1, "pfctl_set_interface_flags: strlcpy");
27583b3a8eb9SGleb Smirnoff 
27593b3a8eb9SGleb Smirnoff 	if ((pf->opts & PF_OPT_NOACTION) == 0) {
27603b3a8eb9SGleb Smirnoff 		if (how == 0) {
27613b3a8eb9SGleb Smirnoff 			if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi))
27623b3a8eb9SGleb Smirnoff 				err(1, "DIOCCLRIFFLAG");
27633b3a8eb9SGleb Smirnoff 		} else {
27643b3a8eb9SGleb Smirnoff 			if (ioctl(pf->dev, DIOCSETIFFLAG, &pi))
27653b3a8eb9SGleb Smirnoff 				err(1, "DIOCSETIFFLAG");
2766c5e10565SKristof Provost 			pfctl_check_skip_ifaces(ifname);
27673b3a8eb9SGleb Smirnoff 		}
27683b3a8eb9SGleb Smirnoff 	}
27693b3a8eb9SGleb Smirnoff 	return (0);
27703b3a8eb9SGleb Smirnoff }
27713b3a8eb9SGleb Smirnoff 
27723b3a8eb9SGleb Smirnoff void
27733b3a8eb9SGleb Smirnoff pfctl_debug(int dev, u_int32_t level, int opts)
27743b3a8eb9SGleb Smirnoff {
2775375aaa29SKristof Provost 	int ret;
2776375aaa29SKristof Provost 
2777375aaa29SKristof Provost 	if ((ret = pfctl_set_debug(pfh, level)) != 0)
2778375aaa29SKristof Provost 		errc(1, ret, "DIOCSETDEBUG");
27793b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_QUIET) == 0) {
27803b3a8eb9SGleb Smirnoff 		fprintf(stderr, "debug level set to '");
27813b3a8eb9SGleb Smirnoff 		switch (level) {
27823b3a8eb9SGleb Smirnoff 		case PF_DEBUG_NONE:
27833b3a8eb9SGleb Smirnoff 			fprintf(stderr, "none");
27843b3a8eb9SGleb Smirnoff 			break;
27853b3a8eb9SGleb Smirnoff 		case PF_DEBUG_URGENT:
27863b3a8eb9SGleb Smirnoff 			fprintf(stderr, "urgent");
27873b3a8eb9SGleb Smirnoff 			break;
27883b3a8eb9SGleb Smirnoff 		case PF_DEBUG_MISC:
27893b3a8eb9SGleb Smirnoff 			fprintf(stderr, "misc");
27903b3a8eb9SGleb Smirnoff 			break;
27913b3a8eb9SGleb Smirnoff 		case PF_DEBUG_NOISY:
27923b3a8eb9SGleb Smirnoff 			fprintf(stderr, "loud");
27933b3a8eb9SGleb Smirnoff 			break;
27943b3a8eb9SGleb Smirnoff 		default:
27953b3a8eb9SGleb Smirnoff 			fprintf(stderr, "<invalid>");
27963b3a8eb9SGleb Smirnoff 			break;
27973b3a8eb9SGleb Smirnoff 		}
27983b3a8eb9SGleb Smirnoff 		fprintf(stderr, "'\n");
27993b3a8eb9SGleb Smirnoff 	}
28003b3a8eb9SGleb Smirnoff }
28013b3a8eb9SGleb Smirnoff 
28023b3a8eb9SGleb Smirnoff int
28033b3a8eb9SGleb Smirnoff pfctl_test_altqsupport(int dev, int opts)
28043b3a8eb9SGleb Smirnoff {
28053b3a8eb9SGleb Smirnoff 	struct pfioc_altq pa;
28063b3a8eb9SGleb Smirnoff 
2807249cc75fSPatrick Kelsey 	pa.version = PFIOC_ALTQ_VERSION;
28083b3a8eb9SGleb Smirnoff 	if (ioctl(dev, DIOCGETALTQS, &pa)) {
28093b3a8eb9SGleb Smirnoff 		if (errno == ENODEV) {
2810a4134647SGeorge V. Neville-Neil 			if (opts & PF_OPT_VERBOSE)
28113b3a8eb9SGleb Smirnoff 				fprintf(stderr, "No ALTQ support in kernel\n"
28123b3a8eb9SGleb Smirnoff 				    "ALTQ related functions disabled\n");
28133b3a8eb9SGleb Smirnoff 			return (0);
28143b3a8eb9SGleb Smirnoff 		} else
28153b3a8eb9SGleb Smirnoff 			err(1, "DIOCGETALTQS");
28163b3a8eb9SGleb Smirnoff 	}
28173b3a8eb9SGleb Smirnoff 	return (1);
28183b3a8eb9SGleb Smirnoff }
28193b3a8eb9SGleb Smirnoff 
28203b3a8eb9SGleb Smirnoff int
28213b3a8eb9SGleb Smirnoff pfctl_show_anchors(int dev, int opts, char *anchorname)
28223b3a8eb9SGleb Smirnoff {
28233b3a8eb9SGleb Smirnoff 	struct pfioc_ruleset	 pr;
28243b3a8eb9SGleb Smirnoff 	u_int32_t		 mnr, nr;
282525e0f8f9SKristof Provost 	int			 ret;
28263b3a8eb9SGleb Smirnoff 
28273b3a8eb9SGleb Smirnoff 	memset(&pr, 0, sizeof(pr));
282825e0f8f9SKristof Provost 	if ((ret = pfctl_get_rulesets(pfh, anchorname, &mnr)) != 0) {
282925e0f8f9SKristof Provost 		if (ret == EINVAL)
28303b3a8eb9SGleb Smirnoff 			fprintf(stderr, "Anchor '%s' not found.\n",
28313b3a8eb9SGleb Smirnoff 			    anchorname);
28323b3a8eb9SGleb Smirnoff 		else
283325e0f8f9SKristof Provost 			errc(1, ret, "DIOCGETRULESETS");
28343b3a8eb9SGleb Smirnoff 		return (-1);
28353b3a8eb9SGleb Smirnoff 	}
28363b3a8eb9SGleb Smirnoff 	for (nr = 0; nr < mnr; ++nr) {
28373b3a8eb9SGleb Smirnoff 		char sub[MAXPATHLEN];
28383b3a8eb9SGleb Smirnoff 
283948f5bf8bSKristof Provost 		if ((ret = pfctl_get_ruleset(pfh, anchorname, nr, &pr)) != 0)
284048f5bf8bSKristof Provost 			errc(1, ret, "DIOCGETRULESET");
28413b3a8eb9SGleb Smirnoff 		if (!strcmp(pr.name, PF_RESERVED_ANCHOR))
28423b3a8eb9SGleb Smirnoff 			continue;
28433b3a8eb9SGleb Smirnoff 		sub[0] = 0;
28443b3a8eb9SGleb Smirnoff 		if (pr.path[0]) {
28453b3a8eb9SGleb Smirnoff 			strlcat(sub, pr.path, sizeof(sub));
28463b3a8eb9SGleb Smirnoff 			strlcat(sub, "/", sizeof(sub));
28473b3a8eb9SGleb Smirnoff 		}
28483b3a8eb9SGleb Smirnoff 		strlcat(sub, pr.name, sizeof(sub));
28493b3a8eb9SGleb Smirnoff 		if (sub[0] != '_' || (opts & PF_OPT_VERBOSE))
28503b3a8eb9SGleb Smirnoff 			printf("  %s\n", sub);
28513b3a8eb9SGleb Smirnoff 		if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub))
28523b3a8eb9SGleb Smirnoff 			return (-1);
28533b3a8eb9SGleb Smirnoff 	}
28543b3a8eb9SGleb Smirnoff 	return (0);
28553b3a8eb9SGleb Smirnoff }
28563b3a8eb9SGleb Smirnoff 
28579bb06778SKristof Provost int
28589bb06778SKristof Provost pfctl_show_eth_anchors(int dev, int opts, char *anchorname)
28599bb06778SKristof Provost {
28609bb06778SKristof Provost 	struct pfctl_eth_rulesets_info ri;
28619bb06778SKristof Provost 	struct pfctl_eth_ruleset_info rs;
28629bb06778SKristof Provost 	int ret;
28639bb06778SKristof Provost 
28649bb06778SKristof Provost 	if ((ret = pfctl_get_eth_rulesets_info(dev, &ri, anchorname)) != 0) {
28659bb06778SKristof Provost 		if (ret == ENOENT)
28669bb06778SKristof Provost 			fprintf(stderr, "Anchor '%s' not found.\n",
28679bb06778SKristof Provost 			    anchorname);
28689bb06778SKristof Provost 		else
2869375aaa29SKristof Provost 			errc(1, ret, "DIOCGETETHRULESETS");
28709bb06778SKristof Provost 		return (-1);
28719bb06778SKristof Provost 	}
28729bb06778SKristof Provost 
28739bb06778SKristof Provost 	for (int nr = 0; nr < ri.nr; nr++) {
28749bb06778SKristof Provost 		char sub[MAXPATHLEN];
28759bb06778SKristof Provost 
2876375aaa29SKristof Provost 		if ((ret = pfctl_get_eth_ruleset(dev, anchorname, nr, &rs)) != 0)
2877375aaa29SKristof Provost 			errc(1, ret, "DIOCGETETHRULESET");
28789bb06778SKristof Provost 
28799bb06778SKristof Provost 		if (!strcmp(rs.name, PF_RESERVED_ANCHOR))
28809bb06778SKristof Provost 			continue;
28819bb06778SKristof Provost 		sub[0] = 0;
28829bb06778SKristof Provost 		if (rs.path[0]) {
28839bb06778SKristof Provost 			strlcat(sub, rs.path, sizeof(sub));
28849bb06778SKristof Provost 			strlcat(sub, "/", sizeof(sub));
28859bb06778SKristof Provost 		}
28869bb06778SKristof Provost 		strlcat(sub, rs.name, sizeof(sub));
28879bb06778SKristof Provost 		if (sub[0] != '_' || (opts & PF_OPT_VERBOSE))
28889bb06778SKristof Provost 			printf("  %s\n", sub);
28899bb06778SKristof Provost 		if ((opts & PF_OPT_VERBOSE) && pfctl_show_eth_anchors(dev, opts, sub))
28909bb06778SKristof Provost 			return (-1);
28919bb06778SKristof Provost 	}
28929bb06778SKristof Provost 	return (0);
28939bb06778SKristof Provost }
28949bb06778SKristof Provost 
28953b3a8eb9SGleb Smirnoff const char *
289672a3cf0fSKristof Provost pfctl_lookup_option(char *cmd, const char * const *list)
28973b3a8eb9SGleb Smirnoff {
28983b3a8eb9SGleb Smirnoff 	if (cmd != NULL && *cmd)
28993b3a8eb9SGleb Smirnoff 		for (; *list; list++)
29003b3a8eb9SGleb Smirnoff 			if (!strncmp(cmd, *list, strlen(cmd)))
29013b3a8eb9SGleb Smirnoff 				return (*list);
29023b3a8eb9SGleb Smirnoff 	return (NULL);
29033b3a8eb9SGleb Smirnoff }
29043b3a8eb9SGleb Smirnoff 
29053b3a8eb9SGleb Smirnoff int
29063b3a8eb9SGleb Smirnoff main(int argc, char *argv[])
29073b3a8eb9SGleb Smirnoff {
29083b3a8eb9SGleb Smirnoff 	int	 error = 0;
29093b3a8eb9SGleb Smirnoff 	int	 ch;
29103b3a8eb9SGleb Smirnoff 	int	 mode = O_RDONLY;
29113b3a8eb9SGleb Smirnoff 	int	 opts = 0;
29123b3a8eb9SGleb Smirnoff 	int	 optimize = PF_OPTIMIZE_BASIC;
29133b3a8eb9SGleb Smirnoff 	char	 anchorname[MAXPATHLEN];
29143b3a8eb9SGleb Smirnoff 	char	*path;
29153b3a8eb9SGleb Smirnoff 
29163b3a8eb9SGleb Smirnoff 	if (argc < 2)
29173b3a8eb9SGleb Smirnoff 		usage();
29183b3a8eb9SGleb Smirnoff 
29193b3a8eb9SGleb Smirnoff 	while ((ch = getopt(argc, argv,
292093abcf17SKristof Provost 	    "a:AdD:eqf:F:ghi:k:K:mMnNOo:Pp:rRs:t:T:vx:z")) != -1) {
29213b3a8eb9SGleb Smirnoff 		switch (ch) {
29223b3a8eb9SGleb Smirnoff 		case 'a':
29233b3a8eb9SGleb Smirnoff 			anchoropt = optarg;
29243b3a8eb9SGleb Smirnoff 			break;
29253b3a8eb9SGleb Smirnoff 		case 'd':
29263b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_DISABLE;
29273b3a8eb9SGleb Smirnoff 			mode = O_RDWR;
29283b3a8eb9SGleb Smirnoff 			break;
29293b3a8eb9SGleb Smirnoff 		case 'D':
29303b3a8eb9SGleb Smirnoff 			if (pfctl_cmdline_symset(optarg) < 0)
29313b3a8eb9SGleb Smirnoff 				warnx("could not parse macro definition %s",
29323b3a8eb9SGleb Smirnoff 				    optarg);
29333b3a8eb9SGleb Smirnoff 			break;
29343b3a8eb9SGleb Smirnoff 		case 'e':
29353b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_ENABLE;
29363b3a8eb9SGleb Smirnoff 			mode = O_RDWR;
29373b3a8eb9SGleb Smirnoff 			break;
29383b3a8eb9SGleb Smirnoff 		case 'q':
29393b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_QUIET;
29403b3a8eb9SGleb Smirnoff 			break;
29413b3a8eb9SGleb Smirnoff 		case 'F':
29423b3a8eb9SGleb Smirnoff 			clearopt = pfctl_lookup_option(optarg, clearopt_list);
29433b3a8eb9SGleb Smirnoff 			if (clearopt == NULL) {
29443b3a8eb9SGleb Smirnoff 				warnx("Unknown flush modifier '%s'", optarg);
29453b3a8eb9SGleb Smirnoff 				usage();
29463b3a8eb9SGleb Smirnoff 			}
29473b3a8eb9SGleb Smirnoff 			mode = O_RDWR;
29483b3a8eb9SGleb Smirnoff 			break;
29493b3a8eb9SGleb Smirnoff 		case 'i':
29503b3a8eb9SGleb Smirnoff 			ifaceopt = optarg;
29513b3a8eb9SGleb Smirnoff 			break;
29523b3a8eb9SGleb Smirnoff 		case 'k':
29533b3a8eb9SGleb Smirnoff 			if (state_killers >= 2) {
29543b3a8eb9SGleb Smirnoff 				warnx("can only specify -k twice");
29553b3a8eb9SGleb Smirnoff 				usage();
29563b3a8eb9SGleb Smirnoff 				/* NOTREACHED */
29573b3a8eb9SGleb Smirnoff 			}
29583b3a8eb9SGleb Smirnoff 			state_kill[state_killers++] = optarg;
29593b3a8eb9SGleb Smirnoff 			mode = O_RDWR;
29603b3a8eb9SGleb Smirnoff 			break;
29613b3a8eb9SGleb Smirnoff 		case 'K':
29623b3a8eb9SGleb Smirnoff 			if (src_node_killers >= 2) {
29633b3a8eb9SGleb Smirnoff 				warnx("can only specify -K twice");
29643b3a8eb9SGleb Smirnoff 				usage();
29653b3a8eb9SGleb Smirnoff 				/* NOTREACHED */
29663b3a8eb9SGleb Smirnoff 			}
29673b3a8eb9SGleb Smirnoff 			src_node_kill[src_node_killers++] = optarg;
29683b3a8eb9SGleb Smirnoff 			mode = O_RDWR;
29693b3a8eb9SGleb Smirnoff 			break;
29703b3a8eb9SGleb Smirnoff 		case 'm':
29713b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_MERGE;
29723b3a8eb9SGleb Smirnoff 			break;
297393abcf17SKristof Provost 		case 'M':
297493abcf17SKristof Provost 			opts |= PF_OPT_KILLMATCH;
297593abcf17SKristof Provost 			break;
29763b3a8eb9SGleb Smirnoff 		case 'n':
29773b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_NOACTION;
29783b3a8eb9SGleb Smirnoff 			break;
29793b3a8eb9SGleb Smirnoff 		case 'N':
29803b3a8eb9SGleb Smirnoff 			loadopt |= PFCTL_FLAG_NAT;
29813b3a8eb9SGleb Smirnoff 			break;
29823b3a8eb9SGleb Smirnoff 		case 'r':
29833b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_USEDNS;
29843b3a8eb9SGleb Smirnoff 			break;
29853b3a8eb9SGleb Smirnoff 		case 'f':
29863b3a8eb9SGleb Smirnoff 			rulesopt = optarg;
29873b3a8eb9SGleb Smirnoff 			mode = O_RDWR;
29883b3a8eb9SGleb Smirnoff 			break;
29893b3a8eb9SGleb Smirnoff 		case 'g':
29903b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_DEBUG;
29913b3a8eb9SGleb Smirnoff 			break;
29923b3a8eb9SGleb Smirnoff 		case 'A':
29933b3a8eb9SGleb Smirnoff 			loadopt |= PFCTL_FLAG_ALTQ;
29943b3a8eb9SGleb Smirnoff 			break;
29953b3a8eb9SGleb Smirnoff 		case 'R':
29963b3a8eb9SGleb Smirnoff 			loadopt |= PFCTL_FLAG_FILTER;
29973b3a8eb9SGleb Smirnoff 			break;
29983b3a8eb9SGleb Smirnoff 		case 'o':
29993b3a8eb9SGleb Smirnoff 			optiopt = pfctl_lookup_option(optarg, optiopt_list);
30003b3a8eb9SGleb Smirnoff 			if (optiopt == NULL) {
30013b3a8eb9SGleb Smirnoff 				warnx("Unknown optimization '%s'", optarg);
30023b3a8eb9SGleb Smirnoff 				usage();
30033b3a8eb9SGleb Smirnoff 			}
30043b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_OPTIMIZE;
30053b3a8eb9SGleb Smirnoff 			break;
30063b3a8eb9SGleb Smirnoff 		case 'O':
30073b3a8eb9SGleb Smirnoff 			loadopt |= PFCTL_FLAG_OPTION;
30083b3a8eb9SGleb Smirnoff 			break;
30093b3a8eb9SGleb Smirnoff 		case 'p':
30103b3a8eb9SGleb Smirnoff 			pf_device = optarg;
30113b3a8eb9SGleb Smirnoff 			break;
30123b3a8eb9SGleb Smirnoff 		case 'P':
30133b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_NUMERIC;
30143b3a8eb9SGleb Smirnoff 			break;
30153b3a8eb9SGleb Smirnoff 		case 's':
30163b3a8eb9SGleb Smirnoff 			showopt = pfctl_lookup_option(optarg, showopt_list);
30173b3a8eb9SGleb Smirnoff 			if (showopt == NULL) {
30183b3a8eb9SGleb Smirnoff 				warnx("Unknown show modifier '%s'", optarg);
30193b3a8eb9SGleb Smirnoff 				usage();
30203b3a8eb9SGleb Smirnoff 			}
30213b3a8eb9SGleb Smirnoff 			break;
30223b3a8eb9SGleb Smirnoff 		case 't':
30233b3a8eb9SGleb Smirnoff 			tableopt = optarg;
30243b3a8eb9SGleb Smirnoff 			break;
30253b3a8eb9SGleb Smirnoff 		case 'T':
30263b3a8eb9SGleb Smirnoff 			tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list);
30273b3a8eb9SGleb Smirnoff 			if (tblcmdopt == NULL) {
30283b3a8eb9SGleb Smirnoff 				warnx("Unknown table command '%s'", optarg);
30293b3a8eb9SGleb Smirnoff 				usage();
30303b3a8eb9SGleb Smirnoff 			}
30313b3a8eb9SGleb Smirnoff 			break;
30323b3a8eb9SGleb Smirnoff 		case 'v':
30333b3a8eb9SGleb Smirnoff 			if (opts & PF_OPT_VERBOSE)
30343b3a8eb9SGleb Smirnoff 				opts |= PF_OPT_VERBOSE2;
30353b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_VERBOSE;
30363b3a8eb9SGleb Smirnoff 			break;
30373b3a8eb9SGleb Smirnoff 		case 'x':
30383b3a8eb9SGleb Smirnoff 			debugopt = pfctl_lookup_option(optarg, debugopt_list);
30393b3a8eb9SGleb Smirnoff 			if (debugopt == NULL) {
30403b3a8eb9SGleb Smirnoff 				warnx("Unknown debug level '%s'", optarg);
30413b3a8eb9SGleb Smirnoff 				usage();
30423b3a8eb9SGleb Smirnoff 			}
30433b3a8eb9SGleb Smirnoff 			mode = O_RDWR;
30443b3a8eb9SGleb Smirnoff 			break;
30453b3a8eb9SGleb Smirnoff 		case 'z':
30463b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_CLRRULECTRS;
30473b3a8eb9SGleb Smirnoff 			mode = O_RDWR;
30483b3a8eb9SGleb Smirnoff 			break;
30493b3a8eb9SGleb Smirnoff 		case 'h':
30503b3a8eb9SGleb Smirnoff 			/* FALLTHROUGH */
30513b3a8eb9SGleb Smirnoff 		default:
30523b3a8eb9SGleb Smirnoff 			usage();
30533b3a8eb9SGleb Smirnoff 			/* NOTREACHED */
30543b3a8eb9SGleb Smirnoff 		}
30553b3a8eb9SGleb Smirnoff 	}
30563b3a8eb9SGleb Smirnoff 
30573b3a8eb9SGleb Smirnoff 	if (tblcmdopt != NULL) {
30583b3a8eb9SGleb Smirnoff 		argc -= optind;
30593b3a8eb9SGleb Smirnoff 		argv += optind;
30603b3a8eb9SGleb Smirnoff 		ch = *tblcmdopt;
30613b3a8eb9SGleb Smirnoff 		if (ch == 'l') {
30623b3a8eb9SGleb Smirnoff 			loadopt |= PFCTL_FLAG_TABLE;
30633b3a8eb9SGleb Smirnoff 			tblcmdopt = NULL;
30643b3a8eb9SGleb Smirnoff 		} else
30653b3a8eb9SGleb Smirnoff 			mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY;
30663b3a8eb9SGleb Smirnoff 	} else if (argc != optind) {
30673b3a8eb9SGleb Smirnoff 		warnx("unknown command line argument: %s ...", argv[optind]);
30683b3a8eb9SGleb Smirnoff 		usage();
30693b3a8eb9SGleb Smirnoff 		/* NOTREACHED */
30703b3a8eb9SGleb Smirnoff 	}
30713b3a8eb9SGleb Smirnoff 	if (loadopt == 0)
30723b3a8eb9SGleb Smirnoff 		loadopt = ~0;
30733b3a8eb9SGleb Smirnoff 
30743b3a8eb9SGleb Smirnoff 	if ((path = calloc(1, MAXPATHLEN)) == NULL)
30753b3a8eb9SGleb Smirnoff 		errx(1, "pfctl: calloc");
30763b3a8eb9SGleb Smirnoff 	memset(anchorname, 0, sizeof(anchorname));
30773b3a8eb9SGleb Smirnoff 	if (anchoropt != NULL) {
30783b3a8eb9SGleb Smirnoff 		int len = strlen(anchoropt);
30793b3a8eb9SGleb Smirnoff 
308029866385SJessica Clarke 		if (len >= 1 && anchoropt[len - 1] == '*') {
30813b3a8eb9SGleb Smirnoff 			if (len >= 2 && anchoropt[len - 2] == '/')
30823b3a8eb9SGleb Smirnoff 				anchoropt[len - 2] = '\0';
30833b3a8eb9SGleb Smirnoff 			else
30843b3a8eb9SGleb Smirnoff 				anchoropt[len - 1] = '\0';
30853b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_RECURSE;
30863b3a8eb9SGleb Smirnoff 		}
30873b3a8eb9SGleb Smirnoff 		if (strlcpy(anchorname, anchoropt,
30883b3a8eb9SGleb Smirnoff 		    sizeof(anchorname)) >= sizeof(anchorname))
30893b3a8eb9SGleb Smirnoff 			errx(1, "anchor name '%s' too long",
30903b3a8eb9SGleb Smirnoff 			    anchoropt);
3091c5131afeSKristof Provost 		loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE|PFCTL_FLAG_ETH;
30923b3a8eb9SGleb Smirnoff 	}
30933b3a8eb9SGleb Smirnoff 
30943b3a8eb9SGleb Smirnoff 	if ((opts & PF_OPT_NOACTION) == 0) {
30953b3a8eb9SGleb Smirnoff 		dev = open(pf_device, mode);
30963b3a8eb9SGleb Smirnoff 		if (dev == -1)
30973b3a8eb9SGleb Smirnoff 			err(1, "%s", pf_device);
30983b3a8eb9SGleb Smirnoff 		altqsupport = pfctl_test_altqsupport(dev, opts);
30993b3a8eb9SGleb Smirnoff 	} else {
31003b3a8eb9SGleb Smirnoff 		dev = open(pf_device, O_RDONLY);
31013b3a8eb9SGleb Smirnoff 		if (dev >= 0)
31023b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_DUMMYACTION;
31033b3a8eb9SGleb Smirnoff 		/* turn off options */
31043b3a8eb9SGleb Smirnoff 		opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE);
31053b3a8eb9SGleb Smirnoff 		clearopt = showopt = debugopt = NULL;
3106116e43f0SGleb Smirnoff #if !defined(ENABLE_ALTQ)
31073b3a8eb9SGleb Smirnoff 		altqsupport = 0;
31083b3a8eb9SGleb Smirnoff #else
31093b3a8eb9SGleb Smirnoff 		altqsupport = 1;
31103b3a8eb9SGleb Smirnoff #endif
31113b3a8eb9SGleb Smirnoff 	}
311266cacc14SKristof Provost 	pfh = pfctl_open(pf_device);
311366cacc14SKristof Provost 	if (pfh == NULL)
311466cacc14SKristof Provost 		err(1, "Failed to open netlink");
31153b3a8eb9SGleb Smirnoff 
31163b3a8eb9SGleb Smirnoff 	if (opts & PF_OPT_DISABLE)
31173b3a8eb9SGleb Smirnoff 		if (pfctl_disable(dev, opts))
31183b3a8eb9SGleb Smirnoff 			error = 1;
31193b3a8eb9SGleb Smirnoff 
31203b3a8eb9SGleb Smirnoff 	if (showopt != NULL) {
31213b3a8eb9SGleb Smirnoff 		switch (*showopt) {
31223b3a8eb9SGleb Smirnoff 		case 'A':
31233b3a8eb9SGleb Smirnoff 			pfctl_show_anchors(dev, opts, anchorname);
3124f8b4f9aaSKristof Provost 			if (opts & PF_OPT_VERBOSE2)
3125f8b4f9aaSKristof Provost 				printf("Ethernet:\n");
31269bb06778SKristof Provost 			pfctl_show_eth_anchors(dev, opts, anchorname);
31273b3a8eb9SGleb Smirnoff 			break;
31283b3a8eb9SGleb Smirnoff 		case 'r':
31293b3a8eb9SGleb Smirnoff 			pfctl_load_fingerprints(dev, opts);
31303b3a8eb9SGleb Smirnoff 			pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES,
3131585a5ed0SKristof Provost 			    anchorname, 0, 0);
31323b3a8eb9SGleb Smirnoff 			break;
31333b3a8eb9SGleb Smirnoff 		case 'l':
31343b3a8eb9SGleb Smirnoff 			pfctl_load_fingerprints(dev, opts);
31353b3a8eb9SGleb Smirnoff 			pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS,
3136585a5ed0SKristof Provost 			    anchorname, 0, 0);
31373b3a8eb9SGleb Smirnoff 			break;
31383b3a8eb9SGleb Smirnoff 		case 'n':
31393b3a8eb9SGleb Smirnoff 			pfctl_load_fingerprints(dev, opts);
31408ddd0359SKristof Provost 			pfctl_show_nat(dev, path, opts, anchorname, 0, 0);
31413b3a8eb9SGleb Smirnoff 			break;
31423b3a8eb9SGleb Smirnoff 		case 'q':
31433b3a8eb9SGleb Smirnoff 			pfctl_show_altq(dev, ifaceopt, opts,
31443b3a8eb9SGleb Smirnoff 			    opts & PF_OPT_VERBOSE2);
31453b3a8eb9SGleb Smirnoff 			break;
31463b3a8eb9SGleb Smirnoff 		case 's':
31473b3a8eb9SGleb Smirnoff 			pfctl_show_states(dev, ifaceopt, opts);
31483b3a8eb9SGleb Smirnoff 			break;
31493b3a8eb9SGleb Smirnoff 		case 'S':
31503b3a8eb9SGleb Smirnoff 			pfctl_show_src_nodes(dev, opts);
31513b3a8eb9SGleb Smirnoff 			break;
31523b3a8eb9SGleb Smirnoff 		case 'i':
31533b3a8eb9SGleb Smirnoff 			pfctl_show_status(dev, opts);
31543b3a8eb9SGleb Smirnoff 			break;
3155fa1d4439SKristof Provost 		case 'R':
3156fa1d4439SKristof Provost 			error = pfctl_show_running(dev);
3157fa1d4439SKristof Provost 			break;
31583b3a8eb9SGleb Smirnoff 		case 't':
31593b3a8eb9SGleb Smirnoff 			pfctl_show_timeouts(dev, opts);
31603b3a8eb9SGleb Smirnoff 			break;
31613b3a8eb9SGleb Smirnoff 		case 'm':
31623b3a8eb9SGleb Smirnoff 			pfctl_show_limits(dev, opts);
31633b3a8eb9SGleb Smirnoff 			break;
31642b29ceb8SKristof Provost 		case 'e':
3165cfa1a130SKristof Provost 			pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0,
3166cfa1a130SKristof Provost 			    0);
31672b29ceb8SKristof Provost 			break;
31683b3a8eb9SGleb Smirnoff 		case 'a':
31693b3a8eb9SGleb Smirnoff 			opts |= PF_OPT_SHOWALL;
31703b3a8eb9SGleb Smirnoff 			pfctl_load_fingerprints(dev, opts);
31713b3a8eb9SGleb Smirnoff 
3172cfa1a130SKristof Provost 			pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0,
3173cfa1a130SKristof Provost 			    0);
31742b29ceb8SKristof Provost 
31758ddd0359SKristof Provost 			pfctl_show_nat(dev, path, opts, anchorname, 0, 0);
3176585a5ed0SKristof Provost 			pfctl_show_rules(dev, path, opts, 0, anchorname, 0, 0);
31773b3a8eb9SGleb Smirnoff 			pfctl_show_altq(dev, ifaceopt, opts, 0);
31783b3a8eb9SGleb Smirnoff 			pfctl_show_states(dev, ifaceopt, opts);
31793b3a8eb9SGleb Smirnoff 			pfctl_show_src_nodes(dev, opts);
31803b3a8eb9SGleb Smirnoff 			pfctl_show_status(dev, opts);
3181585a5ed0SKristof Provost 			pfctl_show_rules(dev, path, opts, 1, anchorname, 0, 0);
31823b3a8eb9SGleb Smirnoff 			pfctl_show_timeouts(dev, opts);
31833b3a8eb9SGleb Smirnoff 			pfctl_show_limits(dev, opts);
31843b3a8eb9SGleb Smirnoff 			pfctl_show_tables(anchorname, opts);
31853b3a8eb9SGleb Smirnoff 			pfctl_show_fingerprints(opts);
31863b3a8eb9SGleb Smirnoff 			break;
31873b3a8eb9SGleb Smirnoff 		case 'T':
31883b3a8eb9SGleb Smirnoff 			pfctl_show_tables(anchorname, opts);
31893b3a8eb9SGleb Smirnoff 			break;
31903b3a8eb9SGleb Smirnoff 		case 'o':
31913b3a8eb9SGleb Smirnoff 			pfctl_load_fingerprints(dev, opts);
31923b3a8eb9SGleb Smirnoff 			pfctl_show_fingerprints(opts);
31933b3a8eb9SGleb Smirnoff 			break;
31943b3a8eb9SGleb Smirnoff 		case 'I':
31953b3a8eb9SGleb Smirnoff 			pfctl_show_ifaces(ifaceopt, opts);
31963b3a8eb9SGleb Smirnoff 			break;
3197a7191e5dSKristof Provost 		case 'c':
3198a7191e5dSKristof Provost 			pfctl_show_creators(opts);
3199a7191e5dSKristof Provost 			break;
32003b3a8eb9SGleb Smirnoff 		}
32013b3a8eb9SGleb Smirnoff 	}
32023b3a8eb9SGleb Smirnoff 
320330087aa2SKristof Provost 	if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) {
3204c5131afeSKristof Provost 		pfctl_show_eth_rules(dev, path, opts, PFCTL_SHOW_NOTHING,
3205cfa1a130SKristof Provost 		    anchorname, 0, 0);
32063b3a8eb9SGleb Smirnoff 		pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING,
3207585a5ed0SKristof Provost 		    anchorname, 0, 0);
320830087aa2SKristof Provost 	}
32093b3a8eb9SGleb Smirnoff 
32103b3a8eb9SGleb Smirnoff 	if (clearopt != NULL) {
32113b3a8eb9SGleb Smirnoff 		if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
32123b3a8eb9SGleb Smirnoff 			errx(1, "anchor names beginning with '_' cannot "
32133b3a8eb9SGleb Smirnoff 			    "be modified from the command line");
32143b3a8eb9SGleb Smirnoff 
32153b3a8eb9SGleb Smirnoff 		switch (*clearopt) {
32166ea1c3cfSKristof Provost 		case 'e':
3217f0c334e4SKristof Provost 			pfctl_flush_eth_rules(dev, opts, anchorname);
32186ea1c3cfSKristof Provost 			break;
32193b3a8eb9SGleb Smirnoff 		case 'r':
3220f0c334e4SKristof Provost 			pfctl_flush_rules(dev, opts, anchorname);
32213b3a8eb9SGleb Smirnoff 			break;
32223b3a8eb9SGleb Smirnoff 		case 'n':
3223f0c334e4SKristof Provost 			pfctl_flush_nat(dev, opts, anchorname);
32243b3a8eb9SGleb Smirnoff 			break;
32253b3a8eb9SGleb Smirnoff 		case 'q':
32263b3a8eb9SGleb Smirnoff 			pfctl_clear_altq(dev, opts);
32273b3a8eb9SGleb Smirnoff 			break;
32283b3a8eb9SGleb Smirnoff 		case 's':
322953714a58SKristof Provost 			pfctl_clear_iface_states(dev, ifaceopt, opts);
32303b3a8eb9SGleb Smirnoff 			break;
32313b3a8eb9SGleb Smirnoff 		case 'S':
32323b3a8eb9SGleb Smirnoff 			pfctl_clear_src_nodes(dev, opts);
32333b3a8eb9SGleb Smirnoff 			break;
32343b3a8eb9SGleb Smirnoff 		case 'i':
32359dbbe68bSKristof Provost 			pfctl_clear_stats(pfh, opts);
32363b3a8eb9SGleb Smirnoff 			break;
32373b3a8eb9SGleb Smirnoff 		case 'a':
3238f0c334e4SKristof Provost 			pfctl_flush_eth_rules(dev, opts, anchorname);
3239f0c334e4SKristof Provost 			pfctl_flush_rules(dev, opts, anchorname);
3240f0c334e4SKristof Provost 			pfctl_flush_nat(dev, opts, anchorname);
3241441d4894SKristof Provost 			pfctl_do_clear_tables(anchorname, opts);
32423b3a8eb9SGleb Smirnoff 			if (!*anchorname) {
32433b3a8eb9SGleb Smirnoff 				pfctl_clear_altq(dev, opts);
324453714a58SKristof Provost 				pfctl_clear_iface_states(dev, ifaceopt, opts);
32453b3a8eb9SGleb Smirnoff 				pfctl_clear_src_nodes(dev, opts);
32469dbbe68bSKristof Provost 				pfctl_clear_stats(pfh, opts);
32473b3a8eb9SGleb Smirnoff 				pfctl_clear_fingerprints(dev, opts);
32483b3a8eb9SGleb Smirnoff 				pfctl_clear_interface_flags(dev, opts);
32493b3a8eb9SGleb Smirnoff 			}
32503b3a8eb9SGleb Smirnoff 			break;
32513b3a8eb9SGleb Smirnoff 		case 'o':
32523b3a8eb9SGleb Smirnoff 			pfctl_clear_fingerprints(dev, opts);
32533b3a8eb9SGleb Smirnoff 			break;
32543b3a8eb9SGleb Smirnoff 		case 'T':
3255441d4894SKristof Provost 			pfctl_do_clear_tables(anchorname, opts);
32563b3a8eb9SGleb Smirnoff 			break;
32573b3a8eb9SGleb Smirnoff 		}
32583b3a8eb9SGleb Smirnoff 	}
32593b3a8eb9SGleb Smirnoff 	if (state_killers) {
32603b3a8eb9SGleb Smirnoff 		if (!strcmp(state_kill[0], "label"))
32613b3a8eb9SGleb Smirnoff 			pfctl_label_kill_states(dev, ifaceopt, opts);
32623b3a8eb9SGleb Smirnoff 		else if (!strcmp(state_kill[0], "id"))
32633b3a8eb9SGleb Smirnoff 			pfctl_id_kill_states(dev, ifaceopt, opts);
3264abbcba9cSKristof Provost 		else if (!strcmp(state_kill[0], "gateway"))
3265abbcba9cSKristof Provost 			pfctl_gateway_kill_states(dev, ifaceopt, opts);
32663b3a8eb9SGleb Smirnoff 		else
32673b3a8eb9SGleb Smirnoff 			pfctl_net_kill_states(dev, ifaceopt, opts);
32683b3a8eb9SGleb Smirnoff 	}
32693b3a8eb9SGleb Smirnoff 
32703b3a8eb9SGleb Smirnoff 	if (src_node_killers)
32713b3a8eb9SGleb Smirnoff 		pfctl_kill_src_nodes(dev, ifaceopt, opts);
32723b3a8eb9SGleb Smirnoff 
32733b3a8eb9SGleb Smirnoff 	if (tblcmdopt != NULL) {
32743b3a8eb9SGleb Smirnoff 		error = pfctl_command_tables(argc, argv, tableopt,
32753b3a8eb9SGleb Smirnoff 		    tblcmdopt, rulesopt, anchorname, opts);
32763b3a8eb9SGleb Smirnoff 		rulesopt = NULL;
32773b3a8eb9SGleb Smirnoff 	}
32783b3a8eb9SGleb Smirnoff 	if (optiopt != NULL) {
32793b3a8eb9SGleb Smirnoff 		switch (*optiopt) {
32803b3a8eb9SGleb Smirnoff 		case 'n':
32813b3a8eb9SGleb Smirnoff 			optimize = 0;
32823b3a8eb9SGleb Smirnoff 			break;
32833b3a8eb9SGleb Smirnoff 		case 'b':
32843b3a8eb9SGleb Smirnoff 			optimize |= PF_OPTIMIZE_BASIC;
32853b3a8eb9SGleb Smirnoff 			break;
32863b3a8eb9SGleb Smirnoff 		case 'o':
32873b3a8eb9SGleb Smirnoff 		case 'p':
32883b3a8eb9SGleb Smirnoff 			optimize |= PF_OPTIMIZE_PROFILE;
32893b3a8eb9SGleb Smirnoff 			break;
32903b3a8eb9SGleb Smirnoff 		}
32913b3a8eb9SGleb Smirnoff 	}
32923b3a8eb9SGleb Smirnoff 
32933b3a8eb9SGleb Smirnoff 	if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) &&
32947a2bf4c5SKristof Provost 	    !anchorname[0] && !(opts & PF_OPT_NOACTION))
3295c5e10565SKristof Provost 		if (pfctl_get_skip_ifaces())
32963b3a8eb9SGleb Smirnoff 			error = 1;
32973b3a8eb9SGleb Smirnoff 
32983b3a8eb9SGleb Smirnoff 	if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) &&
32993b3a8eb9SGleb Smirnoff 	    !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION))
33003b3a8eb9SGleb Smirnoff 		if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE))
33013b3a8eb9SGleb Smirnoff 			error = 1;
33023b3a8eb9SGleb Smirnoff 
33033b3a8eb9SGleb Smirnoff 	if (rulesopt != NULL) {
33043b3a8eb9SGleb Smirnoff 		if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
33053b3a8eb9SGleb Smirnoff 			errx(1, "anchor names beginning with '_' cannot "
33063b3a8eb9SGleb Smirnoff 			    "be modified from the command line");
33073b3a8eb9SGleb Smirnoff 		if (pfctl_rules(dev, rulesopt, opts, optimize,
33083b3a8eb9SGleb Smirnoff 		    anchorname, NULL))
33093b3a8eb9SGleb Smirnoff 			error = 1;
33103b3a8eb9SGleb Smirnoff 		else if (!(opts & PF_OPT_NOACTION) &&
33113b3a8eb9SGleb Smirnoff 		    (loadopt & PFCTL_FLAG_TABLE))
33123b3a8eb9SGleb Smirnoff 			warn_namespace_collision(NULL);
33133b3a8eb9SGleb Smirnoff 	}
33143b3a8eb9SGleb Smirnoff 
33153b3a8eb9SGleb Smirnoff 	if (opts & PF_OPT_ENABLE)
33163b3a8eb9SGleb Smirnoff 		if (pfctl_enable(dev, opts))
33173b3a8eb9SGleb Smirnoff 			error = 1;
33183b3a8eb9SGleb Smirnoff 
33193b3a8eb9SGleb Smirnoff 	if (debugopt != NULL) {
33203b3a8eb9SGleb Smirnoff 		switch (*debugopt) {
33213b3a8eb9SGleb Smirnoff 		case 'n':
33223b3a8eb9SGleb Smirnoff 			pfctl_debug(dev, PF_DEBUG_NONE, opts);
33233b3a8eb9SGleb Smirnoff 			break;
33243b3a8eb9SGleb Smirnoff 		case 'u':
33253b3a8eb9SGleb Smirnoff 			pfctl_debug(dev, PF_DEBUG_URGENT, opts);
33263b3a8eb9SGleb Smirnoff 			break;
33273b3a8eb9SGleb Smirnoff 		case 'm':
33283b3a8eb9SGleb Smirnoff 			pfctl_debug(dev, PF_DEBUG_MISC, opts);
33293b3a8eb9SGleb Smirnoff 			break;
33303b3a8eb9SGleb Smirnoff 		case 'l':
33313b3a8eb9SGleb Smirnoff 			pfctl_debug(dev, PF_DEBUG_NOISY, opts);
33323b3a8eb9SGleb Smirnoff 			break;
33333b3a8eb9SGleb Smirnoff 		}
33343b3a8eb9SGleb Smirnoff 	}
33353b3a8eb9SGleb Smirnoff 
33363b3a8eb9SGleb Smirnoff 	exit(error);
33373b3a8eb9SGleb Smirnoff }
3338