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