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