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