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