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