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