1/*	$OpenBSD: pfctl.c,v 1.278 2008/08/31 20:18:17 jmc Exp $ */
2
3/*-
4 * SPDX-License-Identifier: BSD-2-Clause
5 *
6 * Copyright (c) 2001 Daniel Hartmeier
7 * Copyright (c) 2002,2003 Henning Brauer
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 *    - Redistributions of source code must retain the above copyright
15 *      notice, this list of conditions and the following disclaimer.
16 *    - Redistributions in binary form must reproduce the above
17 *      copyright notice, this list of conditions and the following
18 *      disclaimer in the documentation and/or other materials provided
19 *      with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
35
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD$");
38
39#define PFIOC_USE_LATEST
40
41#include <sys/types.h>
42#include <sys/ioctl.h>
43#include <sys/nv.h>
44#include <sys/socket.h>
45#include <sys/stat.h>
46#include <sys/endian.h>
47
48#include <net/if.h>
49#include <netinet/in.h>
50#include <net/pfvar.h>
51#include <arpa/inet.h>
52#include <net/altq/altq.h>
53#include <sys/sysctl.h>
54
55#include <err.h>
56#include <errno.h>
57#include <fcntl.h>
58#include <libpfctl.h>
59#include <limits.h>
60#include <netdb.h>
61#include <stdint.h>
62#include <stdio.h>
63#include <stdlib.h>
64#include <string.h>
65#include <unistd.h>
66
67#include "pfctl_parser.h"
68#include "pfctl.h"
69
70void	 usage(void);
71int	 pfctl_enable(int, int);
72int	 pfctl_disable(int, int);
73int	 pfctl_clear_stats(int, int);
74int	 pfctl_get_skip_ifaces(void);
75int	 pfctl_check_skip_ifaces(char *);
76int	 pfctl_adjust_skip_ifaces(struct pfctl *);
77int	 pfctl_clear_interface_flags(int, int);
78int	 pfctl_clear_rules(int, int, char *);
79int	 pfctl_clear_nat(int, int, char *);
80int	 pfctl_clear_altq(int, int);
81int	 pfctl_clear_src_nodes(int, int);
82int	 pfctl_clear_iface_states(int, const char *, int);
83void	 pfctl_addrprefix(char *, struct pf_addr *);
84int	 pfctl_kill_src_nodes(int, const char *, int);
85int	 pfctl_net_kill_states(int, const char *, int);
86int	 pfctl_gateway_kill_states(int, const char *, int);
87int	 pfctl_label_kill_states(int, const char *, int);
88int	 pfctl_id_kill_states(int, const char *, int);
89void	 pfctl_init_options(struct pfctl *);
90int	 pfctl_load_options(struct pfctl *);
91int	 pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
92int	 pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int);
93int	 pfctl_load_debug(struct pfctl *, unsigned int);
94int	 pfctl_load_logif(struct pfctl *, char *);
95int	 pfctl_load_hostid(struct pfctl *, u_int32_t);
96int	 pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int,
97	    char *);
98void	 pfctl_print_rule_counters(struct pfctl_rule *, int);
99int	 pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int);
100int	 pfctl_show_nat(int, int, char *);
101int	 pfctl_show_src_nodes(int, int);
102int	 pfctl_show_states(int, const char *, int);
103int	 pfctl_show_status(int, int);
104int	 pfctl_show_running(int);
105int	 pfctl_show_timeouts(int, int);
106int	 pfctl_show_limits(int, int);
107void	 pfctl_debug(int, u_int32_t, int);
108int	 pfctl_test_altqsupport(int, int);
109int	 pfctl_show_anchors(int, int, char *);
110int	 pfctl_ruleset_trans(struct pfctl *, char *, struct pfctl_anchor *);
111int	 pfctl_load_ruleset(struct pfctl *, char *,
112		struct pfctl_ruleset *, int, int);
113int	 pfctl_load_rule(struct pfctl *, char *, struct pfctl_rule *, int);
114const char	*pfctl_lookup_option(char *, const char * const *);
115
116static struct pfctl_anchor_global	 pf_anchors;
117static struct pfctl_anchor	 pf_main_anchor;
118static struct pfr_buffer skip_b;
119
120static const char	*clearopt;
121static char		*rulesopt;
122static const char	*showopt;
123static const char	*debugopt;
124static char		*anchoropt;
125static const char	*optiopt = NULL;
126static const char	*pf_device = "/dev/pf";
127static char		*ifaceopt;
128static char		*tableopt;
129static const char	*tblcmdopt;
130static int		 src_node_killers;
131static char		*src_node_kill[2];
132static int		 state_killers;
133static char		*state_kill[2];
134int			 loadopt;
135int			 altqsupport;
136
137int			 dev = -1;
138static int		 first_title = 1;
139static int		 labels = 0;
140
141#define INDENT(d, o)	do {						\
142				if (o) {				\
143					int i;				\
144					for (i=0; i < d; i++)		\
145						printf("  ");		\
146				}					\
147			} while (0);					\
148
149
150static const struct {
151	const char	*name;
152	int		index;
153} pf_limits[] = {
154	{ "states",		PF_LIMIT_STATES },
155	{ "src-nodes",		PF_LIMIT_SRC_NODES },
156	{ "frags",		PF_LIMIT_FRAGS },
157	{ "table-entries",	PF_LIMIT_TABLE_ENTRIES },
158	{ NULL,			0 }
159};
160
161struct pf_hint {
162	const char	*name;
163	int		timeout;
164};
165static const struct pf_hint pf_hint_normal[] = {
166	{ "tcp.first",		2 * 60 },
167	{ "tcp.opening",	30 },
168	{ "tcp.established",	24 * 60 * 60 },
169	{ "tcp.closing",	15 * 60 },
170	{ "tcp.finwait",	45 },
171	{ "tcp.closed",		90 },
172	{ "tcp.tsdiff",		30 },
173	{ NULL,			0 }
174};
175static const struct pf_hint pf_hint_satellite[] = {
176	{ "tcp.first",		3 * 60 },
177	{ "tcp.opening",	30 + 5 },
178	{ "tcp.established",	24 * 60 * 60 },
179	{ "tcp.closing",	15 * 60 + 5 },
180	{ "tcp.finwait",	45 + 5 },
181	{ "tcp.closed",		90 + 5 },
182	{ "tcp.tsdiff",		60 },
183	{ NULL,			0 }
184};
185static const struct pf_hint pf_hint_conservative[] = {
186	{ "tcp.first",		60 * 60 },
187	{ "tcp.opening",	15 * 60 },
188	{ "tcp.established",	5 * 24 * 60 * 60 },
189	{ "tcp.closing",	60 * 60 },
190	{ "tcp.finwait",	10 * 60 },
191	{ "tcp.closed",		3 * 60 },
192	{ "tcp.tsdiff",		60 },
193	{ NULL,			0 }
194};
195static const struct pf_hint pf_hint_aggressive[] = {
196	{ "tcp.first",		30 },
197	{ "tcp.opening",	5 },
198	{ "tcp.established",	5 * 60 * 60 },
199	{ "tcp.closing",	60 },
200	{ "tcp.finwait",	30 },
201	{ "tcp.closed",		30 },
202	{ "tcp.tsdiff",		10 },
203	{ NULL,			0 }
204};
205
206static const struct {
207	const char *name;
208	const struct pf_hint *hint;
209} pf_hints[] = {
210	{ "normal",		pf_hint_normal },
211	{ "satellite",		pf_hint_satellite },
212	{ "high-latency",	pf_hint_satellite },
213	{ "conservative",	pf_hint_conservative },
214	{ "aggressive",		pf_hint_aggressive },
215	{ NULL,			NULL }
216};
217
218static const char * const clearopt_list[] = {
219	"nat", "queue", "rules", "Sources",
220	"states", "info", "Tables", "osfp", "all", NULL
221};
222
223static const char * const showopt_list[] = {
224	"nat", "queue", "rules", "Anchors", "Sources", "states", "info",
225	"Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
226	"Running", "all", NULL
227};
228
229static const char * const tblcmdopt_list[] = {
230	"kill", "flush", "add", "delete", "load", "replace", "show",
231	"test", "zero", "expire", NULL
232};
233
234static const char * const debugopt_list[] = {
235	"none", "urgent", "misc", "loud", NULL
236};
237
238static const char * const optiopt_list[] = {
239	"none", "basic", "profile", NULL
240};
241
242void
243usage(void)
244{
245	extern char *__progname;
246
247	fprintf(stderr,
248"usage: %s [-AdeghMmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n"
249	"\t[-f file] [-i interface] [-K host | network]\n"
250	"\t[-k host | network | gateway | label | id] [-o level] [-p device]\n"
251	"\t[-s modifier] [-t table -T command [address ...]] [-x level]\n",
252	    __progname);
253
254	exit(1);
255}
256
257int
258pfctl_enable(int dev, int opts)
259{
260	if (ioctl(dev, DIOCSTART)) {
261		if (errno == EEXIST)
262			errx(1, "pf already enabled");
263		else if (errno == ESRCH)
264			errx(1, "pfil registeration failed");
265		else
266			err(1, "DIOCSTART");
267	}
268	if ((opts & PF_OPT_QUIET) == 0)
269		fprintf(stderr, "pf enabled\n");
270
271	if (altqsupport && ioctl(dev, DIOCSTARTALTQ))
272		if (errno != EEXIST)
273			err(1, "DIOCSTARTALTQ");
274
275	return (0);
276}
277
278int
279pfctl_disable(int dev, int opts)
280{
281	if (ioctl(dev, DIOCSTOP)) {
282		if (errno == ENOENT)
283			errx(1, "pf not enabled");
284		else
285			err(1, "DIOCSTOP");
286	}
287	if ((opts & PF_OPT_QUIET) == 0)
288		fprintf(stderr, "pf disabled\n");
289
290	if (altqsupport && ioctl(dev, DIOCSTOPALTQ))
291			if (errno != ENOENT)
292				err(1, "DIOCSTOPALTQ");
293
294	return (0);
295}
296
297int
298pfctl_clear_stats(int dev, int opts)
299{
300	if (ioctl(dev, DIOCCLRSTATUS))
301		err(1, "DIOCCLRSTATUS");
302	if ((opts & PF_OPT_QUIET) == 0)
303		fprintf(stderr, "pf: statistics cleared\n");
304	return (0);
305}
306
307int
308pfctl_get_skip_ifaces(void)
309{
310	bzero(&skip_b, sizeof(skip_b));
311	skip_b.pfrb_type = PFRB_IFACES;
312	for (;;) {
313		pfr_buf_grow(&skip_b, skip_b.pfrb_size);
314		skip_b.pfrb_size = skip_b.pfrb_msize;
315		if (pfi_get_ifaces(NULL, skip_b.pfrb_caddr, &skip_b.pfrb_size))
316			err(1, "pfi_get_ifaces");
317		if (skip_b.pfrb_size <= skip_b.pfrb_msize)
318			break;
319	}
320	return (0);
321}
322
323int
324pfctl_check_skip_ifaces(char *ifname)
325{
326	struct pfi_kif		*p;
327	struct node_host	*h = NULL, *n = NULL;
328
329	PFRB_FOREACH(p, &skip_b) {
330		if (!strcmp(ifname, p->pfik_name) &&
331		    (p->pfik_flags & PFI_IFLAG_SKIP))
332			p->pfik_flags &= ~PFI_IFLAG_SKIP;
333		if (!strcmp(ifname, p->pfik_name) && p->pfik_group != NULL) {
334			if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL)
335				continue;
336
337			for (n = h; n != NULL; n = n->next) {
338				if (p->pfik_ifp == NULL)
339					continue;
340				if (strncmp(p->pfik_name, ifname, IFNAMSIZ))
341					continue;
342
343				p->pfik_flags &= ~PFI_IFLAG_SKIP;
344			}
345		}
346	}
347	return (0);
348}
349
350int
351pfctl_adjust_skip_ifaces(struct pfctl *pf)
352{
353	struct pfi_kif		*p, *pp;
354	struct node_host	*h = NULL, *n = NULL;
355
356	PFRB_FOREACH(p, &skip_b) {
357		if (p->pfik_group == NULL || !(p->pfik_flags & PFI_IFLAG_SKIP))
358			continue;
359
360		pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0);
361		if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL)
362			continue;
363
364		for (n = h; n != NULL; n = n->next)
365			PFRB_FOREACH(pp, &skip_b) {
366				if (pp->pfik_ifp == NULL)
367					continue;
368
369				if (strncmp(pp->pfik_name, n->ifname, IFNAMSIZ))
370					continue;
371
372				if (!(pp->pfik_flags & PFI_IFLAG_SKIP))
373					pfctl_set_interface_flags(pf,
374					    pp->pfik_name, PFI_IFLAG_SKIP, 1);
375				if (pp->pfik_flags & PFI_IFLAG_SKIP)
376					pp->pfik_flags &= ~PFI_IFLAG_SKIP;
377			}
378	}
379
380	PFRB_FOREACH(p, &skip_b) {
381		if (p->pfik_ifp == NULL || ! (p->pfik_flags & PFI_IFLAG_SKIP))
382			continue;
383
384		pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0);
385	}
386
387	return (0);
388}
389
390int
391pfctl_clear_interface_flags(int dev, int opts)
392{
393	struct pfioc_iface	pi;
394
395	if ((opts & PF_OPT_NOACTION) == 0) {
396		bzero(&pi, sizeof(pi));
397		pi.pfiio_flags = PFI_IFLAG_SKIP;
398
399		if (ioctl(dev, DIOCCLRIFFLAG, &pi))
400			err(1, "DIOCCLRIFFLAG");
401		if ((opts & PF_OPT_QUIET) == 0)
402			fprintf(stderr, "pf: interface flags reset\n");
403	}
404	return (0);
405}
406
407int
408pfctl_clear_rules(int dev, int opts, char *anchorname)
409{
410	struct pfr_buffer t;
411
412	memset(&t, 0, sizeof(t));
413	t.pfrb_type = PFRB_TRANS;
414	if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname) ||
415	    pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) ||
416	    pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
417	    pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
418		err(1, "pfctl_clear_rules");
419	if ((opts & PF_OPT_QUIET) == 0)
420		fprintf(stderr, "rules cleared\n");
421	return (0);
422}
423
424int
425pfctl_clear_nat(int dev, int opts, char *anchorname)
426{
427	struct pfr_buffer t;
428
429	memset(&t, 0, sizeof(t));
430	t.pfrb_type = PFRB_TRANS;
431	if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname) ||
432	    pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname) ||
433	    pfctl_add_trans(&t, PF_RULESET_RDR, anchorname) ||
434	    pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
435	    pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
436		err(1, "pfctl_clear_nat");
437	if ((opts & PF_OPT_QUIET) == 0)
438		fprintf(stderr, "nat cleared\n");
439	return (0);
440}
441
442int
443pfctl_clear_altq(int dev, int opts)
444{
445	struct pfr_buffer t;
446
447	if (!altqsupport)
448		return (-1);
449	memset(&t, 0, sizeof(t));
450	t.pfrb_type = PFRB_TRANS;
451	if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") ||
452	    pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
453	    pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
454		err(1, "pfctl_clear_altq");
455	if ((opts & PF_OPT_QUIET) == 0)
456		fprintf(stderr, "altq cleared\n");
457	return (0);
458}
459
460int
461pfctl_clear_src_nodes(int dev, int opts)
462{
463	if (ioctl(dev, DIOCCLRSRCNODES))
464		err(1, "DIOCCLRSRCNODES");
465	if ((opts & PF_OPT_QUIET) == 0)
466		fprintf(stderr, "source tracking entries cleared\n");
467	return (0);
468}
469
470int
471pfctl_clear_iface_states(int dev, const char *iface, int opts)
472{
473	struct pfctl_kill kill;
474	unsigned int killed;
475
476	memset(&kill, 0, sizeof(kill));
477	if (iface != NULL && strlcpy(kill.ifname, iface,
478	    sizeof(kill.ifname)) >= sizeof(kill.ifname))
479		errx(1, "invalid interface: %s", iface);
480
481	if (opts & PF_OPT_KILLMATCH)
482		kill.kill_match = true;
483
484	if (pfctl_clear_states(dev, &kill, &killed))
485		err(1, "DIOCCLRSTATES");
486	if ((opts & PF_OPT_QUIET) == 0)
487		fprintf(stderr, "%d states cleared\n", killed);
488	return (0);
489}
490
491void
492pfctl_addrprefix(char *addr, struct pf_addr *mask)
493{
494	char *p;
495	const char *errstr;
496	int prefix, ret_ga, q, r;
497	struct addrinfo hints, *res;
498
499	if ((p = strchr(addr, '/')) == NULL)
500		return;
501
502	*p++ = '\0';
503	prefix = strtonum(p, 0, 128, &errstr);
504	if (errstr)
505		errx(1, "prefix is %s: %s", errstr, p);
506
507	bzero(&hints, sizeof(hints));
508	/* prefix only with numeric addresses */
509	hints.ai_flags |= AI_NUMERICHOST;
510
511	if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) {
512		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
513		/* NOTREACHED */
514	}
515
516	if (res->ai_family == AF_INET && prefix > 32)
517		errx(1, "prefix too long for AF_INET");
518	else if (res->ai_family == AF_INET6 && prefix > 128)
519		errx(1, "prefix too long for AF_INET6");
520
521	q = prefix >> 3;
522	r = prefix & 7;
523	switch (res->ai_family) {
524	case AF_INET:
525		bzero(&mask->v4, sizeof(mask->v4));
526		mask->v4.s_addr = htonl((u_int32_t)
527		    (0xffffffffffULL << (32 - prefix)));
528		break;
529	case AF_INET6:
530		bzero(&mask->v6, sizeof(mask->v6));
531		if (q > 0)
532			memset((void *)&mask->v6, 0xff, q);
533		if (r > 0)
534			*((u_char *)&mask->v6 + q) =
535			    (0xff00 >> r) & 0xff;
536		break;
537	}
538	freeaddrinfo(res);
539}
540
541int
542pfctl_kill_src_nodes(int dev, const char *iface, int opts)
543{
544	struct pfioc_src_node_kill psnk;
545	struct addrinfo *res[2], *resp[2];
546	struct sockaddr last_src, last_dst;
547	int killed, sources, dests;
548	int ret_ga;
549
550	killed = sources = dests = 0;
551
552	memset(&psnk, 0, sizeof(psnk));
553	memset(&psnk.psnk_src.addr.v.a.mask, 0xff,
554	    sizeof(psnk.psnk_src.addr.v.a.mask));
555	memset(&last_src, 0xff, sizeof(last_src));
556	memset(&last_dst, 0xff, sizeof(last_dst));
557
558	pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask);
559
560	if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) {
561		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
562		/* NOTREACHED */
563	}
564	for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
565		if (resp[0]->ai_addr == NULL)
566			continue;
567		/* We get lots of duplicates.  Catch the easy ones */
568		if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
569			continue;
570		last_src = *(struct sockaddr *)resp[0]->ai_addr;
571
572		psnk.psnk_af = resp[0]->ai_family;
573		sources++;
574
575		if (psnk.psnk_af == AF_INET)
576			psnk.psnk_src.addr.v.a.addr.v4 =
577			    ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
578		else if (psnk.psnk_af == AF_INET6)
579			psnk.psnk_src.addr.v.a.addr.v6 =
580			    ((struct sockaddr_in6 *)resp[0]->ai_addr)->
581			    sin6_addr;
582		else
583			errx(1, "Unknown address family %d", psnk.psnk_af);
584
585		if (src_node_killers > 1) {
586			dests = 0;
587			memset(&psnk.psnk_dst.addr.v.a.mask, 0xff,
588			    sizeof(psnk.psnk_dst.addr.v.a.mask));
589			memset(&last_dst, 0xff, sizeof(last_dst));
590			pfctl_addrprefix(src_node_kill[1],
591			    &psnk.psnk_dst.addr.v.a.mask);
592			if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL,
593			    &res[1]))) {
594				errx(1, "getaddrinfo: %s",
595				    gai_strerror(ret_ga));
596				/* NOTREACHED */
597			}
598			for (resp[1] = res[1]; resp[1];
599			    resp[1] = resp[1]->ai_next) {
600				if (resp[1]->ai_addr == NULL)
601					continue;
602				if (psnk.psnk_af != resp[1]->ai_family)
603					continue;
604
605				if (memcmp(&last_dst, resp[1]->ai_addr,
606				    sizeof(last_dst)) == 0)
607					continue;
608				last_dst = *(struct sockaddr *)resp[1]->ai_addr;
609
610				dests++;
611
612				if (psnk.psnk_af == AF_INET)
613					psnk.psnk_dst.addr.v.a.addr.v4 =
614					    ((struct sockaddr_in *)resp[1]->
615					    ai_addr)->sin_addr;
616				else if (psnk.psnk_af == AF_INET6)
617					psnk.psnk_dst.addr.v.a.addr.v6 =
618					    ((struct sockaddr_in6 *)resp[1]->
619					    ai_addr)->sin6_addr;
620				else
621					errx(1, "Unknown address family %d",
622					    psnk.psnk_af);
623
624				if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
625					err(1, "DIOCKILLSRCNODES");
626				killed += psnk.psnk_killed;
627			}
628			freeaddrinfo(res[1]);
629		} else {
630			if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
631				err(1, "DIOCKILLSRCNODES");
632			killed += psnk.psnk_killed;
633		}
634	}
635
636	freeaddrinfo(res[0]);
637
638	if ((opts & PF_OPT_QUIET) == 0)
639		fprintf(stderr, "killed %d src nodes from %d sources and %d "
640		    "destinations\n", killed, sources, dests);
641	return (0);
642}
643
644int
645pfctl_net_kill_states(int dev, const char *iface, int opts)
646{
647	struct pfctl_kill kill;
648	struct addrinfo *res[2], *resp[2];
649	struct sockaddr last_src, last_dst;
650	unsigned int newkilled;
651	int killed, sources, dests;
652	int ret_ga;
653
654	killed = sources = dests = 0;
655
656	memset(&kill, 0, sizeof(kill));
657	memset(&kill.src.addr.v.a.mask, 0xff,
658	    sizeof(kill.src.addr.v.a.mask));
659	memset(&last_src, 0xff, sizeof(last_src));
660	memset(&last_dst, 0xff, sizeof(last_dst));
661	if (iface != NULL && strlcpy(kill.ifname, iface,
662	    sizeof(kill.ifname)) >= sizeof(kill.ifname))
663		errx(1, "invalid interface: %s", iface);
664
665	pfctl_addrprefix(state_kill[0], &kill.src.addr.v.a.mask);
666
667	if (opts & PF_OPT_KILLMATCH)
668		kill.kill_match = true;
669
670	if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) {
671		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
672		/* NOTREACHED */
673	}
674	for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
675		if (resp[0]->ai_addr == NULL)
676			continue;
677		/* We get lots of duplicates.  Catch the easy ones */
678		if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
679			continue;
680		last_src = *(struct sockaddr *)resp[0]->ai_addr;
681
682		kill.af = resp[0]->ai_family;
683		sources++;
684
685		if (kill.af == AF_INET)
686			kill.src.addr.v.a.addr.v4 =
687			    ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
688		else if (kill.af == AF_INET6)
689			kill.src.addr.v.a.addr.v6 =
690			    ((struct sockaddr_in6 *)resp[0]->ai_addr)->
691			    sin6_addr;
692		else
693			errx(1, "Unknown address family %d", kill.af);
694
695		if (state_killers > 1) {
696			dests = 0;
697			memset(&kill.dst.addr.v.a.mask, 0xff,
698			    sizeof(kill.dst.addr.v.a.mask));
699			memset(&last_dst, 0xff, sizeof(last_dst));
700			pfctl_addrprefix(state_kill[1],
701			    &kill.dst.addr.v.a.mask);
702			if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL,
703			    &res[1]))) {
704				errx(1, "getaddrinfo: %s",
705				    gai_strerror(ret_ga));
706				/* NOTREACHED */
707			}
708			for (resp[1] = res[1]; resp[1];
709			    resp[1] = resp[1]->ai_next) {
710				if (resp[1]->ai_addr == NULL)
711					continue;
712				if (kill.af != resp[1]->ai_family)
713					continue;
714
715				if (memcmp(&last_dst, resp[1]->ai_addr,
716				    sizeof(last_dst)) == 0)
717					continue;
718				last_dst = *(struct sockaddr *)resp[1]->ai_addr;
719
720				dests++;
721
722				if (kill.af == AF_INET)
723					kill.dst.addr.v.a.addr.v4 =
724					    ((struct sockaddr_in *)resp[1]->
725					    ai_addr)->sin_addr;
726				else if (kill.af == AF_INET6)
727					kill.dst.addr.v.a.addr.v6 =
728					    ((struct sockaddr_in6 *)resp[1]->
729					    ai_addr)->sin6_addr;
730				else
731					errx(1, "Unknown address family %d",
732					    kill.af);
733
734				if (pfctl_kill_states(dev, &kill, &newkilled))
735					err(1, "DIOCKILLSTATES");
736				killed += newkilled;
737			}
738			freeaddrinfo(res[1]);
739		} else {
740			if (pfctl_kill_states(dev, &kill, &newkilled))
741				err(1, "DIOCKILLSTATES");
742			killed += newkilled;
743		}
744	}
745
746	freeaddrinfo(res[0]);
747
748	if ((opts & PF_OPT_QUIET) == 0)
749		fprintf(stderr, "killed %d states from %d sources and %d "
750		    "destinations\n", killed, sources, dests);
751	return (0);
752}
753
754int
755pfctl_gateway_kill_states(int dev, const char *iface, int opts)
756{
757	struct pfctl_kill kill;
758	struct addrinfo *res, *resp;
759	struct sockaddr last_src;
760	unsigned int newkilled;
761	int killed = 0;
762	int ret_ga;
763
764	if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
765		warnx("no gateway specified");
766		usage();
767	}
768
769	memset(&kill, 0, sizeof(kill));
770	memset(&kill.rt_addr.addr.v.a.mask, 0xff,
771	    sizeof(kill.rt_addr.addr.v.a.mask));
772	memset(&last_src, 0xff, sizeof(last_src));
773	if (iface != NULL && strlcpy(kill.ifname, iface,
774	    sizeof(kill.ifname)) >= sizeof(kill.ifname))
775		errx(1, "invalid interface: %s", iface);
776
777	if (opts & PF_OPT_KILLMATCH)
778		kill.kill_match = true;
779
780	pfctl_addrprefix(state_kill[1], &kill.rt_addr.addr.v.a.mask);
781
782	if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, &res))) {
783		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
784		/* NOTREACHED */
785	}
786	for (resp = res; resp; resp = resp->ai_next) {
787		if (resp->ai_addr == NULL)
788			continue;
789		/* We get lots of duplicates.  Catch the easy ones */
790		if (memcmp(&last_src, resp->ai_addr, sizeof(last_src)) == 0)
791			continue;
792		last_src = *(struct sockaddr *)resp->ai_addr;
793
794		kill.af = resp->ai_family;
795
796		if (kill.af == AF_INET)
797			kill.rt_addr.addr.v.a.addr.v4 =
798			    ((struct sockaddr_in *)resp->ai_addr)->sin_addr;
799		else if (kill.af == AF_INET6)
800			kill.rt_addr.addr.v.a.addr.v6 =
801			    ((struct sockaddr_in6 *)resp->ai_addr)->
802			    sin6_addr;
803		else
804			errx(1, "Unknown address family %d", kill.af);
805
806		if (pfctl_kill_states(dev, &kill, &newkilled))
807			err(1, "DIOCKILLSTATES");
808		killed += newkilled;
809	}
810
811	freeaddrinfo(res);
812
813	if ((opts & PF_OPT_QUIET) == 0)
814		fprintf(stderr, "killed %d states\n", killed);
815	return (0);
816}
817
818int
819pfctl_label_kill_states(int dev, const char *iface, int opts)
820{
821	struct pfctl_kill kill;
822	unsigned int killed;
823
824	if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
825		warnx("no label specified");
826		usage();
827	}
828	memset(&kill, 0, sizeof(kill));
829	if (iface != NULL && strlcpy(kill.ifname, iface,
830	    sizeof(kill.ifname)) >= sizeof(kill.ifname))
831		errx(1, "invalid interface: %s", iface);
832
833	if (opts & PF_OPT_KILLMATCH)
834		kill.kill_match = true;
835
836	if (strlcpy(kill.label, state_kill[1], sizeof(kill.label)) >=
837	    sizeof(kill.label))
838		errx(1, "label too long: %s", state_kill[1]);
839
840	if (pfctl_kill_states(dev, &kill, &killed))
841		err(1, "DIOCKILLSTATES");
842
843	if ((opts & PF_OPT_QUIET) == 0)
844		fprintf(stderr, "killed %d states\n", killed);
845
846	return (0);
847}
848
849int
850pfctl_id_kill_states(int dev, const char *iface, int opts)
851{
852	struct pfctl_kill kill;
853	unsigned int killed;
854
855	if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
856		warnx("no id specified");
857		usage();
858	}
859
860	memset(&kill, 0, sizeof(kill));
861
862	if (opts & PF_OPT_KILLMATCH)
863		kill.kill_match = true;
864
865	if ((sscanf(state_kill[1], "%jx/%x",
866	    &kill.cmp.id, &kill.cmp.creatorid)) == 2)
867		HTONL(kill.cmp.creatorid);
868	else if ((sscanf(state_kill[1], "%jx", &kill.cmp.id)) == 1) {
869		kill.cmp.creatorid = 0;
870	} else {
871		warnx("wrong id format specified");
872		usage();
873	}
874	if (kill.cmp.id == 0) {
875		warnx("cannot kill id 0");
876		usage();
877	}
878
879	kill.cmp.id = htobe64(kill.cmp.id);
880	if (pfctl_kill_states(dev, &kill, &killed))
881		err(1, "DIOCKILLSTATES");
882
883	if ((opts & PF_OPT_QUIET) == 0)
884		fprintf(stderr, "killed %d states\n", killed);
885
886	return (0);
887}
888
889int
890pfctl_get_pool(int dev, struct pfctl_pool *pool, u_int32_t nr,
891    u_int32_t ticket, int r_action, char *anchorname)
892{
893	struct pfioc_pooladdr pp;
894	struct pf_pooladdr *pa;
895	u_int32_t pnr, mpnr;
896
897	memset(&pp, 0, sizeof(pp));
898	memcpy(pp.anchor, anchorname, sizeof(pp.anchor));
899	pp.r_action = r_action;
900	pp.r_num = nr;
901	pp.ticket = ticket;
902	if (ioctl(dev, DIOCGETADDRS, &pp)) {
903		warn("DIOCGETADDRS");
904		return (-1);
905	}
906	mpnr = pp.nr;
907	TAILQ_INIT(&pool->list);
908	for (pnr = 0; pnr < mpnr; ++pnr) {
909		pp.nr = pnr;
910		if (ioctl(dev, DIOCGETADDR, &pp)) {
911			warn("DIOCGETADDR");
912			return (-1);
913		}
914		pa = calloc(1, sizeof(struct pf_pooladdr));
915		if (pa == NULL)
916			err(1, "calloc");
917		bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr));
918		TAILQ_INSERT_TAIL(&pool->list, pa, entries);
919	}
920
921	return (0);
922}
923
924void
925pfctl_move_pool(struct pfctl_pool *src, struct pfctl_pool *dst)
926{
927	struct pf_pooladdr *pa;
928
929	while ((pa = TAILQ_FIRST(&src->list)) != NULL) {
930		TAILQ_REMOVE(&src->list, pa, entries);
931		TAILQ_INSERT_TAIL(&dst->list, pa, entries);
932	}
933}
934
935void
936pfctl_clear_pool(struct pfctl_pool *pool)
937{
938	struct pf_pooladdr *pa;
939
940	while ((pa = TAILQ_FIRST(&pool->list)) != NULL) {
941		TAILQ_REMOVE(&pool->list, pa, entries);
942		free(pa);
943	}
944}
945
946void
947pfctl_print_rule_counters(struct pfctl_rule *rule, int opts)
948{
949	if (opts & PF_OPT_DEBUG) {
950		const char *t[PF_SKIP_COUNT] = { "i", "d", "f",
951		    "p", "sa", "sp", "da", "dp" };
952		int i;
953
954		printf("  [ Skip steps: ");
955		for (i = 0; i < PF_SKIP_COUNT; ++i) {
956			if (rule->skip[i].nr == rule->nr + 1)
957				continue;
958			printf("%s=", t[i]);
959			if (rule->skip[i].nr == -1)
960				printf("end ");
961			else
962				printf("%u ", rule->skip[i].nr);
963		}
964		printf("]\n");
965
966		printf("  [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
967		    rule->qname, rule->qid, rule->pqname, rule->pqid);
968	}
969	if (opts & PF_OPT_VERBOSE) {
970		printf("  [ Evaluations: %-8llu  Packets: %-8llu  "
971			    "Bytes: %-10llu  States: %-6ju]\n",
972			    (unsigned long long)rule->evaluations,
973			    (unsigned long long)(rule->packets[0] +
974			    rule->packets[1]),
975			    (unsigned long long)(rule->bytes[0] +
976			    rule->bytes[1]), (uintmax_t)rule->states_cur);
977		if (!(opts & PF_OPT_DEBUG))
978			printf("  [ Inserted: uid %u pid %u "
979			    "State Creations: %-6ju]\n",
980			    (unsigned)rule->cuid, (unsigned)rule->cpid,
981			    (uintmax_t)rule->states_tot);
982	}
983}
984
985void
986pfctl_print_title(char *title)
987{
988	if (!first_title)
989		printf("\n");
990	first_title = 0;
991	printf("%s\n", title);
992}
993
994int
995pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
996    char *anchorname, int depth)
997{
998	struct pfioc_rule pr;
999	struct pfctl_rule rule;
1000	u_int32_t nr, mnr, header = 0;
1001	int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
1002	int numeric = opts & PF_OPT_NUMERIC;
1003	int len = strlen(path);
1004	int brace;
1005	char *p;
1006
1007	if (path[0])
1008		snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
1009	else
1010		snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
1011
1012	memset(&pr, 0, sizeof(pr));
1013	memcpy(pr.anchor, path, sizeof(pr.anchor));
1014	if (opts & PF_OPT_SHOWALL) {
1015		pr.rule.action = PF_PASS;
1016		if (ioctl(dev, DIOCGETRULES, &pr)) {
1017			warn("DIOCGETRULES");
1018			goto error;
1019		}
1020		header++;
1021	}
1022	pr.rule.action = PF_SCRUB;
1023	if (ioctl(dev, DIOCGETRULES, &pr)) {
1024		warn("DIOCGETRULES");
1025		goto error;
1026	}
1027	if (opts & PF_OPT_SHOWALL) {
1028		if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header))
1029			pfctl_print_title("FILTER RULES:");
1030		else if (format == PFCTL_SHOW_LABELS && labels)
1031			pfctl_print_title("LABEL COUNTERS:");
1032	}
1033	mnr = pr.nr;
1034
1035	for (nr = 0; nr < mnr; ++nr) {
1036		pr.nr = nr;
1037		if (pfctl_get_clear_rule(dev, nr, pr.ticket, path, PF_SCRUB,
1038		    &rule, pr.anchor_call, opts & PF_OPT_CLRRULECTRS)) {
1039			warn("DIOCGETRULENV");
1040			goto error;
1041		}
1042
1043		if (pfctl_get_pool(dev, &rule.rpool,
1044		    nr, pr.ticket, PF_SCRUB, path) != 0)
1045			goto error;
1046
1047		switch (format) {
1048		case PFCTL_SHOW_LABELS:
1049			break;
1050		case PFCTL_SHOW_RULES:
1051			if (rule.label[0] && (opts & PF_OPT_SHOWALL))
1052				labels = 1;
1053			print_rule(&rule, pr.anchor_call, rule_numbers, numeric);
1054			printf("\n");
1055			pfctl_print_rule_counters(&rule, opts);
1056			break;
1057		case PFCTL_SHOW_NOTHING:
1058			break;
1059		}
1060		pfctl_clear_pool(&rule.rpool);
1061	}
1062	pr.rule.action = PF_PASS;
1063	if (ioctl(dev, DIOCGETRULES, &pr)) {
1064		warn("DIOCGETRULES");
1065		goto error;
1066	}
1067	mnr = pr.nr;
1068	for (nr = 0; nr < mnr; ++nr) {
1069		pr.nr = nr;
1070		if (pfctl_get_clear_rule(dev, nr, pr.ticket, path, PF_PASS,
1071		    &rule, pr.anchor_call, opts & PF_OPT_CLRRULECTRS)) {
1072			warn("DIOCGETRULE");
1073			goto error;
1074		}
1075
1076		if (pfctl_get_pool(dev, &rule.rpool,
1077		    nr, pr.ticket, PF_PASS, path) != 0)
1078			goto error;
1079
1080		switch (format) {
1081		case PFCTL_SHOW_LABELS: {
1082			bool show = false;
1083			int i = 0;
1084
1085			while (rule.label[i][0]) {
1086				printf("%s ", rule.label[i++]);
1087				show = true;
1088			}
1089
1090			if (show) {
1091				printf("%llu %llu %llu %llu"
1092				    " %llu %llu %llu %ju\n",
1093				    (unsigned long long)rule.evaluations,
1094				    (unsigned long long)(rule.packets[0] +
1095				    rule.packets[1]),
1096				    (unsigned long long)(rule.bytes[0] +
1097				    rule.bytes[1]),
1098				    (unsigned long long)rule.packets[0],
1099				    (unsigned long long)rule.bytes[0],
1100				    (unsigned long long)rule.packets[1],
1101				    (unsigned long long)rule.bytes[1],
1102				    (uintmax_t)rule.states_tot);
1103			}
1104			break;
1105		}
1106		case PFCTL_SHOW_RULES:
1107			brace = 0;
1108			if (rule.label[0] && (opts & PF_OPT_SHOWALL))
1109				labels = 1;
1110			INDENT(depth, !(opts & PF_OPT_VERBOSE));
1111			if (pr.anchor_call[0] &&
1112			   ((((p = strrchr(pr.anchor_call, '_')) != NULL) &&
1113			   ((void *)p == (void *)pr.anchor_call ||
1114			   *(--p) == '/')) || (opts & PF_OPT_RECURSE))) {
1115				brace++;
1116				if ((p = strrchr(pr.anchor_call, '/')) !=
1117				    NULL)
1118					p++;
1119				else
1120					p = &pr.anchor_call[0];
1121			} else
1122				p = &pr.anchor_call[0];
1123
1124			print_rule(&rule, p, rule_numbers, numeric);
1125			if (brace)
1126				printf(" {\n");
1127			else
1128				printf("\n");
1129			pfctl_print_rule_counters(&rule, opts);
1130			if (brace) {
1131				pfctl_show_rules(dev, path, opts, format,
1132				    p, depth + 1);
1133				INDENT(depth, !(opts & PF_OPT_VERBOSE));
1134				printf("}\n");
1135			}
1136			break;
1137		case PFCTL_SHOW_NOTHING:
1138			break;
1139		}
1140		pfctl_clear_pool(&rule.rpool);
1141	}
1142	path[len] = '\0';
1143	return (0);
1144
1145 error:
1146	path[len] = '\0';
1147	return (-1);
1148}
1149
1150int
1151pfctl_show_nat(int dev, int opts, char *anchorname)
1152{
1153	struct pfioc_rule pr;
1154	struct pfctl_rule rule;
1155	u_int32_t mnr, nr;
1156	static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT };
1157	int i, dotitle = opts & PF_OPT_SHOWALL;
1158
1159	memset(&pr, 0, sizeof(pr));
1160	memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
1161	for (i = 0; i < 3; i++) {
1162		pr.rule.action = nattype[i];
1163		if (ioctl(dev, DIOCGETRULES, &pr)) {
1164			warn("DIOCGETRULES");
1165			return (-1);
1166		}
1167		mnr = pr.nr;
1168		for (nr = 0; nr < mnr; ++nr) {
1169			pr.nr = nr;
1170			if (pfctl_get_rule(dev, nr, pr.ticket, anchorname,
1171			    nattype[i], &rule, pr.anchor_call)) {
1172				warn("DIOCGETRULE");
1173				return (-1);
1174			}
1175			if (pfctl_get_pool(dev, &rule.rpool, nr,
1176			    pr.ticket, nattype[i], anchorname) != 0)
1177				return (-1);
1178			if (dotitle) {
1179				pfctl_print_title("TRANSLATION RULES:");
1180				dotitle = 0;
1181			}
1182			print_rule(&rule, pr.anchor_call,
1183			    opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC);
1184			printf("\n");
1185			pfctl_print_rule_counters(&rule, opts);
1186			pfctl_clear_pool(&rule.rpool);
1187		}
1188	}
1189	return (0);
1190}
1191
1192int
1193pfctl_show_src_nodes(int dev, int opts)
1194{
1195	struct pfioc_src_nodes psn;
1196	struct pf_src_node *p;
1197	char *inbuf = NULL, *newinbuf = NULL;
1198	unsigned int len = 0;
1199	int i;
1200
1201	memset(&psn, 0, sizeof(psn));
1202	for (;;) {
1203		psn.psn_len = len;
1204		if (len) {
1205			newinbuf = realloc(inbuf, len);
1206			if (newinbuf == NULL)
1207				err(1, "realloc");
1208			psn.psn_buf = inbuf = newinbuf;
1209		}
1210		if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) {
1211			warn("DIOCGETSRCNODES");
1212			free(inbuf);
1213			return (-1);
1214		}
1215		if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len)
1216			break;
1217		if (len == 0 && psn.psn_len == 0)
1218			goto done;
1219		if (len == 0 && psn.psn_len != 0)
1220			len = psn.psn_len;
1221		if (psn.psn_len == 0)
1222			goto done;	/* no src_nodes */
1223		len *= 2;
1224	}
1225	p = psn.psn_src_nodes;
1226	if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL))
1227		pfctl_print_title("SOURCE TRACKING NODES:");
1228	for (i = 0; i < psn.psn_len; i += sizeof(*p)) {
1229		print_src_node(p, opts);
1230		p++;
1231	}
1232done:
1233	free(inbuf);
1234	return (0);
1235}
1236
1237int
1238pfctl_show_states(int dev, const char *iface, int opts)
1239{
1240	struct pfctl_states states;
1241	struct pfctl_state *s;
1242	int dotitle = (opts & PF_OPT_SHOWALL);
1243
1244	memset(&states, 0, sizeof(states));
1245
1246	if (pfctl_get_states(dev, &states))
1247		return (-1);
1248
1249	TAILQ_FOREACH(s, &states.states, entry) {
1250		if (iface != NULL && strcmp(s->ifname, iface))
1251			continue;
1252		if (dotitle) {
1253			pfctl_print_title("STATES:");
1254			dotitle = 0;
1255		}
1256		print_state(s, opts);
1257	}
1258
1259	pfctl_free_states(&states);
1260
1261	return (0);
1262}
1263
1264int
1265pfctl_show_status(int dev, int opts)
1266{
1267	struct pf_status status;
1268
1269	if (ioctl(dev, DIOCGETSTATUS, &status)) {
1270		warn("DIOCGETSTATUS");
1271		return (-1);
1272	}
1273	if (opts & PF_OPT_SHOWALL)
1274		pfctl_print_title("INFO:");
1275	print_status(&status, opts);
1276	return (0);
1277}
1278
1279int
1280pfctl_show_running(int dev)
1281{
1282	struct pf_status status;
1283
1284	if (ioctl(dev, DIOCGETSTATUS, &status)) {
1285		warn("DIOCGETSTATUS");
1286		return (-1);
1287	}
1288
1289	print_running(&status);
1290	return (!status.running);
1291}
1292
1293int
1294pfctl_show_timeouts(int dev, int opts)
1295{
1296	struct pfioc_tm pt;
1297	int i;
1298
1299	if (opts & PF_OPT_SHOWALL)
1300		pfctl_print_title("TIMEOUTS:");
1301	memset(&pt, 0, sizeof(pt));
1302	for (i = 0; pf_timeouts[i].name; i++) {
1303		pt.timeout = pf_timeouts[i].timeout;
1304		if (ioctl(dev, DIOCGETTIMEOUT, &pt))
1305			err(1, "DIOCGETTIMEOUT");
1306		printf("%-20s %10d", pf_timeouts[i].name, pt.seconds);
1307		if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START &&
1308		    pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END)
1309			printf(" states");
1310		else
1311			printf("s");
1312		printf("\n");
1313	}
1314	return (0);
1315
1316}
1317
1318int
1319pfctl_show_limits(int dev, int opts)
1320{
1321	struct pfioc_limit pl;
1322	int i;
1323
1324	if (opts & PF_OPT_SHOWALL)
1325		pfctl_print_title("LIMITS:");
1326	memset(&pl, 0, sizeof(pl));
1327	for (i = 0; pf_limits[i].name; i++) {
1328		pl.index = pf_limits[i].index;
1329		if (ioctl(dev, DIOCGETLIMIT, &pl))
1330			err(1, "DIOCGETLIMIT");
1331		printf("%-13s ", pf_limits[i].name);
1332		if (pl.limit == UINT_MAX)
1333			printf("unlimited\n");
1334		else
1335			printf("hard limit %8u\n", pl.limit);
1336	}
1337	return (0);
1338}
1339
1340/* callbacks for rule/nat/rdr/addr */
1341int
1342pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af)
1343{
1344	struct pf_pooladdr *pa;
1345
1346	if ((pf->opts & PF_OPT_NOACTION) == 0) {
1347		if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr))
1348			err(1, "DIOCBEGINADDRS");
1349	}
1350
1351	pf->paddr.af = af;
1352	TAILQ_FOREACH(pa, &p->list, entries) {
1353		memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr));
1354		if ((pf->opts & PF_OPT_NOACTION) == 0) {
1355			if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr))
1356				err(1, "DIOCADDADDR");
1357		}
1358	}
1359	return (0);
1360}
1361
1362int
1363pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r,
1364    const char *anchor_call)
1365{
1366	u_int8_t		rs_num;
1367	struct pfctl_rule	*rule;
1368	struct pfctl_ruleset	*rs;
1369	char 			*p;
1370
1371	rs_num = pf_get_ruleset_number(r->action);
1372	if (rs_num == PF_RULESET_MAX)
1373		errx(1, "Invalid rule type %d", r->action);
1374
1375	rs = &pf->anchor->ruleset;
1376
1377	if (anchor_call[0] && r->anchor == NULL) {
1378		/*
1379		 * Don't make non-brace anchors part of the main anchor pool.
1380		 */
1381		if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL)
1382			err(1, "pfctl_append_rule: calloc");
1383
1384		pf_init_ruleset(&r->anchor->ruleset);
1385		r->anchor->ruleset.anchor = r->anchor;
1386		if (strlcpy(r->anchor->path, anchor_call,
1387		    sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
1388			errx(1, "pfctl_append_rule: strlcpy");
1389		if ((p = strrchr(anchor_call, '/')) != NULL) {
1390			if (!strlen(p))
1391				err(1, "pfctl_append_rule: bad anchor name %s",
1392				    anchor_call);
1393		} else
1394			p = (char *)anchor_call;
1395		if (strlcpy(r->anchor->name, p,
1396		    sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
1397			errx(1, "pfctl_append_rule: strlcpy");
1398	}
1399
1400	if ((rule = calloc(1, sizeof(*rule))) == NULL)
1401		err(1, "calloc");
1402	bcopy(r, rule, sizeof(*rule));
1403	TAILQ_INIT(&rule->rpool.list);
1404	pfctl_move_pool(&r->rpool, &rule->rpool);
1405
1406	TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries);
1407	return (0);
1408}
1409
1410int
1411pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pfctl_anchor *a)
1412{
1413	int osize = pf->trans->pfrb_size;
1414
1415	if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) {
1416		if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) ||
1417		    pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) ||
1418		    pfctl_add_trans(pf->trans, PF_RULESET_RDR, path))
1419			return (1);
1420	}
1421	if (a == pf->astack[0] && ((altqsupport &&
1422	    (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) {
1423		if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path))
1424			return (2);
1425	}
1426	if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) {
1427		if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) ||
1428		    pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path))
1429			return (3);
1430	}
1431	if (pf->loadopt & PFCTL_FLAG_TABLE)
1432		if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path))
1433			return (4);
1434	if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize))
1435		return (5);
1436
1437	return (0);
1438}
1439
1440int
1441pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs,
1442    int rs_num, int depth)
1443{
1444	struct pfctl_rule *r;
1445	int		error, len = strlen(path);
1446	int		brace = 0;
1447
1448	pf->anchor = rs->anchor;
1449
1450	if (path[0])
1451		snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name);
1452	else
1453		snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name);
1454
1455	if (depth) {
1456		if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) {
1457			brace++;
1458			if (pf->opts & PF_OPT_VERBOSE)
1459				printf(" {\n");
1460			if ((pf->opts & PF_OPT_NOACTION) == 0 &&
1461			    (error = pfctl_ruleset_trans(pf,
1462			    path, rs->anchor))) {
1463				printf("pfctl_load_rulesets: "
1464				    "pfctl_ruleset_trans %d\n", error);
1465				goto error;
1466			}
1467		} else if (pf->opts & PF_OPT_VERBOSE)
1468			printf("\n");
1469
1470	}
1471
1472	if (pf->optimize && rs_num == PF_RULESET_FILTER)
1473		pfctl_optimize_ruleset(pf, rs);
1474
1475	while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) {
1476		TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries);
1477		if ((error = pfctl_load_rule(pf, path, r, depth)))
1478			goto error;
1479		if (r->anchor) {
1480			if ((error = pfctl_load_ruleset(pf, path,
1481			    &r->anchor->ruleset, rs_num, depth + 1)))
1482				goto error;
1483		} else if (pf->opts & PF_OPT_VERBOSE)
1484			printf("\n");
1485		free(r);
1486	}
1487	if (brace && pf->opts & PF_OPT_VERBOSE) {
1488		INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE));
1489		printf("}\n");
1490	}
1491	path[len] = '\0';
1492	return (0);
1493
1494 error:
1495	path[len] = '\0';
1496	return (error);
1497
1498}
1499
1500int
1501pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth)
1502{
1503	u_int8_t		rs_num = pf_get_ruleset_number(r->action);
1504	char			*name;
1505	u_int32_t		ticket;
1506	char			anchor[PF_ANCHOR_NAME_SIZE];
1507	int			len = strlen(path);
1508
1509	/* set up anchor before adding to path for anchor_call */
1510	if ((pf->opts & PF_OPT_NOACTION) == 0)
1511		ticket = pfctl_get_ticket(pf->trans, rs_num, path);
1512	if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor))
1513		errx(1, "pfctl_load_rule: strlcpy");
1514
1515	if (r->anchor) {
1516		if (r->anchor->match) {
1517			if (path[0])
1518				snprintf(&path[len], MAXPATHLEN - len,
1519				    "/%s", r->anchor->name);
1520			else
1521				snprintf(&path[len], MAXPATHLEN - len,
1522				    "%s", r->anchor->name);
1523			name = r->anchor->name;
1524		} else
1525			name = r->anchor->path;
1526	} else
1527		name = "";
1528
1529	if ((pf->opts & PF_OPT_NOACTION) == 0) {
1530		if (pfctl_add_pool(pf, &r->rpool, r->af))
1531			return (1);
1532		if (pfctl_add_rule(pf->dev, r, anchor, name, ticket,
1533		    pf->paddr.ticket))
1534			err(1, "DIOCADDRULENV");
1535	}
1536
1537	if (pf->opts & PF_OPT_VERBOSE) {
1538		INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2));
1539		print_rule(r, r->anchor ? r->anchor->name : "",
1540		    pf->opts & PF_OPT_VERBOSE2,
1541		    pf->opts & PF_OPT_NUMERIC);
1542	}
1543	path[len] = '\0';
1544	pfctl_clear_pool(&r->rpool);
1545	return (0);
1546}
1547
1548int
1549pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
1550{
1551	if (altqsupport &&
1552	    (loadopt & PFCTL_FLAG_ALTQ) != 0) {
1553		memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq));
1554		if ((pf->opts & PF_OPT_NOACTION) == 0) {
1555			if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) {
1556				if (errno == ENXIO)
1557					errx(1, "qtype not configured");
1558				else if (errno == ENODEV)
1559					errx(1, "%s: driver does not support "
1560					    "altq", a->ifname);
1561				else
1562					err(1, "DIOCADDALTQ");
1563			}
1564		}
1565		pfaltq_store(&pf->paltq->altq);
1566	}
1567	return (0);
1568}
1569
1570int
1571pfctl_rules(int dev, char *filename, int opts, int optimize,
1572    char *anchorname, struct pfr_buffer *trans)
1573{
1574#define ERR(x) do { warn(x); goto _error; } while(0)
1575#define ERRX(x) do { warnx(x); goto _error; } while(0)
1576
1577	struct pfr_buffer	*t, buf;
1578	struct pfioc_altq	 pa;
1579	struct pfctl		 pf;
1580	struct pfctl_ruleset	*rs;
1581	struct pfr_table	 trs;
1582	char			*path;
1583	int			 osize;
1584
1585	RB_INIT(&pf_anchors);
1586	memset(&pf_main_anchor, 0, sizeof(pf_main_anchor));
1587	pf_init_ruleset(&pf_main_anchor.ruleset);
1588	pf_main_anchor.ruleset.anchor = &pf_main_anchor;
1589	if (trans == NULL) {
1590		bzero(&buf, sizeof(buf));
1591		buf.pfrb_type = PFRB_TRANS;
1592		t = &buf;
1593		osize = 0;
1594	} else {
1595		t = trans;
1596		osize = t->pfrb_size;
1597	}
1598
1599	memset(&pa, 0, sizeof(pa));
1600	pa.version = PFIOC_ALTQ_VERSION;
1601	memset(&pf, 0, sizeof(pf));
1602	memset(&trs, 0, sizeof(trs));
1603	if ((path = calloc(1, MAXPATHLEN)) == NULL)
1604		ERRX("pfctl_rules: calloc");
1605	if (strlcpy(trs.pfrt_anchor, anchorname,
1606	    sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor))
1607		ERRX("pfctl_rules: strlcpy");
1608	pf.dev = dev;
1609	pf.opts = opts;
1610	pf.optimize = optimize;
1611	pf.loadopt = loadopt;
1612
1613	/* non-brace anchor, create without resolving the path */
1614	if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL)
1615		ERRX("pfctl_rules: calloc");
1616	rs = &pf.anchor->ruleset;
1617	pf_init_ruleset(rs);
1618	rs->anchor = pf.anchor;
1619	if (strlcpy(pf.anchor->path, anchorname,
1620	    sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path))
1621		errx(1, "pfctl_add_rule: strlcpy");
1622	if (strlcpy(pf.anchor->name, anchorname,
1623	    sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name))
1624		errx(1, "pfctl_add_rule: strlcpy");
1625
1626
1627	pf.astack[0] = pf.anchor;
1628	pf.asd = 0;
1629	if (anchorname[0])
1630		pf.loadopt &= ~PFCTL_FLAG_ALTQ;
1631	pf.paltq = &pa;
1632	pf.trans = t;
1633	pfctl_init_options(&pf);
1634
1635	if ((opts & PF_OPT_NOACTION) == 0) {
1636		/*
1637		 * XXX For the time being we need to open transactions for
1638		 * the main ruleset before parsing, because tables are still
1639		 * loaded at parse time.
1640		 */
1641		if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor))
1642			ERRX("pfctl_rules");
1643		if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ))
1644			pa.ticket =
1645			    pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname);
1646		if (pf.loadopt & PFCTL_FLAG_TABLE)
1647			pf.astack[0]->ruleset.tticket =
1648			    pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname);
1649	}
1650
1651	if (parse_config(filename, &pf) < 0) {
1652		if ((opts & PF_OPT_NOACTION) == 0)
1653			ERRX("Syntax error in config file: "
1654			    "pf rules not loaded");
1655		else
1656			goto _error;
1657	}
1658	if (loadopt & PFCTL_FLAG_OPTION)
1659		pfctl_adjust_skip_ifaces(&pf);
1660
1661	if ((pf.loadopt & PFCTL_FLAG_FILTER &&
1662	    (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) ||
1663	    (pf.loadopt & PFCTL_FLAG_NAT &&
1664	    (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) ||
1665	    pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) ||
1666	    pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) ||
1667	    (pf.loadopt & PFCTL_FLAG_FILTER &&
1668	    pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) {
1669		if ((opts & PF_OPT_NOACTION) == 0)
1670			ERRX("Unable to load rules into kernel");
1671		else
1672			goto _error;
1673	}
1674
1675	if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))
1676		if (check_commit_altq(dev, opts) != 0)
1677			ERRX("errors in altq config");
1678
1679	/* process "load anchor" directives */
1680	if (!anchorname[0])
1681		if (pfctl_load_anchors(dev, &pf, t) == -1)
1682			ERRX("load anchors");
1683
1684	if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) {
1685		if (!anchorname[0])
1686			if (pfctl_load_options(&pf))
1687				goto _error;
1688		if (pfctl_trans(dev, t, DIOCXCOMMIT, osize))
1689			ERR("DIOCXCOMMIT");
1690	}
1691	free(path);
1692	return (0);
1693
1694_error:
1695	if (trans == NULL) {	/* main ruleset */
1696		if ((opts & PF_OPT_NOACTION) == 0)
1697			if (pfctl_trans(dev, t, DIOCXROLLBACK, osize))
1698				err(1, "DIOCXROLLBACK");
1699		exit(1);
1700	} else {		/* sub ruleset */
1701		free(path);
1702		return (-1);
1703	}
1704
1705#undef ERR
1706#undef ERRX
1707}
1708
1709FILE *
1710pfctl_fopen(const char *name, const char *mode)
1711{
1712	struct stat	 st;
1713	FILE		*fp;
1714
1715	fp = fopen(name, mode);
1716	if (fp == NULL)
1717		return (NULL);
1718	if (fstat(fileno(fp), &st)) {
1719		fclose(fp);
1720		return (NULL);
1721	}
1722	if (S_ISDIR(st.st_mode)) {
1723		fclose(fp);
1724		errno = EISDIR;
1725		return (NULL);
1726	}
1727	return (fp);
1728}
1729
1730void
1731pfctl_init_options(struct pfctl *pf)
1732{
1733
1734	pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
1735	pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
1736	pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
1737	pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
1738	pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
1739	pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
1740	pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
1741	pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
1742	pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
1743	pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
1744	pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
1745	pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
1746	pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
1747	pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
1748	pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
1749	pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
1750	pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
1751	pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
1752	pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START;
1753	pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
1754
1755	pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT;
1756	pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT;
1757	pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT;
1758	pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
1759
1760	pf->debug = PF_DEBUG_URGENT;
1761}
1762
1763int
1764pfctl_load_options(struct pfctl *pf)
1765{
1766	int i, error = 0;
1767
1768	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
1769		return (0);
1770
1771	/* load limits */
1772	for (i = 0; i < PF_LIMIT_MAX; i++) {
1773		if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i])
1774			continue;
1775		if (pfctl_load_limit(pf, i, pf->limit[i]))
1776			error = 1;
1777	}
1778
1779	/*
1780	 * If we've set the limit, but haven't explicitly set adaptive
1781	 * timeouts, do it now with a start of 60% and end of 120%.
1782	 */
1783	if (pf->limit_set[PF_LIMIT_STATES] &&
1784	    !pf->timeout_set[PFTM_ADAPTIVE_START] &&
1785	    !pf->timeout_set[PFTM_ADAPTIVE_END]) {
1786		pf->timeout[PFTM_ADAPTIVE_START] =
1787			(pf->limit[PF_LIMIT_STATES] / 10) * 6;
1788		pf->timeout_set[PFTM_ADAPTIVE_START] = 1;
1789		pf->timeout[PFTM_ADAPTIVE_END] =
1790			(pf->limit[PF_LIMIT_STATES] / 10) * 12;
1791		pf->timeout_set[PFTM_ADAPTIVE_END] = 1;
1792	}
1793
1794	/* load timeouts */
1795	for (i = 0; i < PFTM_MAX; i++) {
1796		if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i])
1797			continue;
1798		if (pfctl_load_timeout(pf, i, pf->timeout[i]))
1799			error = 1;
1800	}
1801
1802	/* load debug */
1803	if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set)
1804		if (pfctl_load_debug(pf, pf->debug))
1805			error = 1;
1806
1807	/* load logif */
1808	if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set)
1809		if (pfctl_load_logif(pf, pf->ifname))
1810			error = 1;
1811
1812	/* load hostid */
1813	if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set)
1814		if (pfctl_load_hostid(pf, pf->hostid))
1815			error = 1;
1816
1817	/* load keepcounters */
1818	if (pfctl_set_keepcounters(pf->dev, pf->keep_counters))
1819		error = 1;
1820
1821	return (error);
1822}
1823
1824int
1825pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
1826{
1827	int i;
1828
1829
1830	for (i = 0; pf_limits[i].name; i++) {
1831		if (strcasecmp(opt, pf_limits[i].name) == 0) {
1832			pf->limit[pf_limits[i].index] = limit;
1833			pf->limit_set[pf_limits[i].index] = 1;
1834			break;
1835		}
1836	}
1837	if (pf_limits[i].name == NULL) {
1838		warnx("Bad pool name.");
1839		return (1);
1840	}
1841
1842	if (pf->opts & PF_OPT_VERBOSE)
1843		printf("set limit %s %d\n", opt, limit);
1844
1845	return (0);
1846}
1847
1848int
1849pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit)
1850{
1851	struct pfioc_limit pl;
1852
1853	memset(&pl, 0, sizeof(pl));
1854	pl.index = index;
1855	pl.limit = limit;
1856	if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) {
1857		if (errno == EBUSY)
1858			warnx("Current pool size exceeds requested hard limit");
1859		else
1860			warnx("DIOCSETLIMIT");
1861		return (1);
1862	}
1863	return (0);
1864}
1865
1866int
1867pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
1868{
1869	int i;
1870
1871	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
1872		return (0);
1873
1874	for (i = 0; pf_timeouts[i].name; i++) {
1875		if (strcasecmp(opt, pf_timeouts[i].name) == 0) {
1876			pf->timeout[pf_timeouts[i].timeout] = seconds;
1877			pf->timeout_set[pf_timeouts[i].timeout] = 1;
1878			break;
1879		}
1880	}
1881
1882	if (pf_timeouts[i].name == NULL) {
1883		warnx("Bad timeout name.");
1884		return (1);
1885	}
1886
1887
1888	if (pf->opts & PF_OPT_VERBOSE && ! quiet)
1889		printf("set timeout %s %d\n", opt, seconds);
1890
1891	return (0);
1892}
1893
1894int
1895pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds)
1896{
1897	struct pfioc_tm pt;
1898
1899	memset(&pt, 0, sizeof(pt));
1900	pt.timeout = timeout;
1901	pt.seconds = seconds;
1902	if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) {
1903		warnx("DIOCSETTIMEOUT");
1904		return (1);
1905	}
1906	return (0);
1907}
1908
1909int
1910pfctl_set_optimization(struct pfctl *pf, const char *opt)
1911{
1912	const struct pf_hint *hint;
1913	int i, r;
1914
1915	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
1916		return (0);
1917
1918	for (i = 0; pf_hints[i].name; i++)
1919		if (strcasecmp(opt, pf_hints[i].name) == 0)
1920			break;
1921
1922	hint = pf_hints[i].hint;
1923	if (hint == NULL) {
1924		warnx("invalid state timeouts optimization");
1925		return (1);
1926	}
1927
1928	for (i = 0; hint[i].name; i++)
1929		if ((r = pfctl_set_timeout(pf, hint[i].name,
1930		    hint[i].timeout, 1)))
1931			return (r);
1932
1933	if (pf->opts & PF_OPT_VERBOSE)
1934		printf("set optimization %s\n", opt);
1935
1936	return (0);
1937}
1938
1939int
1940pfctl_set_logif(struct pfctl *pf, char *ifname)
1941{
1942
1943	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
1944		return (0);
1945
1946	if (!strcmp(ifname, "none")) {
1947		free(pf->ifname);
1948		pf->ifname = NULL;
1949	} else {
1950		pf->ifname = strdup(ifname);
1951		if (!pf->ifname)
1952			errx(1, "pfctl_set_logif: strdup");
1953	}
1954	pf->ifname_set = 1;
1955
1956	if (pf->opts & PF_OPT_VERBOSE)
1957		printf("set loginterface %s\n", ifname);
1958
1959	return (0);
1960}
1961
1962int
1963pfctl_load_logif(struct pfctl *pf, char *ifname)
1964{
1965	struct pfioc_if pi;
1966
1967	memset(&pi, 0, sizeof(pi));
1968	if (ifname && strlcpy(pi.ifname, ifname,
1969	    sizeof(pi.ifname)) >= sizeof(pi.ifname)) {
1970		warnx("pfctl_load_logif: strlcpy");
1971		return (1);
1972	}
1973	if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) {
1974		warnx("DIOCSETSTATUSIF");
1975		return (1);
1976	}
1977	return (0);
1978}
1979
1980int
1981pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
1982{
1983	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
1984		return (0);
1985
1986	HTONL(hostid);
1987
1988	pf->hostid = hostid;
1989	pf->hostid_set = 1;
1990
1991	if (pf->opts & PF_OPT_VERBOSE)
1992		printf("set hostid 0x%08x\n", ntohl(hostid));
1993
1994	return (0);
1995}
1996
1997int
1998pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid)
1999{
2000	if (ioctl(dev, DIOCSETHOSTID, &hostid)) {
2001		warnx("DIOCSETHOSTID");
2002		return (1);
2003	}
2004	return (0);
2005}
2006
2007int
2008pfctl_set_debug(struct pfctl *pf, char *d)
2009{
2010	u_int32_t	level;
2011
2012	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
2013		return (0);
2014
2015	if (!strcmp(d, "none"))
2016		pf->debug = PF_DEBUG_NONE;
2017	else if (!strcmp(d, "urgent"))
2018		pf->debug = PF_DEBUG_URGENT;
2019	else if (!strcmp(d, "misc"))
2020		pf->debug = PF_DEBUG_MISC;
2021	else if (!strcmp(d, "loud"))
2022		pf->debug = PF_DEBUG_NOISY;
2023	else {
2024		warnx("unknown debug level \"%s\"", d);
2025		return (-1);
2026	}
2027
2028	pf->debug_set = 1;
2029	level = pf->debug;
2030
2031	if ((pf->opts & PF_OPT_NOACTION) == 0)
2032		if (ioctl(dev, DIOCSETDEBUG, &level))
2033			err(1, "DIOCSETDEBUG");
2034
2035	if (pf->opts & PF_OPT_VERBOSE)
2036		printf("set debug %s\n", d);
2037
2038	return (0);
2039}
2040
2041int
2042pfctl_load_debug(struct pfctl *pf, unsigned int level)
2043{
2044	if (ioctl(pf->dev, DIOCSETDEBUG, &level)) {
2045		warnx("DIOCSETDEBUG");
2046		return (1);
2047	}
2048	return (0);
2049}
2050
2051int
2052pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how)
2053{
2054	struct pfioc_iface	pi;
2055	struct node_host	*h = NULL, *n = NULL;
2056
2057	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
2058		return (0);
2059
2060	bzero(&pi, sizeof(pi));
2061
2062	pi.pfiio_flags = flags;
2063
2064	/* Make sure our cache matches the kernel. If we set or clear the flag
2065	 * for a group this applies to all members. */
2066	h = ifa_grouplookup(ifname, 0);
2067	for (n = h; n != NULL; n = n->next)
2068		pfctl_set_interface_flags(pf, n->ifname, flags, how);
2069
2070	if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >=
2071	    sizeof(pi.pfiio_name))
2072		errx(1, "pfctl_set_interface_flags: strlcpy");
2073
2074	if ((pf->opts & PF_OPT_NOACTION) == 0) {
2075		if (how == 0) {
2076			if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi))
2077				err(1, "DIOCCLRIFFLAG");
2078		} else {
2079			if (ioctl(pf->dev, DIOCSETIFFLAG, &pi))
2080				err(1, "DIOCSETIFFLAG");
2081			pfctl_check_skip_ifaces(ifname);
2082		}
2083	}
2084	return (0);
2085}
2086
2087void
2088pfctl_debug(int dev, u_int32_t level, int opts)
2089{
2090	if (ioctl(dev, DIOCSETDEBUG, &level))
2091		err(1, "DIOCSETDEBUG");
2092	if ((opts & PF_OPT_QUIET) == 0) {
2093		fprintf(stderr, "debug level set to '");
2094		switch (level) {
2095		case PF_DEBUG_NONE:
2096			fprintf(stderr, "none");
2097			break;
2098		case PF_DEBUG_URGENT:
2099			fprintf(stderr, "urgent");
2100			break;
2101		case PF_DEBUG_MISC:
2102			fprintf(stderr, "misc");
2103			break;
2104		case PF_DEBUG_NOISY:
2105			fprintf(stderr, "loud");
2106			break;
2107		default:
2108			fprintf(stderr, "<invalid>");
2109			break;
2110		}
2111		fprintf(stderr, "'\n");
2112	}
2113}
2114
2115int
2116pfctl_test_altqsupport(int dev, int opts)
2117{
2118	struct pfioc_altq pa;
2119
2120	pa.version = PFIOC_ALTQ_VERSION;
2121	if (ioctl(dev, DIOCGETALTQS, &pa)) {
2122		if (errno == ENODEV) {
2123			if (opts & PF_OPT_VERBOSE)
2124				fprintf(stderr, "No ALTQ support in kernel\n"
2125				    "ALTQ related functions disabled\n");
2126			return (0);
2127		} else
2128			err(1, "DIOCGETALTQS");
2129	}
2130	return (1);
2131}
2132
2133int
2134pfctl_show_anchors(int dev, int opts, char *anchorname)
2135{
2136	struct pfioc_ruleset	 pr;
2137	u_int32_t		 mnr, nr;
2138
2139	memset(&pr, 0, sizeof(pr));
2140	memcpy(pr.path, anchorname, sizeof(pr.path));
2141	if (ioctl(dev, DIOCGETRULESETS, &pr)) {
2142		if (errno == EINVAL)
2143			fprintf(stderr, "Anchor '%s' not found.\n",
2144			    anchorname);
2145		else
2146			err(1, "DIOCGETRULESETS");
2147		return (-1);
2148	}
2149	mnr = pr.nr;
2150	for (nr = 0; nr < mnr; ++nr) {
2151		char sub[MAXPATHLEN];
2152
2153		pr.nr = nr;
2154		if (ioctl(dev, DIOCGETRULESET, &pr))
2155			err(1, "DIOCGETRULESET");
2156		if (!strcmp(pr.name, PF_RESERVED_ANCHOR))
2157			continue;
2158		sub[0] = 0;
2159		if (pr.path[0]) {
2160			strlcat(sub, pr.path, sizeof(sub));
2161			strlcat(sub, "/", sizeof(sub));
2162		}
2163		strlcat(sub, pr.name, sizeof(sub));
2164		if (sub[0] != '_' || (opts & PF_OPT_VERBOSE))
2165			printf("  %s\n", sub);
2166		if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub))
2167			return (-1);
2168	}
2169	return (0);
2170}
2171
2172const char *
2173pfctl_lookup_option(char *cmd, const char * const *list)
2174{
2175	if (cmd != NULL && *cmd)
2176		for (; *list; list++)
2177			if (!strncmp(cmd, *list, strlen(cmd)))
2178				return (*list);
2179	return (NULL);
2180}
2181
2182int
2183main(int argc, char *argv[])
2184{
2185	int	 error = 0;
2186	int	 ch;
2187	int	 mode = O_RDONLY;
2188	int	 opts = 0;
2189	int	 optimize = PF_OPTIMIZE_BASIC;
2190	char	 anchorname[MAXPATHLEN];
2191	char	*path;
2192
2193	if (argc < 2)
2194		usage();
2195
2196	while ((ch = getopt(argc, argv,
2197	    "a:AdD:eqf:F:ghi:k:K:mMnNOo:Pp:rRs:t:T:vx:z")) != -1) {
2198		switch (ch) {
2199		case 'a':
2200			anchoropt = optarg;
2201			break;
2202		case 'd':
2203			opts |= PF_OPT_DISABLE;
2204			mode = O_RDWR;
2205			break;
2206		case 'D':
2207			if (pfctl_cmdline_symset(optarg) < 0)
2208				warnx("could not parse macro definition %s",
2209				    optarg);
2210			break;
2211		case 'e':
2212			opts |= PF_OPT_ENABLE;
2213			mode = O_RDWR;
2214			break;
2215		case 'q':
2216			opts |= PF_OPT_QUIET;
2217			break;
2218		case 'F':
2219			clearopt = pfctl_lookup_option(optarg, clearopt_list);
2220			if (clearopt == NULL) {
2221				warnx("Unknown flush modifier '%s'", optarg);
2222				usage();
2223			}
2224			mode = O_RDWR;
2225			break;
2226		case 'i':
2227			ifaceopt = optarg;
2228			break;
2229		case 'k':
2230			if (state_killers >= 2) {
2231				warnx("can only specify -k twice");
2232				usage();
2233				/* NOTREACHED */
2234			}
2235			state_kill[state_killers++] = optarg;
2236			mode = O_RDWR;
2237			break;
2238		case 'K':
2239			if (src_node_killers >= 2) {
2240				warnx("can only specify -K twice");
2241				usage();
2242				/* NOTREACHED */
2243			}
2244			src_node_kill[src_node_killers++] = optarg;
2245			mode = O_RDWR;
2246			break;
2247		case 'm':
2248			opts |= PF_OPT_MERGE;
2249			break;
2250		case 'M':
2251			opts |= PF_OPT_KILLMATCH;
2252			break;
2253		case 'n':
2254			opts |= PF_OPT_NOACTION;
2255			break;
2256		case 'N':
2257			loadopt |= PFCTL_FLAG_NAT;
2258			break;
2259		case 'r':
2260			opts |= PF_OPT_USEDNS;
2261			break;
2262		case 'f':
2263			rulesopt = optarg;
2264			mode = O_RDWR;
2265			break;
2266		case 'g':
2267			opts |= PF_OPT_DEBUG;
2268			break;
2269		case 'A':
2270			loadopt |= PFCTL_FLAG_ALTQ;
2271			break;
2272		case 'R':
2273			loadopt |= PFCTL_FLAG_FILTER;
2274			break;
2275		case 'o':
2276			optiopt = pfctl_lookup_option(optarg, optiopt_list);
2277			if (optiopt == NULL) {
2278				warnx("Unknown optimization '%s'", optarg);
2279				usage();
2280			}
2281			opts |= PF_OPT_OPTIMIZE;
2282			break;
2283		case 'O':
2284			loadopt |= PFCTL_FLAG_OPTION;
2285			break;
2286		case 'p':
2287			pf_device = optarg;
2288			break;
2289		case 'P':
2290			opts |= PF_OPT_NUMERIC;
2291			break;
2292		case 's':
2293			showopt = pfctl_lookup_option(optarg, showopt_list);
2294			if (showopt == NULL) {
2295				warnx("Unknown show modifier '%s'", optarg);
2296				usage();
2297			}
2298			break;
2299		case 't':
2300			tableopt = optarg;
2301			break;
2302		case 'T':
2303			tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list);
2304			if (tblcmdopt == NULL) {
2305				warnx("Unknown table command '%s'", optarg);
2306				usage();
2307			}
2308			break;
2309		case 'v':
2310			if (opts & PF_OPT_VERBOSE)
2311				opts |= PF_OPT_VERBOSE2;
2312			opts |= PF_OPT_VERBOSE;
2313			break;
2314		case 'x':
2315			debugopt = pfctl_lookup_option(optarg, debugopt_list);
2316			if (debugopt == NULL) {
2317				warnx("Unknown debug level '%s'", optarg);
2318				usage();
2319			}
2320			mode = O_RDWR;
2321			break;
2322		case 'z':
2323			opts |= PF_OPT_CLRRULECTRS;
2324			mode = O_RDWR;
2325			break;
2326		case 'h':
2327			/* FALLTHROUGH */
2328		default:
2329			usage();
2330			/* NOTREACHED */
2331		}
2332	}
2333
2334	if (tblcmdopt != NULL) {
2335		argc -= optind;
2336		argv += optind;
2337		ch = *tblcmdopt;
2338		if (ch == 'l') {
2339			loadopt |= PFCTL_FLAG_TABLE;
2340			tblcmdopt = NULL;
2341		} else
2342			mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY;
2343	} else if (argc != optind) {
2344		warnx("unknown command line argument: %s ...", argv[optind]);
2345		usage();
2346		/* NOTREACHED */
2347	}
2348	if (loadopt == 0)
2349		loadopt = ~0;
2350
2351	if ((path = calloc(1, MAXPATHLEN)) == NULL)
2352		errx(1, "pfctl: calloc");
2353	memset(anchorname, 0, sizeof(anchorname));
2354	if (anchoropt != NULL) {
2355		int len = strlen(anchoropt);
2356
2357		if (anchoropt[len - 1] == '*') {
2358			if (len >= 2 && anchoropt[len - 2] == '/')
2359				anchoropt[len - 2] = '\0';
2360			else
2361				anchoropt[len - 1] = '\0';
2362			opts |= PF_OPT_RECURSE;
2363		}
2364		if (strlcpy(anchorname, anchoropt,
2365		    sizeof(anchorname)) >= sizeof(anchorname))
2366			errx(1, "anchor name '%s' too long",
2367			    anchoropt);
2368		loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE;
2369	}
2370
2371	if ((opts & PF_OPT_NOACTION) == 0) {
2372		dev = open(pf_device, mode);
2373		if (dev == -1)
2374			err(1, "%s", pf_device);
2375		altqsupport = pfctl_test_altqsupport(dev, opts);
2376	} else {
2377		dev = open(pf_device, O_RDONLY);
2378		if (dev >= 0)
2379			opts |= PF_OPT_DUMMYACTION;
2380		/* turn off options */
2381		opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE);
2382		clearopt = showopt = debugopt = NULL;
2383#if !defined(ENABLE_ALTQ)
2384		altqsupport = 0;
2385#else
2386		altqsupport = 1;
2387#endif
2388	}
2389
2390	if (opts & PF_OPT_DISABLE)
2391		if (pfctl_disable(dev, opts))
2392			error = 1;
2393
2394	if (showopt != NULL) {
2395		switch (*showopt) {
2396		case 'A':
2397			pfctl_show_anchors(dev, opts, anchorname);
2398			break;
2399		case 'r':
2400			pfctl_load_fingerprints(dev, opts);
2401			pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES,
2402			    anchorname, 0);
2403			break;
2404		case 'l':
2405			pfctl_load_fingerprints(dev, opts);
2406			pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS,
2407			    anchorname, 0);
2408			break;
2409		case 'n':
2410			pfctl_load_fingerprints(dev, opts);
2411			pfctl_show_nat(dev, opts, anchorname);
2412			break;
2413		case 'q':
2414			pfctl_show_altq(dev, ifaceopt, opts,
2415			    opts & PF_OPT_VERBOSE2);
2416			break;
2417		case 's':
2418			pfctl_show_states(dev, ifaceopt, opts);
2419			break;
2420		case 'S':
2421			pfctl_show_src_nodes(dev, opts);
2422			break;
2423		case 'i':
2424			pfctl_show_status(dev, opts);
2425			break;
2426		case 'R':
2427			error = pfctl_show_running(dev);
2428			break;
2429		case 't':
2430			pfctl_show_timeouts(dev, opts);
2431			break;
2432		case 'm':
2433			pfctl_show_limits(dev, opts);
2434			break;
2435		case 'a':
2436			opts |= PF_OPT_SHOWALL;
2437			pfctl_load_fingerprints(dev, opts);
2438
2439			pfctl_show_nat(dev, opts, anchorname);
2440			pfctl_show_rules(dev, path, opts, 0, anchorname, 0);
2441			pfctl_show_altq(dev, ifaceopt, opts, 0);
2442			pfctl_show_states(dev, ifaceopt, opts);
2443			pfctl_show_src_nodes(dev, opts);
2444			pfctl_show_status(dev, opts);
2445			pfctl_show_rules(dev, path, opts, 1, anchorname, 0);
2446			pfctl_show_timeouts(dev, opts);
2447			pfctl_show_limits(dev, opts);
2448			pfctl_show_tables(anchorname, opts);
2449			pfctl_show_fingerprints(opts);
2450			break;
2451		case 'T':
2452			pfctl_show_tables(anchorname, opts);
2453			break;
2454		case 'o':
2455			pfctl_load_fingerprints(dev, opts);
2456			pfctl_show_fingerprints(opts);
2457			break;
2458		case 'I':
2459			pfctl_show_ifaces(ifaceopt, opts);
2460			break;
2461		}
2462	}
2463
2464	if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL)
2465		pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING,
2466		    anchorname, 0);
2467
2468	if (clearopt != NULL) {
2469		if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
2470			errx(1, "anchor names beginning with '_' cannot "
2471			    "be modified from the command line");
2472
2473		switch (*clearopt) {
2474		case 'r':
2475			pfctl_clear_rules(dev, opts, anchorname);
2476			break;
2477		case 'n':
2478			pfctl_clear_nat(dev, opts, anchorname);
2479			break;
2480		case 'q':
2481			pfctl_clear_altq(dev, opts);
2482			break;
2483		case 's':
2484			pfctl_clear_iface_states(dev, ifaceopt, opts);
2485			break;
2486		case 'S':
2487			pfctl_clear_src_nodes(dev, opts);
2488			break;
2489		case 'i':
2490			pfctl_clear_stats(dev, opts);
2491			break;
2492		case 'a':
2493			pfctl_clear_rules(dev, opts, anchorname);
2494			pfctl_clear_nat(dev, opts, anchorname);
2495			pfctl_clear_tables(anchorname, opts);
2496			if (!*anchorname) {
2497				pfctl_clear_altq(dev, opts);
2498				pfctl_clear_iface_states(dev, ifaceopt, opts);
2499				pfctl_clear_src_nodes(dev, opts);
2500				pfctl_clear_stats(dev, opts);
2501				pfctl_clear_fingerprints(dev, opts);
2502				pfctl_clear_interface_flags(dev, opts);
2503			}
2504			break;
2505		case 'o':
2506			pfctl_clear_fingerprints(dev, opts);
2507			break;
2508		case 'T':
2509			pfctl_clear_tables(anchorname, opts);
2510			break;
2511		}
2512	}
2513	if (state_killers) {
2514		if (!strcmp(state_kill[0], "label"))
2515			pfctl_label_kill_states(dev, ifaceopt, opts);
2516		else if (!strcmp(state_kill[0], "id"))
2517			pfctl_id_kill_states(dev, ifaceopt, opts);
2518		else if (!strcmp(state_kill[0], "gateway"))
2519			pfctl_gateway_kill_states(dev, ifaceopt, opts);
2520		else
2521			pfctl_net_kill_states(dev, ifaceopt, opts);
2522	}
2523
2524	if (src_node_killers)
2525		pfctl_kill_src_nodes(dev, ifaceopt, opts);
2526
2527	if (tblcmdopt != NULL) {
2528		error = pfctl_command_tables(argc, argv, tableopt,
2529		    tblcmdopt, rulesopt, anchorname, opts);
2530		rulesopt = NULL;
2531	}
2532	if (optiopt != NULL) {
2533		switch (*optiopt) {
2534		case 'n':
2535			optimize = 0;
2536			break;
2537		case 'b':
2538			optimize |= PF_OPTIMIZE_BASIC;
2539			break;
2540		case 'o':
2541		case 'p':
2542			optimize |= PF_OPTIMIZE_PROFILE;
2543			break;
2544		}
2545	}
2546
2547	if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) &&
2548	    !anchorname[0] && !(opts & PF_OPT_NOACTION))
2549		if (pfctl_get_skip_ifaces())
2550			error = 1;
2551
2552	if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) &&
2553	    !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION))
2554		if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE))
2555			error = 1;
2556
2557	if (rulesopt != NULL) {
2558		if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
2559			errx(1, "anchor names beginning with '_' cannot "
2560			    "be modified from the command line");
2561		if (pfctl_rules(dev, rulesopt, opts, optimize,
2562		    anchorname, NULL))
2563			error = 1;
2564		else if (!(opts & PF_OPT_NOACTION) &&
2565		    (loadopt & PFCTL_FLAG_TABLE))
2566			warn_namespace_collision(NULL);
2567	}
2568
2569	if (opts & PF_OPT_ENABLE)
2570		if (pfctl_enable(dev, opts))
2571			error = 1;
2572
2573	if (debugopt != NULL) {
2574		switch (*debugopt) {
2575		case 'n':
2576			pfctl_debug(dev, PF_DEBUG_NONE, opts);
2577			break;
2578		case 'u':
2579			pfctl_debug(dev, PF_DEBUG_URGENT, opts);
2580			break;
2581		case 'm':
2582			pfctl_debug(dev, PF_DEBUG_MISC, opts);
2583			break;
2584		case 'l':
2585			pfctl_debug(dev, PF_DEBUG_NOISY, opts);
2586			break;
2587		}
2588	}
2589
2590	exit(error);
2591}
2592