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