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