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