2 /* $OpenBSD: pfctl.c,v 1.268 2007/06/30 18:25:08 henning 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>
41 #include <netinet/in.h>
42 #include <net/pfvar.h>
43 #include <arpa/inet.h>
44 #include <altq/altq.h>
45 #include <sys/sysctl.h>
57 #include "pfctl_parser.h"
61 int pfctl_enable(int, int);
62 int pfctl_disable(int, int);
63 int pfctl_clear_stats(int, int);
64 int pfctl_clear_interface_flags(int, int);
65 int pfctl_clear_rules(int, int, char *);
66 int pfctl_clear_nat(int, int, char *);
67 int pfctl_clear_altq(int, int);
68 int pfctl_clear_src_nodes(int, int);
69 int pfctl_clear_states(int, const char *, int);
70 void pfctl_addrprefix(char *, struct pf_addr
*);
71 int pfctl_kill_src_nodes(int, const char *, int);
72 int pfctl_kill_states(int, const char *, int);
73 void pfctl_init_options(struct pfctl
*);
74 int pfctl_load_options(struct pfctl
*);
75 int pfctl_load_limit(struct pfctl
*, unsigned int, unsigned int);
76 int pfctl_load_timeout(struct pfctl
*, unsigned int, unsigned int);
77 int pfctl_load_debug(struct pfctl
*, unsigned int);
78 int pfctl_load_logif(struct pfctl
*, char *);
79 int pfctl_load_hostid(struct pfctl
*, unsigned int);
80 int pfctl_get_pool(int, struct pf_pool
*, u_int32_t
, u_int32_t
, int,
82 void pfctl_print_rule_counters(struct pf_rule
*, int);
83 int pfctl_show_rules(int, char *, int, enum pfctl_show
, char *, int);
84 int pfctl_show_nat(int, int, char *);
85 int pfctl_show_src_nodes(int, int);
86 int pfctl_show_states(int, const char *, int);
87 int pfctl_show_status(int, int);
88 int pfctl_show_timeouts(int, int);
89 int pfctl_show_limits(int, int);
90 void pfctl_debug(int, u_int32_t
, int);
91 int pfctl_test_altqsupport(int, int);
92 int pfctl_show_anchors(int, int, char *);
93 int pfctl_ruleset_trans(struct pfctl
*, char *, struct pf_anchor
*);
94 int pfctl_load_ruleset(struct pfctl
*, char *,
95 struct pf_ruleset
*, int, int);
96 int pfctl_load_rule(struct pfctl
*, char *, struct pf_rule
*, int);
97 const char *pfctl_lookup_option(char *, const char **);
99 struct pf_anchor_global pf_anchors
;
100 struct pf_anchor pf_main_anchor
;
102 const char *clearopt
;
105 const char *debugopt
;
107 const char *optiopt
= NULL
;
108 char *pf_device
= "/dev/pf";
111 const char *tblcmdopt
;
112 int src_node_killers
;
113 char *src_node_kill
[2];
125 #define INDENT(d, o) do { \
128 for (i=0; i < d; i++) \
134 static const struct {
138 { "states", PF_LIMIT_STATES
},
139 { "src-nodes", PF_LIMIT_SRC_NODES
},
140 { "frags", PF_LIMIT_FRAGS
},
141 { "tables", PF_LIMIT_TABLES
},
142 { "table-entries", PF_LIMIT_TABLE_ENTRIES
},
150 static const struct pf_hint pf_hint_normal
[] = {
151 { "tcp.first", 2 * 60 },
152 { "tcp.opening", 30 },
153 { "tcp.established", 24 * 60 * 60 },
154 { "tcp.closing", 15 * 60 },
155 { "tcp.finwait", 45 },
156 { "tcp.closed", 90 },
157 { "tcp.tsdiff", 30 },
160 static const struct pf_hint pf_hint_satellite
[] = {
161 { "tcp.first", 3 * 60 },
162 { "tcp.opening", 30 + 5 },
163 { "tcp.established", 24 * 60 * 60 },
164 { "tcp.closing", 15 * 60 + 5 },
165 { "tcp.finwait", 45 + 5 },
166 { "tcp.closed", 90 + 5 },
167 { "tcp.tsdiff", 60 },
170 static const struct pf_hint pf_hint_conservative
[] = {
171 { "tcp.first", 60 * 60 },
172 { "tcp.opening", 15 * 60 },
173 { "tcp.established", 5 * 24 * 60 * 60 },
174 { "tcp.closing", 60 * 60 },
175 { "tcp.finwait", 10 * 60 },
176 { "tcp.closed", 3 * 60 },
177 { "tcp.tsdiff", 60 },
180 static const struct pf_hint pf_hint_aggressive
[] = {
182 { "tcp.opening", 5 },
183 { "tcp.established", 5 * 60 * 60 },
184 { "tcp.closing", 60 },
185 { "tcp.finwait", 30 },
186 { "tcp.closed", 30 },
187 { "tcp.tsdiff", 10 },
191 static const struct {
193 const struct pf_hint
*hint
;
195 { "normal", pf_hint_normal
},
196 { "satellite", pf_hint_satellite
},
197 { "high-latency", pf_hint_satellite
},
198 { "conservative", pf_hint_conservative
},
199 { "aggressive", pf_hint_aggressive
},
203 static const char *clearopt_list
[] = {
204 "nat", "queue", "rules", "Sources",
205 "states", "info", "Tables", "osfp", "all", NULL
208 static const char *showopt_list
[] = {
209 "nat", "queue", "rules", "Anchors", "Sources", "states", "info",
210 "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
214 static const char *tblcmdopt_list
[] = {
215 "kill", "flush", "add", "delete", "load", "replace", "show",
216 "test", "zero", "expire", NULL
219 static const char *debugopt_list
[] = {
220 "none", "urgent", "misc", "loud", NULL
223 static const char *optiopt_list
[] = {
224 "none", "basic", "profile", NULL
230 extern char *__progname
;
232 fprintf(stderr
, "usage: %s [-AdeghmNnOqRrvz] ", __progname
);
233 fprintf(stderr
, "[-a anchor] [-D macro=value] [-F modifier]\n");
234 fprintf(stderr
, "\t[-f file] [-i interface] [-K host | network] ");
235 fprintf(stderr
, "[-k host | network]\n");
236 fprintf(stderr
, "\t[-o level] [-p device] [-s modifier]\n");
237 fprintf(stderr
, "\t[-t table -T command [address ...]] [-x level]\n");
242 pfctl_enable(int dev
, int opts
)
244 if (ioctl(dev
, DIOCSTART
)) {
246 errx(1, "pf already enabled");
250 if ((opts
& PF_OPT_QUIET
) == 0)
251 fprintf(stderr
, "pf enabled\n");
253 if (altqsupport
&& ioctl(dev
, DIOCSTARTALTQ
))
255 err(1, "DIOCSTARTALTQ");
261 pfctl_disable(int dev
, int opts
)
263 if (ioctl(dev
, DIOCSTOP
)) {
265 errx(1, "pf not enabled");
269 if ((opts
& PF_OPT_QUIET
) == 0)
270 fprintf(stderr
, "pf disabled\n");
272 if (altqsupport
&& ioctl(dev
, DIOCSTOPALTQ
))
274 err(1, "DIOCSTOPALTQ");
280 pfctl_clear_stats(int dev
, int opts
)
282 if (ioctl(dev
, DIOCCLRSTATUS
))
283 err(1, "DIOCCLRSTATUS");
284 if ((opts
& PF_OPT_QUIET
) == 0)
285 fprintf(stderr
, "pf: statistics cleared\n");
290 pfctl_clear_interface_flags(int dev
, int opts
)
292 struct pfioc_iface pi
;
294 if ((opts
& PF_OPT_NOACTION
) == 0) {
295 bzero(&pi
, sizeof(pi
));
296 pi
.pfiio_flags
= PFI_IFLAG_SKIP
;
298 if (ioctl(dev
, DIOCCLRIFFLAG
, &pi
))
299 err(1, "DIOCCLRIFFLAG");
300 if ((opts
& PF_OPT_QUIET
) == 0)
301 fprintf(stderr
, "pf: interface flags reset\n");
307 pfctl_clear_rules(int dev
, int opts
, char *anchorname
)
311 memset(&t
, 0, sizeof(t
));
312 t
.pfrb_type
= PFRB_TRANS
;
313 if (pfctl_add_trans(&t
, PF_RULESET_SCRUB
, anchorname
) ||
314 pfctl_add_trans(&t
, PF_RULESET_FILTER
, anchorname
) ||
315 pfctl_trans(dev
, &t
, DIOCXBEGIN
, 0) ||
316 pfctl_trans(dev
, &t
, DIOCXCOMMIT
, 0))
317 err(1, "pfctl_clear_rules");
318 if ((opts
& PF_OPT_QUIET
) == 0)
319 fprintf(stderr
, "rules cleared\n");
324 pfctl_clear_nat(int dev
, int opts
, char *anchorname
)
328 memset(&t
, 0, sizeof(t
));
329 t
.pfrb_type
= PFRB_TRANS
;
330 if (pfctl_add_trans(&t
, PF_RULESET_NAT
, anchorname
) ||
331 pfctl_add_trans(&t
, PF_RULESET_BINAT
, anchorname
) ||
332 pfctl_add_trans(&t
, PF_RULESET_RDR
, anchorname
) ||
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_addrprefix(char *addr
, struct pf_addr
*mask
)
390 const char *errstr
= NULL
; /* XXX gcc */
391 int prefix
, ret_ga
, q
, r
;
392 struct addrinfo hints
, *res
;
394 if ((p
= strchr(addr
, '/')) == NULL
)
398 prefix
= strtonum(p
, 0, 128, &errstr
);
400 errx(1, "prefix is %s: %s", errstr
, p
);
402 bzero(&hints
, sizeof(hints
));
403 /* prefix only with numeric addresses */
404 hints
.ai_flags
|= AI_NUMERICHOST
;
406 if ((ret_ga
= getaddrinfo(addr
, NULL
, &hints
, &res
))) {
407 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga
));
411 if (res
->ai_family
== AF_INET
&& prefix
> 32)
412 errx(1, "prefix too long for AF_INET");
413 else if (res
->ai_family
== AF_INET6
&& prefix
> 128)
414 errx(1, "prefix too long for AF_INET6");
418 switch (res
->ai_family
) {
420 bzero(&mask
->v4
, sizeof(mask
->v4
));
421 mask
->v4
.s_addr
= htonl((u_int32_t
)
422 (0xffffffffffULL
<< (32 - prefix
)));
425 bzero(&mask
->v6
, sizeof(mask
->v6
));
427 memset((void *)&mask
->v6
, 0xff, q
);
429 *((u_char
*)&mask
->v6
+ q
) =
430 (0xff00 >> r
) & 0xff;
437 pfctl_kill_src_nodes(int dev
, const char *iface
, int opts
)
439 struct pfioc_src_node_kill psnk
;
440 struct addrinfo
*res
[2], *resp
[2];
441 struct sockaddr last_src
, last_dst
;
442 int killed
, sources
, dests
;
445 killed
= sources
= dests
= 0;
447 memset(&psnk
, 0, sizeof(psnk
));
448 memset(&psnk
.psnk_src
.addr
.v
.a
.mask
, 0xff,
449 sizeof(psnk
.psnk_src
.addr
.v
.a
.mask
));
450 memset(&last_src
, 0xff, sizeof(last_src
));
451 memset(&last_dst
, 0xff, sizeof(last_dst
));
453 pfctl_addrprefix(src_node_kill
[0], &psnk
.psnk_src
.addr
.v
.a
.mask
);
455 if ((ret_ga
= getaddrinfo(src_node_kill
[0], NULL
, NULL
, &res
[0]))) {
456 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga
));
459 for (resp
[0] = res
[0]; resp
[0]; resp
[0] = resp
[0]->ai_next
) {
460 if (resp
[0]->ai_addr
== NULL
)
462 /* We get lots of duplicates. Catch the easy ones */
463 if (memcmp(&last_src
, resp
[0]->ai_addr
, sizeof(last_src
)) == 0)
465 last_src
= *(struct sockaddr
*)resp
[0]->ai_addr
;
467 psnk
.psnk_af
= resp
[0]->ai_family
;
470 if (psnk
.psnk_af
== AF_INET
)
471 psnk
.psnk_src
.addr
.v
.a
.addr
.v4
=
472 ((struct sockaddr_in
*)resp
[0]->ai_addr
)->sin_addr
;
473 else if (psnk
.psnk_af
== AF_INET6
)
474 psnk
.psnk_src
.addr
.v
.a
.addr
.v6
=
475 ((struct sockaddr_in6
*)resp
[0]->ai_addr
)->
478 errx(1, "Unknown address family %d", psnk
.psnk_af
);
480 if (src_node_killers
> 1) {
482 memset(&psnk
.psnk_dst
.addr
.v
.a
.mask
, 0xff,
483 sizeof(psnk
.psnk_dst
.addr
.v
.a
.mask
));
484 memset(&last_dst
, 0xff, sizeof(last_dst
));
485 pfctl_addrprefix(src_node_kill
[1],
486 &psnk
.psnk_dst
.addr
.v
.a
.mask
);
487 if ((ret_ga
= getaddrinfo(src_node_kill
[1], NULL
, NULL
,
489 errx(1, "getaddrinfo: %s",
490 gai_strerror(ret_ga
));
493 for (resp
[1] = res
[1]; resp
[1];
494 resp
[1] = resp
[1]->ai_next
) {
495 if (resp
[1]->ai_addr
== NULL
)
497 if (psnk
.psnk_af
!= resp
[1]->ai_family
)
500 if (memcmp(&last_dst
, resp
[1]->ai_addr
,
501 sizeof(last_dst
)) == 0)
503 last_dst
= *(struct sockaddr
*)resp
[1]->ai_addr
;
507 if (psnk
.psnk_af
== AF_INET
)
508 psnk
.psnk_dst
.addr
.v
.a
.addr
.v4
=
509 ((struct sockaddr_in
*)resp
[1]->
511 else if (psnk
.psnk_af
== AF_INET6
)
512 psnk
.psnk_dst
.addr
.v
.a
.addr
.v6
=
513 ((struct sockaddr_in6
*)resp
[1]->
516 errx(1, "Unknown address family %d",
519 if (ioctl(dev
, DIOCKILLSRCNODES
, &psnk
))
520 err(1, "DIOCKILLSRCNODES");
521 killed
+= psnk
.psnk_af
;
522 /* fixup psnk.psnk_af */
523 psnk
.psnk_af
= resp
[1]->ai_family
;
525 freeaddrinfo(res
[1]);
527 if (ioctl(dev
, DIOCKILLSRCNODES
, &psnk
))
528 err(1, "DIOCKILLSRCNODES");
529 killed
+= psnk
.psnk_af
;
530 /* fixup psnk.psnk_af */
531 psnk
.psnk_af
= res
[0]->ai_family
;
535 freeaddrinfo(res
[0]);
537 if ((opts
& PF_OPT_QUIET
) == 0)
538 fprintf(stderr
, "killed %d src nodes from %d sources and %d "
539 "destinations\n", killed
, sources
, dests
);
544 pfctl_kill_states(int dev
, const char *iface
, int opts
)
546 struct pfioc_state_kill psk
;
547 struct addrinfo
*res
[2], *resp
[2];
548 struct sockaddr last_src
, last_dst
;
549 int killed
, sources
, dests
;
552 killed
= sources
= dests
= 0;
554 memset(&psk
, 0, sizeof(psk
));
555 memset(&psk
.psk_src
.addr
.v
.a
.mask
, 0xff,
556 sizeof(psk
.psk_src
.addr
.v
.a
.mask
));
557 memset(&last_src
, 0xff, sizeof(last_src
));
558 memset(&last_dst
, 0xff, sizeof(last_dst
));
559 if (iface
!= NULL
&& strlcpy(psk
.psk_ifname
, iface
,
560 sizeof(psk
.psk_ifname
)) >= sizeof(psk
.psk_ifname
))
561 errx(1, "invalid interface: %s", iface
);
563 pfctl_addrprefix(state_kill
[0], &psk
.psk_src
.addr
.v
.a
.mask
);
565 if ((ret_ga
= getaddrinfo(state_kill
[0], NULL
, NULL
, &res
[0]))) {
566 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga
));
569 for (resp
[0] = res
[0]; resp
[0]; resp
[0] = resp
[0]->ai_next
) {
570 if (resp
[0]->ai_addr
== NULL
)
572 /* We get lots of duplicates. Catch the easy ones */
573 if (memcmp(&last_src
, resp
[0]->ai_addr
, sizeof(last_src
)) == 0)
575 last_src
= *(struct sockaddr
*)resp
[0]->ai_addr
;
577 psk
.psk_af
= resp
[0]->ai_family
;
580 if (psk
.psk_af
== AF_INET
)
581 psk
.psk_src
.addr
.v
.a
.addr
.v4
=
582 ((struct sockaddr_in
*)resp
[0]->ai_addr
)->sin_addr
;
583 else if (psk
.psk_af
== AF_INET6
)
584 psk
.psk_src
.addr
.v
.a
.addr
.v6
=
585 ((struct sockaddr_in6
*)resp
[0]->ai_addr
)->
588 errx(1, "Unknown address family %d", psk
.psk_af
);
590 if (state_killers
> 1) {
592 memset(&psk
.psk_dst
.addr
.v
.a
.mask
, 0xff,
593 sizeof(psk
.psk_dst
.addr
.v
.a
.mask
));
594 memset(&last_dst
, 0xff, sizeof(last_dst
));
595 pfctl_addrprefix(state_kill
[1],
596 &psk
.psk_dst
.addr
.v
.a
.mask
);
597 if ((ret_ga
= getaddrinfo(state_kill
[1], NULL
, NULL
,
599 errx(1, "getaddrinfo: %s",
600 gai_strerror(ret_ga
));
603 for (resp
[1] = res
[1]; resp
[1];
604 resp
[1] = resp
[1]->ai_next
) {
605 if (resp
[1]->ai_addr
== NULL
)
607 if (psk
.psk_af
!= resp
[1]->ai_family
)
610 if (memcmp(&last_dst
, resp
[1]->ai_addr
,
611 sizeof(last_dst
)) == 0)
613 last_dst
= *(struct sockaddr
*)resp
[1]->ai_addr
;
617 if (psk
.psk_af
== AF_INET
)
618 psk
.psk_dst
.addr
.v
.a
.addr
.v4
=
619 ((struct sockaddr_in
*)resp
[1]->
621 else if (psk
.psk_af
== AF_INET6
)
622 psk
.psk_dst
.addr
.v
.a
.addr
.v6
=
623 ((struct sockaddr_in6
*)resp
[1]->
626 errx(1, "Unknown address family %d",
629 if (ioctl(dev
, DIOCKILLSTATES
, &psk
))
630 err(1, "DIOCKILLSTATES");
631 killed
+= psk
.psk_af
;
632 /* fixup psk.psk_af */
633 psk
.psk_af
= resp
[1]->ai_family
;
635 freeaddrinfo(res
[1]);
637 if (ioctl(dev
, DIOCKILLSTATES
, &psk
))
638 err(1, "DIOCKILLSTATES");
639 killed
+= psk
.psk_af
;
640 /* fixup psk.psk_af */
641 psk
.psk_af
= res
[0]->ai_family
;
645 freeaddrinfo(res
[0]);
647 if ((opts
& PF_OPT_QUIET
) == 0)
648 fprintf(stderr
, "killed %d states from %d sources and %d "
649 "destinations\n", killed
, sources
, dests
);
654 pfctl_get_pool(int dev
, struct pf_pool
*pool
, u_int32_t nr
,
655 u_int32_t ticket
, int r_action
, char *anchorname
)
657 struct pfioc_pooladdr pp
;
658 struct pf_pooladdr
*pa
;
661 memset(&pp
, 0, sizeof(pp
));
662 memcpy(pp
.anchor
, anchorname
, sizeof(pp
.anchor
));
663 pp
.r_action
= r_action
;
666 if (ioctl(dev
, DIOCGETADDRS
, &pp
)) {
667 warn("DIOCGETADDRS");
671 TAILQ_INIT(&pool
->list
);
672 for (pnr
= 0; pnr
< mpnr
; ++pnr
) {
674 if (ioctl(dev
, DIOCGETADDR
, &pp
)) {
678 pa
= calloc(1, sizeof(struct pf_pooladdr
));
681 bcopy(&pp
.addr
, pa
, sizeof(struct pf_pooladdr
));
682 TAILQ_INSERT_TAIL(&pool
->list
, pa
, entries
);
689 pfctl_move_pool(struct pf_pool
*src
, struct pf_pool
*dst
)
691 struct pf_pooladdr
*pa
;
693 while ((pa
= TAILQ_FIRST(&src
->list
)) != NULL
) {
694 TAILQ_REMOVE(&src
->list
, pa
, entries
);
695 TAILQ_INSERT_TAIL(&dst
->list
, pa
, entries
);
700 pfctl_clear_pool(struct pf_pool
*pool
)
702 struct pf_pooladdr
*pa
;
704 while ((pa
= TAILQ_FIRST(&pool
->list
)) != NULL
) {
705 TAILQ_REMOVE(&pool
->list
, pa
, entries
);
711 pfctl_print_rule_counters(struct pf_rule
*rule
, int opts
)
713 if (opts
& PF_OPT_DEBUG
) {
714 const char *t
[PF_SKIP_COUNT
] = { "i", "d", "f",
715 "p", "sa", "sp", "da", "dp" };
718 printf(" [ Skip steps: ");
719 for (i
= 0; i
< PF_SKIP_COUNT
; ++i
) {
720 if (rule
->skip
[i
].nr
== rule
->nr
+ 1)
723 if (rule
->skip
[i
].nr
== -1)
726 printf("%u ", rule
->skip
[i
].nr
);
730 printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
731 rule
->qname
, rule
->qid
, rule
->pqname
, rule
->pqid
);
733 if (opts
& PF_OPT_VERBOSE
) {
734 printf(" [ Evaluations: %-8llu Packets: %-8llu "
735 "Bytes: %-10llu States: %-6u]\n",
736 (unsigned long long)rule
->evaluations
,
737 (unsigned long long)(rule
->packets
[0] +
739 (unsigned long long)(rule
->bytes
[0] +
740 rule
->bytes
[1]), rule
->states
);
741 if (!(opts
& PF_OPT_DEBUG
))
742 printf(" [ Inserted: uid %u pid %u ]\n",
743 (unsigned)rule
->cuid
, (unsigned)rule
->cpid
);
748 pfctl_print_title(char *title
)
753 printf("%s\n", title
);
757 pfctl_show_rules(int dev
, char *path
, int opts
, enum pfctl_show format
,
758 char *anchorname
, int depth
)
760 struct pfioc_rule pr
;
761 u_int32_t nr
, mnr
, header
= 0;
762 int rule_numbers
= opts
& (PF_OPT_VERBOSE2
| PF_OPT_DEBUG
);
763 int len
= strlen(path
);
768 snprintf(&path
[len
], MAXPATHLEN
- len
, "/%s", anchorname
);
770 snprintf(&path
[len
], MAXPATHLEN
- len
, "%s", anchorname
);
772 memset(&pr
, 0, sizeof(pr
));
773 memcpy(pr
.anchor
, path
, sizeof(pr
.anchor
));
774 if (opts
& PF_OPT_SHOWALL
) {
775 pr
.rule
.action
= PF_PASS
;
776 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
777 warn("DIOCGETRULES");
782 pr
.rule
.action
= PF_SCRUB
;
783 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
784 warn("DIOCGETRULES");
787 if (opts
& PF_OPT_SHOWALL
) {
788 if (format
== PFCTL_SHOW_RULES
&& (pr
.nr
> 0 || header
))
789 pfctl_print_title("FILTER RULES:");
790 else if (format
== PFCTL_SHOW_LABELS
&& labels
)
791 pfctl_print_title("LABEL COUNTERS:");
794 if (opts
& PF_OPT_CLRRULECTRS
)
795 pr
.action
= PF_GET_CLR_CNTR
;
797 for (nr
= 0; nr
< mnr
; ++nr
) {
799 if (ioctl(dev
, DIOCGETRULE
, &pr
)) {
804 if (pfctl_get_pool(dev
, &pr
.rule
.rpool
,
805 nr
, pr
.ticket
, PF_SCRUB
, path
) != 0)
809 case PFCTL_SHOW_LABELS
:
810 if (pr
.rule
.label
[0]) {
811 printf("%s ", pr
.rule
.label
);
812 printf("%llu %llu %llu %llu %llu %llu %llu\n",
813 (unsigned long long)pr
.rule
.evaluations
,
814 (unsigned long long)(pr
.rule
.packets
[0] +
816 (unsigned long long)(pr
.rule
.bytes
[0] +
818 (unsigned long long)pr
.rule
.packets
[0],
819 (unsigned long long)pr
.rule
.bytes
[0],
820 (unsigned long long)pr
.rule
.packets
[1],
821 (unsigned long long)pr
.rule
.bytes
[1]);
824 case PFCTL_SHOW_RULES
:
825 if (pr
.rule
.label
[0] && (opts
& PF_OPT_SHOWALL
))
827 print_rule(&pr
.rule
, pr
.anchor_call
, rule_numbers
);
829 pfctl_print_rule_counters(&pr
.rule
, opts
);
831 case PFCTL_SHOW_NOTHING
:
834 pfctl_clear_pool(&pr
.rule
.rpool
);
836 pr
.rule
.action
= PF_PASS
;
837 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
838 warn("DIOCGETRULES");
842 for (nr
= 0; nr
< mnr
; ++nr
) {
844 if (ioctl(dev
, DIOCGETRULE
, &pr
)) {
849 if (pfctl_get_pool(dev
, &pr
.rule
.rpool
,
850 nr
, pr
.ticket
, PF_PASS
, path
) != 0)
854 case PFCTL_SHOW_LABELS
:
855 if (pr
.rule
.label
[0]) {
856 printf("%s ", pr
.rule
.label
);
857 printf("%llu %llu %llu %llu %llu %llu %llu\n",
858 (unsigned long long)pr
.rule
.evaluations
,
859 (unsigned long long)(pr
.rule
.packets
[0] +
861 (unsigned long long)(pr
.rule
.bytes
[0] +
863 (unsigned long long)pr
.rule
.packets
[0],
864 (unsigned long long)pr
.rule
.bytes
[0],
865 (unsigned long long)pr
.rule
.packets
[1],
866 (unsigned long long)pr
.rule
.bytes
[1]);
869 case PFCTL_SHOW_RULES
:
871 if (pr
.rule
.label
[0] && (opts
& PF_OPT_SHOWALL
))
873 INDENT(depth
, !(opts
& PF_OPT_VERBOSE
));
874 if (pr
.anchor_call
[0] &&
875 ((((p
= strrchr(pr
.anchor_call
, '_')) != NULL
) &&
876 ((void *)p
== (void *)pr
.anchor_call
||
877 *(--p
) == '/')) || (opts
& PF_OPT_RECURSE
))) {
879 if ((p
= strrchr(pr
.anchor_call
, '/')) !=
883 p
= &pr
.anchor_call
[0];
885 p
= &pr
.anchor_call
[0];
887 print_rule(&pr
.rule
, p
, rule_numbers
);
892 pfctl_print_rule_counters(&pr
.rule
, opts
);
894 pfctl_show_rules(dev
, path
, opts
, format
,
896 INDENT(depth
, !(opts
& PF_OPT_VERBOSE
));
900 case PFCTL_SHOW_NOTHING
:
903 pfctl_clear_pool(&pr
.rule
.rpool
);
914 pfctl_show_nat(int dev
, int opts
, char *anchorname
)
916 struct pfioc_rule pr
;
918 static int nattype
[3] = { PF_NAT
, PF_RDR
, PF_BINAT
};
919 int i
, dotitle
= opts
& PF_OPT_SHOWALL
;
921 memset(&pr
, 0, sizeof(pr
));
922 memcpy(pr
.anchor
, anchorname
, sizeof(pr
.anchor
));
923 for (i
= 0; i
< 3; i
++) {
924 pr
.rule
.action
= nattype
[i
];
925 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
926 warn("DIOCGETRULES");
930 for (nr
= 0; nr
< mnr
; ++nr
) {
932 if (ioctl(dev
, DIOCGETRULE
, &pr
)) {
936 if (pfctl_get_pool(dev
, &pr
.rule
.rpool
, nr
,
937 pr
.ticket
, nattype
[i
], anchorname
) != 0)
940 pfctl_print_title("TRANSLATION RULES:");
943 print_rule(&pr
.rule
, pr
.anchor_call
,
944 opts
& PF_OPT_VERBOSE2
);
946 pfctl_print_rule_counters(&pr
.rule
, opts
);
947 pfctl_clear_pool(&pr
.rule
.rpool
);
954 pfctl_show_src_nodes(int dev
, int opts
)
956 struct pfioc_src_nodes psn
;
957 struct pf_src_node
*p
;
958 char *inbuf
= NULL
, *newinbuf
= NULL
;
962 memset(&psn
, 0, sizeof(psn
));
966 newinbuf
= realloc(inbuf
, len
);
967 if (newinbuf
== NULL
)
969 psn
.psn_buf
= inbuf
= newinbuf
;
971 if (ioctl(dev
, DIOCGETSRCNODES
, &psn
) < 0) {
972 warn("DIOCGETSRCNODES");
976 if (psn
.psn_len
+ sizeof(struct pfioc_src_nodes
) < len
)
978 if (len
== 0 && psn
.psn_len
== 0)
980 if (len
== 0 && psn
.psn_len
!= 0)
982 if (psn
.psn_len
== 0)
983 goto done
; /* no src_nodes */
986 p
= psn
.psn_src_nodes
;
987 if (psn
.psn_len
> 0 && (opts
& PF_OPT_SHOWALL
))
988 pfctl_print_title("SOURCE TRACKING NODES:");
989 for (i
= 0; i
< psn
.psn_len
; i
+= sizeof(*p
)) {
990 print_src_node(p
, opts
);
999 pfctl_show_states(int dev
, const char *iface
, int opts
)
1001 struct pfioc_states ps
;
1002 struct pfsync_state
*p
;
1003 char *inbuf
= NULL
, *newinbuf
= NULL
;
1005 int i
, dotitle
= (opts
& PF_OPT_SHOWALL
);
1007 memset(&ps
, 0, sizeof(ps
));
1011 newinbuf
= realloc(inbuf
, len
);
1012 if (newinbuf
== NULL
)
1014 ps
.ps_buf
= inbuf
= newinbuf
;
1016 if (ioctl(dev
, DIOCGETSTATES
, &ps
) < 0) {
1017 warn("DIOCGETSTATES");
1021 if (ps
.ps_len
+ sizeof(struct pfioc_states
) < len
)
1023 if (len
== 0 && ps
.ps_len
== 0)
1025 if (len
== 0 && ps
.ps_len
!= 0)
1028 goto done
; /* no states */
1032 for (i
= 0; i
< ps
.ps_len
; i
+= sizeof(*p
), p
++) {
1033 if (iface
!= NULL
&& strcmp(p
->ifname
, iface
))
1036 pfctl_print_title("STATES:");
1039 print_state(p
, opts
);
1047 pfctl_show_status(int dev
, int opts
)
1049 struct pf_status status
;
1051 if (ioctl(dev
, DIOCGETSTATUS
, &status
)) {
1052 warn("DIOCGETSTATUS");
1055 if (opts
& PF_OPT_SHOWALL
)
1056 pfctl_print_title("INFO:");
1057 print_status(&status
, opts
);
1062 pfctl_show_timeouts(int dev
, int opts
)
1067 if (opts
& PF_OPT_SHOWALL
)
1068 pfctl_print_title("TIMEOUTS:");
1069 memset(&pt
, 0, sizeof(pt
));
1070 for (i
= 0; pf_timeouts
[i
].name
; i
++) {
1071 pt
.timeout
= pf_timeouts
[i
].timeout
;
1072 if (ioctl(dev
, DIOCGETTIMEOUT
, &pt
))
1073 err(1, "DIOCGETTIMEOUT");
1074 printf("%-20s %10d", pf_timeouts
[i
].name
, pt
.seconds
);
1075 if (pf_timeouts
[i
].timeout
>= PFTM_ADAPTIVE_START
&&
1076 pf_timeouts
[i
].timeout
<= PFTM_ADAPTIVE_END
)
1087 pfctl_show_limits(int dev
, int opts
)
1089 struct pfioc_limit pl
;
1092 if (opts
& PF_OPT_SHOWALL
)
1093 pfctl_print_title("LIMITS:");
1094 memset(&pl
, 0, sizeof(pl
));
1095 for (i
= 0; pf_limits
[i
].name
; i
++) {
1096 pl
.index
= pf_limits
[i
].index
;
1097 if (ioctl(dev
, DIOCGETLIMIT
, &pl
))
1098 err(1, "DIOCGETLIMIT");
1099 printf("%-13s ", pf_limits
[i
].name
);
1100 if (pl
.limit
== UINT_MAX
)
1101 printf("unlimited\n");
1103 printf("hard limit %8u\n", pl
.limit
);
1108 /* callbacks for rule/nat/rdr/addr */
1110 pfctl_add_pool(struct pfctl
*pf
, struct pf_pool
*p
, sa_family_t af
)
1112 struct pf_pooladdr
*pa
;
1114 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1115 if (ioctl(pf
->dev
, DIOCBEGINADDRS
, &pf
->paddr
))
1116 err(1, "DIOCBEGINADDRS");
1120 TAILQ_FOREACH(pa
, &p
->list
, entries
) {
1121 memcpy(&pf
->paddr
.addr
, pa
, sizeof(struct pf_pooladdr
));
1122 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1123 if (ioctl(pf
->dev
, DIOCADDADDR
, &pf
->paddr
))
1124 err(1, "DIOCADDADDR");
1131 pfctl_add_rule(struct pfctl
*pf
, struct pf_rule
*r
, const char *anchor_call
)
1134 struct pf_rule
*rule
;
1135 struct pf_ruleset
*rs
;
1138 rs_num
= pf_get_ruleset_number(r
->action
);
1139 if (rs_num
== PF_RULESET_MAX
)
1140 errx(1, "Invalid rule type %d", r
->action
);
1142 rs
= &pf
->anchor
->ruleset
;
1144 if (anchor_call
[0] && r
->anchor
== NULL
) {
1146 * Don't make non-brace anchors part of the main anchor pool.
1148 if ((r
->anchor
= calloc(1, sizeof(*r
->anchor
))) == NULL
)
1149 err(1, "pfctl_add_rule: calloc");
1151 pf_init_ruleset(&r
->anchor
->ruleset
);
1152 r
->anchor
->ruleset
.anchor
= r
->anchor
;
1153 if (strlcpy(r
->anchor
->path
, anchor_call
,
1154 sizeof(rule
->anchor
->path
)) >= sizeof(rule
->anchor
->path
))
1155 errx(1, "pfctl_add_rule: strlcpy");
1156 if ((p
= strrchr(anchor_call
, '/')) != NULL
) {
1158 err(1, "pfctl_add_rule: bad anchor name %s",
1161 p
= (char *)anchor_call
;
1162 if (strlcpy(r
->anchor
->name
, p
,
1163 sizeof(rule
->anchor
->name
)) >= sizeof(rule
->anchor
->name
))
1164 errx(1, "pfctl_add_rule: strlcpy");
1167 if ((rule
= calloc(1, sizeof(*rule
))) == NULL
)
1169 bcopy(r
, rule
, sizeof(*rule
));
1170 TAILQ_INIT(&rule
->rpool
.list
);
1171 pfctl_move_pool(&r
->rpool
, &rule
->rpool
);
1173 TAILQ_INSERT_TAIL(rs
->rules
[rs_num
].active
.ptr
, rule
, entries
);
1178 pfctl_ruleset_trans(struct pfctl
*pf
, char *path
, struct pf_anchor
*a
)
1180 int osize
= pf
->trans
->pfrb_size
;
1182 if ((pf
->loadopt
& PFCTL_FLAG_NAT
) != 0) {
1183 if (pfctl_add_trans(pf
->trans
, PF_RULESET_NAT
, path
) ||
1184 pfctl_add_trans(pf
->trans
, PF_RULESET_BINAT
, path
) ||
1185 pfctl_add_trans(pf
->trans
, PF_RULESET_RDR
, path
))
1188 if (a
== pf
->astack
[0] && ((altqsupport
&&
1189 (pf
->loadopt
& PFCTL_FLAG_ALTQ
) != 0))) {
1190 if (pfctl_add_trans(pf
->trans
, PF_RULESET_ALTQ
, path
))
1193 if ((pf
->loadopt
& PFCTL_FLAG_FILTER
) != 0) {
1194 if (pfctl_add_trans(pf
->trans
, PF_RULESET_SCRUB
, path
) ||
1195 pfctl_add_trans(pf
->trans
, PF_RULESET_FILTER
, path
))
1198 if (pf
->loadopt
& PFCTL_FLAG_TABLE
)
1199 if (pfctl_add_trans(pf
->trans
, PF_RULESET_TABLE
, path
))
1201 if (pfctl_trans(pf
->dev
, pf
->trans
, DIOCXBEGIN
, osize
))
1208 pfctl_load_ruleset(struct pfctl
*pf
, char *path
, struct pf_ruleset
*rs
,
1209 int rs_num
, int depth
)
1212 int error
, len
= strlen(path
);
1215 pf
->anchor
= rs
->anchor
;
1218 snprintf(&path
[len
], MAXPATHLEN
- len
, "/%s", pf
->anchor
->name
);
1220 snprintf(&path
[len
], MAXPATHLEN
- len
, "%s", pf
->anchor
->name
);
1223 if (TAILQ_FIRST(rs
->rules
[rs_num
].active
.ptr
) != NULL
) {
1225 if (pf
->opts
& PF_OPT_VERBOSE
)
1227 if ((pf
->opts
& PF_OPT_NOACTION
) == 0 &&
1228 (error
= pfctl_ruleset_trans(pf
,
1229 path
, rs
->anchor
))) {
1230 printf("pfctl_load_rulesets: "
1231 "pfctl_ruleset_trans %d\n", error
);
1234 } else if (pf
->opts
& PF_OPT_VERBOSE
)
1239 if (pf
->optimize
&& rs_num
== PF_RULESET_FILTER
)
1240 pfctl_optimize_ruleset(pf
, rs
);
1242 while ((r
= TAILQ_FIRST(rs
->rules
[rs_num
].active
.ptr
)) != NULL
) {
1243 TAILQ_REMOVE(rs
->rules
[rs_num
].active
.ptr
, r
, entries
);
1244 if ((error
= pfctl_load_rule(pf
, path
, r
, depth
)))
1247 if ((error
= pfctl_load_ruleset(pf
, path
,
1248 &r
->anchor
->ruleset
, rs_num
, depth
+ 1)))
1250 } else if (pf
->opts
& PF_OPT_VERBOSE
)
1254 if (brace
&& pf
->opts
& PF_OPT_VERBOSE
) {
1255 INDENT(depth
- 1, (pf
->opts
& PF_OPT_VERBOSE
));
1268 pfctl_load_rule(struct pfctl
*pf
, char *path
, struct pf_rule
*r
, int depth
)
1270 u_int8_t rs_num
= pf_get_ruleset_number(r
->action
);
1272 struct pfioc_rule pr
;
1273 int len
= strlen(path
);
1275 bzero(&pr
, sizeof(pr
));
1276 /* set up anchor before adding to path for anchor_call */
1277 if ((pf
->opts
& PF_OPT_NOACTION
) == 0)
1278 pr
.ticket
= pfctl_get_ticket(pf
->trans
, rs_num
, path
);
1279 if (strlcpy(pr
.anchor
, path
, sizeof(pr
.anchor
)) >= sizeof(pr
.anchor
))
1280 errx(1, "pfctl_load_rule: strlcpy");
1283 if (r
->anchor
->match
) {
1285 snprintf(&path
[len
], MAXPATHLEN
- len
,
1286 "/%s", r
->anchor
->name
);
1288 snprintf(&path
[len
], MAXPATHLEN
- len
,
1289 "%s", r
->anchor
->name
);
1292 name
= r
->anchor
->path
;
1296 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1297 if (pfctl_add_pool(pf
, &r
->rpool
, r
->af
))
1299 pr
.pool_ticket
= pf
->paddr
.ticket
;
1300 memcpy(&pr
.rule
, r
, sizeof(pr
.rule
));
1301 if (r
->anchor
&& strlcpy(pr
.anchor_call
, name
,
1302 sizeof(pr
.anchor_call
)) >= sizeof(pr
.anchor_call
))
1303 errx(1, "pfctl_load_rule: strlcpy");
1304 if (ioctl(pf
->dev
, DIOCADDRULE
, &pr
))
1305 err(1, "DIOCADDRULE");
1308 if (pf
->opts
& PF_OPT_VERBOSE
) {
1309 INDENT(depth
, !(pf
->opts
& PF_OPT_VERBOSE2
));
1310 print_rule(r
, r
->anchor
? r
->anchor
->name
: "",
1311 pf
->opts
& PF_OPT_VERBOSE2
);
1314 pfctl_clear_pool(&r
->rpool
);
1319 pfctl_add_altq(struct pfctl
*pf
, struct pf_altq
*a
)
1322 (loadopt
& PFCTL_FLAG_ALTQ
) != 0) {
1323 memcpy(&pf
->paltq
->altq
, a
, sizeof(struct pf_altq
));
1324 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1325 if (ioctl(pf
->dev
, DIOCADDALTQ
, pf
->paltq
)) {
1327 errx(1, "qtype not configured");
1328 else if (errno
== ENODEV
)
1329 errx(1, "%s: driver does not support "
1332 err(1, "DIOCADDALTQ");
1335 pfaltq_store(&pf
->paltq
->altq
);
1341 pfctl_rules(int dev
, char *filename
, FILE *fin
, int opts
, int optimize
,
1342 char *anchorname
, struct pfr_buffer
*trans
)
1344 #define ERR(x) do { warn(x); goto _error; } while(0)
1345 #define ERRX(x) do { warnx(x); goto _error; } while(0)
1347 struct pfr_buffer
*t
, buf
;
1348 struct pfioc_altq pa
;
1350 struct pf_ruleset
*rs
;
1351 struct pfr_table trs
;
1355 RB_INIT(&pf_anchors
);
1356 memset(&pf_main_anchor
, 0, sizeof(pf_main_anchor
));
1357 pf_init_ruleset(&pf_main_anchor
.ruleset
);
1358 pf_main_anchor
.ruleset
.anchor
= &pf_main_anchor
;
1359 if (trans
== NULL
) {
1360 bzero(&buf
, sizeof(buf
));
1361 buf
.pfrb_type
= PFRB_TRANS
;
1366 osize
= t
->pfrb_size
;
1369 memset(&pa
, 0, sizeof(pa
));
1370 memset(&pf
, 0, sizeof(pf
));
1371 memset(&trs
, 0, sizeof(trs
));
1372 if ((path
= calloc(1, MAXPATHLEN
)) == NULL
)
1373 ERRX("pfctl_rules: calloc");
1374 if (strlcpy(trs
.pfrt_anchor
, anchorname
,
1375 sizeof(trs
.pfrt_anchor
)) >= sizeof(trs
.pfrt_anchor
))
1376 ERRX("pfctl_rules: strlcpy");
1380 pf
.optimize
= optimize
;
1381 pf
.loadopt
= loadopt
;
1383 /* non-brace anchor, create without resolving the path */
1384 if ((pf
.anchor
= calloc(1, sizeof(*pf
.anchor
))) == NULL
)
1385 ERRX("pfctl_rules: calloc");
1386 rs
= &pf
.anchor
->ruleset
;
1387 pf_init_ruleset(rs
);
1388 rs
->anchor
= pf
.anchor
;
1389 if (strlcpy(pf
.anchor
->path
, anchorname
,
1390 sizeof(pf
.anchor
->path
)) >= sizeof(pf
.anchor
->path
))
1391 errx(1, "pfctl_add_rule: strlcpy");
1392 if (strlcpy(pf
.anchor
->name
, anchorname
,
1393 sizeof(pf
.anchor
->name
)) >= sizeof(pf
.anchor
->name
))
1394 errx(1, "pfctl_add_rule: strlcpy");
1397 pf
.astack
[0] = pf
.anchor
;
1400 pf
.loadopt
&= ~PFCTL_FLAG_ALTQ
;
1403 pfctl_init_options(&pf
);
1405 if ((opts
& PF_OPT_NOACTION
) == 0) {
1407 * XXX For the time being we need to open transactions for
1408 * the main ruleset before parsing, because tables are still
1409 * loaded at parse time.
1411 if (pfctl_ruleset_trans(&pf
, anchorname
, pf
.anchor
))
1412 ERRX("pfctl_rules");
1413 if (altqsupport
&& (pf
.loadopt
& PFCTL_FLAG_ALTQ
))
1415 pfctl_get_ticket(t
, PF_RULESET_ALTQ
, anchorname
);
1416 if (pf
.loadopt
& PFCTL_FLAG_TABLE
)
1417 pf
.astack
[0]->ruleset
.tticket
=
1418 pfctl_get_ticket(t
, PF_RULESET_TABLE
, anchorname
);
1421 if (parse_rules(fin
, &pf
) < 0) {
1422 if ((opts
& PF_OPT_NOACTION
) == 0)
1423 ERRX("Syntax error in config file: "
1424 "pf rules not loaded");
1429 if ((pf
.loadopt
& PFCTL_FLAG_FILTER
&&
1430 (pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_SCRUB
, 0))) ||
1431 (pf
.loadopt
& PFCTL_FLAG_NAT
&&
1432 (pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_NAT
, 0) ||
1433 pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_RDR
, 0) ||
1434 pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_BINAT
, 0))) ||
1435 (pf
.loadopt
& PFCTL_FLAG_FILTER
&&
1436 pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_FILTER
, 0))) {
1437 if ((opts
& PF_OPT_NOACTION
) == 0)
1438 ERRX("Unable to load rules into kernel");
1443 if ((altqsupport
&& (pf
.loadopt
& PFCTL_FLAG_ALTQ
) != 0))
1444 if (check_commit_altq(dev
, opts
) != 0)
1445 ERRX("errors in altq config");
1452 /* process "load anchor" directives */
1454 if (pfctl_load_anchors(dev
, &pf
, t
) == -1)
1455 ERRX("load anchors");
1457 if (trans
== NULL
&& (opts
& PF_OPT_NOACTION
) == 0) {
1459 if (pfctl_load_options(&pf
))
1461 if (pfctl_trans(dev
, t
, DIOCXCOMMIT
, osize
))
1467 if (trans
== NULL
) { /* main ruleset */
1468 if ((opts
& PF_OPT_NOACTION
) == 0)
1469 if (pfctl_trans(dev
, t
, DIOCXROLLBACK
, osize
))
1470 err(1, "DIOCXROLLBACK");
1472 } else { /* sub ruleset */
1473 if (fin
!= NULL
&& fin
!= stdin
)
1483 pfctl_fopen(const char *name
, const char *mode
)
1488 fp
= fopen(name
, mode
);
1491 if (fstat(fileno(fp
), &st
)) {
1495 if (S_ISDIR(st
.st_mode
)) {
1504 pfctl_init_options(struct pfctl
*pf
)
1509 pf
->timeout
[PFTM_TCP_FIRST_PACKET
] = PFTM_TCP_FIRST_PACKET_VAL
;
1510 pf
->timeout
[PFTM_TCP_OPENING
] = PFTM_TCP_OPENING_VAL
;
1511 pf
->timeout
[PFTM_TCP_ESTABLISHED
] = PFTM_TCP_ESTABLISHED_VAL
;
1512 pf
->timeout
[PFTM_TCP_CLOSING
] = PFTM_TCP_CLOSING_VAL
;
1513 pf
->timeout
[PFTM_TCP_FIN_WAIT
] = PFTM_TCP_FIN_WAIT_VAL
;
1514 pf
->timeout
[PFTM_TCP_CLOSED
] = PFTM_TCP_CLOSED_VAL
;
1515 pf
->timeout
[PFTM_UDP_FIRST_PACKET
] = PFTM_UDP_FIRST_PACKET_VAL
;
1516 pf
->timeout
[PFTM_UDP_SINGLE
] = PFTM_UDP_SINGLE_VAL
;
1517 pf
->timeout
[PFTM_UDP_MULTIPLE
] = PFTM_UDP_MULTIPLE_VAL
;
1518 pf
->timeout
[PFTM_ICMP_FIRST_PACKET
] = PFTM_ICMP_FIRST_PACKET_VAL
;
1519 pf
->timeout
[PFTM_ICMP_ERROR_REPLY
] = PFTM_ICMP_ERROR_REPLY_VAL
;
1520 pf
->timeout
[PFTM_OTHER_FIRST_PACKET
] = PFTM_OTHER_FIRST_PACKET_VAL
;
1521 pf
->timeout
[PFTM_OTHER_SINGLE
] = PFTM_OTHER_SINGLE_VAL
;
1522 pf
->timeout
[PFTM_OTHER_MULTIPLE
] = PFTM_OTHER_MULTIPLE_VAL
;
1523 pf
->timeout
[PFTM_FRAG
] = PFTM_FRAG_VAL
;
1524 pf
->timeout
[PFTM_INTERVAL
] = PFTM_INTERVAL_VAL
;
1525 pf
->timeout
[PFTM_SRC_NODE
] = PFTM_SRC_NODE_VAL
;
1526 pf
->timeout
[PFTM_TS_DIFF
] = PFTM_TS_DIFF_VAL
;
1527 pf
->timeout
[PFTM_ADAPTIVE_START
] = PFSTATE_ADAPT_START
;
1528 pf
->timeout
[PFTM_ADAPTIVE_END
] = PFSTATE_ADAPT_END
;
1530 pf
->limit
[PF_LIMIT_STATES
] = PFSTATE_HIWAT
;
1531 pf
->limit
[PF_LIMIT_FRAGS
] = PFFRAG_FRENT_HIWAT
;
1532 pf
->limit
[PF_LIMIT_SRC_NODES
] = PFSNODE_HIWAT
;
1533 pf
->limit
[PF_LIMIT_TABLES
] = PFR_KTABLE_HIWAT
;
1534 pf
->limit
[PF_LIMIT_TABLE_ENTRIES
] = PFR_KENTRY_HIWAT
;
1537 mib
[1] = HW_PHYSMEM
;
1539 (void) sysctl(mib
, 2, &mem
, &size
, NULL
, 0);
1540 if (mem
<= 100*1024*1024)
1541 pf
->limit
[PF_LIMIT_TABLE_ENTRIES
] = PFR_KENTRY_HIWAT_SMALL
;
1543 pf
->debug
= PF_DEBUG_URGENT
;
1547 pfctl_load_options(struct pfctl
*pf
)
1551 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1555 for (i
= 0; i
< PF_LIMIT_MAX
; i
++) {
1556 if ((pf
->opts
& PF_OPT_MERGE
) && !pf
->limit_set
[i
])
1558 if (pfctl_load_limit(pf
, i
, pf
->limit
[i
]))
1563 * If we've set the limit, but havn't explicitly set adaptive
1564 * timeouts, do it now with a start of 60% and end of 120%.
1566 if (pf
->limit_set
[PF_LIMIT_STATES
] &&
1567 !pf
->timeout_set
[PFTM_ADAPTIVE_START
] &&
1568 !pf
->timeout_set
[PFTM_ADAPTIVE_END
]) {
1569 pf
->timeout
[PFTM_ADAPTIVE_START
] =
1570 (pf
->limit
[PF_LIMIT_STATES
] / 10) * 6;
1571 pf
->timeout_set
[PFTM_ADAPTIVE_START
] = 1;
1572 pf
->timeout
[PFTM_ADAPTIVE_END
] =
1573 (pf
->limit
[PF_LIMIT_STATES
] / 10) * 12;
1574 pf
->timeout_set
[PFTM_ADAPTIVE_END
] = 1;
1578 for (i
= 0; i
< PFTM_MAX
; i
++) {
1579 if ((pf
->opts
& PF_OPT_MERGE
) && !pf
->timeout_set
[i
])
1581 if (pfctl_load_timeout(pf
, i
, pf
->timeout
[i
]))
1586 if (!(pf
->opts
& PF_OPT_MERGE
) || pf
->debug_set
)
1587 if (pfctl_load_debug(pf
, pf
->debug
))
1591 if (!(pf
->opts
& PF_OPT_MERGE
) || pf
->ifname_set
)
1592 if (pfctl_load_logif(pf
, pf
->ifname
))
1596 if (!(pf
->opts
& PF_OPT_MERGE
) || pf
->hostid_set
)
1597 if (pfctl_load_hostid(pf
, pf
->hostid
))
1604 pfctl_set_limit(struct pfctl
*pf
, const char *opt
, unsigned int limit
)
1609 for (i
= 0; pf_limits
[i
].name
; i
++) {
1610 if (strcasecmp(opt
, pf_limits
[i
].name
) == 0) {
1611 pf
->limit
[pf_limits
[i
].index
] = limit
;
1612 pf
->limit_set
[pf_limits
[i
].index
] = 1;
1616 if (pf_limits
[i
].name
== NULL
) {
1617 warnx("Bad pool name.");
1621 if (pf
->opts
& PF_OPT_VERBOSE
)
1622 printf("set limit %s %d\n", opt
, limit
);
1628 pfctl_load_limit(struct pfctl
*pf
, unsigned int index
, unsigned int limit
)
1630 struct pfioc_limit pl
;
1632 memset(&pl
, 0, sizeof(pl
));
1635 if (ioctl(pf
->dev
, DIOCSETLIMIT
, &pl
)) {
1637 warnx("Current pool size exceeds requested hard limit");
1639 warnx("DIOCSETLIMIT");
1646 pfctl_set_timeout(struct pfctl
*pf
, const char *opt
, int seconds
, int quiet
)
1650 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1653 for (i
= 0; pf_timeouts
[i
].name
; i
++) {
1654 if (strcasecmp(opt
, pf_timeouts
[i
].name
) == 0) {
1655 pf
->timeout
[pf_timeouts
[i
].timeout
] = seconds
;
1656 pf
->timeout_set
[pf_timeouts
[i
].timeout
] = 1;
1661 if (pf_timeouts
[i
].name
== NULL
) {
1662 warnx("Bad timeout name.");
1667 if (pf
->opts
& PF_OPT_VERBOSE
&& ! quiet
)
1668 printf("set timeout %s %d\n", opt
, seconds
);
1674 pfctl_load_timeout(struct pfctl
*pf
, unsigned int timeout
, unsigned int seconds
)
1678 memset(&pt
, 0, sizeof(pt
));
1679 pt
.timeout
= timeout
;
1680 pt
.seconds
= seconds
;
1681 if (ioctl(pf
->dev
, DIOCSETTIMEOUT
, &pt
)) {
1682 warnx("DIOCSETTIMEOUT");
1689 pfctl_set_optimization(struct pfctl
*pf
, const char *opt
)
1691 const struct pf_hint
*hint
;
1694 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1697 for (i
= 0; pf_hints
[i
].name
; i
++)
1698 if (strcasecmp(opt
, pf_hints
[i
].name
) == 0)
1701 hint
= pf_hints
[i
].hint
;
1703 warnx("invalid state timeouts optimization");
1707 for (i
= 0; hint
[i
].name
; i
++)
1708 if ((r
= pfctl_set_timeout(pf
, hint
[i
].name
,
1709 hint
[i
].timeout
, 1)))
1712 if (pf
->opts
& PF_OPT_VERBOSE
)
1713 printf("set optimization %s\n", opt
);
1719 pfctl_set_logif(struct pfctl
*pf
, char *ifname
)
1722 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1725 if (!strcmp(ifname
, "none")) {
1729 pf
->ifname
= strdup(ifname
);
1731 errx(1, "pfctl_set_logif: strdup");
1735 if (pf
->opts
& PF_OPT_VERBOSE
)
1736 printf("set loginterface %s\n", ifname
);
1742 pfctl_load_logif(struct pfctl
*pf
, char *ifname
)
1746 memset(&pi
, 0, sizeof(pi
));
1747 if (ifname
&& strlcpy(pi
.ifname
, ifname
,
1748 sizeof(pi
.ifname
)) >= sizeof(pi
.ifname
)) {
1749 warnx("pfctl_load_logif: strlcpy");
1752 if (ioctl(pf
->dev
, DIOCSETSTATUSIF
, &pi
)) {
1753 warnx("DIOCSETSTATUSIF");
1760 pfctl_set_hostid(struct pfctl
*pf
, u_int32_t hostid
)
1762 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1767 pf
->hostid
= hostid
;
1770 if (pf
->opts
& PF_OPT_VERBOSE
)
1771 printf("set hostid 0x%08x\n", ntohl(hostid
));
1777 pfctl_load_hostid(struct pfctl
*pf
, u_int32_t hostid
)
1779 if (ioctl(dev
, DIOCSETHOSTID
, &hostid
)) {
1780 warnx("DIOCSETHOSTID");
1787 pfctl_set_debug(struct pfctl
*pf
, char *d
)
1791 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1794 if (!strcmp(d
, "none"))
1795 pf
->debug
= PF_DEBUG_NONE
;
1796 else if (!strcmp(d
, "urgent"))
1797 pf
->debug
= PF_DEBUG_URGENT
;
1798 else if (!strcmp(d
, "misc"))
1799 pf
->debug
= PF_DEBUG_MISC
;
1800 else if (!strcmp(d
, "loud"))
1801 pf
->debug
= PF_DEBUG_NOISY
;
1803 warnx("unknown debug level \"%s\"", d
);
1809 if ((pf
->opts
& PF_OPT_NOACTION
) == 0)
1810 if (ioctl(dev
, DIOCSETDEBUG
, &level
))
1811 err(1, "DIOCSETDEBUG");
1813 if (pf
->opts
& PF_OPT_VERBOSE
)
1814 printf("set debug %s\n", d
);
1820 pfctl_load_debug(struct pfctl
*pf
, unsigned int level
)
1822 if (ioctl(pf
->dev
, DIOCSETDEBUG
, &level
)) {
1823 warnx("DIOCSETDEBUG");
1830 pfctl_set_interface_flags(struct pfctl
*pf
, char *ifname
, int flags
, int how
)
1832 struct pfioc_iface pi
;
1834 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1837 bzero(&pi
, sizeof(pi
));
1839 pi
.pfiio_flags
= flags
;
1841 if (strlcpy(pi
.pfiio_name
, ifname
, sizeof(pi
.pfiio_name
)) >=
1842 sizeof(pi
.pfiio_name
))
1843 errx(1, "pfctl_set_interface_flags: strlcpy");
1845 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1847 if (ioctl(pf
->dev
, DIOCCLRIFFLAG
, &pi
))
1848 err(1, "DIOCCLRIFFLAG");
1850 if (ioctl(pf
->dev
, DIOCSETIFFLAG
, &pi
))
1851 err(1, "DIOCSETIFFLAG");
1858 pfctl_debug(int dev
, u_int32_t level
, int opts
)
1860 if (ioctl(dev
, DIOCSETDEBUG
, &level
))
1861 err(1, "DIOCSETDEBUG");
1862 if ((opts
& PF_OPT_QUIET
) == 0) {
1863 fprintf(stderr
, "debug level set to '");
1866 fprintf(stderr
, "none");
1868 case PF_DEBUG_URGENT
:
1869 fprintf(stderr
, "urgent");
1872 fprintf(stderr
, "misc");
1874 case PF_DEBUG_NOISY
:
1875 fprintf(stderr
, "loud");
1878 fprintf(stderr
, "<invalid>");
1881 fprintf(stderr
, "'\n");
1886 pfctl_test_altqsupport(int dev
, int opts
)
1888 struct pfioc_altq pa
;
1890 if (ioctl(dev
, DIOCGETALTQS
, &pa
)) {
1891 if (errno
== ENODEV
) {
1892 if (!(opts
& PF_OPT_QUIET
))
1893 fprintf(stderr
, "No ALTQ support in kernel\n"
1894 "ALTQ related functions disabled\n");
1897 err(1, "DIOCGETALTQS");
1903 pfctl_show_anchors(int dev
, int opts
, char *anchorname
)
1905 struct pfioc_ruleset pr
;
1908 memset(&pr
, 0, sizeof(pr
));
1909 memcpy(pr
.path
, anchorname
, sizeof(pr
.path
));
1910 if (ioctl(dev
, DIOCGETRULESETS
, &pr
)) {
1911 if (errno
== EINVAL
)
1912 fprintf(stderr
, "Anchor '%s' not found.\n",
1915 err(1, "DIOCGETRULESETS");
1919 for (nr
= 0; nr
< mnr
; ++nr
) {
1920 char sub
[MAXPATHLEN
];
1923 if (ioctl(dev
, DIOCGETRULESET
, &pr
))
1924 err(1, "DIOCGETRULESET");
1925 if (!strcmp(pr
.name
, PF_RESERVED_ANCHOR
))
1929 strlcat(sub
, pr
.path
, sizeof(sub
));
1930 strlcat(sub
, "/", sizeof(sub
));
1932 strlcat(sub
, pr
.name
, sizeof(sub
));
1933 if (sub
[0] != '_' || (opts
& PF_OPT_VERBOSE
))
1934 printf(" %s\n", sub
);
1935 if ((opts
& PF_OPT_VERBOSE
) && pfctl_show_anchors(dev
, opts
, sub
))
1942 pfctl_lookup_option(char *cmd
, const char **list
)
1944 if (cmd
!= NULL
&& *cmd
)
1945 for (; *list
; list
++)
1946 if (!strncmp(cmd
, *list
, strlen(cmd
)))
1952 main(int argc
, char *argv
[])
1956 int mode
= O_RDONLY
;
1958 int optimize
= PF_OPTIMIZE_BASIC
;
1959 char anchorname
[MAXPATHLEN
];
1966 while ((ch
= getopt(argc
, argv
,
1967 "a:AdD:eqf:F:ghi:k:K:mnNOo:p:rRs:t:T:vx:z")) != -1) {
1973 opts
|= PF_OPT_DISABLE
;
1977 if (pfctl_cmdline_symset(optarg
) < 0)
1978 warnx("could not parse macro definition %s",
1982 opts
|= PF_OPT_ENABLE
;
1986 opts
|= PF_OPT_QUIET
;
1989 clearopt
= pfctl_lookup_option(optarg
, clearopt_list
);
1990 if (clearopt
== NULL
) {
1991 warnx("Unknown flush modifier '%s'", optarg
);
2000 if (state_killers
>= 2) {
2001 warnx("can only specify -k twice");
2005 state_kill
[state_killers
++] = optarg
;
2009 if (src_node_killers
>= 2) {
2010 warnx("can only specify -K twice");
2014 src_node_kill
[src_node_killers
++] = optarg
;
2018 opts
|= PF_OPT_MERGE
;
2021 opts
|= PF_OPT_NOACTION
;
2024 loadopt
|= PFCTL_FLAG_NAT
;
2027 opts
|= PF_OPT_USEDNS
;
2034 opts
|= PF_OPT_DEBUG
;
2037 loadopt
|= PFCTL_FLAG_ALTQ
;
2040 loadopt
|= PFCTL_FLAG_FILTER
;
2043 optiopt
= pfctl_lookup_option(optarg
, optiopt_list
);
2044 if (optiopt
== NULL
) {
2045 warnx("Unknown optimization '%s'", optarg
);
2048 opts
|= PF_OPT_OPTIMIZE
;
2051 loadopt
|= PFCTL_FLAG_OPTION
;
2057 showopt
= pfctl_lookup_option(optarg
, showopt_list
);
2058 if (showopt
== NULL
) {
2059 warnx("Unknown show modifier '%s'", optarg
);
2067 tblcmdopt
= pfctl_lookup_option(optarg
, tblcmdopt_list
);
2068 if (tblcmdopt
== NULL
) {
2069 warnx("Unknown table command '%s'", optarg
);
2074 if (opts
& PF_OPT_VERBOSE
)
2075 opts
|= PF_OPT_VERBOSE2
;
2076 opts
|= PF_OPT_VERBOSE
;
2079 debugopt
= pfctl_lookup_option(optarg
, debugopt_list
);
2080 if (debugopt
== NULL
) {
2081 warnx("Unknown debug level '%s'", optarg
);
2087 opts
|= PF_OPT_CLRRULECTRS
;
2098 if (tblcmdopt
!= NULL
) {
2103 loadopt
|= PFCTL_FLAG_TABLE
;
2106 mode
= strchr("acdefkrz", ch
) ? O_RDWR
: O_RDONLY
;
2107 } else if (argc
!= optind
) {
2108 warnx("unknown command line argument: %s ...", argv
[optind
]);
2115 if ((path
= calloc(1, MAXPATHLEN
)) == NULL
)
2116 errx(1, "pfctl: calloc");
2117 memset(anchorname
, 0, sizeof(anchorname
));
2118 if (anchoropt
!= NULL
) {
2119 int len
= strlen(anchoropt
);
2121 if (anchoropt
[len
- 1] == '*') {
2122 if (len
>= 2 && anchoropt
[len
- 2] == '/')
2123 anchoropt
[len
- 2] = '\0';
2125 anchoropt
[len
- 1] = '\0';
2126 opts
|= PF_OPT_RECURSE
;
2128 if (strlcpy(anchorname
, anchoropt
,
2129 sizeof(anchorname
)) >= sizeof(anchorname
))
2130 errx(1, "anchor name '%s' too long",
2132 loadopt
&= PFCTL_FLAG_FILTER
|PFCTL_FLAG_NAT
|PFCTL_FLAG_TABLE
;
2135 if ((opts
& PF_OPT_NOACTION
) == 0) {
2136 dev
= open(pf_device
, mode
);
2138 err(1, "%s", pf_device
);
2139 altqsupport
= pfctl_test_altqsupport(dev
, opts
);
2141 dev
= open(pf_device
, O_RDONLY
);
2143 opts
|= PF_OPT_DUMMYACTION
;
2144 /* turn off options */
2145 opts
&= ~ (PF_OPT_DISABLE
| PF_OPT_ENABLE
);
2146 clearopt
= showopt
= debugopt
= NULL
;
2150 if (opts
& PF_OPT_DISABLE
)
2151 if (pfctl_disable(dev
, opts
))
2154 if (showopt
!= NULL
) {
2157 pfctl_show_anchors(dev
, opts
, anchorname
);
2160 pfctl_load_fingerprints(dev
, opts
);
2161 pfctl_show_rules(dev
, path
, opts
, PFCTL_SHOW_RULES
,
2165 pfctl_load_fingerprints(dev
, opts
);
2166 pfctl_show_rules(dev
, path
, opts
, PFCTL_SHOW_LABELS
,
2170 pfctl_load_fingerprints(dev
, opts
);
2171 pfctl_show_nat(dev
, opts
, anchorname
);
2174 pfctl_show_altq(dev
, ifaceopt
, opts
,
2175 opts
& PF_OPT_VERBOSE2
);
2178 pfctl_show_states(dev
, ifaceopt
, opts
);
2181 pfctl_show_src_nodes(dev
, opts
);
2184 pfctl_show_status(dev
, opts
);
2187 pfctl_show_timeouts(dev
, opts
);
2190 pfctl_show_limits(dev
, opts
);
2193 opts
|= PF_OPT_SHOWALL
;
2194 pfctl_load_fingerprints(dev
, opts
);
2196 pfctl_show_nat(dev
, opts
, anchorname
);
2197 pfctl_show_rules(dev
, path
, opts
, 0, anchorname
, 0);
2198 pfctl_show_altq(dev
, ifaceopt
, opts
, 0);
2199 pfctl_show_states(dev
, ifaceopt
, opts
);
2200 pfctl_show_src_nodes(dev
, opts
);
2201 pfctl_show_status(dev
, opts
);
2202 pfctl_show_rules(dev
, path
, opts
, 1, anchorname
, 0);
2203 pfctl_show_timeouts(dev
, opts
);
2204 pfctl_show_limits(dev
, opts
);
2205 pfctl_show_tables(anchorname
, opts
);
2206 pfctl_show_fingerprints(opts
);
2209 pfctl_show_tables(anchorname
, opts
);
2212 pfctl_load_fingerprints(dev
, opts
);
2213 pfctl_show_fingerprints(opts
);
2216 pfctl_show_ifaces(ifaceopt
, opts
);
2221 if ((opts
& PF_OPT_CLRRULECTRS
) && showopt
== NULL
)
2222 pfctl_show_rules(dev
, path
, opts
, PFCTL_SHOW_NOTHING
,
2225 if (clearopt
!= NULL
) {
2226 if (anchorname
[0] == '_' || strstr(anchorname
, "/_") != NULL
)
2227 errx(1, "anchor names beginning with '_' cannot "
2228 "be modified from the command line");
2230 switch (*clearopt
) {
2232 pfctl_clear_rules(dev
, opts
, anchorname
);
2235 pfctl_clear_nat(dev
, opts
, anchorname
);
2238 pfctl_clear_altq(dev
, opts
);
2241 pfctl_clear_states(dev
, ifaceopt
, opts
);
2244 pfctl_clear_src_nodes(dev
, opts
);
2247 pfctl_clear_stats(dev
, opts
);
2250 pfctl_clear_rules(dev
, opts
, anchorname
);
2251 pfctl_clear_nat(dev
, opts
, anchorname
);
2252 pfctl_clear_tables(anchorname
, opts
);
2254 pfctl_clear_altq(dev
, opts
);
2255 pfctl_clear_states(dev
, ifaceopt
, opts
);
2256 pfctl_clear_src_nodes(dev
, opts
);
2257 pfctl_clear_stats(dev
, opts
);
2258 pfctl_clear_fingerprints(dev
, opts
);
2259 pfctl_clear_interface_flags(dev
, opts
);
2263 pfctl_clear_fingerprints(dev
, opts
);
2266 pfctl_clear_tables(anchorname
, opts
);
2271 pfctl_kill_states(dev
, ifaceopt
, opts
);
2273 if (src_node_killers
)
2274 pfctl_kill_src_nodes(dev
, ifaceopt
, opts
);
2276 if (tblcmdopt
!= NULL
) {
2277 error
= pfctl_command_tables(argc
, argv
, tableopt
,
2278 tblcmdopt
, rulesopt
, anchorname
, opts
);
2281 if (optiopt
!= NULL
) {
2287 optimize
|= PF_OPTIMIZE_BASIC
;
2291 optimize
|= PF_OPTIMIZE_PROFILE
;
2296 if (rulesopt
!= NULL
) {
2297 if (strcmp(rulesopt
, "-") == 0) {
2301 if ((fin
= pfctl_fopen(rulesopt
, "r")) == NULL
)
2302 err(1, "%s", rulesopt
);
2305 if ((rulesopt
!= NULL
) && (loadopt
& PFCTL_FLAG_OPTION
) &&
2307 if (pfctl_clear_interface_flags(dev
, opts
| PF_OPT_QUIET
))
2310 if (rulesopt
!= NULL
&& !(opts
& (PF_OPT_MERGE
|PF_OPT_NOACTION
)) &&
2311 !anchorname
[0] && (loadopt
& PFCTL_FLAG_OPTION
))
2312 if (pfctl_file_fingerprints(dev
, opts
, PF_OSFP_FILE
))
2315 if (rulesopt
!= NULL
) {
2316 if (anchorname
[0] == '_' || strstr(anchorname
, "/_") != NULL
)
2317 errx(1, "anchor names beginning with '_' cannot "
2318 "be modified from the command line");
2319 if (pfctl_rules(dev
, rulesopt
, fin
, opts
, optimize
,
2322 else if (!(opts
& PF_OPT_NOACTION
) &&
2323 (loadopt
& PFCTL_FLAG_TABLE
))
2324 warn_namespace_collision(NULL
);
2327 if (opts
& PF_OPT_ENABLE
)
2328 if (pfctl_enable(dev
, opts
))
2331 if (debugopt
!= NULL
) {
2332 switch (*debugopt
) {
2334 pfctl_debug(dev
, PF_DEBUG_NONE
, opts
);
2337 pfctl_debug(dev
, PF_DEBUG_URGENT
, opts
);
2340 pfctl_debug(dev
, PF_DEBUG_MISC
, opts
);
2343 pfctl_debug(dev
, PF_DEBUG_NOISY
, opts
);