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