xref: /netbsd-src/dist/pf/sbin/pfctl/pfctl.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: pfctl.c,v 1.4 2005/07/01 12:43:50 peter Exp $	*/
2 /*	$OpenBSD: pfctl.c,v 1.234 2005/03/07 13:52:50 henning Exp $ */
3 
4 /*
5  * Copyright (c) 2001 Daniel Hartmeier
6  * Copyright (c) 2002,2003 Henning Brauer
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  *    - Redistributions of source code must retain the above copyright
14  *      notice, this list of conditions and the following disclaimer.
15  *    - Redistributions in binary form must reproduce the above
16  *      copyright notice, this list of conditions and the following
17  *      disclaimer in the documentation and/or other materials provided
18  *      with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34 
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
38 #include <sys/stat.h>
39 
40 #include <net/if.h>
41 #include <netinet/in.h>
42 #include <net/pfvar.h>
43 #include <arpa/inet.h>
44 #include <altq/altq.h>
45 
46 #include <err.h>
47 #include <errno.h>
48 #include <fcntl.h>
49 #include <limits.h>
50 #include <netdb.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55 
56 #include "pfctl_parser.h"
57 #include "pfctl.h"
58 
59 void	 usage(void);
60 int	 pfctl_enable(int, int);
61 int	 pfctl_disable(int, int);
62 int	 pfctl_clear_stats(int, int);
63 int	 pfctl_clear_interface_flags(int, int);
64 int	 pfctl_clear_rules(int, int, char *);
65 int	 pfctl_clear_nat(int, int, char *);
66 int	 pfctl_clear_altq(int, int);
67 int	 pfctl_clear_src_nodes(int, int);
68 int	 pfctl_clear_states(int, const char *, int);
69 int	 pfctl_kill_states(int, const char *, int);
70 void	 pfctl_init_options(struct pfctl *);
71 int	 pfctl_load_options(struct pfctl *);
72 int	 pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
73 int	 pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int);
74 int	 pfctl_load_debug(struct pfctl *, unsigned int);
75 int	 pfctl_load_logif(struct pfctl *, char *);
76 int	 pfctl_load_hostid(struct pfctl *, unsigned int);
77 int	 pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int,
78 	    char *);
79 void	 pfctl_print_rule_counters(struct pf_rule *, int);
80 int	 pfctl_show_rules(int, int, int, char *);
81 int	 pfctl_show_nat(int, int, char *);
82 int	 pfctl_show_src_nodes(int, int);
83 int	 pfctl_show_states(int, const char *, int);
84 int	 pfctl_show_status(int, int);
85 int	 pfctl_show_timeouts(int, int);
86 int	 pfctl_show_limits(int, int);
87 void	 pfctl_debug(int, u_int32_t, int);
88 int	 pfctl_clear_rule_counters(int, int);
89 int	 pfctl_test_altqsupport(int, int);
90 int	 pfctl_show_anchors(int, int, char *);
91 const char	*pfctl_lookup_option(char *, const char **);
92 
93 const char	*clearopt;
94 char		*rulesopt;
95 const char	*showopt;
96 const char	*debugopt;
97 char		*anchoropt;
98 char		*pf_device = "/dev/pf";
99 char		*ifaceopt;
100 char		*tableopt;
101 const char	*tblcmdopt;
102 int		 state_killers;
103 char		*state_kill[2];
104 int		 loadopt;
105 int		 altqsupport;
106 
107 int		 dev = -1;
108 int		 first_title = 1;
109 int		 labels = 0;
110 
111 const char	*infile;
112 
113 static const struct {
114 	const char	*name;
115 	int		index;
116 } pf_limits[] = {
117 	{ "states",	PF_LIMIT_STATES },
118 	{ "src-nodes",	PF_LIMIT_SRC_NODES },
119 	{ "frags",	PF_LIMIT_FRAGS },
120 	{ NULL,		0 }
121 };
122 
123 struct pf_hint {
124 	const char	*name;
125 	int		timeout;
126 };
127 static const struct pf_hint pf_hint_normal[] = {
128 	{ "tcp.first",		2 * 60 },
129 	{ "tcp.opening",	30 },
130 	{ "tcp.established",	24 * 60 * 60 },
131 	{ "tcp.closing",	15 * 60 },
132 	{ "tcp.finwait",	45 },
133 	{ "tcp.closed",		90 },
134 	{ "tcp.tsdiff",		30 },
135 	{ NULL,			0 }
136 };
137 static const struct pf_hint pf_hint_satellite[] = {
138 	{ "tcp.first",		3 * 60 },
139 	{ "tcp.opening",	30 + 5 },
140 	{ "tcp.established",	24 * 60 * 60 },
141 	{ "tcp.closing",	15 * 60 + 5 },
142 	{ "tcp.finwait",	45 + 5 },
143 	{ "tcp.closed",		90 + 5 },
144 	{ "tcp.tsdiff",		60 },
145 	{ NULL,			0 }
146 };
147 static const struct pf_hint pf_hint_conservative[] = {
148 	{ "tcp.first",		60 * 60 },
149 	{ "tcp.opening",	15 * 60 },
150 	{ "tcp.established",	5 * 24 * 60 * 60 },
151 	{ "tcp.closing",	60 * 60 },
152 	{ "tcp.finwait",	10 * 60 },
153 	{ "tcp.closed",		3 * 60 },
154 	{ "tcp.tsdiff",		60 },
155 	{ NULL,			0 }
156 };
157 static const struct pf_hint pf_hint_aggressive[] = {
158 	{ "tcp.first",		30 },
159 	{ "tcp.opening",	5 },
160 	{ "tcp.established",	5 * 60 * 60 },
161 	{ "tcp.closing",	60 },
162 	{ "tcp.finwait",	30 },
163 	{ "tcp.closed",		30 },
164 	{ "tcp.tsdiff",		10 },
165 	{ NULL,			0 }
166 };
167 
168 static const struct {
169 	const char *name;
170 	const struct pf_hint *hint;
171 } pf_hints[] = {
172 	{ "normal",		pf_hint_normal },
173 	{ "satellite",		pf_hint_satellite },
174 	{ "high-latency",	pf_hint_satellite },
175 	{ "conservative",	pf_hint_conservative },
176 	{ "aggressive",		pf_hint_aggressive },
177 	{ NULL,			NULL }
178 };
179 
180 static const char *clearopt_list[] = {
181 	"nat", "queue", "rules", "Sources",
182 	"state", "info", "Tables", "osfp", "all", NULL
183 };
184 
185 static const char *showopt_list[] = {
186 	"nat", "queue", "rules", "Anchors", "Sources", "state", "info",
187 	"Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
188 	"all", NULL
189 };
190 
191 static const char *tblcmdopt_list[] = {
192 	"kill", "flush", "add", "delete", "load", "replace", "show",
193 	"test", "zero", NULL
194 };
195 
196 static const char *debugopt_list[] = {
197 	"none", "urgent", "misc", "loud", NULL
198 };
199 
200 
201 void
202 usage(void)
203 {
204 	extern char *__progname;
205 
206 	fprintf(stderr, "usage: %s [-AdeghmNnOoqRrvz] ", __progname);
207 	fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n");
208 	fprintf(stderr, "             ");
209 	fprintf(stderr, "[-f file] [-i interface] [-k host] ");
210 	fprintf(stderr, "[-p device] [-s modifier]\n");
211 	fprintf(stderr, "             ");
212 	fprintf(stderr, "[-t table -T command [address ...]] ");
213 	fprintf(stderr, "[-x level]\n");
214 	exit(1);
215 }
216 
217 int
218 pfctl_enable(int dev, int opts)
219 {
220 	if (ioctl(dev, DIOCSTART)) {
221 		if (errno == EEXIST)
222 			errx(1, "pf already enabled");
223 		else
224 			err(1, "DIOCSTART");
225 	}
226 	if ((opts & PF_OPT_QUIET) == 0)
227 		fprintf(stderr, "pf enabled\n");
228 
229 	if (altqsupport && ioctl(dev, DIOCSTARTALTQ))
230 		if (errno != EEXIST)
231 			err(1, "DIOCSTARTALTQ");
232 
233 	return (0);
234 }
235 
236 int
237 pfctl_disable(int dev, int opts)
238 {
239 	if (ioctl(dev, DIOCSTOP)) {
240 		if (errno == ENOENT)
241 			errx(1, "pf not enabled");
242 		else
243 			err(1, "DIOCSTOP");
244 	}
245 	if ((opts & PF_OPT_QUIET) == 0)
246 		fprintf(stderr, "pf disabled\n");
247 
248 	if (altqsupport && ioctl(dev, DIOCSTOPALTQ))
249 			if (errno != ENOENT)
250 				err(1, "DIOCSTOPALTQ");
251 
252 	return (0);
253 }
254 
255 int
256 pfctl_clear_stats(int dev, int opts)
257 {
258 	if (ioctl(dev, DIOCCLRSTATUS))
259 		err(1, "DIOCCLRSTATUS");
260 	if ((opts & PF_OPT_QUIET) == 0)
261 		fprintf(stderr, "pf: statistics cleared\n");
262 	return (0);
263 }
264 
265 int
266 pfctl_clear_interface_flags(int dev, int opts)
267 {
268 	struct pfioc_iface	pi;
269 
270 	if ((opts & PF_OPT_NOACTION) == 0) {
271 		bzero(&pi, sizeof(pi));
272 		pi.pfiio_flags = PFI_IFLAG_SETABLE_MASK;
273 
274 		if (ioctl(dev, DIOCCLRIFFLAG, &pi))
275 			err(1, "DIOCCLRIFFLAG");
276 		if ((opts & PF_OPT_QUIET) == 0)
277 			fprintf(stderr, "pf: interface flags reset\n");
278 	}
279 	return (0);
280 }
281 
282 int
283 pfctl_clear_rules(int dev, int opts, char *anchorname)
284 {
285 	struct pfr_buffer t;
286 
287 	memset(&t, 0, sizeof(t));
288 	t.pfrb_type = PFRB_TRANS;
289 	if (pfctl_add_trans(&t, PF_RULESET_SCRUB, anchorname) ||
290 	    pfctl_add_trans(&t, PF_RULESET_FILTER, anchorname) ||
291 	    pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
292 	    pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
293 		err(1, "pfctl_clear_rules");
294 	if ((opts & PF_OPT_QUIET) == 0)
295 		fprintf(stderr, "rules cleared\n");
296 	return (0);
297 }
298 
299 int
300 pfctl_clear_nat(int dev, int opts, char *anchorname)
301 {
302 	struct pfr_buffer t;
303 
304 	memset(&t, 0, sizeof(t));
305 	t.pfrb_type = PFRB_TRANS;
306 	if (pfctl_add_trans(&t, PF_RULESET_NAT, anchorname) ||
307 	    pfctl_add_trans(&t, PF_RULESET_BINAT, anchorname) ||
308 	    pfctl_add_trans(&t, PF_RULESET_RDR, anchorname) ||
309 	    pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
310 	    pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
311 		err(1, "pfctl_clear_nat");
312 	if ((opts & PF_OPT_QUIET) == 0)
313 		fprintf(stderr, "nat cleared\n");
314 	return (0);
315 }
316 
317 int
318 pfctl_clear_altq(int dev, int opts)
319 {
320 	struct pfr_buffer t;
321 
322 	if (!altqsupport)
323 		return (-1);
324 	memset(&t, 0, sizeof(t));
325 	t.pfrb_type = PFRB_TRANS;
326 	if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") ||
327 	    pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
328 	    pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
329 		err(1, "pfctl_clear_altq");
330 	if ((opts & PF_OPT_QUIET) == 0)
331 		fprintf(stderr, "altq cleared\n");
332 	return (0);
333 }
334 
335 int
336 pfctl_clear_src_nodes(int dev, int opts)
337 {
338 	if (ioctl(dev, DIOCCLRSRCNODES))
339 		err(1, "DIOCCLRSRCNODES");
340 	if ((opts & PF_OPT_QUIET) == 0)
341 		fprintf(stderr, "source tracking entries cleared\n");
342 	return (0);
343 }
344 
345 int
346 pfctl_clear_states(int dev, const char *iface, int opts)
347 {
348 	struct pfioc_state_kill psk;
349 
350 	memset(&psk, 0, sizeof(psk));
351 	if (iface != NULL && strlcpy(psk.psk_ifname, iface,
352 	    sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
353 		errx(1, "invalid interface: %s", iface);
354 
355 	if (ioctl(dev, DIOCCLRSTATES, &psk))
356 		err(1, "DIOCCLRSTATES");
357 	if ((opts & PF_OPT_QUIET) == 0)
358 		fprintf(stderr, "%d states cleared\n", psk.psk_af);
359 	return (0);
360 }
361 
362 int
363 pfctl_kill_states(int dev, const char *iface, int opts)
364 {
365 	struct pfioc_state_kill psk;
366 	struct addrinfo *res[2], *resp[2];
367 	struct sockaddr last_src, last_dst;
368 	int killed, sources, dests;
369 	int ret_ga;
370 
371 	killed = sources = dests = 0;
372 
373 	memset(&psk, 0, sizeof(psk));
374 	memset(&psk.psk_src.addr.v.a.mask, 0xff,
375 	    sizeof(psk.psk_src.addr.v.a.mask));
376 	memset(&last_src, 0xff, sizeof(last_src));
377 	memset(&last_dst, 0xff, sizeof(last_dst));
378 	if (iface != NULL && strlcpy(psk.psk_ifname, iface,
379 	    sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
380 		errx(1, "invalid interface: %s", iface);
381 
382 	if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) {
383 		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
384 		/* NOTREACHED */
385 	}
386 	for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
387 		if (resp[0]->ai_addr == NULL)
388 			continue;
389 		/* We get lots of duplicates.  Catch the easy ones */
390 		if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
391 			continue;
392 		last_src = *(struct sockaddr *)resp[0]->ai_addr;
393 
394 		psk.psk_af = resp[0]->ai_family;
395 		sources++;
396 
397 		if (psk.psk_af == AF_INET)
398 			psk.psk_src.addr.v.a.addr.v4 =
399 			    ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
400 		else if (psk.psk_af == AF_INET6)
401 			psk.psk_src.addr.v.a.addr.v6 =
402 			    ((struct sockaddr_in6 *)resp[0]->ai_addr)->
403 			    sin6_addr;
404 		else
405 			errx(1, "Unknown address family %d", psk.psk_af);
406 
407 		if (state_killers > 1) {
408 			dests = 0;
409 			memset(&psk.psk_dst.addr.v.a.mask, 0xff,
410 			    sizeof(psk.psk_dst.addr.v.a.mask));
411 			memset(&last_dst, 0xff, sizeof(last_dst));
412 			if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL,
413 			    &res[1]))) {
414 				errx(1, "getaddrinfo: %s",
415 				    gai_strerror(ret_ga));
416 				/* NOTREACHED */
417 			}
418 			for (resp[1] = res[1]; resp[1];
419 			    resp[1] = resp[1]->ai_next) {
420 				if (resp[1]->ai_addr == NULL)
421 					continue;
422 				if (psk.psk_af != resp[1]->ai_family)
423 					continue;
424 
425 				if (memcmp(&last_dst, resp[1]->ai_addr,
426 				    sizeof(last_dst)) == 0)
427 					continue;
428 				last_dst = *(struct sockaddr *)resp[1]->ai_addr;
429 
430 				dests++;
431 
432 				if (psk.psk_af == AF_INET)
433 					psk.psk_dst.addr.v.a.addr.v4 =
434 					    ((struct sockaddr_in *)resp[1]->
435 					    ai_addr)->sin_addr;
436 				else if (psk.psk_af == AF_INET6)
437 					psk.psk_dst.addr.v.a.addr.v6 =
438 					    ((struct sockaddr_in6 *)resp[1]->
439 					    ai_addr)->sin6_addr;
440 				else
441 					errx(1, "Unknown address family %d",
442 					    psk.psk_af);
443 
444 				if (ioctl(dev, DIOCKILLSTATES, &psk))
445 					err(1, "DIOCKILLSTATES");
446 				killed += psk.psk_af;
447 				/* fixup psk.psk_af */
448 				psk.psk_af = resp[1]->ai_family;
449 			}
450 			freeaddrinfo(res[1]);
451 		} else {
452 			if (ioctl(dev, DIOCKILLSTATES, &psk))
453 				err(1, "DIOCKILLSTATES");
454 			killed += psk.psk_af;
455 			/* fixup psk.psk_af */
456 			psk.psk_af = res[0]->ai_family;
457 		}
458 	}
459 
460 	freeaddrinfo(res[0]);
461 
462 	if ((opts & PF_OPT_QUIET) == 0)
463 		fprintf(stderr, "killed %d states from %d sources and %d "
464 		    "destinations\n", killed, sources, dests);
465 	return (0);
466 }
467 
468 int
469 pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr,
470     u_int32_t ticket, int r_action, char *anchorname)
471 {
472 	struct pfioc_pooladdr pp;
473 	struct pf_pooladdr *pa;
474 	u_int32_t pnr, mpnr;
475 
476 	memset(&pp, 0, sizeof(pp));
477 	memcpy(pp.anchor, anchorname, sizeof(pp.anchor));
478 	pp.r_action = r_action;
479 	pp.r_num = nr;
480 	pp.ticket = ticket;
481 	if (ioctl(dev, DIOCGETADDRS, &pp)) {
482 		warn("DIOCGETADDRS");
483 		return (-1);
484 	}
485 	mpnr = pp.nr;
486 	TAILQ_INIT(&pool->list);
487 	for (pnr = 0; pnr < mpnr; ++pnr) {
488 		pp.nr = pnr;
489 		if (ioctl(dev, DIOCGETADDR, &pp)) {
490 			warn("DIOCGETADDR");
491 			return (-1);
492 		}
493 		pa = calloc(1, sizeof(struct pf_pooladdr));
494 		if (pa == NULL)
495 			err(1, "calloc");
496 		bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr));
497 		TAILQ_INSERT_TAIL(&pool->list, pa, entries);
498 	}
499 
500 	return (0);
501 }
502 
503 void
504 pfctl_clear_pool(struct pf_pool *pool)
505 {
506 	struct pf_pooladdr *pa;
507 
508 	while ((pa = TAILQ_FIRST(&pool->list)) != NULL) {
509 		TAILQ_REMOVE(&pool->list, pa, entries);
510 		free(pa);
511 	}
512 }
513 
514 void
515 pfctl_print_rule_counters(struct pf_rule *rule, int opts)
516 {
517 	if (opts & PF_OPT_DEBUG) {
518 		const char *t[PF_SKIP_COUNT] = { "i", "d", "f",
519 		    "p", "sa", "sp", "da", "dp" };
520 		int i;
521 
522 		printf("  [ Skip steps: ");
523 		for (i = 0; i < PF_SKIP_COUNT; ++i) {
524 			if (rule->skip[i].nr == rule->nr + 1)
525 				continue;
526 			printf("%s=", t[i]);
527 			if (rule->skip[i].nr == -1)
528 				printf("end ");
529 			else
530 				printf("%u ", rule->skip[i].nr);
531 		}
532 		printf("]\n");
533 
534 		printf("  [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
535 		    rule->qname, rule->qid, rule->pqname, rule->pqid);
536 	}
537 	if (opts & PF_OPT_VERBOSE)
538 		printf("  [ Evaluations: %-8llu  Packets: %-8llu  "
539 			    "Bytes: %-10llu  States: %-6u]\n",
540 			    (unsigned long long)rule->evaluations,
541 			    (unsigned long long)rule->packets,
542 			    (unsigned long long)rule->bytes, rule->states);
543 }
544 
545 void
546 pfctl_print_title(char *title)
547 {
548 	if (!first_title)
549 		printf("\n");
550 	first_title = 0;
551 	printf("%s\n", title);
552 }
553 
554 int
555 pfctl_show_rules(int dev, int opts, int format, char *anchorname)
556 {
557 	struct pfioc_rule pr;
558 	u_int32_t nr, mnr, header = 0;
559 	int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
560 
561 	memset(&pr, 0, sizeof(pr));
562 	memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
563 	if (opts & PF_OPT_SHOWALL) {
564 		pr.rule.action = PF_PASS;
565 		if (ioctl(dev, DIOCGETRULES, &pr)) {
566 			warn("DIOCGETRULES");
567 			return (-1);
568 		}
569 		header++;
570 	}
571 	pr.rule.action = PF_SCRUB;
572 	if (ioctl(dev, DIOCGETRULES, &pr)) {
573 		warn("DIOCGETRULES");
574 		return (-1);
575 	}
576 	if (opts & PF_OPT_SHOWALL) {
577 		if (format == 0 && (pr.nr > 0 || header))
578 			pfctl_print_title("FILTER RULES:");
579 		else if (format == 1 && labels)
580 			pfctl_print_title("LABEL COUNTERS:");
581 	}
582 	mnr = pr.nr;
583 	for (nr = 0; nr < mnr; ++nr) {
584 		pr.nr = nr;
585 		if (ioctl(dev, DIOCGETRULE, &pr)) {
586 			warn("DIOCGETRULE");
587 			return (-1);
588 		}
589 
590 		if (pfctl_get_pool(dev, &pr.rule.rpool,
591 		    nr, pr.ticket, PF_SCRUB, anchorname) != 0)
592 			return (-1);
593 
594 		switch (format) {
595 		case 1:
596 			if (pr.rule.label[0]) {
597 				printf("%s ", pr.rule.label);
598 				printf("%llu %llu %llu\n",
599 				    (unsigned long long)pr.rule.evaluations,
600 				    (unsigned long long)pr.rule.packets,
601 				    (unsigned long long)pr.rule.bytes);
602 			}
603 			break;
604 		default:
605 			if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
606 				labels = 1;
607 			print_rule(&pr.rule, pr.anchor_call, rule_numbers);
608 			pfctl_print_rule_counters(&pr.rule, opts);
609 		}
610 		pfctl_clear_pool(&pr.rule.rpool);
611 	}
612 	pr.rule.action = PF_PASS;
613 	if (ioctl(dev, DIOCGETRULES, &pr)) {
614 		warn("DIOCGETRULES");
615 		return (-1);
616 	}
617 	mnr = pr.nr;
618 	for (nr = 0; nr < mnr; ++nr) {
619 		pr.nr = nr;
620 		if (ioctl(dev, DIOCGETRULE, &pr)) {
621 			warn("DIOCGETRULE");
622 			return (-1);
623 		}
624 
625 		if (pfctl_get_pool(dev, &pr.rule.rpool,
626 		    nr, pr.ticket, PF_PASS, anchorname) != 0)
627 			return (-1);
628 
629 		switch (format) {
630 		case 1:
631 			if (pr.rule.label[0]) {
632 				printf("%s ", pr.rule.label);
633 				printf("%llu %llu %llu\n",
634 				    (unsigned long long)pr.rule.evaluations,
635 				    (unsigned long long)pr.rule.packets,
636 				    (unsigned long long)pr.rule.bytes);
637 			}
638 			break;
639 		default:
640 			if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
641 				labels = 1;
642 			print_rule(&pr.rule, pr.anchor_call, rule_numbers);
643 			pfctl_print_rule_counters(&pr.rule, opts);
644 		}
645 		pfctl_clear_pool(&pr.rule.rpool);
646 	}
647 	return (0);
648 }
649 
650 int
651 pfctl_show_nat(int dev, int opts, char *anchorname)
652 {
653 	struct pfioc_rule pr;
654 	u_int32_t mnr, nr;
655 	static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT };
656 	int i, dotitle = opts & PF_OPT_SHOWALL;
657 
658 	memset(&pr, 0, sizeof(pr));
659 	memcpy(pr.anchor, anchorname, sizeof(pr.anchor));
660 	for (i = 0; i < 3; i++) {
661 		pr.rule.action = nattype[i];
662 		if (ioctl(dev, DIOCGETRULES, &pr)) {
663 			warn("DIOCGETRULES");
664 			return (-1);
665 		}
666 		mnr = pr.nr;
667 		for (nr = 0; nr < mnr; ++nr) {
668 			pr.nr = nr;
669 			if (ioctl(dev, DIOCGETRULE, &pr)) {
670 				warn("DIOCGETRULE");
671 				return (-1);
672 			}
673 			if (pfctl_get_pool(dev, &pr.rule.rpool, nr,
674 			    pr.ticket, nattype[i], anchorname) != 0)
675 				return (-1);
676 			if (dotitle) {
677 				pfctl_print_title("TRANSLATION RULES:");
678 				dotitle = 0;
679 			}
680 			print_rule(&pr.rule, pr.anchor_call,
681 			    opts & PF_OPT_VERBOSE2);
682 			pfctl_print_rule_counters(&pr.rule, opts);
683 			pfctl_clear_pool(&pr.rule.rpool);
684 		}
685 	}
686 	return (0);
687 }
688 
689 int
690 pfctl_show_src_nodes(int dev, int opts)
691 {
692 	struct pfioc_src_nodes psn;
693 	struct pf_src_node *p;
694 	char *inbuf = NULL, *newinbuf = NULL;
695 	unsigned len = 0;
696 	int i;
697 
698 	memset(&psn, 0, sizeof(psn));
699 	for (;;) {
700 		psn.psn_len = len;
701 		if (len) {
702 			newinbuf = realloc(inbuf, len);
703 			if (newinbuf == NULL)
704 				err(1, "realloc");
705 			psn.psn_buf = inbuf = newinbuf;
706 		}
707 		if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) {
708 			warn("DIOCGETSRCNODES");
709 			return (-1);
710 		}
711 		if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len)
712 			break;
713 		if (len == 0 && psn.psn_len == 0)
714 			return (0);
715 		if (len == 0 && psn.psn_len != 0)
716 			len = psn.psn_len;
717 		if (psn.psn_len == 0)
718 			return (0);	/* no src_nodes */
719 		len *= 2;
720 	}
721 	p = psn.psn_src_nodes;
722 	if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL))
723 		pfctl_print_title("SOURCE TRACKING NODES:");
724 	for (i = 0; i < psn.psn_len; i += sizeof(*p)) {
725 		print_src_node(p, opts);
726 		p++;
727 	}
728 	return (0);
729 }
730 
731 int
732 pfctl_show_states(int dev, const char *iface, int opts)
733 {
734 	struct pfioc_states ps;
735 	struct pf_state *p;
736 	char *inbuf = NULL, *newinbuf = NULL;
737 	unsigned len = 0;
738 	int i, dotitle = (opts & PF_OPT_SHOWALL);
739 
740 	memset(&ps, 0, sizeof(ps));
741 	for (;;) {
742 		ps.ps_len = len;
743 		if (len) {
744 			newinbuf = realloc(inbuf, len);
745 			if (newinbuf == NULL)
746 				err(1, "realloc");
747 			ps.ps_buf = inbuf = newinbuf;
748 		}
749 		if (ioctl(dev, DIOCGETSTATES, &ps) < 0) {
750 			warn("DIOCGETSTATES");
751 			return (-1);
752 		}
753 		if (ps.ps_len + sizeof(struct pfioc_states) < len)
754 			break;
755 		if (len == 0 && ps.ps_len == 0)
756 			return (0);
757 		if (len == 0 && ps.ps_len != 0)
758 			len = ps.ps_len;
759 		if (ps.ps_len == 0)
760 			return (0);	/* no states */
761 		len *= 2;
762 	}
763 	p = ps.ps_states;
764 	for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) {
765 		if (iface != NULL && strcmp(p->u.ifname, iface))
766 			continue;
767 		if (dotitle) {
768 			pfctl_print_title("STATES:");
769 			dotitle = 0;
770 		}
771 		print_state(p, opts);
772 	}
773 	return (0);
774 }
775 
776 int
777 pfctl_show_status(int dev, int opts)
778 {
779 	struct pf_status status;
780 
781 	if (ioctl(dev, DIOCGETSTATUS, &status)) {
782 		warn("DIOCGETSTATUS");
783 		return (-1);
784 	}
785 	if (opts & PF_OPT_SHOWALL)
786 		pfctl_print_title("INFO:");
787 	print_status(&status, opts);
788 	return (0);
789 }
790 
791 int
792 pfctl_show_timeouts(int dev, int opts)
793 {
794 	struct pfioc_tm pt;
795 	int i;
796 
797 	if (opts & PF_OPT_SHOWALL)
798 		pfctl_print_title("TIMEOUTS:");
799 	memset(&pt, 0, sizeof(pt));
800 	for (i = 0; pf_timeouts[i].name; i++) {
801 		pt.timeout = pf_timeouts[i].timeout;
802 		if (ioctl(dev, DIOCGETTIMEOUT, &pt))
803 			err(1, "DIOCGETTIMEOUT");
804 		printf("%-20s %10d", pf_timeouts[i].name, pt.seconds);
805 		if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START &&
806 		    pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END)
807 			printf(" states");
808 		else
809 			printf("s");
810 		printf("\n");
811 	}
812 	return (0);
813 
814 }
815 
816 int
817 pfctl_show_limits(int dev, int opts)
818 {
819 	struct pfioc_limit pl;
820 	int i;
821 
822 	if (opts & PF_OPT_SHOWALL)
823 		pfctl_print_title("LIMITS:");
824 	memset(&pl, 0, sizeof(pl));
825 	for (i = 0; pf_limits[i].name; i++) {
826 		pl.index = pf_limits[i].index;
827 		if (ioctl(dev, DIOCGETLIMIT, &pl))
828 			err(1, "DIOCGETLIMIT");
829 		printf("%-10s ", pf_limits[i].name);
830 		if (pl.limit == UINT_MAX)
831 			printf("unlimited\n");
832 		else
833 			printf("hard limit %6u\n", pl.limit);
834 	}
835 	return (0);
836 }
837 
838 /* callbacks for rule/nat/rdr/addr */
839 int
840 pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af)
841 {
842 	struct pf_pooladdr *pa;
843 
844 	if ((pf->opts & PF_OPT_NOACTION) == 0) {
845 		if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr))
846 			err(1, "DIOCBEGINADDRS");
847 	}
848 
849 	pf->paddr.af = af;
850 	TAILQ_FOREACH(pa, &p->list, entries) {
851 		memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr));
852 		if ((pf->opts & PF_OPT_NOACTION) == 0) {
853 			if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr))
854 				err(1, "DIOCADDADDR");
855 		}
856 	}
857 	return (0);
858 }
859 
860 int
861 pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
862 {
863 	u_int8_t		rs_num;
864 	struct pfioc_rule	pr;
865 
866 	switch (r->action) {
867 	case PF_SCRUB:
868 	case PF_NOSCRUB:
869 		if ((loadopt & PFCTL_FLAG_FILTER) == 0)
870 			return (0);
871 		rs_num = PF_RULESET_SCRUB;
872 		break;
873 	case PF_DROP:
874 	case PF_PASS:
875 		if ((loadopt & PFCTL_FLAG_FILTER) == 0)
876 			return (0);
877 		rs_num = PF_RULESET_FILTER;
878 		break;
879 	case PF_NAT:
880 	case PF_NONAT:
881 		if ((loadopt & PFCTL_FLAG_NAT) == 0)
882 			return (0);
883 		rs_num = PF_RULESET_NAT;
884 		break;
885 	case PF_RDR:
886 	case PF_NORDR:
887 		if ((loadopt & PFCTL_FLAG_NAT) == 0)
888 			return (0);
889 		rs_num = PF_RULESET_RDR;
890 		break;
891 	case PF_BINAT:
892 	case PF_NOBINAT:
893 		if ((loadopt & PFCTL_FLAG_NAT) == 0)
894 			return (0);
895 		rs_num = PF_RULESET_BINAT;
896 		break;
897 	default:
898 		errx(1, "Invalid rule type %d", r->action);
899 		break;
900 	}
901 
902 
903 	if ((pf->opts & PF_OPT_OPTIMIZE) && rs_num == PF_RULESET_FILTER) {
904 		/*
905 		 * We'll do an optimization post-pass before finally adding the
906 		 * rules.  Then we'll disable the optimization flag and feed
907 		 * the rules right back into this function.
908 		 */
909 		struct pf_opt_rule *pfr;
910 		struct pf_pooladdr *pa;
911 
912 		if ((pfr = calloc(1, sizeof(*pfr))) == NULL)
913 			err(1, "calloc");
914 		memcpy(&pfr->por_rule, r, sizeof(*r));
915 		if (strlcpy(pfr->por_anchor, anchor_call,
916 		    sizeof(pfr->por_anchor)) >= sizeof(pfr->por_anchor))
917 			errx(1, "pfctl_add_rule: strlcpy");
918 		TAILQ_INSERT_TAIL(&pf->opt_queue, pfr, por_entry);
919 
920 		if (TAILQ_FIRST(&r->rpool.list) != NULL)  {
921 			TAILQ_INIT(&pfr->por_rule.rpool.list);
922 			while ((pa = TAILQ_FIRST(&r->rpool.list)) != NULL) {
923 				TAILQ_REMOVE(&r->rpool.list, pa, entries);
924 				TAILQ_INSERT_TAIL(&pfr->por_rule.rpool.list, pa,
925 			    	entries);
926 			}
927 		} else {
928 			memset(&pfr->por_rule.rpool, 0,
929 			    sizeof(pfr->por_rule.rpool));
930 
931 		}
932 		return (0);
933 	}
934 
935 	if ((pf->opts & PF_OPT_NOACTION) == 0) {
936 		bzero(&pr, sizeof(pr));
937 		if (strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor)) >=
938 		    sizeof(pr.anchor))
939 			errx(1, "pfctl_add_rule: strlcpy");
940 		if (pfctl_add_pool(pf, &r->rpool, r->af))
941 			return (1);
942 		pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor);
943 		pr.pool_ticket = pf->paddr.ticket;
944 		memcpy(&pr.rule, r, sizeof(pr.rule));
945 		strlcpy(pr.anchor_call, anchor_call, sizeof(pr.anchor_call));
946 		if (ioctl(pf->dev, DIOCADDRULE, &pr))
947 			err(1, "DIOCADDRULE");
948 	}
949 	if (pf->opts & PF_OPT_VERBOSE)
950 		print_rule(r, anchor_call, pf->opts & PF_OPT_VERBOSE2);
951 	pfctl_clear_pool(&r->rpool);
952 	return (0);
953 }
954 
955 int
956 pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
957 {
958 	if (altqsupport &&
959 	    (loadopt & PFCTL_FLAG_ALTQ) != 0) {
960 		memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq));
961 		if ((pf->opts & PF_OPT_NOACTION) == 0) {
962 			if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) {
963 				if (errno == ENXIO)
964 					errx(1, "qtype not configured");
965 				else if (errno == ENODEV)
966 					errx(1, "%s: driver does not support "
967 					    "altq", a->ifname);
968 				else
969 					err(1, "DIOCADDALTQ");
970 			}
971 		}
972 		pfaltq_store(&pf->paltq->altq);
973 	}
974 	return (0);
975 }
976 
977 int
978 pfctl_rules(int dev, char *filename, int opts, char *anchorname,
979     struct pfr_buffer *trans)
980 {
981 #define ERR(x) do { warn(x); goto _error; } while(0)
982 #define ERRX(x) do { warnx(x); goto _error; } while(0)
983 
984 	FILE			*fin = NULL;	/* XXX gcc */
985 	struct pfr_buffer	*t, buf;
986 	struct pfioc_altq	 pa;
987 	struct pfctl		 pf;
988 	struct pfr_table	 trs;
989 	int			 osize;
990 
991 	if (trans == NULL) {
992 	    bzero(&buf, sizeof(buf));
993 	    buf.pfrb_type = PFRB_TRANS;
994 	    t = &buf;
995 	    osize = 0;
996 	} else {
997 	    t = trans;
998 	    osize = t->pfrb_size;
999 	}
1000 
1001 	memset(&pa, 0, sizeof(pa));
1002 	memset(&pf, 0, sizeof(pf));
1003 	memset(&trs, 0, sizeof(trs));
1004 	if (strlcpy(trs.pfrt_anchor, anchorname,
1005 	    sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor))
1006 		ERRX("pfctl_rules: strlcpy");
1007 	if (strcmp(filename, "-") == 0) {
1008 		fin = stdin;
1009 		infile = "stdin";
1010 	} else {
1011 		if ((fin = pfctl_fopen(filename, "r")) == NULL) {
1012 			warn("%s", filename);
1013 			return (1);
1014 		}
1015 		infile = filename;
1016 	}
1017 	pf.dev = dev;
1018 	pf.opts = opts;
1019 	pf.loadopt = loadopt;
1020 	if (anchorname[0])
1021 		pf.loadopt &= ~PFCTL_FLAG_ALTQ;
1022 	pf.paltq = &pa;
1023 	pf.trans = t;
1024 	pf.rule_nr = 0;
1025 	pf.anchor = anchorname;
1026 	TAILQ_INIT(&pf.opt_queue);
1027 	pfctl_init_options(&pf);
1028 
1029 	if ((opts & PF_OPT_NOACTION) == 0) {
1030 		if ((pf.loadopt & PFCTL_FLAG_NAT) != 0) {
1031 			if (pfctl_add_trans(t, PF_RULESET_NAT, anchorname) ||
1032 			    pfctl_add_trans(t, PF_RULESET_BINAT, anchorname) ||
1033 			    pfctl_add_trans(t, PF_RULESET_RDR, anchorname))
1034 				ERR("pfctl_rules");
1035 		}
1036 		if (((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))) {
1037 			if (pfctl_add_trans(t, PF_RULESET_ALTQ, anchorname))
1038 				ERR("pfctl_rules");
1039 		}
1040 		if ((pf.loadopt & PFCTL_FLAG_FILTER) != 0) {
1041 			if (pfctl_add_trans(t, PF_RULESET_SCRUB, anchorname) ||
1042 			    pfctl_add_trans(t, PF_RULESET_FILTER, anchorname))
1043 				ERR("pfctl_rules");
1044 		}
1045 		if (pf.loadopt & PFCTL_FLAG_TABLE) {
1046 			if (pfctl_add_trans(t, PF_RULESET_TABLE, anchorname))
1047 				ERR("pfctl_rules");
1048 		}
1049 		if (pfctl_trans(dev, t, DIOCXBEGIN, osize))
1050 			ERR("DIOCXBEGIN");
1051 		if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ))
1052 			pa.ticket = pfctl_get_ticket(t, PF_RULESET_ALTQ,
1053 			    anchorname);
1054 		if (pf.loadopt & PFCTL_FLAG_TABLE)
1055 			pf.tticket = pfctl_get_ticket(t, PF_RULESET_TABLE,
1056 			    anchorname);
1057 	}
1058 	if (parse_rules(fin, &pf) < 0) {
1059 		if ((opts & PF_OPT_NOACTION) == 0)
1060 			ERRX("Syntax error in config file: "
1061 			    "pf rules not loaded");
1062 		else
1063 			goto _error;
1064 	}
1065 	if (pf.opts & PF_OPT_OPTIMIZE) {
1066 		if (pfctl_optimize_rules(&pf))
1067 			ERRX("Failed to optimize ruleset: pf rules not loaded");
1068 	}
1069 
1070 	if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0))
1071 		if (check_commit_altq(dev, opts) != 0)
1072 			ERRX("errors in altq config");
1073 
1074 	if (fin != stdin) {
1075 		fclose(fin);
1076 		fin = NULL;
1077 	}
1078 
1079 	/* process "load anchor" directives */
1080 	if (!anchorname[0])
1081 		if (pfctl_load_anchors(dev, opts, t) == -1)
1082 			ERRX("load anchors");
1083 
1084 	if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) {
1085 		if (!anchorname[0])
1086 			if (pfctl_load_options(&pf))
1087 				goto _error;
1088 		if (pfctl_trans(dev, t, DIOCXCOMMIT, 0))
1089 			ERR("DIOCXCOMMIT");
1090 	}
1091 	return (0);
1092 
1093 _error:
1094 	if (trans == NULL) {	/* main ruleset */
1095 		if ((opts & PF_OPT_NOACTION) == 0)
1096 			if (pfctl_trans(dev, t, DIOCXROLLBACK, 0))
1097 				err(1, "DIOCXROLLBACK");
1098 		exit(1);
1099 	} else {		/* sub ruleset */
1100 		if (fin != NULL && fin != stdin)
1101 			fclose(fin);
1102 		return (-1);
1103 	}
1104 
1105 #undef ERR
1106 #undef ERRX
1107 }
1108 
1109 FILE *
1110 pfctl_fopen(const char *name, const char *mode)
1111 {
1112 	struct stat	 st;
1113 	FILE		*fp;
1114 
1115 	fp = fopen(name, mode);
1116 	if (fp == NULL)
1117 		return (NULL);
1118 	if (fstat(fileno(fp), &st)) {
1119 		fclose(fp);
1120 		return (NULL);
1121 	}
1122 	if (S_ISDIR(st.st_mode)) {
1123 		fclose(fp);
1124 		errno = EISDIR;
1125 		return (NULL);
1126 	}
1127 	return (fp);
1128 }
1129 
1130 void
1131 pfctl_init_options(struct pfctl *pf)
1132 {
1133 	pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
1134 	pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
1135 	pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
1136 	pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
1137 	pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
1138 	pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
1139 	pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
1140 	pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
1141 	pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
1142 	pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
1143 	pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
1144 	pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
1145 	pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
1146 	pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
1147 	pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
1148 	pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
1149 	pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
1150 	pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
1151 
1152 	pf->limit[PF_LIMIT_STATES]	= PFSTATE_HIWAT;
1153 	pf->limit[PF_LIMIT_FRAGS]	= PFFRAG_FRENT_HIWAT;
1154 	pf->limit[PF_LIMIT_SRC_NODES]	= PFSNODE_HIWAT;
1155 
1156 	pf->debug = PF_DEBUG_URGENT;
1157 }
1158 
1159 int
1160 pfctl_load_options(struct pfctl *pf)
1161 {
1162 	int i, error = 0;
1163 
1164 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
1165 		return (0);
1166 
1167 	/* load limits */
1168 	for (i = 0; i < PF_LIMIT_MAX; i++) {
1169 		if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i])
1170 			continue;
1171 		if (pfctl_load_limit(pf, i, pf->limit[i]))
1172 			error = 1;
1173 	}
1174 
1175 	/* load timeouts */
1176 	for (i = 0; i < PFTM_MAX; i++) {
1177 		if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i])
1178 			continue;
1179 		if (pfctl_load_timeout(pf, i, pf->timeout[i]))
1180 			error = 1;
1181 	}
1182 
1183 	/* load debug */
1184 	if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set)
1185 		if (pfctl_load_debug(pf, pf->debug))
1186 			error = 1;
1187 
1188 	/* load logif */
1189 	if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set)
1190 		if (pfctl_load_logif(pf, pf->ifname))
1191 			error = 1;
1192 
1193 	/* load hostid */
1194 	if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set)
1195 		if (pfctl_load_hostid(pf, pf->hostid))
1196 			error = 1;
1197 
1198 	return (error);
1199 }
1200 
1201 int
1202 pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
1203 {
1204 	int i;
1205 
1206 
1207 	for (i = 0; pf_limits[i].name; i++) {
1208 		if (strcasecmp(opt, pf_limits[i].name) == 0) {
1209 			pf->limit[pf_limits[i].index] = limit;
1210 			pf->limit_set[pf_limits[i].index] = 1;
1211 			break;
1212 		}
1213 	}
1214 	if (pf_limits[i].name == NULL) {
1215 		warnx("Bad pool name.");
1216 		return (1);
1217 	}
1218 
1219 	if (pf->opts & PF_OPT_VERBOSE)
1220 		printf("set limit %s %d\n", opt, limit);
1221 
1222 	return (0);
1223 }
1224 
1225 int
1226 pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit)
1227 {
1228 	struct pfioc_limit pl;
1229 
1230 	memset(&pl, 0, sizeof(pl));
1231 	pl.index = index;
1232 	pl.limit = limit;
1233 	if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) {
1234 		if (errno == EBUSY)
1235 			warnx("Current pool size exceeds requested hard limit");
1236 		else
1237 			warnx("DIOCSETLIMIT");
1238 		return (1);
1239 	}
1240 	return (0);
1241 }
1242 
1243 int
1244 pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
1245 {
1246 	int i;
1247 
1248 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
1249 		return (0);
1250 
1251 	for (i = 0; pf_timeouts[i].name; i++) {
1252 		if (strcasecmp(opt, pf_timeouts[i].name) == 0) {
1253 			pf->timeout[pf_timeouts[i].timeout] = seconds;
1254 			pf->timeout_set[pf_timeouts[i].timeout] = 1;
1255 			break;
1256 		}
1257 	}
1258 
1259 	if (pf_timeouts[i].name == NULL) {
1260 		warnx("Bad timeout name.");
1261 		return (1);
1262 	}
1263 
1264 
1265 	if (pf->opts & PF_OPT_VERBOSE && ! quiet)
1266 		printf("set timeout %s %d\n", opt, seconds);
1267 
1268 	return (0);
1269 }
1270 
1271 int
1272 pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds)
1273 {
1274 	struct pfioc_tm pt;
1275 
1276 	memset(&pt, 0, sizeof(pt));
1277 	pt.timeout = timeout;
1278 	pt.seconds = seconds;
1279 	if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) {
1280 		warnx("DIOCSETTIMEOUT");
1281 		return (1);
1282 	}
1283 	return (0);
1284 }
1285 
1286 int
1287 pfctl_set_optimization(struct pfctl *pf, const char *opt)
1288 {
1289 	const struct pf_hint *hint;
1290 	int i, r;
1291 
1292 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
1293 		return (0);
1294 
1295 	for (i = 0; pf_hints[i].name; i++)
1296 		if (strcasecmp(opt, pf_hints[i].name) == 0)
1297 			break;
1298 
1299 	hint = pf_hints[i].hint;
1300 	if (hint == NULL) {
1301 		warnx("Bad hint name.");
1302 		return (1);
1303 	}
1304 
1305 	for (i = 0; hint[i].name; i++)
1306 		if ((r = pfctl_set_timeout(pf, hint[i].name,
1307 		    hint[i].timeout, 1)))
1308 			return (r);
1309 
1310 	if (pf->opts & PF_OPT_VERBOSE)
1311 		printf("set optimization %s\n", opt);
1312 
1313 	return (0);
1314 }
1315 
1316 int
1317 pfctl_set_logif(struct pfctl *pf, char *ifname)
1318 {
1319 
1320 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
1321 		return (0);
1322 
1323 	if (!strcmp(ifname, "none")) {
1324 		free(pf->ifname);
1325 		pf->ifname = NULL;
1326 	} else {
1327 		pf->ifname = strdup(ifname);
1328 		if (!pf->ifname)
1329 			errx(1, "pfctl_set_logif: strdup");
1330 	}
1331 	pf->ifname_set = 1;
1332 
1333 	if (pf->opts & PF_OPT_VERBOSE)
1334 		printf("set loginterface %s\n", ifname);
1335 
1336 	return (0);
1337 }
1338 
1339 int
1340 pfctl_load_logif(struct pfctl *pf, char *ifname)
1341 {
1342 	struct pfioc_if pi;
1343 
1344 	memset(&pi, 0, sizeof(pi));
1345 	if (ifname && strlcpy(pi.ifname, ifname,
1346 	    sizeof(pi.ifname)) >= sizeof(pi.ifname)) {
1347 		warnx("pfctl_set_logif: strlcpy");
1348 		return (1);
1349 	}
1350 	if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) {
1351 		warnx("DIOCSETSTATUSIF");
1352 		return (1);
1353 	}
1354 	return (0);
1355 }
1356 
1357 int
1358 pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
1359 {
1360 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
1361 		return (0);
1362 
1363 	HTONL(hostid);
1364 
1365 	pf->hostid = hostid;
1366 	pf->hostid_set = 1;
1367 
1368 	if (pf->opts & PF_OPT_VERBOSE)
1369 		printf("set hostid 0x%08x\n", ntohl(hostid));
1370 
1371 	return (0);
1372 }
1373 
1374 int
1375 pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid)
1376 {
1377 	if (ioctl(dev, DIOCSETHOSTID, &hostid)) {
1378 		warnx("DIOCSETHOSTID");
1379 		return (1);
1380 	}
1381 	return (0);
1382 }
1383 
1384 int
1385 pfctl_set_debug(struct pfctl *pf, char *d)
1386 {
1387 	u_int32_t	level;
1388 
1389 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
1390 		return (0);
1391 
1392 	if (!strcmp(d, "none"))
1393 		pf->debug = PF_DEBUG_NONE;
1394 	else if (!strcmp(d, "urgent"))
1395 		pf->debug = PF_DEBUG_URGENT;
1396 	else if (!strcmp(d, "misc"))
1397 		pf->debug = PF_DEBUG_MISC;
1398 	else if (!strcmp(d, "loud"))
1399 		pf->debug = PF_DEBUG_NOISY;
1400 	else {
1401 		warnx("unknown debug level \"%s\"", d);
1402 		return (-1);
1403 	}
1404 
1405 	pf->debug_set = 1;
1406 
1407 	if ((pf->opts & PF_OPT_NOACTION) == 0)
1408 		if (ioctl(dev, DIOCSETDEBUG, &level))
1409 			err(1, "DIOCSETDEBUG");
1410 
1411 	if (pf->opts & PF_OPT_VERBOSE)
1412 		printf("set debug %s\n", d);
1413 
1414 	return (0);
1415 }
1416 
1417 int
1418 pfctl_load_debug(struct pfctl *pf, unsigned int level)
1419 {
1420 	if (ioctl(pf->dev, DIOCSETDEBUG, &level)) {
1421 		warnx("DIOCSETDEBUG");
1422 		return (1);
1423 	}
1424 	return (0);
1425 }
1426 
1427 int
1428 pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how)
1429 {
1430 	struct pfioc_iface	pi;
1431 
1432 	if ((loadopt & PFCTL_FLAG_OPTION) == 0)
1433 		return (0);
1434 
1435 	bzero(&pi, sizeof(pi));
1436 
1437 	pi.pfiio_flags = flags;
1438 
1439 	if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >=
1440 	    sizeof(pi.pfiio_name))
1441 		errx(1, "pfctl_set_interface_flags: strlcpy");
1442 
1443 	if ((pf->opts & PF_OPT_NOACTION) == 0) {
1444 		if (how == 0) {
1445 			if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi))
1446 				err(1, "DIOCCLRIFFLAG");
1447 		} else {
1448 			if (ioctl(pf->dev, DIOCSETIFFLAG, &pi))
1449 				err(1, "DIOCSETIFFLAG");
1450 		}
1451 	}
1452 	return (0);
1453 }
1454 
1455 void
1456 pfctl_debug(int dev, u_int32_t level, int opts)
1457 {
1458 	if (ioctl(dev, DIOCSETDEBUG, &level))
1459 		err(1, "DIOCSETDEBUG");
1460 	if ((opts & PF_OPT_QUIET) == 0) {
1461 		fprintf(stderr, "debug level set to '");
1462 		switch (level) {
1463 		case PF_DEBUG_NONE:
1464 			fprintf(stderr, "none");
1465 			break;
1466 		case PF_DEBUG_URGENT:
1467 			fprintf(stderr, "urgent");
1468 			break;
1469 		case PF_DEBUG_MISC:
1470 			fprintf(stderr, "misc");
1471 			break;
1472 		case PF_DEBUG_NOISY:
1473 			fprintf(stderr, "loud");
1474 			break;
1475 		default:
1476 			fprintf(stderr, "<invalid>");
1477 			break;
1478 		}
1479 		fprintf(stderr, "'\n");
1480 	}
1481 }
1482 
1483 int
1484 pfctl_clear_rule_counters(int dev, int opts)
1485 {
1486 	if (ioctl(dev, DIOCCLRRULECTRS))
1487 		err(1, "DIOCCLRRULECTRS");
1488 	if ((opts & PF_OPT_QUIET) == 0)
1489 		fprintf(stderr, "pf: rule counters cleared\n");
1490 	return (0);
1491 }
1492 
1493 int
1494 pfctl_test_altqsupport(int dev, int opts)
1495 {
1496 	struct pfioc_altq pa;
1497 
1498 	if (ioctl(dev, DIOCGETALTQS, &pa)) {
1499 		if (errno == ENODEV) {
1500 			if (!(opts & PF_OPT_QUIET))
1501 				fprintf(stderr, "No ALTQ support in kernel\n"
1502 				    "ALTQ related functions disabled\n");
1503 			return (0);
1504 		} else
1505 			err(1, "DIOCGETALTQS");
1506 	}
1507 	return (1);
1508 }
1509 
1510 int
1511 pfctl_show_anchors(int dev, int opts, char *anchorname)
1512 {
1513 	struct pfioc_ruleset	 pr;
1514 	u_int32_t		 mnr, nr;
1515 
1516 	memset(&pr, 0, sizeof(pr));
1517 	memcpy(pr.path, anchorname, sizeof(pr.path));
1518 	if (ioctl(dev, DIOCGETRULESETS, &pr)) {
1519 		if (errno == EINVAL)
1520 			fprintf(stderr, "Anchor '%s' not found.\n",
1521 			    anchorname);
1522 		else
1523 			err(1, "DIOCGETRULESETS");
1524 		return (-1);
1525 	}
1526 	mnr = pr.nr;
1527 	for (nr = 0; nr < mnr; ++nr) {
1528 		char sub[MAXPATHLEN];
1529 
1530 		pr.nr = nr;
1531 		if (ioctl(dev, DIOCGETRULESET, &pr))
1532 			err(1, "DIOCGETRULESET");
1533 		if (!strcmp(pr.name, PF_RESERVED_ANCHOR))
1534 			continue;
1535 		sub[0] = 0;
1536 		if (pr.path[0]) {
1537 			strlcat(sub, pr.path, sizeof(sub));
1538 			strlcat(sub, "/", sizeof(sub));
1539 		}
1540 		strlcat(sub, pr.name, sizeof(sub));
1541 		printf("  %s\n", sub);
1542 		if (opts & PF_OPT_VERBOSE && pfctl_show_anchors(dev, opts, sub))
1543 			return (-1);
1544 	}
1545 	return (0);
1546 }
1547 
1548 const char *
1549 pfctl_lookup_option(char *cmd, const char **list)
1550 {
1551 	if (cmd != NULL && *cmd)
1552 		for (; *list; list++)
1553 			if (!strncmp(cmd, *list, strlen(cmd)))
1554 				return (*list);
1555 	return (NULL);
1556 }
1557 
1558 int
1559 main(int argc, char *argv[])
1560 {
1561 	int	error = 0;
1562 	int	ch;
1563 	int	mode = O_RDONLY;
1564 	int	opts = 0;
1565 	char	anchorname[MAXPATHLEN];
1566 
1567 	if (argc < 2)
1568 		usage();
1569 
1570 	while ((ch = getopt(argc, argv,
1571 	    "a:AdD:eqf:F:ghi:k:mnNOop:rRs:t:T:vx:z")) != -1) {
1572 		switch (ch) {
1573 		case 'a':
1574 			anchoropt = optarg;
1575 			break;
1576 		case 'd':
1577 			opts |= PF_OPT_DISABLE;
1578 			mode = O_RDWR;
1579 			break;
1580 		case 'D':
1581 			if (pfctl_cmdline_symset(optarg) < 0)
1582 				warnx("could not parse macro definition %s",
1583 				    optarg);
1584 			break;
1585 		case 'e':
1586 			opts |= PF_OPT_ENABLE;
1587 			mode = O_RDWR;
1588 			break;
1589 		case 'q':
1590 			opts |= PF_OPT_QUIET;
1591 			break;
1592 		case 'F':
1593 			clearopt = pfctl_lookup_option(optarg, clearopt_list);
1594 			if (clearopt == NULL) {
1595 				warnx("Unknown flush modifier '%s'", optarg);
1596 				usage();
1597 			}
1598 			mode = O_RDWR;
1599 			break;
1600 		case 'i':
1601 			ifaceopt = optarg;
1602 			break;
1603 		case 'k':
1604 			if (state_killers >= 2) {
1605 				warnx("can only specify -k twice");
1606 				usage();
1607 				/* NOTREACHED */
1608 			}
1609 			state_kill[state_killers++] = optarg;
1610 			mode = O_RDWR;
1611 			break;
1612 		case 'm':
1613 			opts |= PF_OPT_MERGE;
1614 			break;
1615 		case 'n':
1616 			opts |= PF_OPT_NOACTION;
1617 			break;
1618 		case 'N':
1619 			loadopt |= PFCTL_FLAG_NAT;
1620 			break;
1621 		case 'r':
1622 			opts |= PF_OPT_USEDNS;
1623 			break;
1624 		case 'f':
1625 			rulesopt = optarg;
1626 			mode = O_RDWR;
1627 			break;
1628 		case 'g':
1629 			opts |= PF_OPT_DEBUG;
1630 			break;
1631 		case 'A':
1632 			loadopt |= PFCTL_FLAG_ALTQ;
1633 			break;
1634 		case 'R':
1635 			loadopt |= PFCTL_FLAG_FILTER;
1636 			break;
1637 		case 'o':
1638 			if (opts & PF_OPT_OPTIMIZE)
1639 				opts |= PF_OPT_OPTIMIZE_PROFILE;
1640 			else
1641 				opts |= PF_OPT_OPTIMIZE;
1642 			break;
1643 		case 'O':
1644 			loadopt |= PFCTL_FLAG_OPTION;
1645 			break;
1646 		case 'p':
1647 			pf_device = optarg;
1648 			break;
1649 		case 's':
1650 			showopt = pfctl_lookup_option(optarg, showopt_list);
1651 			if (showopt == NULL) {
1652 				warnx("Unknown show modifier '%s'", optarg);
1653 				usage();
1654 			}
1655 			break;
1656 		case 't':
1657 			tableopt = optarg;
1658 			break;
1659 		case 'T':
1660 			tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list);
1661 			if (tblcmdopt == NULL) {
1662 				warnx("Unknown table command '%s'", optarg);
1663 				usage();
1664 			}
1665 			break;
1666 		case 'v':
1667 			if (opts & PF_OPT_VERBOSE)
1668 				opts |= PF_OPT_VERBOSE2;
1669 			opts |= PF_OPT_VERBOSE;
1670 			break;
1671 		case 'x':
1672 			debugopt = pfctl_lookup_option(optarg, debugopt_list);
1673 			if (debugopt == NULL) {
1674 				warnx("Unknown debug level '%s'", optarg);
1675 				usage();
1676 			}
1677 			mode = O_RDWR;
1678 			break;
1679 		case 'z':
1680 			opts |= PF_OPT_CLRRULECTRS;
1681 			mode = O_RDWR;
1682 			break;
1683 		case 'h':
1684 			/* FALLTHROUGH */
1685 		default:
1686 			usage();
1687 			/* NOTREACHED */
1688 		}
1689 	}
1690 
1691 	if (tblcmdopt != NULL) {
1692 		argc -= optind;
1693 		argv += optind;
1694 		ch = *tblcmdopt;
1695 		if (ch == 'l') {
1696 			loadopt |= PFCTL_FLAG_TABLE;
1697 			tblcmdopt = NULL;
1698 		} else
1699 			mode = strchr("acdfkrz", ch) ? O_RDWR : O_RDONLY;
1700 	} else if (argc != optind) {
1701 		warnx("unknown command line argument: %s ...", argv[optind]);
1702 		usage();
1703 		/* NOTREACHED */
1704 	}
1705 	if (loadopt == 0)
1706 		loadopt = ~0;
1707 
1708 	memset(anchorname, 0, sizeof(anchorname));
1709 	if (anchoropt != NULL) {
1710 		if (strlcpy(anchorname, anchoropt,
1711 		    sizeof(anchorname)) >= sizeof(anchorname))
1712 			errx(1, "anchor name '%s' too long",
1713 			    anchoropt);
1714 		loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE;
1715 	}
1716 
1717 	if ((opts & PF_OPT_NOACTION) == 0) {
1718 		dev = open(pf_device, mode);
1719 		if (dev == -1)
1720 			err(1, "%s", pf_device);
1721 		altqsupport = pfctl_test_altqsupport(dev, opts);
1722 	} else {
1723 		dev = open(pf_device, O_RDONLY);
1724 		if (dev >= 0)
1725 			opts |= PF_OPT_DUMMYACTION;
1726 		/* turn off options */
1727 		opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE);
1728 		clearopt = showopt = debugopt = NULL;
1729 		altqsupport = 1;
1730 	}
1731 
1732 	if (opts & PF_OPT_DISABLE)
1733 		if (pfctl_disable(dev, opts))
1734 			error = 1;
1735 
1736 	if (showopt != NULL) {
1737 		switch (*showopt) {
1738 		case 'A':
1739 			pfctl_show_anchors(dev, opts, anchorname);
1740 			break;
1741 		case 'r':
1742 			pfctl_load_fingerprints(dev, opts);
1743 			pfctl_show_rules(dev, opts, 0, anchorname);
1744 			break;
1745 		case 'l':
1746 			pfctl_load_fingerprints(dev, opts);
1747 			pfctl_show_rules(dev, opts, 1, anchorname);
1748 			break;
1749 		case 'n':
1750 			pfctl_load_fingerprints(dev, opts);
1751 			pfctl_show_nat(dev, opts, anchorname);
1752 			break;
1753 		case 'q':
1754 			pfctl_show_altq(dev, ifaceopt, opts,
1755 			    opts & PF_OPT_VERBOSE2);
1756 			break;
1757 		case 's':
1758 			pfctl_show_states(dev, ifaceopt, opts);
1759 			break;
1760 		case 'S':
1761 			pfctl_show_src_nodes(dev, opts);
1762 			break;
1763 		case 'i':
1764 			pfctl_show_status(dev, opts);
1765 			break;
1766 		case 't':
1767 			pfctl_show_timeouts(dev, opts);
1768 			break;
1769 		case 'm':
1770 			pfctl_show_limits(dev, opts);
1771 			break;
1772 		case 'a':
1773 			opts |= PF_OPT_SHOWALL;
1774 			pfctl_load_fingerprints(dev, opts);
1775 
1776 			pfctl_show_nat(dev, opts, anchorname);
1777 			pfctl_show_rules(dev, opts, 0, anchorname);
1778 			pfctl_show_altq(dev, ifaceopt, opts, 0);
1779 			pfctl_show_states(dev, ifaceopt, opts);
1780 			pfctl_show_src_nodes(dev, opts);
1781 			pfctl_show_status(dev, opts);
1782 			pfctl_show_rules(dev, opts, 1, anchorname);
1783 			pfctl_show_timeouts(dev, opts);
1784 			pfctl_show_limits(dev, opts);
1785 			pfctl_show_tables(anchorname, opts);
1786 			pfctl_show_fingerprints(opts);
1787 			break;
1788 		case 'T':
1789 			pfctl_show_tables(anchorname, opts);
1790 			break;
1791 		case 'o':
1792 			pfctl_load_fingerprints(dev, opts);
1793 			pfctl_show_fingerprints(opts);
1794 			break;
1795 		case 'I':
1796 			pfctl_show_ifaces(ifaceopt, opts);
1797 			break;
1798 		}
1799 	}
1800 
1801 	if (clearopt != NULL) {
1802 		switch (*clearopt) {
1803 		case 'r':
1804 			pfctl_clear_rules(dev, opts, anchorname);
1805 			break;
1806 		case 'n':
1807 			pfctl_clear_nat(dev, opts, anchorname);
1808 			break;
1809 		case 'q':
1810 			pfctl_clear_altq(dev, opts);
1811 			break;
1812 		case 's':
1813 			pfctl_clear_states(dev, ifaceopt, opts);
1814 			break;
1815 		case 'S':
1816 			pfctl_clear_src_nodes(dev, opts);
1817 			break;
1818 		case 'i':
1819 			pfctl_clear_stats(dev, opts);
1820 			break;
1821 		case 'a':
1822 			pfctl_clear_rules(dev, opts, anchorname);
1823 			pfctl_clear_nat(dev, opts, anchorname);
1824 			pfctl_clear_tables(anchorname, opts);
1825 			if (!*anchorname) {
1826 				pfctl_clear_altq(dev, opts);
1827 				pfctl_clear_states(dev, ifaceopt, opts);
1828 				pfctl_clear_src_nodes(dev, opts);
1829 				pfctl_clear_stats(dev, opts);
1830 				pfctl_clear_fingerprints(dev, opts);
1831 				pfctl_clear_interface_flags(dev, opts);
1832 			}
1833 			break;
1834 		case 'o':
1835 			pfctl_clear_fingerprints(dev, opts);
1836 			break;
1837 		case 'T':
1838 			pfctl_clear_tables(anchorname, opts);
1839 			break;
1840 		}
1841 	}
1842 	if (state_killers)
1843 		pfctl_kill_states(dev, ifaceopt, opts);
1844 
1845 	if (tblcmdopt != NULL) {
1846 		error = pfctl_command_tables(argc, argv, tableopt,
1847 		    tblcmdopt, rulesopt, anchorname, opts);
1848 		rulesopt = NULL;
1849 	}
1850 
1851 	if ((rulesopt != NULL) && (!*anchorname))
1852 		if (pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET))
1853 			error = 1;
1854 
1855 	if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) &&
1856 	    !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION))
1857 		if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE))
1858 			error = 1;
1859 
1860 	if (rulesopt != NULL) {
1861 		if (pfctl_rules(dev, rulesopt, opts, anchorname, NULL))
1862 			error = 1;
1863 		else if (!(opts & PF_OPT_NOACTION) &&
1864 		    (loadopt & PFCTL_FLAG_TABLE))
1865 			warn_namespace_collision(NULL);
1866 	}
1867 
1868 	if (opts & PF_OPT_ENABLE)
1869 		if (pfctl_enable(dev, opts))
1870 			error = 1;
1871 
1872 	if (debugopt != NULL) {
1873 		switch (*debugopt) {
1874 		case 'n':
1875 			pfctl_debug(dev, PF_DEBUG_NONE, opts);
1876 			break;
1877 		case 'u':
1878 			pfctl_debug(dev, PF_DEBUG_URGENT, opts);
1879 			break;
1880 		case 'm':
1881 			pfctl_debug(dev, PF_DEBUG_MISC, opts);
1882 			break;
1883 		case 'l':
1884 			pfctl_debug(dev, PF_DEBUG_NOISY, opts);
1885 			break;
1886 		}
1887 	}
1888 
1889 	if (opts & PF_OPT_CLRRULECTRS) {
1890 		if (pfctl_clear_rule_counters(dev, opts))
1891 			error = 1;
1892 	}
1893 	exit(error);
1894 }
1895