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