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