1 /* $OpenBSD: pfctl.c,v 1.213 2004/03/20 09:31:42 david Exp $ */
2 /* $DragonFly: src/usr.sbin/pfctl/pfctl.c,v 1.2 2005/02/11 22:31:45 joerg Exp $ */
5 * Copyright (c) 2001 Daniel Hartmeier
6 * Copyright (c) 2002,2003 Henning Brauer
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <net/pf/pfvar.h>
42 #include <arpa/inet.h>
43 #include <net/altq/altq.h>
55 #include "pfctl_parser.h"
59 int pfctl_enable(int, int);
60 int pfctl_disable(int, int);
61 int pfctl_clear_stats(int, int);
62 int pfctl_clear_rules(int, int, char *, char *);
63 int pfctl_clear_nat(int, int, char *, char *);
64 int pfctl_clear_altq(int, int);
65 int pfctl_clear_src_nodes(int, int);
66 int pfctl_clear_states(int, const char *, int);
67 int pfctl_kill_states(int, const char *, int);
68 int pfctl_get_pool(int, struct pf_pool
*, u_int32_t
, u_int32_t
, int,
70 void pfctl_print_rule_counters(struct pf_rule
*, int);
71 int pfctl_show_rules(int, int, int, char *, char *);
72 int pfctl_show_nat(int, int, char *, char *);
73 int pfctl_show_src_nodes(int, int);
74 int pfctl_show_states(int, const char *, int);
75 int pfctl_show_status(int, int);
76 int pfctl_show_timeouts(int, int);
77 int pfctl_show_limits(int, int);
78 int pfctl_debug(int, u_int32_t
, int);
79 int pfctl_clear_rule_counters(int, int);
80 int pfctl_test_altqsupport(int, int);
81 int pfctl_show_anchors(int, int, char *);
82 const char *pfctl_lookup_option(char *, const char **);
89 const char *pf_device
= "/dev/pf";
92 const char *tblcmdopt
;
104 static const struct {
108 { "states", PF_LIMIT_STATES
},
109 { "src-nodes", PF_LIMIT_SRC_NODES
},
110 { "frags", PF_LIMIT_FRAGS
},
118 static const struct pf_hint pf_hint_normal
[] = {
119 { "tcp.first", 2 * 60 },
120 { "tcp.opening", 30 },
121 { "tcp.established", 24 * 60 * 60 },
122 { "tcp.closing", 15 * 60 },
123 { "tcp.finwait", 45 },
124 { "tcp.closed", 90 },
127 static const struct pf_hint pf_hint_satellite
[] = {
128 { "tcp.first", 3 * 60 },
129 { "tcp.opening", 30 + 5 },
130 { "tcp.established", 24 * 60 * 60 },
131 { "tcp.closing", 15 * 60 + 5 },
132 { "tcp.finwait", 45 + 5 },
133 { "tcp.closed", 90 + 5 },
136 static const struct pf_hint pf_hint_conservative
[] = {
137 { "tcp.first", 60 * 60 },
138 { "tcp.opening", 15 * 60 },
139 { "tcp.established", 5 * 24 * 60 * 60 },
140 { "tcp.closing", 60 * 60 },
141 { "tcp.finwait", 10 * 60 },
142 { "tcp.closed", 3 * 60 },
145 static const struct pf_hint pf_hint_aggressive
[] = {
147 { "tcp.opening", 5 },
148 { "tcp.established", 5 * 60 * 60 },
149 { "tcp.closing", 60 },
150 { "tcp.finwait", 30 },
151 { "tcp.closed", 30 },
155 static const struct {
157 const struct pf_hint
*hint
;
159 { "normal", pf_hint_normal
},
160 { "satellite", pf_hint_satellite
},
161 { "high-latency", pf_hint_satellite
},
162 { "conservative", pf_hint_conservative
},
163 { "aggressive", pf_hint_aggressive
},
167 static const char *clearopt_list
[] = {
168 "nat", "queue", "rules", "Sources",
169 "state", "info", "Tables", "osfp", "all", NULL
172 static const char *showopt_list
[] = {
173 "nat", "queue", "rules", "Anchors", "Sources", "state", "info",
174 "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
178 static const char *tblcmdopt_list
[] = {
179 "kill", "flush", "add", "delete", "load", "replace", "show",
183 static const char *debugopt_list
[] = {
184 "none", "urgent", "misc", "loud", NULL
191 fprintf(stderr
, "usage: %s [-AdeghNnOqRrvz] ", getprogname());
192 fprintf(stderr
, "[-a anchor[:ruleset]] [-D macro=value]\n");
193 fprintf(stderr
, " ");
194 fprintf(stderr
, "[-F modifier] [-f file] [-i interface] ");
195 fprintf(stderr
, "[-k host] [-p device]\n");
196 fprintf(stderr
, " ");
197 fprintf(stderr
, "[-s modifier] [-T command [address ...]] ");
198 fprintf(stderr
, "[-t table] [-x level]\n");
203 pfctl_enable(int dev
, int opts
)
205 if (ioctl(dev
, DIOCSTART
)) {
207 errx(1, "pf already enabled");
211 if ((opts
& PF_OPT_QUIET
) == 0)
212 fprintf(stderr
, "pf enabled\n");
214 if (altqsupport
&& ioctl(dev
, DIOCSTARTALTQ
))
216 err(1, "DIOCSTARTALTQ");
222 pfctl_disable(int dev
, int opts
)
224 if (ioctl(dev
, DIOCSTOP
)) {
226 errx(1, "pf not enabled");
230 if ((opts
& PF_OPT_QUIET
) == 0)
231 fprintf(stderr
, "pf disabled\n");
233 if (altqsupport
&& ioctl(dev
, DIOCSTOPALTQ
))
235 err(1, "DIOCSTOPALTQ");
241 pfctl_clear_stats(int dev
, int opts
)
243 if (ioctl(dev
, DIOCCLRSTATUS
))
244 err(1, "DIOCCLRSTATUS");
245 if ((opts
& PF_OPT_QUIET
) == 0)
246 fprintf(stderr
, "pf: statistics cleared\n");
251 pfctl_clear_rules(int dev
, int opts
, char *anchorname
, char *rulesetname
)
255 if (*anchorname
&& !*rulesetname
) {
256 struct pfioc_ruleset pr
;
259 memset(&pr
, 0, sizeof(pr
));
260 memcpy(pr
.anchor
, anchorname
, sizeof(pr
.anchor
));
261 if (ioctl(dev
, DIOCGETRULESETS
, &pr
)) {
263 fprintf(stderr
, "No rulesets in anchor '%s'.\n",
266 err(1, "DIOCGETRULESETS");
270 for (nr
= mnr
- 1; nr
>= 0; --nr
) {
272 if (ioctl(dev
, DIOCGETRULESET
, &pr
))
273 err(1, "DIOCGETRULESET");
274 r
= pfctl_clear_rules(dev
, opts
| PF_OPT_QUIET
,
275 anchorname
, pr
.name
);
279 if ((opts
& PF_OPT_QUIET
) == 0)
280 fprintf(stderr
, "rules cleared\n");
283 memset(&t
, 0, sizeof(t
));
284 t
.pfrb_type
= PFRB_TRANS
;
285 if (pfctl_add_trans(&t
, PF_RULESET_SCRUB
, anchorname
, rulesetname
) ||
286 pfctl_add_trans(&t
, PF_RULESET_FILTER
, anchorname
, rulesetname
) ||
287 pfctl_trans(dev
, &t
, DIOCXBEGIN
, 0) ||
288 pfctl_trans(dev
, &t
, DIOCXCOMMIT
, 0))
289 err(1, "pfctl_clear_rules");
290 if ((opts
& PF_OPT_QUIET
) == 0)
291 fprintf(stderr
, "rules cleared\n");
296 pfctl_clear_nat(int dev
, int opts
, char *anchorname
, char *rulesetname
)
300 if (*anchorname
&& !*rulesetname
) {
301 struct pfioc_ruleset pr
;
304 memset(&pr
, 0, sizeof(pr
));
305 memcpy(pr
.anchor
, anchorname
, sizeof(pr
.anchor
));
306 if (ioctl(dev
, DIOCGETRULESETS
, &pr
)) {
308 fprintf(stderr
, "No rulesets in anchor '%s'.\n",
311 err(1, "DIOCGETRULESETS");
315 for (nr
= mnr
- 1; nr
>= 0; --nr
) {
317 if (ioctl(dev
, DIOCGETRULESET
, &pr
))
318 err(1, "DIOCGETRULESET");
319 r
= pfctl_clear_nat(dev
, opts
| PF_OPT_QUIET
,
320 anchorname
, pr
.name
);
324 if ((opts
& PF_OPT_QUIET
) == 0)
325 fprintf(stderr
, "nat cleared\n");
328 memset(&t
, 0, sizeof(t
));
329 t
.pfrb_type
= PFRB_TRANS
;
330 if (pfctl_add_trans(&t
, PF_RULESET_NAT
, anchorname
, rulesetname
) ||
331 pfctl_add_trans(&t
, PF_RULESET_BINAT
, anchorname
, rulesetname
) ||
332 pfctl_add_trans(&t
, PF_RULESET_RDR
, anchorname
, rulesetname
) ||
333 pfctl_trans(dev
, &t
, DIOCXBEGIN
, 0) ||
334 pfctl_trans(dev
, &t
, DIOCXCOMMIT
, 0))
335 err(1, "pfctl_clear_nat");
336 if ((opts
& PF_OPT_QUIET
) == 0)
337 fprintf(stderr
, "nat cleared\n");
342 pfctl_clear_altq(int dev
, int opts
)
348 memset(&t
, 0, sizeof(t
));
349 t
.pfrb_type
= PFRB_TRANS
;
350 if (pfctl_add_trans(&t
, PF_RULESET_ALTQ
, "", "") ||
351 pfctl_trans(dev
, &t
, DIOCXBEGIN
, 0) ||
352 pfctl_trans(dev
, &t
, DIOCXCOMMIT
, 0))
353 err(1, "pfctl_clear_altq");
354 if ((opts
& PF_OPT_QUIET
) == 0)
355 fprintf(stderr
, "altq cleared\n");
360 pfctl_clear_src_nodes(int dev
, int opts
)
362 if (ioctl(dev
, DIOCCLRSRCNODES
))
363 err(1, "DIOCCLRSRCNODES");
364 if ((opts
& PF_OPT_QUIET
) == 0)
365 fprintf(stderr
, "source tracking entries cleared\n");
370 pfctl_clear_states(int dev
, const char *iface
, int opts
)
372 struct pfioc_state_kill psk
;
374 memset(&psk
, 0, sizeof(psk
));
375 if (iface
!= NULL
&& strlcpy(psk
.psk_ifname
, iface
,
376 sizeof(psk
.psk_ifname
)) >= sizeof(psk
.psk_ifname
))
377 errx(1, "invalid interface: %s", iface
);
379 if (ioctl(dev
, DIOCCLRSTATES
, &psk
))
380 err(1, "DIOCCLRSTATES");
381 if ((opts
& PF_OPT_QUIET
) == 0)
382 fprintf(stderr
, "%d states cleared\n", psk
.psk_af
);
387 pfctl_kill_states(int dev
, const char *iface
, int opts
)
389 struct pfioc_state_kill psk
;
390 struct addrinfo
*res
[2], *resp
[2];
391 struct sockaddr last_src
, last_dst
;
392 int killed
, sources
, dests
;
395 killed
= sources
= dests
= 0;
397 memset(&psk
, 0, sizeof(psk
));
398 memset(&psk
.psk_src
.addr
.v
.a
.mask
, 0xff,
399 sizeof(psk
.psk_src
.addr
.v
.a
.mask
));
400 memset(&last_src
, 0xff, sizeof(last_src
));
401 memset(&last_dst
, 0xff, sizeof(last_dst
));
402 if (iface
!= NULL
&& strlcpy(psk
.psk_ifname
, iface
,
403 sizeof(psk
.psk_ifname
)) >= sizeof(psk
.psk_ifname
))
404 errx(1, "invalid interface: %s", iface
);
406 if ((ret_ga
= getaddrinfo(state_kill
[0], NULL
, NULL
, &res
[0]))) {
407 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga
));
410 for (resp
[0] = res
[0]; resp
[0]; resp
[0] = resp
[0]->ai_next
) {
411 if (resp
[0]->ai_addr
== NULL
)
413 /* We get lots of duplicates. Catch the easy ones */
414 if (memcmp(&last_src
, resp
[0]->ai_addr
, sizeof(last_src
)) == 0)
416 last_src
= *(struct sockaddr
*)resp
[0]->ai_addr
;
418 psk
.psk_af
= resp
[0]->ai_family
;
421 if (psk
.psk_af
== AF_INET
)
422 psk
.psk_src
.addr
.v
.a
.addr
.v4
=
423 ((struct sockaddr_in
*)resp
[0]->ai_addr
)->sin_addr
;
424 else if (psk
.psk_af
== AF_INET6
)
425 psk
.psk_src
.addr
.v
.a
.addr
.v6
=
426 ((struct sockaddr_in6
*)resp
[0]->ai_addr
)->
429 errx(1, "Unknown address family %d", psk
.psk_af
);
431 if (state_killers
> 1) {
433 memset(&psk
.psk_dst
.addr
.v
.a
.mask
, 0xff,
434 sizeof(psk
.psk_dst
.addr
.v
.a
.mask
));
435 memset(&last_dst
, 0xff, sizeof(last_dst
));
436 if ((ret_ga
= getaddrinfo(state_kill
[1], NULL
, NULL
,
438 errx(1, "getaddrinfo: %s",
439 gai_strerror(ret_ga
));
442 for (resp
[1] = res
[1]; resp
[1];
443 resp
[1] = resp
[1]->ai_next
) {
444 if (resp
[1]->ai_addr
== NULL
)
446 if (psk
.psk_af
!= resp
[1]->ai_family
)
449 if (memcmp(&last_dst
, resp
[1]->ai_addr
,
450 sizeof(last_dst
)) == 0)
452 last_dst
= *(struct sockaddr
*)resp
[1]->ai_addr
;
456 if (psk
.psk_af
== AF_INET
)
457 psk
.psk_dst
.addr
.v
.a
.addr
.v4
=
458 ((struct sockaddr_in
*)resp
[1]->
460 else if (psk
.psk_af
== AF_INET6
)
461 psk
.psk_dst
.addr
.v
.a
.addr
.v6
=
462 ((struct sockaddr_in6
*)resp
[1]->
465 errx(1, "Unknown address family %d",
468 if (ioctl(dev
, DIOCKILLSTATES
, &psk
))
469 err(1, "DIOCKILLSTATES");
470 killed
+= psk
.psk_af
;
471 /* fixup psk.psk_af */
472 psk
.psk_af
= resp
[1]->ai_family
;
474 freeaddrinfo(res
[1]);
476 if (ioctl(dev
, DIOCKILLSTATES
, &psk
))
477 err(1, "DIOCKILLSTATES");
478 killed
+= psk
.psk_af
;
479 /* fixup psk.psk_af */
480 psk
.psk_af
= res
[0]->ai_family
;
484 freeaddrinfo(res
[0]);
486 if ((opts
& PF_OPT_QUIET
) == 0)
487 fprintf(stderr
, "killed %d states from %d sources and %d "
488 "destinations\n", killed
, sources
, dests
);
493 pfctl_get_pool(int dev
, struct pf_pool
*pool
, u_int32_t nr
,
494 u_int32_t ticket
, int r_action
, char *anchorname
, char *rulesetname
)
496 struct pfioc_pooladdr pp
;
497 struct pf_pooladdr
*pa
;
500 memset(&pp
, 0, sizeof(pp
));
501 memcpy(pp
.anchor
, anchorname
, sizeof(pp
.anchor
));
502 memcpy(pp
.ruleset
, rulesetname
, sizeof(pp
.ruleset
));
503 pp
.r_action
= r_action
;
506 if (ioctl(dev
, DIOCGETADDRS
, &pp
)) {
507 warn("DIOCGETADDRS");
511 TAILQ_INIT(&pool
->list
);
512 for (pnr
= 0; pnr
< mpnr
; ++pnr
) {
514 if (ioctl(dev
, DIOCGETADDR
, &pp
)) {
518 pa
= calloc(1, sizeof(struct pf_pooladdr
));
521 bcopy(&pp
.addr
, pa
, sizeof(struct pf_pooladdr
));
522 TAILQ_INSERT_TAIL(&pool
->list
, pa
, entries
);
529 pfctl_clear_pool(struct pf_pool
*pool
)
531 struct pf_pooladdr
*pa
;
533 while ((pa
= TAILQ_FIRST(&pool
->list
)) != NULL
) {
534 TAILQ_REMOVE(&pool
->list
, pa
, entries
);
540 pfctl_print_rule_counters(struct pf_rule
*rule
, int opts
)
542 if (opts
& PF_OPT_DEBUG
) {
543 const char *t
[PF_SKIP_COUNT
] = { "i", "d", "f",
544 "p", "sa", "sp", "da", "dp" };
547 printf(" [ Skip steps: ");
548 for (i
= 0; i
< PF_SKIP_COUNT
; ++i
) {
549 if (rule
->skip
[i
].nr
== rule
->nr
+ 1)
552 if (rule
->skip
[i
].nr
== (uint32_t)(-1))
555 printf("%u ", rule
->skip
[i
].nr
);
559 printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
560 rule
->qname
, rule
->qid
, rule
->pqname
, rule
->pqid
);
562 if (opts
& PF_OPT_VERBOSE
)
563 printf(" [ Evaluations: %-8llu Packets: %-8llu "
564 "Bytes: %-10llu States: %-6u]\n",
565 (unsigned long long)rule
->evaluations
,
566 (unsigned long long)rule
->packets
,
567 (unsigned long long)rule
->bytes
, rule
->states
);
571 pfctl_print_title(const char *title
)
576 printf("%s\n", title
);
580 pfctl_show_rules(int dev
, int opts
, int format
, char *anchorname
,
583 struct pfioc_rule pr
;
584 u_int32_t nr
, mnr
, header
= 0;
585 int rule_numbers
= opts
& (PF_OPT_VERBOSE2
| PF_OPT_DEBUG
);
587 if (*anchorname
&& !*rulesetname
) {
588 struct pfioc_ruleset pr2
;
591 memset(&pr2
, 0, sizeof(pr2
));
592 memcpy(pr2
.anchor
, anchorname
, sizeof(pr2
.anchor
));
593 if (ioctl(dev
, DIOCGETRULESETS
, &pr2
)) {
595 fprintf(stderr
, "No rulesets in anchor '%s'.\n",
598 err(1, "DIOCGETRULESETS");
601 if (opts
& PF_OPT_SHOWALL
&& pr2
.nr
)
602 pfctl_print_title("FILTER RULES:");
604 for (nr
= 0; nr
< mnr
; ++nr
) {
606 if (ioctl(dev
, DIOCGETRULESET
, &pr2
))
607 err(1, "DIOCGETRULESET");
608 r
= pfctl_show_rules(dev
, opts
, format
, anchorname
,
616 memset(&pr
, 0, sizeof(pr
));
617 memcpy(pr
.anchor
, anchorname
, sizeof(pr
.anchor
));
618 memcpy(pr
.ruleset
, rulesetname
, sizeof(pr
.ruleset
));
619 if (opts
& PF_OPT_SHOWALL
) {
620 pr
.rule
.action
= PF_PASS
;
621 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
622 warn("DIOCGETRULES");
627 pr
.rule
.action
= PF_SCRUB
;
628 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
629 warn("DIOCGETRULES");
632 if (opts
& PF_OPT_SHOWALL
) {
633 if (format
== 0 && (pr
.nr
> 0 || header
))
634 pfctl_print_title("FILTER RULES:");
635 else if (format
== 1 && labels
)
636 pfctl_print_title("LABEL COUNTERS:");
639 for (nr
= 0; nr
< mnr
; ++nr
) {
641 if (ioctl(dev
, DIOCGETRULE
, &pr
)) {
646 if (pfctl_get_pool(dev
, &pr
.rule
.rpool
,
647 nr
, pr
.ticket
, PF_SCRUB
, anchorname
, rulesetname
) != 0)
652 if (pr
.rule
.label
[0]) {
653 printf("%s ", pr
.rule
.label
);
654 printf("%llu %llu %llu\n",
655 (unsigned long long)pr
.rule
.evaluations
,
656 (unsigned long long)pr
.rule
.packets
,
657 (unsigned long long)pr
.rule
.bytes
);
661 if (pr
.rule
.label
[0] && (opts
& PF_OPT_SHOWALL
))
663 print_rule(&pr
.rule
, rule_numbers
);
664 pfctl_print_rule_counters(&pr
.rule
, opts
);
666 pfctl_clear_pool(&pr
.rule
.rpool
);
668 pr
.rule
.action
= PF_PASS
;
669 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
670 warn("DIOCGETRULES");
674 for (nr
= 0; nr
< mnr
; ++nr
) {
676 if (ioctl(dev
, DIOCGETRULE
, &pr
)) {
681 if (pfctl_get_pool(dev
, &pr
.rule
.rpool
,
682 nr
, pr
.ticket
, PF_PASS
, anchorname
, rulesetname
) != 0)
687 if (pr
.rule
.label
[0]) {
688 printf("%s ", pr
.rule
.label
);
689 printf("%llu %llu %llu\n",
690 (unsigned long long)pr
.rule
.evaluations
,
691 (unsigned long long)pr
.rule
.packets
,
692 (unsigned long long)pr
.rule
.bytes
);
696 if (pr
.rule
.label
[0] && (opts
& PF_OPT_SHOWALL
))
698 print_rule(&pr
.rule
, rule_numbers
);
699 pfctl_print_rule_counters(&pr
.rule
, opts
);
701 pfctl_clear_pool(&pr
.rule
.rpool
);
707 pfctl_show_nat(int dev
, int opts
, char *anchorname
, char *rulesetname
)
709 struct pfioc_rule pr
;
711 static int nattype
[3] = { PF_NAT
, PF_RDR
, PF_BINAT
};
712 int i
, dotitle
= opts
& PF_OPT_SHOWALL
;
714 if (*anchorname
&& !*rulesetname
) {
715 struct pfioc_ruleset pr2
;
718 memset(&pr2
, 0, sizeof(pr2
));
719 memcpy(pr2
.anchor
, anchorname
, sizeof(pr2
.anchor
));
720 if (ioctl(dev
, DIOCGETRULESETS
, &pr2
)) {
722 fprintf(stderr
, "No rulesets in anchor '%s'.\n",
725 err(1, "DIOCGETRULESETS");
729 for (nr
= 0; nr
< mnr
; ++nr
) {
731 if (ioctl(dev
, DIOCGETRULESET
, &pr2
))
732 err(1, "DIOCGETRULESET");
733 r
= pfctl_show_nat(dev
, opts
, anchorname
, pr2
.name
);
740 memset(&pr
, 0, sizeof(pr
));
741 memcpy(pr
.anchor
, anchorname
, sizeof(pr
.anchor
));
742 memcpy(pr
.ruleset
, rulesetname
, sizeof(pr
.ruleset
));
743 for (i
= 0; i
< 3; i
++) {
744 pr
.rule
.action
= nattype
[i
];
745 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
746 warn("DIOCGETRULES");
750 for (nr
= 0; nr
< mnr
; ++nr
) {
752 if (ioctl(dev
, DIOCGETRULE
, &pr
)) {
756 if (pfctl_get_pool(dev
, &pr
.rule
.rpool
, nr
,
757 pr
.ticket
, nattype
[i
], anchorname
,
761 pfctl_print_title("TRANSLATION RULES:");
764 print_rule(&pr
.rule
, opts
& PF_OPT_VERBOSE2
);
765 pfctl_print_rule_counters(&pr
.rule
, opts
);
766 pfctl_clear_pool(&pr
.rule
.rpool
);
773 pfctl_show_src_nodes(int dev
, int opts
)
775 struct pfioc_src_nodes psn
;
776 struct pf_src_node
*p
;
777 char *inbuf
= NULL
, *newinbuf
= NULL
;
781 memset(&psn
, 0, sizeof(psn
));
785 newinbuf
= realloc(inbuf
, len
);
786 if (newinbuf
== NULL
)
788 psn
.psn_buf
= inbuf
= newinbuf
;
790 if (ioctl(dev
, DIOCGETSRCNODES
, &psn
) < 0) {
791 warn("DIOCGETSRCNODES");
794 if (psn
.psn_len
+ sizeof(struct pfioc_src_nodes
) < len
)
796 if (len
== 0 && psn
.psn_len
== 0)
798 if (len
== 0 && psn
.psn_len
!= 0)
800 if (psn
.psn_len
== 0)
801 return (0); /* no src_nodes */
804 p
= psn
.psn_src_nodes
;
805 if (psn
.psn_len
> 0 && (opts
& PF_OPT_SHOWALL
))
806 pfctl_print_title("SOURCE TRACKING NODES:");
807 for (i
= 0; i
< psn
.psn_len
; i
+= sizeof(*p
)) {
808 print_src_node(p
, opts
);
815 pfctl_show_states(int dev
, const char *iface
, int opts
)
817 struct pfioc_states ps
;
819 char *inbuf
= NULL
, *newinbuf
= NULL
;
821 int i
, dotitle
= (opts
& PF_OPT_SHOWALL
);
823 memset(&ps
, 0, sizeof(ps
));
827 newinbuf
= realloc(inbuf
, len
);
828 if (newinbuf
== NULL
)
830 ps
.ps_buf
= inbuf
= newinbuf
;
832 if (ioctl(dev
, DIOCGETSTATES
, &ps
) < 0) {
833 warn("DIOCGETSTATES");
836 if (ps
.ps_len
+ sizeof(struct pfioc_states
) < len
)
838 if (len
== 0 && ps
.ps_len
== 0)
840 if (len
== 0 && ps
.ps_len
!= 0)
843 return (0); /* no states */
847 for (i
= 0; i
< ps
.ps_len
; i
+= sizeof(*p
), p
++) {
848 if (iface
!= NULL
&& strcmp(p
->u
.ifname
, iface
))
851 pfctl_print_title("STATES:");
854 print_state(p
, opts
);
860 pfctl_show_status(int dev
, int opts
)
862 struct pf_status status
;
864 if (ioctl(dev
, DIOCGETSTATUS
, &status
)) {
865 warn("DIOCGETSTATUS");
868 if (opts
& PF_OPT_SHOWALL
)
869 pfctl_print_title("INFO:");
870 print_status(&status
, opts
);
875 pfctl_show_timeouts(int dev
, int opts
)
880 if (opts
& PF_OPT_SHOWALL
)
881 pfctl_print_title("TIMEOUTS:");
882 memset(&pt
, 0, sizeof(pt
));
883 for (i
= 0; pf_timeouts
[i
].name
; i
++) {
884 pt
.timeout
= pf_timeouts
[i
].timeout
;
885 if (ioctl(dev
, DIOCGETTIMEOUT
, &pt
))
886 err(1, "DIOCGETTIMEOUT");
887 printf("%-20s %10d", pf_timeouts
[i
].name
, pt
.seconds
);
888 if (i
>= PFTM_ADAPTIVE_START
&& i
<= PFTM_ADAPTIVE_END
)
899 pfctl_show_limits(int dev
, int opts
)
901 struct pfioc_limit pl
;
904 if (opts
& PF_OPT_SHOWALL
)
905 pfctl_print_title("LIMITS:");
906 memset(&pl
, 0, sizeof(pl
));
907 for (i
= 0; pf_limits
[i
].name
; i
++) {
908 pl
.index
= pf_limits
[i
].index
;
909 if (ioctl(dev
, DIOCGETLIMIT
, &pl
))
910 err(1, "DIOCGETLIMIT");
911 printf("%-10s ", pf_limits
[i
].name
);
912 if (pl
.limit
== UINT_MAX
)
913 printf("unlimited\n");
915 printf("hard limit %6u\n", pl
.limit
);
920 /* callbacks for rule/nat/rdr/addr */
922 pfctl_add_pool(struct pfctl
*pf
, struct pf_pool
*p
, sa_family_t af
)
924 struct pf_pooladdr
*pa
;
926 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
927 if (ioctl(pf
->dev
, DIOCBEGINADDRS
, &pf
->paddr
))
928 err(1, "DIOCBEGINADDRS");
932 TAILQ_FOREACH(pa
, &p
->list
, entries
) {
933 memcpy(&pf
->paddr
.addr
, pa
, sizeof(struct pf_pooladdr
));
934 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
935 if (ioctl(pf
->dev
, DIOCADDADDR
, &pf
->paddr
))
936 err(1, "DIOCADDADDR");
943 pfctl_add_rule(struct pfctl
*pf
, struct pf_rule
*r
)
946 struct pfioc_rule pr
;
950 if ((loadopt
& PFCTL_FLAG_FILTER
) == 0)
952 rs_num
= PF_RULESET_SCRUB
;
956 if ((loadopt
& PFCTL_FLAG_FILTER
) == 0)
958 rs_num
= PF_RULESET_FILTER
;
962 if ((loadopt
& PFCTL_FLAG_NAT
) == 0)
964 rs_num
= PF_RULESET_NAT
;
968 if ((loadopt
& PFCTL_FLAG_NAT
) == 0)
970 rs_num
= PF_RULESET_RDR
;
974 if ((loadopt
& PFCTL_FLAG_NAT
) == 0)
976 rs_num
= PF_RULESET_BINAT
;
979 errx(1, "Invalid rule type");
983 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
984 bzero(&pr
, sizeof(pr
));
985 if (strlcpy(pr
.anchor
, pf
->anchor
, sizeof(pr
.anchor
)) >=
987 strlcpy(pr
.ruleset
, pf
->ruleset
, sizeof(pr
.ruleset
)) >=
989 errx(1, "pfctl_add_rule: strlcpy");
990 if (pfctl_add_pool(pf
, &r
->rpool
, r
->af
))
992 pr
.ticket
= pfctl_get_ticket(pf
->trans
, rs_num
, pf
->anchor
,
994 pr
.pool_ticket
= pf
->paddr
.ticket
;
995 memcpy(&pr
.rule
, r
, sizeof(pr
.rule
));
996 if (ioctl(pf
->dev
, DIOCADDRULE
, &pr
))
997 err(1, "DIOCADDRULE");
999 if (pf
->opts
& PF_OPT_VERBOSE
)
1000 print_rule(r
, pf
->opts
& PF_OPT_VERBOSE2
);
1001 pfctl_clear_pool(&r
->rpool
);
1006 pfctl_add_altq(struct pfctl
*pf
, struct pf_altq
*a
)
1009 (loadopt
& PFCTL_FLAG_ALTQ
) != 0) {
1010 memcpy(&pf
->paltq
->altq
, a
, sizeof(struct pf_altq
));
1011 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1012 if (ioctl(pf
->dev
, DIOCADDALTQ
, pf
->paltq
)) {
1014 errx(1, "qtype not configured");
1015 else if (errno
== ENODEV
)
1016 errx(1, "%s: driver does not support "
1019 err(1, "DIOCADDALTQ");
1022 pfaltq_store(&pf
->paltq
->altq
);
1028 pfctl_rules(int dev
, char *filename
, int opts
, char *anchorname
,
1029 char *rulesetname
, struct pfr_buffer
*trans
)
1031 #define ERR(x) do { warn(x); goto _error; } while(0)
1032 #define ERRX(x) do { warnx(x); goto _error; } while(0)
1035 struct pfr_buffer
*t
, buf
;
1036 struct pfioc_altq pa
;
1038 struct pfr_table trs
;
1041 if (trans
== NULL
) {
1042 bzero(&buf
, sizeof(buf
));
1043 buf
.pfrb_type
= PFRB_TRANS
;
1048 osize
= t
->pfrb_size
;
1051 memset(&pa
, 0, sizeof(pa
));
1052 memset(&pf
, 0, sizeof(pf
));
1053 memset(&trs
, 0, sizeof(trs
));
1054 if (strlcpy(trs
.pfrt_anchor
, anchorname
,
1055 sizeof(trs
.pfrt_anchor
)) >= sizeof(trs
.pfrt_anchor
) ||
1056 strlcpy(trs
.pfrt_ruleset
, rulesetname
,
1057 sizeof(trs
.pfrt_ruleset
)) >= sizeof(trs
.pfrt_ruleset
))
1058 ERRX("pfctl_rules: strlcpy");
1059 if (strcmp(filename
, "-") == 0) {
1063 if ((fin
= fopen(filename
, "r")) == NULL
) {
1064 warn("%s", filename
);
1071 pf
.loadopt
= loadopt
;
1073 pf
.loadopt
&= ~PFCTL_FLAG_ALTQ
;
1077 pf
.anchor
= anchorname
;
1078 pf
.ruleset
= rulesetname
;
1080 if ((opts
& PF_OPT_NOACTION
) == 0) {
1081 if ((pf
.loadopt
& PFCTL_FLAG_NAT
) != 0) {
1082 if (pfctl_add_trans(t
, PF_RULESET_NAT
, anchorname
,
1084 pfctl_add_trans(t
, PF_RULESET_BINAT
, anchorname
,
1086 pfctl_add_trans(t
, PF_RULESET_RDR
, anchorname
,
1090 if (((altqsupport
&& (pf
.loadopt
& PFCTL_FLAG_ALTQ
) != 0))) {
1091 if (pfctl_add_trans(t
, PF_RULESET_ALTQ
, anchorname
,
1095 if ((pf
.loadopt
& PFCTL_FLAG_FILTER
) != 0) {
1096 if (pfctl_add_trans(t
, PF_RULESET_SCRUB
, anchorname
,
1098 pfctl_add_trans(t
, PF_RULESET_FILTER
, anchorname
,
1102 if (pf
.loadopt
& PFCTL_FLAG_TABLE
) {
1103 if (pfctl_add_trans(t
, PF_RULESET_TABLE
, anchorname
,
1107 if (pfctl_trans(dev
, t
, DIOCXBEGIN
, osize
))
1109 if (altqsupport
&& (pf
.loadopt
& PFCTL_FLAG_ALTQ
))
1110 pa
.ticket
= pfctl_get_ticket(t
, PF_RULESET_ALTQ
,
1111 anchorname
, rulesetname
);
1112 if (pf
.loadopt
& PFCTL_FLAG_TABLE
)
1113 pf
.tticket
= pfctl_get_ticket(t
, PF_RULESET_TABLE
,
1114 anchorname
, rulesetname
);
1116 if (parse_rules(fin
, &pf
) < 0) {
1117 if ((opts
& PF_OPT_NOACTION
) == 0)
1118 ERRX("Syntax error in config file: "
1119 "pf rules not loaded");
1123 if ((altqsupport
&& (pf
.loadopt
& PFCTL_FLAG_ALTQ
) != 0))
1124 if (check_commit_altq(dev
, opts
) != 0)
1125 ERRX("errors in altq config");
1129 /* process "load anchor" directives */
1130 if (!anchorname
[0] && !rulesetname
[0])
1131 if (pfctl_load_anchors(dev
, opts
, t
) == -1)
1132 ERRX("load anchors");
1134 if (trans
== NULL
&& (opts
& PF_OPT_NOACTION
) == 0)
1135 if (pfctl_trans(dev
, t
, DIOCXCOMMIT
, 0))
1140 if (trans
== NULL
) { /* main ruleset */
1141 if ((opts
& PF_OPT_NOACTION
) == 0)
1142 if (pfctl_trans(dev
, t
, DIOCXROLLBACK
, 0))
1143 err(1, "DIOCXROLLBACK");
1145 } else /* sub ruleset */
1153 pfctl_set_limit(struct pfctl
*pf
, const char *opt
, unsigned int limit
)
1155 struct pfioc_limit pl
;
1158 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1161 memset(&pl
, 0, sizeof(pl
));
1162 for (i
= 0; pf_limits
[i
].name
; i
++) {
1163 if (strcasecmp(opt
, pf_limits
[i
].name
) == 0) {
1164 pl
.index
= pf_limits
[i
].index
;
1166 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1167 if (ioctl(pf
->dev
, DIOCSETLIMIT
, &pl
)) {
1168 if (errno
== EBUSY
) {
1169 warnx("Current pool "
1170 "size exceeds requested "
1174 err(1, "DIOCSETLIMIT");
1180 if (pf_limits
[i
].name
== NULL
) {
1181 warnx("Bad pool name.");
1185 if (pf
->opts
& PF_OPT_VERBOSE
)
1186 printf("set limit %s %d\n", opt
, limit
);
1192 pfctl_set_timeout(struct pfctl
*pf
, const char *opt
, int seconds
, int quiet
)
1197 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1200 memset(&pt
, 0, sizeof(pt
));
1201 for (i
= 0; pf_timeouts
[i
].name
; i
++) {
1202 if (strcasecmp(opt
, pf_timeouts
[i
].name
) == 0) {
1203 pt
.timeout
= pf_timeouts
[i
].timeout
;
1208 if (pf_timeouts
[i
].name
== NULL
) {
1209 warnx("Bad timeout name.");
1213 pt
.seconds
= seconds
;
1214 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1215 if (ioctl(pf
->dev
, DIOCSETTIMEOUT
, &pt
))
1216 err(1, "DIOCSETTIMEOUT");
1219 if (pf
->opts
& PF_OPT_VERBOSE
&& ! quiet
)
1220 printf("set timeout %s %d\n", opt
, seconds
);
1226 pfctl_set_optimization(struct pfctl
*pf
, const char *opt
)
1228 const struct pf_hint
*hint
;
1231 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1234 for (i
= 0; pf_hints
[i
].name
; i
++)
1235 if (strcasecmp(opt
, pf_hints
[i
].name
) == 0)
1238 hint
= pf_hints
[i
].hint
;
1240 warnx("Bad hint name.");
1244 for (i
= 0; hint
[i
].name
; i
++)
1245 if ((r
= pfctl_set_timeout(pf
, hint
[i
].name
,
1246 hint
[i
].timeout
, 1)))
1249 if (pf
->opts
& PF_OPT_VERBOSE
)
1250 printf("set optimization %s\n", opt
);
1256 pfctl_set_logif(struct pfctl
*pf
, char *ifname
)
1260 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1263 memset(&pi
, 0, sizeof(pi
));
1264 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1265 if (!strcmp(ifname
, "none"))
1266 bzero(pi
.ifname
, sizeof(pi
.ifname
));
1268 if (strlcpy(pi
.ifname
, ifname
,
1269 sizeof(pi
.ifname
)) >= sizeof(pi
.ifname
))
1270 errx(1, "pfctl_set_logif: strlcpy");
1272 if (ioctl(pf
->dev
, DIOCSETSTATUSIF
, &pi
))
1273 err(1, "DIOCSETSTATUSIF");
1276 if (pf
->opts
& PF_OPT_VERBOSE
)
1277 printf("set loginterface %s\n", ifname
);
1283 pfctl_set_hostid(struct pfctl
*pf
, u_int32_t hostid
)
1285 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1288 hostid
= htonl(hostid
);
1290 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1291 if (ioctl(dev_fd
, DIOCSETHOSTID
, &hostid
))
1292 err(1, "DIOCSETHOSTID");
1295 if (pf
->opts
& PF_OPT_VERBOSE
)
1296 printf("set hostid 0x%08x\n", ntohl(hostid
));
1302 pfctl_set_debug(struct pfctl
*pf
, char *d
)
1306 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1309 if (!strcmp(d
, "none"))
1310 level
= PF_DEBUG_NONE
;
1311 else if (!strcmp(d
, "urgent"))
1312 level
= PF_DEBUG_URGENT
;
1313 else if (!strcmp(d
, "misc"))
1314 level
= PF_DEBUG_MISC
;
1315 else if (!strcmp(d
, "loud"))
1316 level
= PF_DEBUG_NOISY
;
1318 warnx("unknown debug level \"%s\"", d
);
1322 if ((pf
->opts
& PF_OPT_NOACTION
) == 0)
1323 if (ioctl(dev_fd
, DIOCSETDEBUG
, &level
))
1324 err(1, "DIOCSETDEBUG");
1326 if (pf
->opts
& PF_OPT_VERBOSE
)
1327 printf("set debug %s\n", d
);
1333 pfctl_debug(int dev
, u_int32_t level
, int opts
)
1335 if (ioctl(dev
, DIOCSETDEBUG
, &level
))
1336 err(1, "DIOCSETDEBUG");
1337 if ((opts
& PF_OPT_QUIET
) == 0) {
1338 fprintf(stderr
, "debug level set to '");
1341 fprintf(stderr
, "none");
1343 case PF_DEBUG_URGENT
:
1344 fprintf(stderr
, "urgent");
1347 fprintf(stderr
, "misc");
1349 case PF_DEBUG_NOISY
:
1350 fprintf(stderr
, "loud");
1353 fprintf(stderr
, "<invalid>");
1356 fprintf(stderr
, "'\n");
1362 pfctl_clear_rule_counters(int dev
, int opts
)
1364 if (ioctl(dev
, DIOCCLRRULECTRS
))
1365 err(1, "DIOCCLRRULECTRS");
1366 if ((opts
& PF_OPT_QUIET
) == 0)
1367 fprintf(stderr
, "pf: rule counters cleared\n");
1372 pfctl_test_altqsupport(int dev
, int opts
)
1374 struct pfioc_altq pa
;
1376 if (ioctl(dev
, DIOCGETALTQS
, &pa
)) {
1377 if (errno
== ENODEV
) {
1378 if (!(opts
& PF_OPT_QUIET
))
1379 fprintf(stderr
, "No ALTQ support in kernel\n"
1380 "ALTQ related functions disabled\n");
1383 err(1, "DIOCGETALTQS");
1389 pfctl_show_anchors(int dev
, int opts
, char *anchorname
)
1394 struct pfioc_anchor pa
;
1396 memset(&pa
, 0, sizeof(pa
));
1397 if (ioctl(dev
, DIOCGETANCHORS
, &pa
)) {
1398 warn("DIOCGETANCHORS");
1402 for (nr
= 0; nr
< mnr
; ++nr
) {
1404 if (ioctl(dev
, DIOCGETANCHOR
, &pa
)) {
1405 warn("DIOCGETANCHOR");
1408 if (!(opts
& PF_OPT_VERBOSE
) &&
1409 !strcmp(pa
.name
, PF_RESERVED_ANCHOR
))
1411 printf(" %s\n", pa
.name
);
1414 struct pfioc_ruleset pr
;
1416 memset(&pr
, 0, sizeof(pr
));
1417 memcpy(pr
.anchor
, anchorname
, sizeof(pr
.anchor
));
1418 if (ioctl(dev
, DIOCGETRULESETS
, &pr
)) {
1419 if (errno
== EINVAL
)
1420 fprintf(stderr
, "No rulesets in anchor '%s'.\n",
1423 err(1, "DIOCGETRULESETS");
1427 for (nr
= 0; nr
< mnr
; ++nr
) {
1429 if (ioctl(dev
, DIOCGETRULESET
, &pr
))
1430 err(1, "DIOCGETRULESET");
1431 printf(" %s:%s\n", pr
.anchor
, pr
.name
);
1438 pfctl_lookup_option(char *cmd
, const char **list
)
1440 if (cmd
!= NULL
&& *cmd
)
1441 for (; *list
; list
++)
1442 if (!strncmp(cmd
, *list
, strlen(cmd
)))
1448 main(int argc
, char *argv
[])
1452 int mode
= O_RDONLY
;
1454 char anchorname
[PF_ANCHOR_NAME_SIZE
];
1455 char rulesetname
[PF_RULESET_NAME_SIZE
];
1460 while ((ch
= getopt(argc
, argv
,
1461 "a:AdD:eqf:F:ghi:k:nNOp:rRs:t:T:vx:z")) != -1) {
1467 opts
|= PF_OPT_DISABLE
;
1471 if (pfctl_cmdline_symset(optarg
) < 0)
1472 warnx("could not parse macro definition %s",
1476 opts
|= PF_OPT_ENABLE
;
1480 opts
|= PF_OPT_QUIET
;
1483 clearopt
= pfctl_lookup_option(optarg
, clearopt_list
);
1484 if (clearopt
== NULL
) {
1485 warnx("Unknown flush modifier '%s'", optarg
);
1494 if (state_killers
>= 2) {
1495 warnx("can only specify -k twice");
1499 state_kill
[state_killers
++] = optarg
;
1503 opts
|= PF_OPT_NOACTION
;
1506 loadopt
|= PFCTL_FLAG_NAT
;
1509 opts
|= PF_OPT_USEDNS
;
1516 opts
|= PF_OPT_DEBUG
;
1519 loadopt
|= PFCTL_FLAG_ALTQ
;
1522 loadopt
|= PFCTL_FLAG_FILTER
;
1525 loadopt
|= PFCTL_FLAG_OPTION
;
1531 showopt
= pfctl_lookup_option(optarg
, showopt_list
);
1532 if (showopt
== NULL
) {
1533 warnx("Unknown show modifier '%s'", optarg
);
1541 tblcmdopt
= pfctl_lookup_option(optarg
, tblcmdopt_list
);
1542 if (tblcmdopt
== NULL
) {
1543 warnx("Unknown table command '%s'", optarg
);
1548 if (opts
& PF_OPT_VERBOSE
)
1549 opts
|= PF_OPT_VERBOSE2
;
1550 opts
|= PF_OPT_VERBOSE
;
1553 debugopt
= pfctl_lookup_option(optarg
, debugopt_list
);
1554 if (debugopt
== NULL
) {
1555 warnx("Unknown debug level '%s'", optarg
);
1561 opts
|= PF_OPT_CLRRULECTRS
;
1572 if (tblcmdopt
!= NULL
) {
1577 loadopt
|= PFCTL_FLAG_TABLE
;
1580 mode
= strchr("acdfkrz", ch
) ? O_RDWR
: O_RDONLY
;
1581 } else if (argc
!= optind
) {
1582 warnx("unknown command line argument: %s ...", argv
[optind
]);
1589 memset(anchorname
, 0, sizeof(anchorname
));
1590 memset(rulesetname
, 0, sizeof(rulesetname
));
1591 if (anchoropt
!= NULL
) {
1594 if ((t
= strchr(anchoropt
, ':')) == NULL
) {
1595 if (strlcpy(anchorname
, anchoropt
,
1596 sizeof(anchorname
)) >= sizeof(anchorname
))
1597 errx(1, "anchor name '%s' too long",
1602 if ((p
= strdup(anchoropt
)) == NULL
)
1603 err(1, "anchoropt: strdup");
1604 t
= strsep(&p
, ":");
1605 if (*t
== '\0' || *p
== '\0')
1606 errx(1, "anchor '%s' invalid", anchoropt
);
1607 if (strlcpy(anchorname
, t
, sizeof(anchorname
)) >=
1609 errx(1, "anchor name '%s' too long", t
);
1610 if (strlcpy(rulesetname
, p
, sizeof(rulesetname
)) >=
1611 sizeof(rulesetname
))
1612 errx(1, "ruleset name '%s' too long", p
);
1613 free(t
); /* not p */
1615 loadopt
&= PFCTL_FLAG_FILTER
|PFCTL_FLAG_NAT
|PFCTL_FLAG_TABLE
;
1618 if ((opts
& PF_OPT_NOACTION
) == 0) {
1619 dev_fd
= open(pf_device
, mode
);
1621 err(1, "%s", pf_device
);
1622 altqsupport
= pfctl_test_altqsupport(dev_fd
, opts
);
1624 dev_fd
= open(pf_device
, O_RDONLY
);
1626 opts
|= PF_OPT_DUMMYACTION
;
1627 /* turn off options */
1628 opts
&= ~ (PF_OPT_DISABLE
| PF_OPT_ENABLE
);
1629 clearopt
= showopt
= debugopt
= NULL
;
1633 if (opts
& PF_OPT_DISABLE
)
1634 if (pfctl_disable(dev_fd
, opts
))
1637 if (showopt
!= NULL
) {
1640 pfctl_show_anchors(dev_fd
, opts
, anchorname
);
1643 pfctl_load_fingerprints(dev_fd
, opts
);
1644 pfctl_show_rules(dev_fd
, opts
, 0, anchorname
,
1648 pfctl_load_fingerprints(dev_fd
, opts
);
1649 pfctl_show_rules(dev_fd
, opts
, 1, anchorname
,
1653 pfctl_load_fingerprints(dev_fd
, opts
);
1654 pfctl_show_nat(dev_fd
, opts
, anchorname
, rulesetname
);
1657 pfctl_show_altq(dev_fd
, ifaceopt
, opts
,
1658 opts
& PF_OPT_VERBOSE2
);
1661 pfctl_show_states(dev_fd
, ifaceopt
, opts
);
1664 pfctl_show_src_nodes(dev_fd
, opts
);
1667 pfctl_show_status(dev_fd
, opts
);
1670 pfctl_show_timeouts(dev_fd
, opts
);
1673 pfctl_show_limits(dev_fd
, opts
);
1676 opts
|= PF_OPT_SHOWALL
;
1677 pfctl_load_fingerprints(dev_fd
, opts
);
1679 pfctl_show_nat(dev_fd
, opts
, anchorname
, rulesetname
);
1680 pfctl_show_rules(dev_fd
, opts
, 0, anchorname
,
1682 pfctl_show_altq(dev_fd
, ifaceopt
, opts
, 0);
1683 pfctl_show_states(dev_fd
, ifaceopt
, opts
);
1684 pfctl_show_src_nodes(dev_fd
, opts
);
1685 pfctl_show_status(dev_fd
, opts
);
1686 pfctl_show_rules(dev_fd
, opts
, 1, anchorname
, rulesetname
);
1687 pfctl_show_timeouts(dev_fd
, opts
);
1688 pfctl_show_limits(dev_fd
, opts
);
1689 pfctl_show_tables(anchorname
, rulesetname
, opts
);
1690 pfctl_show_fingerprints(opts
);
1693 pfctl_show_tables(anchorname
, rulesetname
, opts
);
1696 pfctl_load_fingerprints(dev_fd
, opts
);
1697 pfctl_show_fingerprints(opts
);
1700 pfctl_show_ifaces(ifaceopt
, opts
);
1705 if (clearopt
!= NULL
) {
1706 switch (*clearopt
) {
1708 pfctl_clear_rules(dev_fd
, opts
, anchorname
, rulesetname
);
1711 pfctl_clear_nat(dev_fd
, opts
, anchorname
, rulesetname
);
1714 pfctl_clear_altq(dev_fd
, opts
);
1717 pfctl_clear_states(dev_fd
, ifaceopt
, opts
);
1720 pfctl_clear_src_nodes(dev_fd
, opts
);
1723 pfctl_clear_stats(dev_fd
, opts
);
1726 pfctl_clear_rules(dev_fd
, opts
, anchorname
, rulesetname
);
1727 pfctl_clear_nat(dev_fd
, opts
, anchorname
, rulesetname
);
1728 pfctl_clear_tables(anchorname
, rulesetname
, opts
);
1729 if (!*anchorname
&& !*rulesetname
) {
1730 pfctl_clear_altq(dev_fd
, opts
);
1731 pfctl_clear_states(dev_fd
, ifaceopt
, opts
);
1732 pfctl_clear_src_nodes(dev_fd
, opts
);
1733 pfctl_clear_stats(dev_fd
, opts
);
1734 pfctl_clear_fingerprints(dev_fd
, opts
);
1738 pfctl_clear_fingerprints(dev_fd
, opts
);
1741 pfctl_clear_tables(anchorname
, rulesetname
, opts
);
1746 pfctl_kill_states(dev_fd
, ifaceopt
, opts
);
1748 if (tblcmdopt
!= NULL
) {
1749 error
= pfctl_command_tables(argc
, argv
, tableopt
,
1750 tblcmdopt
, rulesopt
, anchorname
, rulesetname
, opts
);
1754 if (rulesopt
!= NULL
)
1755 if (pfctl_file_fingerprints(dev_fd
, opts
, PF_OSFP_FILE
))
1758 if (rulesopt
!= NULL
) {
1759 if (pfctl_rules(dev_fd
, rulesopt
, opts
, anchorname
, rulesetname
,
1762 else if (!(opts
& PF_OPT_NOACTION
) &&
1763 (loadopt
& PFCTL_FLAG_TABLE
))
1764 warn_namespace_collision(NULL
);
1767 if (opts
& PF_OPT_ENABLE
)
1768 if (pfctl_enable(dev_fd
, opts
))
1771 if (debugopt
!= NULL
) {
1772 switch (*debugopt
) {
1774 pfctl_debug(dev_fd
, PF_DEBUG_NONE
, opts
);
1777 pfctl_debug(dev_fd
, PF_DEBUG_URGENT
, opts
);
1780 pfctl_debug(dev_fd
, PF_DEBUG_MISC
, opts
);
1783 pfctl_debug(dev_fd
, PF_DEBUG_NOISY
, opts
);
1788 if (opts
& PF_OPT_CLRRULECTRS
) {
1789 if (pfctl_clear_rule_counters(dev_fd
, opts
))