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 
67 void	 usage(void);
68 int	 pfctl_enable(int, int);
69 int	 pfctl_disable(int, int);
70 int	 pfctl_clear_stats(int, int);
71 int	 pfctl_get_skip_ifaces(void);
72 int	 pfctl_check_skip_ifaces(char *);
73 int	 pfctl_clear_skip_ifaces(struct pfctl *);
74 int	 pfctl_clear_interface_flags(int, int);
75 int	 pfctl_clear_rules(int, int, char *);
76 int	 pfctl_clear_nat(int, int, char *);
77 int	 pfctl_clear_altq(int, int);
78 int	 pfctl_clear_src_nodes(int, int);
79 int	 pfctl_clear_states(int, const char *, int);
80 void	 pfctl_addrprefix(char *, struct pf_addr *);
81 int	 pfctl_kill_src_nodes(int, const char *, int);
82 int	 pfctl_net_kill_states(int, const char *, int);
83 int	 pfctl_label_kill_states(int, const char *, int);
84 int	 pfctl_id_kill_states(int, const char *, int);
85 void	 pfctl_init_options(struct pfctl *);
86 int	 pfctl_load_options(struct pfctl *);
87 int	 pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
88 int	 pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int);
89 int	 pfctl_load_debug(struct pfctl *, unsigned int);
90 int	 pfctl_load_logif(struct pfctl *, char *);
91 int	 pfctl_load_hostid(struct pfctl *, unsigned int);
92 int	 pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int,
93 	    char *);
94 void	 pfctl_print_rule_counters(struct pf_rule *, int);
95 int	 pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int);
96 int	 pfctl_show_nat(int, int, char *);
97 int	 pfctl_show_src_nodes(int, int);
98 int	 pfctl_show_states(int, const char *, int);
99 int	 pfctl_show_status(int, int);
100 int	 pfctl_show_timeouts(int, int);
101 int	 pfctl_show_limits(int, int);
102 void	 pfctl_debug(int, u_int32_t, int);
103 int	 pfctl_test_altqsupport(int, int);
104 int	 pfctl_show_anchors(int, int, char *);
105 int	 pfctl_ruleset_trans(struct pfctl *, char *, struct pf_anchor *);
106 int	 pfctl_load_ruleset(struct pfctl *, char *,
107 		struct pf_ruleset *, int, int);
108 int	 pfctl_load_rule(struct pfctl *, char *, struct pf_rule *, int);
109 const char	*pfctl_lookup_option(char *, const char **);
110 
111 struct pf_anchor_global	 pf_anchors;
112 struct pf_anchor	 pf_main_anchor;
113 static struct pfr_buffer skip_b;
114 
115 const char	*clearopt;
116 char		*rulesopt;
117 const char	*showopt;
118 const char	*debugopt;
119 char		*anchoropt;
120 const char	*optiopt = NULL;
121 char		*pf_device = "/dev/pf";
122 char		*ifaceopt;
123 char		*tableopt;
124 const char	*tblcmdopt;
125 int		 src_node_killers;
126 char		*src_node_kill[2];
127 int		 state_killers;
128 char		*state_kill[2];
129 int		 loadopt;
130 int		 altqsupport;
131 
132 int		 dev = -1;
133 int		 first_title = 1;
134 int		 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 
145 static 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 
156 struct pf_hint {
157 	const char	*name;
158 	int		timeout;
159 };
160 static 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 };
170 static 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 };
180 static 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 };
190 static 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 
201 static 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 
213 static const char *clearopt_list[] = {
214 	"nat", "queue", "rules", "Sources",
215 	"states", "info", "Tables", "osfp", "all", NULL
216 };
217 
218 static const char *showopt_list[] = {
219 	"nat", "queue", "rules", "Anchors", "Sources", "states", "info",
220 	"Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
221 	"all", NULL
222 };
223 
224 static const char *tblcmdopt_list[] = {
225 	"kill", "flush", "add", "delete", "load", "replace", "show",
226 	"test", "zero", "expire", NULL
227 };
228 
229 static const char *debugopt_list[] = {
230 	"none", "urgent", "misc", "loud", NULL
231 };
232 
233 static const char *optiopt_list[] = {
234 	"none", "basic", "profile", NULL
235 };
236 
237 void
usage(void)238 usage(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 
252 int
pfctl_enable(int dev,int opts)253 pfctl_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 
275 int
pfctl_disable(int dev,int opts)276 pfctl_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 
294 int
pfctl_clear_stats(int dev,int opts)295 pfctl_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 
304 int
pfctl_get_skip_ifaces(void)305 pfctl_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 
320 int
pfctl_check_skip_ifaces(char * ifname)321 pfctl_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 
331 int
pfctl_clear_skip_ifaces(struct pfctl * pf)332 pfctl_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 
342 int
pfctl_clear_interface_flags(int dev,int opts)343 pfctl_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 
359 int
pfctl_clear_rules(int dev,int opts,char * anchorname)360 pfctl_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 
376 int
pfctl_clear_nat(int dev,int opts,char * anchorname)377 pfctl_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 
394 int
pfctl_clear_altq(int dev,int opts)395 pfctl_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 
412 int
pfctl_clear_src_nodes(int dev,int opts)413 pfctl_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 
422 int
pfctl_clear_states(int dev,const char * iface,int opts)423 pfctl_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 
439 void
pfctl_addrprefix(char * addr,struct pf_addr * mask)440 pfctl_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 
489 int
pfctl_kill_src_nodes(int dev,const char * iface,int opts)490 pfctl_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 
592 int
pfctl_net_kill_states(int dev,const char * iface,int opts)593 pfctl_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 
698 int
pfctl_label_kill_states(int dev,const char * iface,int opts)699 pfctl_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 
725 int
pfctl_id_kill_states(int dev,const char * iface,int opts)726 pfctl_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 
760 int
pfctl_get_pool(int dev,struct pf_pool * pool,u_int32_t nr,u_int32_t ticket,int r_action,char * anchorname)761 pfctl_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 
795 void
pfctl_move_pool(struct pf_pool * src,struct pf_pool * dst)796 pfctl_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 
806 void
pfctl_clear_pool(struct pf_pool * pool)807 pfctl_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 
817 void
pfctl_print_rule_counters(struct pf_rule * rule,int opts)818 pfctl_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 
856 void
pfctl_print_title(char * title)857 pfctl_print_title(char *title)
858 {
859 	if (!first_title)
860 		printf("\n");
861 	first_title = 0;
862 	printf("%s\n", title);
863 }
864 
865 int
pfctl_show_rules(int dev,char * path,int opts,enum pfctl_show format,char * anchorname,int depth)866 pfctl_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 
1012 int
pfctl_show_nat(int dev,int opts,char * anchorname)1013 pfctl_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 
1052 int
pfctl_show_src_nodes(int dev,int opts)1053 pfctl_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 	}
1092 done:
1093 	free(inbuf);
1094 	return (0);
1095 }
1096 
1097 int
pfctl_show_states(int dev,const char * iface,int opts)1098 pfctl_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 	}
1140 done:
1141 	free(inbuf);
1142 	return (0);
1143 }
1144 
1145 int
pfctl_show_status(int dev,int opts)1146 pfctl_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 
1160 int
pfctl_show_timeouts(int dev,int opts)1161 pfctl_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 
1185 int
pfctl_show_limits(int dev,int opts)1186 pfctl_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 */
1208 int
pfctl_add_pool(struct pfctl * pf,struct pf_pool * p,sa_family_t af)1209 pfctl_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 
1229 int
pfctl_add_rule(struct pfctl * pf,struct pf_rule * r,const char * anchor_call)1230 pfctl_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 
1276 int
pfctl_ruleset_trans(struct pfctl * pf,char * path,struct pf_anchor * a)1277 pfctl_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 
1306 int
pfctl_load_ruleset(struct pfctl * pf,char * path,struct pf_ruleset * rs,int rs_num,int depth)1307 pfctl_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 
1366 int
pfctl_load_rule(struct pfctl * pf,char * path,struct pf_rule * r,int depth)1367 pfctl_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 
1418 int
pfctl_add_altq(struct pfctl * pf,struct pf_altq * a)1419 pfctl_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 
1440 int
pfctl_rules(int dev,char * filename,int opts,int optimize,char * anchorname,struct pfr_buffer * trans)1441 pfctl_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 
1576 FILE *
pfctl_fopen(const char * name,const char * mode)1577 pfctl_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 
1597 void
pfctl_init_options(struct pfctl * pf)1598 pfctl_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 
1630 int
pfctl_load_options(struct pfctl * pf)1631 pfctl_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 
1687 int
pfctl_set_limit(struct pfctl * pf,const char * opt,unsigned int limit)1688 pfctl_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 
1711 int
pfctl_load_limit(struct pfctl * pf,unsigned int index,unsigned int limit)1712 pfctl_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 
1729 int
pfctl_set_timeout(struct pfctl * pf,const char * opt,int seconds,int quiet)1730 pfctl_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 
1757 int
pfctl_load_timeout(struct pfctl * pf,unsigned int timeout,unsigned int seconds)1758 pfctl_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 
1772 int
pfctl_set_optimization(struct pfctl * pf,const char * opt)1773 pfctl_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 
1802 int
pfctl_set_logif(struct pfctl * pf,char * ifname)1803 pfctl_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 
1825 int
pfctl_load_logif(struct pfctl * pf,char * ifname)1826 pfctl_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 
1843 int
pfctl_set_hostid(struct pfctl * pf,u_int32_t hostid)1844 pfctl_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 
1860 int
pfctl_load_hostid(struct pfctl * pf,u_int32_t hostid)1861 pfctl_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 
1870 int
pfctl_set_debug(struct pfctl * pf,char * d)1871 pfctl_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 
1904 int
pfctl_load_debug(struct pfctl * pf,unsigned int level)1905 pfctl_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 
1914 int
pfctl_set_interface_flags(struct pfctl * pf,char * ifname,int flags,int how)1915 pfctl_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 
1943 void
pfctl_debug(int dev,u_int32_t level,int opts)1944 pfctl_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 
1971 int
pfctl_test_altqsupport(int dev,int opts)1972 pfctl_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 
1988 int
pfctl_show_anchors(int dev,int opts,char * anchorname)1989 pfctl_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 
2027 const char *
pfctl_lookup_option(char * cmd,const char ** list)2028 pfctl_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 
2037 int
main(int argc,char * argv[])2038 main(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