1 /* $OpenBSD: pfctl.c,v 1.268 2007/06/30 18:25:08 henning Exp $ */
4 * Copyright (c) 2001 Daniel Hartmeier
5 * Copyright (c) 2002,2003 Henning Brauer
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
34 #include <sys/types.h>
35 #include <sys/ioctl.h>
36 #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>
44 #include <sys/sysctl.h>
56 #include "pfctl_parser.h"
60 int pfctl_enable(int, int);
61 int pfctl_disable(int, int);
62 int pfctl_clear_stats(int, int);
63 int pfctl_clear_interface_flags(int, int);
64 int pfctl_clear_rules(int, int, char *);
65 int pfctl_clear_nat(int, int, char *);
66 int pfctl_clear_altq(int, int);
67 int pfctl_clear_src_nodes(int, int);
68 int pfctl_clear_states(int, const char *, int);
69 void pfctl_addrprefix(char *, struct pf_addr
*);
70 int pfctl_kill_src_nodes(int, const char *, int);
71 int pfctl_kill_states(int, const char *, int);
72 void pfctl_init_options(struct pfctl
*);
73 int pfctl_load_options(struct pfctl
*);
74 int pfctl_load_limit(struct pfctl
*, unsigned int, unsigned int);
75 int pfctl_load_timeout(struct pfctl
*, unsigned int, unsigned int);
76 int pfctl_load_debug(struct pfctl
*, unsigned int);
77 int pfctl_load_logif(struct pfctl
*, char *);
78 int pfctl_load_hostid(struct pfctl
*, unsigned int);
79 int pfctl_get_pool(int, struct pf_pool
*, u_int32_t
, u_int32_t
, int,
81 void pfctl_print_rule_counters(struct pf_rule
*, int);
82 int pfctl_show_rules(int, char *, int, enum pfctl_show
, char *, int);
83 int pfctl_show_nat(int, int, char *);
84 int pfctl_show_src_nodes(int, int);
85 int pfctl_show_states(int, const char *, int);
86 int pfctl_show_status(int, int);
87 int pfctl_show_timeouts(int, int);
88 int pfctl_show_limits(int, int);
89 void pfctl_debug(int, u_int32_t
, int);
90 int pfctl_test_altqsupport(int, int);
91 int pfctl_show_anchors(int, int, char *);
92 int pfctl_ruleset_trans(struct pfctl
*, char *, struct pf_anchor
*);
93 int pfctl_load_ruleset(struct pfctl
*, char *,
94 struct pf_ruleset
*, int, int);
95 int pfctl_load_rule(struct pfctl
*, char *, struct pf_rule
*, int);
96 const char *pfctl_lookup_option(char *, const char **);
98 struct pf_anchor_global pf_anchors
;
99 struct pf_anchor pf_main_anchor
;
101 const char *clearopt
;
104 const char *debugopt
;
106 const char *optiopt
= NULL
;
107 const char *pf_device
= "/dev/pf";
110 const char *tblcmdopt
;
111 int src_node_killers
;
112 char *src_node_kill
[2];
124 #define INDENT(d, o) do { \
127 for (i=0; i < d; i++) \
133 static const struct {
137 { "states", PF_LIMIT_STATES
},
138 { "src-nodes", PF_LIMIT_SRC_NODES
},
139 { "frags", PF_LIMIT_FRAGS
},
140 { "tables", PF_LIMIT_TABLES
},
141 { "table-entries", PF_LIMIT_TABLE_ENTRIES
},
149 static const struct pf_hint pf_hint_normal
[] = {
150 { "tcp.first", 2 * 60 },
151 { "tcp.opening", 30 },
152 { "tcp.established", 24 * 60 * 60 },
153 { "tcp.closing", 15 * 60 },
154 { "tcp.finwait", 45 },
155 { "tcp.closed", 90 },
156 { "tcp.tsdiff", 30 },
159 static const struct pf_hint pf_hint_satellite
[] = {
160 { "tcp.first", 3 * 60 },
161 { "tcp.opening", 30 + 5 },
162 { "tcp.established", 24 * 60 * 60 },
163 { "tcp.closing", 15 * 60 + 5 },
164 { "tcp.finwait", 45 + 5 },
165 { "tcp.closed", 90 + 5 },
166 { "tcp.tsdiff", 60 },
169 static const struct pf_hint pf_hint_conservative
[] = {
170 { "tcp.first", 60 * 60 },
171 { "tcp.opening", 15 * 60 },
172 { "tcp.established", 5 * 24 * 60 * 60 },
173 { "tcp.closing", 60 * 60 },
174 { "tcp.finwait", 10 * 60 },
175 { "tcp.closed", 3 * 60 },
176 { "tcp.tsdiff", 60 },
179 static const struct pf_hint pf_hint_aggressive
[] = {
181 { "tcp.opening", 5 },
182 { "tcp.established", 5 * 60 * 60 },
183 { "tcp.closing", 60 },
184 { "tcp.finwait", 30 },
185 { "tcp.closed", 30 },
186 { "tcp.tsdiff", 10 },
190 static const struct {
192 const struct pf_hint
*hint
;
194 { "normal", pf_hint_normal
},
195 { "satellite", pf_hint_satellite
},
196 { "high-latency", pf_hint_satellite
},
197 { "conservative", pf_hint_conservative
},
198 { "aggressive", pf_hint_aggressive
},
202 static const char *clearopt_list
[] = {
203 "nat", "queue", "rules", "Sources",
204 "states", "info", "Tables", "osfp", "all", NULL
207 static const char *showopt_list
[] = {
208 "nat", "queue", "rules", "Anchors", "Sources", "states", "info",
209 "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
213 static const char *tblcmdopt_list
[] = {
214 "kill", "flush", "add", "delete", "load", "replace", "show",
215 "test", "zero", "expire", NULL
218 static const char *debugopt_list
[] = {
219 "none", "urgent", "misc", "loud", NULL
222 static const char *optiopt_list
[] = {
223 "none", "basic", "profile", NULL
229 fprintf(stderr
, "usage: %s [-AdeghmNnOqRrvz] ", getprogname());
230 fprintf(stderr
, "[-a anchor] [-D macro=value] [-F modifier]\n");
231 fprintf(stderr
, "\t[-f file] [-i interface] [-K host | network] ");
232 fprintf(stderr
, "[-k host | network]\n");
233 fprintf(stderr
, "\t[-o level] [-p device] [-s modifier]\n");
234 fprintf(stderr
, "\t[-t table -T command [address ...]] [-x level]\n");
239 pfctl_enable(int dev
, int opts
)
241 if (ioctl(dev
, DIOCSTART
)) {
243 errx(1, "pf already enabled");
247 if ((opts
& PF_OPT_QUIET
) == 0)
248 fprintf(stderr
, "pf enabled\n");
250 if (altqsupport
&& ioctl(dev
, DIOCSTARTALTQ
))
252 err(1, "DIOCSTARTALTQ");
258 pfctl_disable(int dev
, int opts
)
260 if (ioctl(dev
, DIOCSTOP
)) {
262 errx(1, "pf not enabled");
266 if ((opts
& PF_OPT_QUIET
) == 0)
267 fprintf(stderr
, "pf disabled\n");
269 if (altqsupport
&& ioctl(dev
, DIOCSTOPALTQ
))
271 err(1, "DIOCSTOPALTQ");
277 pfctl_clear_stats(int dev
, int opts
)
279 if (ioctl(dev
, DIOCCLRSTATUS
))
280 err(1, "DIOCCLRSTATUS");
281 if ((opts
& PF_OPT_QUIET
) == 0)
282 fprintf(stderr
, "pf: statistics cleared\n");
287 pfctl_clear_interface_flags(int dev
, int opts
)
289 struct pfioc_iface pi
;
291 if ((opts
& PF_OPT_NOACTION
) == 0) {
292 bzero(&pi
, sizeof(pi
));
293 pi
.pfiio_flags
= PFI_IFLAG_SKIP
;
295 if (ioctl(dev
, DIOCCLRIFFLAG
, &pi
))
296 err(1, "DIOCCLRIFFLAG");
297 if ((opts
& PF_OPT_QUIET
) == 0)
298 fprintf(stderr
, "pf: interface flags reset\n");
304 pfctl_clear_rules(int dev
, int opts
, char *anchorname
)
308 memset(&t
, 0, sizeof(t
));
309 t
.pfrb_type
= PFRB_TRANS
;
310 if (pfctl_add_trans(&t
, PF_RULESET_SCRUB
, anchorname
) ||
311 pfctl_add_trans(&t
, PF_RULESET_FILTER
, anchorname
) ||
312 pfctl_trans(dev
, &t
, DIOCXBEGIN
, 0) ||
313 pfctl_trans(dev
, &t
, DIOCXCOMMIT
, 0))
314 err(1, "pfctl_clear_rules");
315 if ((opts
& PF_OPT_QUIET
) == 0)
316 fprintf(stderr
, "rules cleared\n");
321 pfctl_clear_nat(int dev
, int opts
, char *anchorname
)
325 memset(&t
, 0, sizeof(t
));
326 t
.pfrb_type
= PFRB_TRANS
;
327 if (pfctl_add_trans(&t
, PF_RULESET_NAT
, anchorname
) ||
328 pfctl_add_trans(&t
, PF_RULESET_BINAT
, anchorname
) ||
329 pfctl_add_trans(&t
, PF_RULESET_RDR
, anchorname
) ||
330 pfctl_trans(dev
, &t
, DIOCXBEGIN
, 0) ||
331 pfctl_trans(dev
, &t
, DIOCXCOMMIT
, 0))
332 err(1, "pfctl_clear_nat");
333 if ((opts
& PF_OPT_QUIET
) == 0)
334 fprintf(stderr
, "nat cleared\n");
339 pfctl_clear_altq(int dev
, int opts
)
345 memset(&t
, 0, sizeof(t
));
346 t
.pfrb_type
= PFRB_TRANS
;
347 if (pfctl_add_trans(&t
, PF_RULESET_ALTQ
, "") ||
348 pfctl_trans(dev
, &t
, DIOCXBEGIN
, 0) ||
349 pfctl_trans(dev
, &t
, DIOCXCOMMIT
, 0))
350 err(1, "pfctl_clear_altq");
351 if ((opts
& PF_OPT_QUIET
) == 0)
352 fprintf(stderr
, "altq cleared\n");
357 pfctl_clear_src_nodes(int dev
, int opts
)
359 if (ioctl(dev
, DIOCCLRSRCNODES
))
360 err(1, "DIOCCLRSRCNODES");
361 if ((opts
& PF_OPT_QUIET
) == 0)
362 fprintf(stderr
, "source tracking entries cleared\n");
367 pfctl_clear_states(int dev
, const char *iface
, int opts
)
369 struct pfioc_state_kill psk
;
371 memset(&psk
, 0, sizeof(psk
));
372 if (iface
!= NULL
&& strlcpy(psk
.psk_ifname
, iface
,
373 sizeof(psk
.psk_ifname
)) >= sizeof(psk
.psk_ifname
))
374 errx(1, "invalid interface: %s", iface
);
376 if (ioctl(dev
, DIOCCLRSTATES
, &psk
))
377 err(1, "DIOCCLRSTATES");
378 if ((opts
& PF_OPT_QUIET
) == 0)
379 fprintf(stderr
, "%d states cleared\n", psk
.psk_af
);
384 pfctl_addrprefix(char *addr
, struct pf_addr
*mask
)
388 int prefix
, ret_ga
, q
, r
;
389 struct addrinfo hints
, *res
;
391 if ((p
= strchr(addr
, '/')) == NULL
)
395 prefix
= strtonum(p
, 0, 128, &errstr
);
397 errx(1, "prefix is %s: %s", errstr
, p
);
399 bzero(&hints
, sizeof(hints
));
400 /* prefix only with numeric addresses */
401 hints
.ai_flags
|= AI_NUMERICHOST
;
403 if ((ret_ga
= getaddrinfo(addr
, NULL
, &hints
, &res
))) {
404 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga
));
408 if (res
->ai_family
== AF_INET
&& prefix
> 32)
409 errx(1, "prefix too long for AF_INET");
410 else if (res
->ai_family
== AF_INET6
&& prefix
> 128)
411 errx(1, "prefix too long for AF_INET6");
415 switch (res
->ai_family
) {
417 bzero(&mask
->v4
, sizeof(mask
->v4
));
418 mask
->v4
.s_addr
= htonl((u_int32_t
)
419 (0xffffffffffULL
<< (32 - prefix
)));
422 bzero(&mask
->v6
, sizeof(mask
->v6
));
424 memset((void *)&mask
->v6
, 0xff, q
);
426 *((u_char
*)&mask
->v6
+ q
) =
427 (0xff00 >> r
) & 0xff;
434 pfctl_kill_src_nodes(int dev
, const char *iface __unused
, int opts
)
436 struct pfioc_src_node_kill psnk
;
437 struct addrinfo
*res
[2], *resp
[2];
438 struct sockaddr last_src
, last_dst
;
439 int killed
, sources
, dests
;
442 killed
= sources
= dests
= 0;
444 memset(&psnk
, 0, sizeof(psnk
));
445 memset(&psnk
.psnk_src
.addr
.v
.a
.mask
, 0xff,
446 sizeof(psnk
.psnk_src
.addr
.v
.a
.mask
));
447 memset(&last_src
, 0xff, sizeof(last_src
));
448 memset(&last_dst
, 0xff, sizeof(last_dst
));
450 pfctl_addrprefix(src_node_kill
[0], &psnk
.psnk_src
.addr
.v
.a
.mask
);
452 if ((ret_ga
= getaddrinfo(src_node_kill
[0], NULL
, NULL
, &res
[0]))) {
453 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga
));
456 for (resp
[0] = res
[0]; resp
[0]; resp
[0] = resp
[0]->ai_next
) {
457 if (resp
[0]->ai_addr
== NULL
)
459 /* We get lots of duplicates. Catch the easy ones */
460 if (memcmp(&last_src
, resp
[0]->ai_addr
, sizeof(last_src
)) == 0)
462 last_src
= *(struct sockaddr
*)resp
[0]->ai_addr
;
464 psnk
.psnk_af
= resp
[0]->ai_family
;
467 if (psnk
.psnk_af
== AF_INET
)
468 psnk
.psnk_src
.addr
.v
.a
.addr
.v4
=
469 ((struct sockaddr_in
*)resp
[0]->ai_addr
)->sin_addr
;
470 else if (psnk
.psnk_af
== AF_INET6
)
471 psnk
.psnk_src
.addr
.v
.a
.addr
.v6
=
472 ((struct sockaddr_in6
*)resp
[0]->ai_addr
)->
475 errx(1, "Unknown address family %d", psnk
.psnk_af
);
477 if (src_node_killers
> 1) {
479 memset(&psnk
.psnk_dst
.addr
.v
.a
.mask
, 0xff,
480 sizeof(psnk
.psnk_dst
.addr
.v
.a
.mask
));
481 memset(&last_dst
, 0xff, sizeof(last_dst
));
482 pfctl_addrprefix(src_node_kill
[1],
483 &psnk
.psnk_dst
.addr
.v
.a
.mask
);
484 if ((ret_ga
= getaddrinfo(src_node_kill
[1], NULL
, NULL
,
486 errx(1, "getaddrinfo: %s",
487 gai_strerror(ret_ga
));
490 for (resp
[1] = res
[1]; resp
[1];
491 resp
[1] = resp
[1]->ai_next
) {
492 if (resp
[1]->ai_addr
== NULL
)
494 if (psnk
.psnk_af
!= resp
[1]->ai_family
)
497 if (memcmp(&last_dst
, resp
[1]->ai_addr
,
498 sizeof(last_dst
)) == 0)
500 last_dst
= *(struct sockaddr
*)resp
[1]->ai_addr
;
504 if (psnk
.psnk_af
== AF_INET
)
505 psnk
.psnk_dst
.addr
.v
.a
.addr
.v4
=
506 ((struct sockaddr_in
*)resp
[1]->
508 else if (psnk
.psnk_af
== AF_INET6
)
509 psnk
.psnk_dst
.addr
.v
.a
.addr
.v6
=
510 ((struct sockaddr_in6
*)resp
[1]->
513 errx(1, "Unknown address family %d",
516 if (ioctl(dev
, DIOCKILLSRCNODES
, &psnk
))
517 err(1, "DIOCKILLSRCNODES");
518 killed
+= psnk
.psnk_af
;
519 /* fixup psnk.psnk_af */
520 psnk
.psnk_af
= resp
[1]->ai_family
;
522 freeaddrinfo(res
[1]);
524 if (ioctl(dev
, DIOCKILLSRCNODES
, &psnk
))
525 err(1, "DIOCKILLSRCNODES");
526 killed
+= psnk
.psnk_af
;
527 /* fixup psnk.psnk_af */
528 psnk
.psnk_af
= res
[0]->ai_family
;
532 freeaddrinfo(res
[0]);
534 if ((opts
& PF_OPT_QUIET
) == 0)
535 fprintf(stderr
, "killed %d src nodes from %d sources and %d "
536 "destinations\n", killed
, sources
, dests
);
541 pfctl_kill_states(int dev
, const char *iface
, int opts
)
543 struct pfioc_state_kill psk
;
544 struct addrinfo
*res
[2], *resp
[2];
545 struct sockaddr last_src
, last_dst
;
546 int killed
, sources
, dests
;
549 killed
= sources
= dests
= 0;
551 memset(&psk
, 0, sizeof(psk
));
552 memset(&psk
.psk_src
.addr
.v
.a
.mask
, 0xff,
553 sizeof(psk
.psk_src
.addr
.v
.a
.mask
));
554 memset(&last_src
, 0xff, sizeof(last_src
));
555 memset(&last_dst
, 0xff, sizeof(last_dst
));
556 if (iface
!= NULL
&& strlcpy(psk
.psk_ifname
, iface
,
557 sizeof(psk
.psk_ifname
)) >= sizeof(psk
.psk_ifname
))
558 errx(1, "invalid interface: %s", iface
);
560 pfctl_addrprefix(state_kill
[0], &psk
.psk_src
.addr
.v
.a
.mask
);
562 if ((ret_ga
= getaddrinfo(state_kill
[0], NULL
, NULL
, &res
[0]))) {
563 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga
));
566 for (resp
[0] = res
[0]; resp
[0]; resp
[0] = resp
[0]->ai_next
) {
567 if (resp
[0]->ai_addr
== NULL
)
569 /* We get lots of duplicates. Catch the easy ones */
570 if (memcmp(&last_src
, resp
[0]->ai_addr
, sizeof(last_src
)) == 0)
572 last_src
= *(struct sockaddr
*)resp
[0]->ai_addr
;
574 psk
.psk_af
= resp
[0]->ai_family
;
577 if (psk
.psk_af
== AF_INET
)
578 psk
.psk_src
.addr
.v
.a
.addr
.v4
=
579 ((struct sockaddr_in
*)resp
[0]->ai_addr
)->sin_addr
;
580 else if (psk
.psk_af
== AF_INET6
)
581 psk
.psk_src
.addr
.v
.a
.addr
.v6
=
582 ((struct sockaddr_in6
*)resp
[0]->ai_addr
)->
585 errx(1, "Unknown address family %d", psk
.psk_af
);
587 if (state_killers
> 1) {
589 memset(&psk
.psk_dst
.addr
.v
.a
.mask
, 0xff,
590 sizeof(psk
.psk_dst
.addr
.v
.a
.mask
));
591 memset(&last_dst
, 0xff, sizeof(last_dst
));
592 pfctl_addrprefix(state_kill
[1],
593 &psk
.psk_dst
.addr
.v
.a
.mask
);
594 if ((ret_ga
= getaddrinfo(state_kill
[1], NULL
, NULL
,
596 errx(1, "getaddrinfo: %s",
597 gai_strerror(ret_ga
));
600 for (resp
[1] = res
[1]; resp
[1];
601 resp
[1] = resp
[1]->ai_next
) {
602 if (resp
[1]->ai_addr
== NULL
)
604 if (psk
.psk_af
!= resp
[1]->ai_family
)
607 if (memcmp(&last_dst
, resp
[1]->ai_addr
,
608 sizeof(last_dst
)) == 0)
610 last_dst
= *(struct sockaddr
*)resp
[1]->ai_addr
;
614 if (psk
.psk_af
== AF_INET
)
615 psk
.psk_dst
.addr
.v
.a
.addr
.v4
=
616 ((struct sockaddr_in
*)resp
[1]->
618 else if (psk
.psk_af
== AF_INET6
)
619 psk
.psk_dst
.addr
.v
.a
.addr
.v6
=
620 ((struct sockaddr_in6
*)resp
[1]->
623 errx(1, "Unknown address family %d",
626 if (ioctl(dev
, DIOCKILLSTATES
, &psk
))
627 err(1, "DIOCKILLSTATES");
628 killed
+= psk
.psk_af
;
629 /* fixup psk.psk_af */
630 psk
.psk_af
= resp
[1]->ai_family
;
632 freeaddrinfo(res
[1]);
634 if (ioctl(dev
, DIOCKILLSTATES
, &psk
))
635 err(1, "DIOCKILLSTATES");
636 killed
+= psk
.psk_af
;
637 /* fixup psk.psk_af */
638 psk
.psk_af
= res
[0]->ai_family
;
642 freeaddrinfo(res
[0]);
644 if ((opts
& PF_OPT_QUIET
) == 0)
645 fprintf(stderr
, "killed %d states from %d sources and %d "
646 "destinations\n", killed
, sources
, dests
);
651 pfctl_get_pool(int dev
, struct pf_pool
*pool
, u_int32_t nr
,
652 u_int32_t ticket
, int r_action
, char *anchorname
)
654 struct pfioc_pooladdr pp
;
655 struct pf_pooladdr
*pa
;
658 memset(&pp
, 0, sizeof(pp
));
659 memcpy(pp
.anchor
, anchorname
, sizeof(pp
.anchor
));
660 pp
.r_action
= r_action
;
663 if (ioctl(dev
, DIOCGETADDRS
, &pp
)) {
664 warn("DIOCGETADDRS");
668 TAILQ_INIT(&pool
->list
);
669 for (pnr
= 0; pnr
< mpnr
; ++pnr
) {
671 if (ioctl(dev
, DIOCGETADDR
, &pp
)) {
675 pa
= calloc(1, sizeof(struct pf_pooladdr
));
678 bcopy(&pp
.addr
, pa
, sizeof(struct pf_pooladdr
));
679 TAILQ_INSERT_TAIL(&pool
->list
, pa
, entries
);
686 pfctl_move_pool(struct pf_pool
*src
, struct pf_pool
*dst
)
688 struct pf_pooladdr
*pa
;
690 while ((pa
= TAILQ_FIRST(&src
->list
)) != NULL
) {
691 TAILQ_REMOVE(&src
->list
, pa
, entries
);
692 TAILQ_INSERT_TAIL(&dst
->list
, pa
, entries
);
697 pfctl_clear_pool(struct pf_pool
*pool
)
699 struct pf_pooladdr
*pa
;
701 while ((pa
= TAILQ_FIRST(&pool
->list
)) != NULL
) {
702 TAILQ_REMOVE(&pool
->list
, pa
, entries
);
708 pfctl_print_rule_counters(struct pf_rule
*rule
, int opts
)
710 if (opts
& PF_OPT_DEBUG
) {
711 const char *t
[PF_SKIP_COUNT
] = { "i", "d", "f",
712 "p", "sa", "sp", "da", "dp" };
715 printf(" [ Skip steps: ");
716 for (i
= 0; i
< PF_SKIP_COUNT
; ++i
) {
717 if (rule
->skip
[i
].nr
== rule
->nr
+ 1)
720 if (rule
->skip
[i
].nr
== (uint32_t)(-1))
723 printf("%u ", rule
->skip
[i
].nr
);
727 printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
728 rule
->qname
, rule
->qid
, rule
->pqname
, rule
->pqid
);
730 if (opts
& PF_OPT_VERBOSE
) {
731 printf(" [ Evaluations: %-8llu Packets: %-8llu "
732 "Bytes: %-10llu States: %-6u]\n",
733 (unsigned long long)rule
->evaluations
,
734 (unsigned long long)(rule
->packets
[0] +
736 (unsigned long long)(rule
->bytes
[0] +
737 rule
->bytes
[1]), rule
->states
);
738 if (!(opts
& PF_OPT_DEBUG
))
739 printf(" [ Inserted: uid %u pid %u ]\n",
740 (unsigned)rule
->cuid
, (unsigned)rule
->cpid
);
745 pfctl_print_title(const char *title
)
750 printf("%s\n", title
);
754 pfctl_show_rules(int dev
, char *path
, int opts
, enum pfctl_show format
,
755 char *anchorname
, int depth
)
757 struct pfioc_rule pr
;
758 u_int32_t nr
, mnr
, header
= 0;
759 int rule_numbers
= opts
& (PF_OPT_VERBOSE2
| PF_OPT_DEBUG
);
760 int len
= strlen(path
);
765 snprintf(&path
[len
], MAXPATHLEN
- len
, "/%s", anchorname
);
767 snprintf(&path
[len
], MAXPATHLEN
- len
, "%s", anchorname
);
769 memset(&pr
, 0, sizeof(pr
));
770 memcpy(pr
.anchor
, path
, sizeof(pr
.anchor
));
771 if (opts
& PF_OPT_SHOWALL
) {
772 pr
.rule
.action
= PF_PASS
;
773 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
774 warn("DIOCGETRULES");
779 pr
.rule
.action
= PF_SCRUB
;
780 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
781 warn("DIOCGETRULES");
784 if (opts
& PF_OPT_SHOWALL
) {
785 if (format
== PFCTL_SHOW_RULES
&& (pr
.nr
> 0 || header
))
786 pfctl_print_title("FILTER RULES:");
787 else if (format
== PFCTL_SHOW_LABELS
&& labels
)
788 pfctl_print_title("LABEL COUNTERS:");
791 if (opts
& PF_OPT_CLRRULECTRS
)
792 pr
.action
= PF_GET_CLR_CNTR
;
794 for (nr
= 0; nr
< mnr
; ++nr
) {
796 if (ioctl(dev
, DIOCGETRULE
, &pr
)) {
801 if (pfctl_get_pool(dev
, &pr
.rule
.rpool
,
802 nr
, pr
.ticket
, PF_SCRUB
, path
) != 0)
806 case PFCTL_SHOW_LABELS
:
807 if (pr
.rule
.label
[0]) {
808 printf("%s ", pr
.rule
.label
);
809 printf("%llu %llu %llu %llu %llu %llu %llu\n",
810 (unsigned long long)pr
.rule
.evaluations
,
811 (unsigned long long)(pr
.rule
.packets
[0] +
813 (unsigned long long)(pr
.rule
.bytes
[0] +
815 (unsigned long long)pr
.rule
.packets
[0],
816 (unsigned long long)pr
.rule
.bytes
[0],
817 (unsigned long long)pr
.rule
.packets
[1],
818 (unsigned long long)pr
.rule
.bytes
[1]);
821 case PFCTL_SHOW_RULES
:
822 if (pr
.rule
.label
[0] && (opts
& PF_OPT_SHOWALL
))
824 print_rule(&pr
.rule
, pr
.anchor_call
, rule_numbers
);
826 pfctl_print_rule_counters(&pr
.rule
, opts
);
828 case PFCTL_SHOW_NOTHING
:
831 pfctl_clear_pool(&pr
.rule
.rpool
);
833 pr
.rule
.action
= PF_PASS
;
834 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
835 warn("DIOCGETRULES");
839 for (nr
= 0; nr
< mnr
; ++nr
) {
841 if (ioctl(dev
, DIOCGETRULE
, &pr
)) {
846 if (pfctl_get_pool(dev
, &pr
.rule
.rpool
,
847 nr
, pr
.ticket
, PF_PASS
, path
) != 0)
851 case PFCTL_SHOW_LABELS
:
852 if (pr
.rule
.label
[0]) {
853 printf("%s ", pr
.rule
.label
);
854 printf("%llu %llu %llu %llu %llu %llu %llu\n",
855 (unsigned long long)pr
.rule
.evaluations
,
856 (unsigned long long)(pr
.rule
.packets
[0] +
858 (unsigned long long)(pr
.rule
.bytes
[0] +
860 (unsigned long long)pr
.rule
.packets
[0],
861 (unsigned long long)pr
.rule
.bytes
[0],
862 (unsigned long long)pr
.rule
.packets
[1],
863 (unsigned long long)pr
.rule
.bytes
[1]);
866 case PFCTL_SHOW_RULES
:
868 if (pr
.rule
.label
[0] && (opts
& PF_OPT_SHOWALL
))
870 INDENT(depth
, !(opts
& PF_OPT_VERBOSE
));
871 if (pr
.anchor_call
[0] &&
872 ((((p
= strrchr(pr
.anchor_call
, '_')) != NULL
) &&
873 ((void *)p
== (void *)pr
.anchor_call
||
874 *(--p
) == '/')) || (opts
& PF_OPT_RECURSE
))) {
876 if ((p
= strrchr(pr
.anchor_call
, '/')) !=
880 p
= &pr
.anchor_call
[0];
882 p
= &pr
.anchor_call
[0];
884 print_rule(&pr
.rule
, p
, rule_numbers
);
889 pfctl_print_rule_counters(&pr
.rule
, opts
);
891 pfctl_show_rules(dev
, path
, opts
, format
,
893 INDENT(depth
, !(opts
& PF_OPT_VERBOSE
));
897 case PFCTL_SHOW_NOTHING
:
900 pfctl_clear_pool(&pr
.rule
.rpool
);
911 pfctl_show_nat(int dev
, int opts
, char *anchorname
)
913 struct pfioc_rule pr
;
915 static int nattype
[3] = { PF_NAT
, PF_RDR
, PF_BINAT
};
916 int i
, dotitle
= opts
& PF_OPT_SHOWALL
;
918 memset(&pr
, 0, sizeof(pr
));
919 memcpy(pr
.anchor
, anchorname
, sizeof(pr
.anchor
));
920 for (i
= 0; i
< 3; i
++) {
921 pr
.rule
.action
= nattype
[i
];
922 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
923 warn("DIOCGETRULES");
927 for (nr
= 0; nr
< mnr
; ++nr
) {
929 if (ioctl(dev
, DIOCGETRULE
, &pr
)) {
933 if (pfctl_get_pool(dev
, &pr
.rule
.rpool
, nr
,
934 pr
.ticket
, nattype
[i
], anchorname
) != 0)
937 pfctl_print_title("TRANSLATION RULES:");
940 print_rule(&pr
.rule
, pr
.anchor_call
,
941 opts
& PF_OPT_VERBOSE2
);
943 pfctl_print_rule_counters(&pr
.rule
, opts
);
944 pfctl_clear_pool(&pr
.rule
.rpool
);
951 pfctl_show_src_nodes(int dev
, int opts
)
953 struct pfioc_src_nodes psn
;
954 struct pf_src_node
*p
;
955 char *inbuf
= NULL
, *newinbuf
= NULL
;
959 memset(&psn
, 0, sizeof(psn
));
963 newinbuf
= realloc(inbuf
, len
);
964 if (newinbuf
== NULL
)
966 psn
.psn_buf
= inbuf
= newinbuf
;
968 if (ioctl(dev
, DIOCGETSRCNODES
, &psn
) < 0) {
969 warn("DIOCGETSRCNODES");
973 if (psn
.psn_len
+ sizeof(struct pfioc_src_nodes
) < len
)
975 if (len
== 0 && psn
.psn_len
== 0)
977 if (len
== 0 && psn
.psn_len
!= 0)
979 if (psn
.psn_len
== 0)
980 goto done
; /* no src_nodes */
983 p
= psn
.psn_src_nodes
;
984 if (psn
.psn_len
> 0 && (opts
& PF_OPT_SHOWALL
))
985 pfctl_print_title("SOURCE TRACKING NODES:");
986 for (i
= 0; i
< psn
.psn_len
; i
+= sizeof(*p
)) {
987 print_src_node(p
, opts
);
996 pfctl_show_states(int dev
, const char *iface
, int opts
)
998 struct pfioc_states ps
;
999 struct pfsync_state
*p
;
1000 char *inbuf
= NULL
, *newinbuf
= NULL
;
1002 int i
, dotitle
= (opts
& PF_OPT_SHOWALL
);
1004 memset(&ps
, 0, sizeof(ps
));
1008 newinbuf
= realloc(inbuf
, len
);
1009 if (newinbuf
== NULL
)
1011 ps
.ps_buf
= inbuf
= newinbuf
;
1013 if (ioctl(dev
, DIOCGETSTATES
, &ps
) < 0) {
1014 warn("DIOCGETSTATES");
1018 if (ps
.ps_len
+ sizeof(struct pfioc_states
) < len
)
1020 if (len
== 0 && ps
.ps_len
== 0)
1022 if (len
== 0 && ps
.ps_len
!= 0)
1025 goto done
; /* no states */
1029 for (i
= 0; i
< ps
.ps_len
; i
+= sizeof(*p
), p
++) {
1030 if (iface
!= NULL
&& strcmp(p
->ifname
, iface
))
1033 pfctl_print_title("STATES:");
1036 print_state(p
, opts
);
1044 pfctl_show_status(int dev
, int opts
)
1046 struct pf_status status
;
1048 if (ioctl(dev
, DIOCGETSTATUS
, &status
)) {
1049 warn("DIOCGETSTATUS");
1052 if (opts
& PF_OPT_SHOWALL
)
1053 pfctl_print_title("INFO:");
1054 print_status(&status
, opts
);
1059 pfctl_show_timeouts(int dev
, int opts
)
1064 if (opts
& PF_OPT_SHOWALL
)
1065 pfctl_print_title("TIMEOUTS:");
1066 memset(&pt
, 0, sizeof(pt
));
1067 for (i
= 0; pf_timeouts
[i
].name
; i
++) {
1068 pt
.timeout
= pf_timeouts
[i
].timeout
;
1069 if (ioctl(dev
, DIOCGETTIMEOUT
, &pt
))
1070 err(1, "DIOCGETTIMEOUT");
1071 printf("%-20s %10d", pf_timeouts
[i
].name
, pt
.seconds
);
1072 if (pf_timeouts
[i
].timeout
>= PFTM_ADAPTIVE_START
&&
1073 pf_timeouts
[i
].timeout
<= PFTM_ADAPTIVE_END
)
1084 pfctl_show_limits(int dev
, int opts
)
1086 struct pfioc_limit pl
;
1089 if (opts
& PF_OPT_SHOWALL
)
1090 pfctl_print_title("LIMITS:");
1091 memset(&pl
, 0, sizeof(pl
));
1092 for (i
= 0; pf_limits
[i
].name
; i
++) {
1093 pl
.index
= pf_limits
[i
].index
;
1094 if (ioctl(dev
, DIOCGETLIMIT
, &pl
))
1095 err(1, "DIOCGETLIMIT");
1096 printf("%-13s ", pf_limits
[i
].name
);
1097 if (pl
.limit
== UINT_MAX
)
1098 printf("unlimited\n");
1100 printf("hard limit %8u\n", pl
.limit
);
1105 /* callbacks for rule/nat/rdr/addr */
1107 pfctl_add_pool(struct pfctl
*pf
, struct pf_pool
*p
, sa_family_t af
)
1109 struct pf_pooladdr
*pa
;
1111 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1112 if (ioctl(pf
->dev
, DIOCBEGINADDRS
, &pf
->paddr
))
1113 err(1, "DIOCBEGINADDRS");
1117 TAILQ_FOREACH(pa
, &p
->list
, entries
) {
1118 memcpy(&pf
->paddr
.addr
, pa
, sizeof(struct pf_pooladdr
));
1119 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1120 if (ioctl(pf
->dev
, DIOCADDADDR
, &pf
->paddr
))
1121 err(1, "DIOCADDADDR");
1128 pfctl_add_rule(struct pfctl
*pf
, struct pf_rule
*r
, const char *anchor_call
)
1131 struct pf_rule
*rule
;
1132 struct pf_ruleset
*rs
;
1135 rs_num
= pf_get_ruleset_number(r
->action
);
1136 if (rs_num
== PF_RULESET_MAX
)
1137 errx(1, "Invalid rule type %d", r
->action
);
1139 rs
= &pf
->anchor
->ruleset
;
1141 if (anchor_call
[0] && r
->anchor
== NULL
) {
1143 * Don't make non-brace anchors part of the main anchor pool.
1145 if ((r
->anchor
= calloc(1, sizeof(*r
->anchor
))) == NULL
)
1146 err(1, "pfctl_add_rule: calloc");
1148 pf_init_ruleset(&r
->anchor
->ruleset
);
1149 r
->anchor
->ruleset
.anchor
= r
->anchor
;
1150 if (strlcpy(r
->anchor
->path
, anchor_call
,
1151 sizeof(rule
->anchor
->path
)) >= sizeof(rule
->anchor
->path
))
1152 errx(1, "pfctl_add_rule: strlcpy");
1153 if ((p
= strrchr(anchor_call
, '/')) != NULL
) {
1155 err(1, "pfctl_add_rule: bad anchor name %s",
1158 p
= __DECONST(char *, anchor_call
);
1159 if (strlcpy(r
->anchor
->name
, p
,
1160 sizeof(rule
->anchor
->name
)) >= sizeof(rule
->anchor
->name
))
1161 errx(1, "pfctl_add_rule: strlcpy");
1164 if ((rule
= calloc(1, sizeof(*rule
))) == NULL
)
1166 bcopy(r
, rule
, sizeof(*rule
));
1167 TAILQ_INIT(&rule
->rpool
.list
);
1168 pfctl_move_pool(&r
->rpool
, &rule
->rpool
);
1170 TAILQ_INSERT_TAIL(rs
->rules
[rs_num
].active
.ptr
, rule
, entries
);
1175 pfctl_ruleset_trans(struct pfctl
*pf
, char *path
, struct pf_anchor
*a
)
1177 int osize
= pf
->trans
->pfrb_size
;
1179 if ((pf
->loadopt
& PFCTL_FLAG_NAT
) != 0) {
1180 if (pfctl_add_trans(pf
->trans
, PF_RULESET_NAT
, path
) ||
1181 pfctl_add_trans(pf
->trans
, PF_RULESET_BINAT
, path
) ||
1182 pfctl_add_trans(pf
->trans
, PF_RULESET_RDR
, path
))
1185 if (a
== pf
->astack
[0] && ((altqsupport
&&
1186 (pf
->loadopt
& PFCTL_FLAG_ALTQ
) != 0))) {
1187 if (pfctl_add_trans(pf
->trans
, PF_RULESET_ALTQ
, path
))
1190 if ((pf
->loadopt
& PFCTL_FLAG_FILTER
) != 0) {
1191 if (pfctl_add_trans(pf
->trans
, PF_RULESET_SCRUB
, path
) ||
1192 pfctl_add_trans(pf
->trans
, PF_RULESET_FILTER
, path
))
1195 if (pf
->loadopt
& PFCTL_FLAG_TABLE
)
1196 if (pfctl_add_trans(pf
->trans
, PF_RULESET_TABLE
, path
))
1198 if (pfctl_trans(pf
->dev
, pf
->trans
, DIOCXBEGIN
, osize
))
1205 pfctl_load_ruleset(struct pfctl
*pf
, char *path
, struct pf_ruleset
*rs
,
1206 int rs_num
, int depth
)
1209 int error
, len
= strlen(path
);
1212 pf
->anchor
= rs
->anchor
;
1215 snprintf(&path
[len
], MAXPATHLEN
- len
, "/%s", pf
->anchor
->name
);
1217 snprintf(&path
[len
], MAXPATHLEN
- len
, "%s", pf
->anchor
->name
);
1220 if (TAILQ_FIRST(rs
->rules
[rs_num
].active
.ptr
) != NULL
) {
1222 if (pf
->opts
& PF_OPT_VERBOSE
)
1224 if ((pf
->opts
& PF_OPT_NOACTION
) == 0 &&
1225 (error
= pfctl_ruleset_trans(pf
,
1226 path
, rs
->anchor
))) {
1227 printf("pfctl_load_rulesets: "
1228 "pfctl_ruleset_trans %d\n", error
);
1231 } else if (pf
->opts
& PF_OPT_VERBOSE
)
1236 if (pf
->optimize
&& rs_num
== PF_RULESET_FILTER
)
1237 pfctl_optimize_ruleset(pf
, rs
);
1239 while ((r
= TAILQ_FIRST(rs
->rules
[rs_num
].active
.ptr
)) != NULL
) {
1240 TAILQ_REMOVE(rs
->rules
[rs_num
].active
.ptr
, r
, entries
);
1241 if ((error
= pfctl_load_rule(pf
, path
, r
, depth
)))
1244 if ((error
= pfctl_load_ruleset(pf
, path
,
1245 &r
->anchor
->ruleset
, rs_num
, depth
+ 1)))
1247 } else if (pf
->opts
& PF_OPT_VERBOSE
)
1251 if (brace
&& pf
->opts
& PF_OPT_VERBOSE
) {
1252 INDENT(depth
- 1, (pf
->opts
& PF_OPT_VERBOSE
));
1265 pfctl_load_rule(struct pfctl
*pf
, char *path
, struct pf_rule
*r
, int depth
)
1267 u_int8_t rs_num
= pf_get_ruleset_number(r
->action
);
1269 struct pfioc_rule pr
;
1270 int len
= strlen(path
);
1272 bzero(&pr
, sizeof(pr
));
1273 /* set up anchor before adding to path for anchor_call */
1274 if ((pf
->opts
& PF_OPT_NOACTION
) == 0)
1275 pr
.ticket
= pfctl_get_ticket(pf
->trans
, rs_num
, path
);
1276 if (strlcpy(pr
.anchor
, path
, sizeof(pr
.anchor
)) >= sizeof(pr
.anchor
))
1277 errx(1, "pfctl_load_rule: strlcpy");
1280 if (r
->anchor
->match
) {
1282 snprintf(&path
[len
], MAXPATHLEN
- len
,
1283 "/%s", r
->anchor
->name
);
1285 snprintf(&path
[len
], MAXPATHLEN
- len
,
1286 "%s", r
->anchor
->name
);
1289 name
= r
->anchor
->path
;
1291 name
= __DECONST(char *, "");
1293 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1294 if (pfctl_add_pool(pf
, &r
->rpool
, r
->af
))
1296 pr
.pool_ticket
= pf
->paddr
.ticket
;
1297 memcpy(&pr
.rule
, r
, sizeof(pr
.rule
));
1298 if (r
->anchor
&& strlcpy(pr
.anchor_call
, name
,
1299 sizeof(pr
.anchor_call
)) >= sizeof(pr
.anchor_call
))
1300 errx(1, "pfctl_load_rule: strlcpy");
1301 if (ioctl(pf
->dev
, DIOCADDRULE
, &pr
))
1302 err(1, "DIOCADDRULE");
1305 if (pf
->opts
& PF_OPT_VERBOSE
) {
1306 INDENT(depth
, !(pf
->opts
& PF_OPT_VERBOSE2
));
1307 print_rule(r
, r
->anchor
? r
->anchor
->name
: "",
1308 pf
->opts
& PF_OPT_VERBOSE2
);
1311 pfctl_clear_pool(&r
->rpool
);
1316 pfctl_add_altq(struct pfctl
*pf
, struct pf_altq
*a
)
1319 (loadopt
& PFCTL_FLAG_ALTQ
) != 0) {
1320 memcpy(&pf
->paltq
->altq
, a
, sizeof(struct pf_altq
));
1321 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1322 if (ioctl(pf
->dev
, DIOCADDALTQ
, pf
->paltq
)) {
1324 errx(1, "qtype not configured");
1325 else if (errno
== ENODEV
)
1326 errx(1, "%s: driver does not support "
1329 err(1, "DIOCADDALTQ");
1332 pfaltq_store(&pf
->paltq
->altq
);
1338 pfctl_rules(int dev
, char *filename
, FILE *fin
, int opts
, int optimize
,
1339 char *anchorname
, struct pfr_buffer
*trans
)
1341 #define ERR(x) do { warn(x); goto _error; } while(0)
1342 #define ERRX(x) do { warnx(x); goto _error; } while(0)
1344 struct pfr_buffer
*t
, buf
;
1345 struct pfioc_altq pa
;
1347 struct pf_ruleset
*rs
;
1348 struct pfr_table trs
;
1352 RB_INIT(&pf_anchors
);
1353 memset(&pf_main_anchor
, 0, sizeof(pf_main_anchor
));
1354 pf_init_ruleset(&pf_main_anchor
.ruleset
);
1355 pf_main_anchor
.ruleset
.anchor
= &pf_main_anchor
;
1356 if (trans
== NULL
) {
1357 bzero(&buf
, sizeof(buf
));
1358 buf
.pfrb_type
= PFRB_TRANS
;
1363 osize
= t
->pfrb_size
;
1366 memset(&pa
, 0, sizeof(pa
));
1367 memset(&pf
, 0, sizeof(pf
));
1368 memset(&trs
, 0, sizeof(trs
));
1369 if ((path
= calloc(1, MAXPATHLEN
)) == NULL
)
1370 ERRX("pfctl_rules: calloc");
1371 if (strlcpy(trs
.pfrt_anchor
, anchorname
,
1372 sizeof(trs
.pfrt_anchor
)) >= sizeof(trs
.pfrt_anchor
))
1373 ERRX("pfctl_rules: strlcpy");
1377 pf
.optimize
= optimize
;
1378 pf
.loadopt
= loadopt
;
1380 /* non-brace anchor, create without resolving the path */
1381 if ((pf
.anchor
= calloc(1, sizeof(*pf
.anchor
))) == NULL
)
1382 ERRX("pfctl_rules: calloc");
1383 rs
= &pf
.anchor
->ruleset
;
1384 pf_init_ruleset(rs
);
1385 rs
->anchor
= pf
.anchor
;
1386 if (strlcpy(pf
.anchor
->path
, anchorname
,
1387 sizeof(pf
.anchor
->path
)) >= sizeof(pf
.anchor
->path
))
1388 errx(1, "pfctl_add_rule: strlcpy");
1389 if (strlcpy(pf
.anchor
->name
, anchorname
,
1390 sizeof(pf
.anchor
->name
)) >= sizeof(pf
.anchor
->name
))
1391 errx(1, "pfctl_add_rule: strlcpy");
1394 pf
.astack
[0] = pf
.anchor
;
1397 pf
.loadopt
&= ~PFCTL_FLAG_ALTQ
;
1400 pfctl_init_options(&pf
);
1402 if ((opts
& PF_OPT_NOACTION
) == 0) {
1404 * XXX For the time being we need to open transactions for
1405 * the main ruleset before parsing, because tables are still
1406 * loaded at parse time.
1408 if (pfctl_ruleset_trans(&pf
, anchorname
, pf
.anchor
))
1409 ERRX("pfctl_rules");
1410 if (altqsupport
&& (pf
.loadopt
& PFCTL_FLAG_ALTQ
))
1412 pfctl_get_ticket(t
, PF_RULESET_ALTQ
, anchorname
);
1413 if (pf
.loadopt
& PFCTL_FLAG_TABLE
)
1414 pf
.astack
[0]->ruleset
.tticket
=
1415 pfctl_get_ticket(t
, PF_RULESET_TABLE
, anchorname
);
1418 if (parse_rules(fin
, &pf
) < 0) {
1419 if ((opts
& PF_OPT_NOACTION
) == 0)
1420 ERRX("Syntax error in config file: "
1421 "pf rules not loaded");
1426 if ((pf
.loadopt
& PFCTL_FLAG_FILTER
&&
1427 (pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_SCRUB
, 0))) ||
1428 (pf
.loadopt
& PFCTL_FLAG_NAT
&&
1429 (pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_NAT
, 0) ||
1430 pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_RDR
, 0) ||
1431 pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_BINAT
, 0))) ||
1432 (pf
.loadopt
& PFCTL_FLAG_FILTER
&&
1433 pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_FILTER
, 0))) {
1434 if ((opts
& PF_OPT_NOACTION
) == 0)
1435 ERRX("Unable to load rules into kernel");
1440 if ((altqsupport
&& (pf
.loadopt
& PFCTL_FLAG_ALTQ
) != 0))
1441 if (check_commit_altq(dev
, opts
) != 0)
1442 ERRX("errors in altq config");
1449 /* process "load anchor" directives */
1451 if (pfctl_load_anchors(dev
, &pf
, t
) == -1)
1452 ERRX("load anchors");
1454 if (trans
== NULL
&& (opts
& PF_OPT_NOACTION
) == 0) {
1456 if (pfctl_load_options(&pf
))
1458 if (pfctl_trans(dev
, t
, DIOCXCOMMIT
, osize
))
1464 if (trans
== NULL
) { /* main ruleset */
1465 if ((opts
& PF_OPT_NOACTION
) == 0)
1466 if (pfctl_trans(dev
, t
, DIOCXROLLBACK
, osize
))
1467 err(1, "DIOCXROLLBACK");
1469 } else { /* sub ruleset */
1470 if (fin
!= NULL
&& fin
!= stdin
)
1480 pfctl_fopen(const char *name
, const char *mode
)
1485 fp
= fopen(name
, mode
);
1488 if (fstat(fileno(fp
), &st
)) {
1492 if (S_ISDIR(st
.st_mode
)) {
1501 pfctl_init_options(struct pfctl
*pf
)
1506 pf
->timeout
[PFTM_TCP_FIRST_PACKET
] = PFTM_TCP_FIRST_PACKET_VAL
;
1507 pf
->timeout
[PFTM_TCP_OPENING
] = PFTM_TCP_OPENING_VAL
;
1508 pf
->timeout
[PFTM_TCP_ESTABLISHED
] = PFTM_TCP_ESTABLISHED_VAL
;
1509 pf
->timeout
[PFTM_TCP_CLOSING
] = PFTM_TCP_CLOSING_VAL
;
1510 pf
->timeout
[PFTM_TCP_FIN_WAIT
] = PFTM_TCP_FIN_WAIT_VAL
;
1511 pf
->timeout
[PFTM_TCP_CLOSED
] = PFTM_TCP_CLOSED_VAL
;
1512 pf
->timeout
[PFTM_UDP_FIRST_PACKET
] = PFTM_UDP_FIRST_PACKET_VAL
;
1513 pf
->timeout
[PFTM_UDP_SINGLE
] = PFTM_UDP_SINGLE_VAL
;
1514 pf
->timeout
[PFTM_UDP_MULTIPLE
] = PFTM_UDP_MULTIPLE_VAL
;
1515 pf
->timeout
[PFTM_ICMP_FIRST_PACKET
] = PFTM_ICMP_FIRST_PACKET_VAL
;
1516 pf
->timeout
[PFTM_ICMP_ERROR_REPLY
] = PFTM_ICMP_ERROR_REPLY_VAL
;
1517 pf
->timeout
[PFTM_OTHER_FIRST_PACKET
] = PFTM_OTHER_FIRST_PACKET_VAL
;
1518 pf
->timeout
[PFTM_OTHER_SINGLE
] = PFTM_OTHER_SINGLE_VAL
;
1519 pf
->timeout
[PFTM_OTHER_MULTIPLE
] = PFTM_OTHER_MULTIPLE_VAL
;
1520 pf
->timeout
[PFTM_FRAG
] = PFTM_FRAG_VAL
;
1521 pf
->timeout
[PFTM_INTERVAL
] = PFTM_INTERVAL_VAL
;
1522 pf
->timeout
[PFTM_SRC_NODE
] = PFTM_SRC_NODE_VAL
;
1523 pf
->timeout
[PFTM_TS_DIFF
] = PFTM_TS_DIFF_VAL
;
1524 pf
->timeout
[PFTM_ADAPTIVE_START
] = PFSTATE_ADAPT_START
;
1525 pf
->timeout
[PFTM_ADAPTIVE_END
] = PFSTATE_ADAPT_END
;
1527 pf
->limit
[PF_LIMIT_STATES
] = PFSTATE_HIWAT
;
1528 pf
->limit
[PF_LIMIT_FRAGS
] = PFFRAG_FRENT_HIWAT
;
1529 pf
->limit
[PF_LIMIT_SRC_NODES
] = PFSNODE_HIWAT
;
1530 pf
->limit
[PF_LIMIT_TABLES
] = PFR_KTABLE_HIWAT
;
1531 pf
->limit
[PF_LIMIT_TABLE_ENTRIES
] = PFR_KENTRY_HIWAT
;
1534 mib
[1] = HW_PHYSMEM
;
1536 (void) sysctl(mib
, 2, &mem
, &size
, NULL
, 0);
1537 if (mem
<= 100*1024*1024)
1538 pf
->limit
[PF_LIMIT_TABLE_ENTRIES
] = PFR_KENTRY_HIWAT_SMALL
;
1540 pf
->debug
= PF_DEBUG_URGENT
;
1544 pfctl_load_options(struct pfctl
*pf
)
1548 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1552 for (i
= 0; i
< PF_LIMIT_MAX
; i
++) {
1553 if ((pf
->opts
& PF_OPT_MERGE
) && !pf
->limit_set
[i
])
1555 if (pfctl_load_limit(pf
, i
, pf
->limit
[i
]))
1560 * If we've set the limit, but havn't explicitly set adaptive
1561 * timeouts, do it now with a start of 60% and end of 120%.
1563 if (pf
->limit_set
[PF_LIMIT_STATES
] &&
1564 !pf
->timeout_set
[PFTM_ADAPTIVE_START
] &&
1565 !pf
->timeout_set
[PFTM_ADAPTIVE_END
]) {
1566 pf
->timeout
[PFTM_ADAPTIVE_START
] =
1567 (pf
->limit
[PF_LIMIT_STATES
] / 10) * 6;
1568 pf
->timeout_set
[PFTM_ADAPTIVE_START
] = 1;
1569 pf
->timeout
[PFTM_ADAPTIVE_END
] =
1570 (pf
->limit
[PF_LIMIT_STATES
] / 10) * 12;
1571 pf
->timeout_set
[PFTM_ADAPTIVE_END
] = 1;
1575 for (i
= 0; i
< PFTM_MAX
; i
++) {
1576 if ((pf
->opts
& PF_OPT_MERGE
) && !pf
->timeout_set
[i
])
1578 if (pfctl_load_timeout(pf
, i
, pf
->timeout
[i
]))
1583 if (!(pf
->opts
& PF_OPT_MERGE
) || pf
->debug_set
)
1584 if (pfctl_load_debug(pf
, pf
->debug
))
1588 if (!(pf
->opts
& PF_OPT_MERGE
) || pf
->ifname_set
)
1589 if (pfctl_load_logif(pf
, pf
->ifname
))
1593 if (!(pf
->opts
& PF_OPT_MERGE
) || pf
->hostid_set
)
1594 if (pfctl_load_hostid(pf
, pf
->hostid
))
1601 pfctl_set_limit(struct pfctl
*pf
, const char *opt
, unsigned int limit
)
1606 for (i
= 0; pf_limits
[i
].name
; i
++) {
1607 if (strcasecmp(opt
, pf_limits
[i
].name
) == 0) {
1608 pf
->limit
[pf_limits
[i
].index
] = limit
;
1609 pf
->limit_set
[pf_limits
[i
].index
] = 1;
1613 if (pf_limits
[i
].name
== NULL
) {
1614 warnx("Bad pool name.");
1618 if (pf
->opts
& PF_OPT_VERBOSE
)
1619 printf("set limit %s %d\n", opt
, limit
);
1625 pfctl_load_limit(struct pfctl
*pf
, unsigned int his_index
, unsigned int limit
)
1627 struct pfioc_limit pl
;
1629 memset(&pl
, 0, sizeof(pl
));
1630 pl
.index
= his_index
;
1632 if (ioctl(pf
->dev
, DIOCSETLIMIT
, &pl
)) {
1634 warnx("Current pool size exceeds requested hard limit");
1636 warnx("DIOCSETLIMIT");
1643 pfctl_set_timeout(struct pfctl
*pf
, const char *opt
, int seconds
, int quiet
)
1647 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1650 for (i
= 0; pf_timeouts
[i
].name
; i
++) {
1651 if (strcasecmp(opt
, pf_timeouts
[i
].name
) == 0) {
1652 pf
->timeout
[pf_timeouts
[i
].timeout
] = seconds
;
1653 pf
->timeout_set
[pf_timeouts
[i
].timeout
] = 1;
1658 if (pf_timeouts
[i
].name
== NULL
) {
1659 warnx("Bad timeout name.");
1664 if (pf
->opts
& PF_OPT_VERBOSE
&& ! quiet
)
1665 printf("set timeout %s %d\n", opt
, seconds
);
1671 pfctl_load_timeout(struct pfctl
*pf
, unsigned int timeout
, unsigned int seconds
)
1675 memset(&pt
, 0, sizeof(pt
));
1676 pt
.timeout
= timeout
;
1677 pt
.seconds
= seconds
;
1678 if (ioctl(pf
->dev
, DIOCSETTIMEOUT
, &pt
)) {
1679 warnx("DIOCSETTIMEOUT");
1686 pfctl_set_optimization(struct pfctl
*pf
, const char *opt
)
1688 const struct pf_hint
*hint
;
1691 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1694 for (i
= 0; pf_hints
[i
].name
; i
++)
1695 if (strcasecmp(opt
, pf_hints
[i
].name
) == 0)
1698 hint
= pf_hints
[i
].hint
;
1700 warnx("invalid state timeouts optimization");
1704 for (i
= 0; hint
[i
].name
; i
++)
1705 if ((r
= pfctl_set_timeout(pf
, hint
[i
].name
,
1706 hint
[i
].timeout
, 1)))
1709 if (pf
->opts
& PF_OPT_VERBOSE
)
1710 printf("set optimization %s\n", opt
);
1716 pfctl_set_logif(struct pfctl
*pf
, char *ifname
)
1719 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1722 if (!strcmp(ifname
, "none")) {
1726 pf
->ifname
= strdup(ifname
);
1728 errx(1, "pfctl_set_logif: strdup");
1732 if (pf
->opts
& PF_OPT_VERBOSE
)
1733 printf("set loginterface %s\n", ifname
);
1739 pfctl_load_logif(struct pfctl
*pf
, char *ifname
)
1743 memset(&pi
, 0, sizeof(pi
));
1744 if (ifname
&& strlcpy(pi
.ifname
, ifname
,
1745 sizeof(pi
.ifname
)) >= sizeof(pi
.ifname
)) {
1746 warnx("pfctl_load_logif: strlcpy");
1749 if (ioctl(pf
->dev
, DIOCSETSTATUSIF
, &pi
)) {
1750 warnx("DIOCSETSTATUSIF");
1757 pfctl_set_hostid(struct pfctl
*pf
, u_int32_t hostid
)
1759 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1762 hostid
= htonl(hostid
);
1764 pf
->hostid
= hostid
;
1767 if (pf
->opts
& PF_OPT_VERBOSE
)
1768 printf("set hostid 0x%08x\n", ntohl(hostid
));
1774 pfctl_load_hostid(struct pfctl
*pf __unused
, u_int32_t hostid
)
1776 if (ioctl(dev_fd
, DIOCSETHOSTID
, &hostid
)) {
1777 warnx("DIOCSETHOSTID");
1784 pfctl_set_debug(struct pfctl
*pf
, char *d
)
1788 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1791 if (!strcmp(d
, "none"))
1792 pf
->debug
= PF_DEBUG_NONE
;
1793 else if (!strcmp(d
, "urgent"))
1794 pf
->debug
= PF_DEBUG_URGENT
;
1795 else if (!strcmp(d
, "misc"))
1796 pf
->debug
= PF_DEBUG_MISC
;
1797 else if (!strcmp(d
, "loud"))
1798 pf
->debug
= PF_DEBUG_NOISY
;
1800 warnx("unknown debug level \"%s\"", d
);
1806 if ((pf
->opts
& PF_OPT_NOACTION
) == 0)
1807 if (ioctl(dev_fd
, DIOCSETDEBUG
, &level
))
1808 err(1, "DIOCSETDEBUG");
1810 if (pf
->opts
& PF_OPT_VERBOSE
)
1811 printf("set debug %s\n", d
);
1817 pfctl_load_debug(struct pfctl
*pf
, unsigned int level
)
1819 if (ioctl(pf
->dev
, DIOCSETDEBUG
, &level
)) {
1820 warnx("DIOCSETDEBUG");
1827 pfctl_set_interface_flags(struct pfctl
*pf
, char *ifname
, int flags
, int how
)
1829 struct pfioc_iface pi
;
1831 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1834 bzero(&pi
, sizeof(pi
));
1836 pi
.pfiio_flags
= flags
;
1838 if (strlcpy(pi
.pfiio_name
, ifname
, sizeof(pi
.pfiio_name
)) >=
1839 sizeof(pi
.pfiio_name
))
1840 errx(1, "pfctl_set_interface_flags: strlcpy");
1842 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1844 if (ioctl(pf
->dev
, DIOCCLRIFFLAG
, &pi
))
1845 err(1, "DIOCCLRIFFLAG");
1847 if (ioctl(pf
->dev
, DIOCSETIFFLAG
, &pi
))
1848 err(1, "DIOCSETIFFLAG");
1855 pfctl_debug(int dev
, u_int32_t level
, int opts
)
1857 if (ioctl(dev
, DIOCSETDEBUG
, &level
))
1858 err(1, "DIOCSETDEBUG");
1859 if ((opts
& PF_OPT_QUIET
) == 0) {
1860 fprintf(stderr
, "debug level set to '");
1863 fprintf(stderr
, "none");
1865 case PF_DEBUG_URGENT
:
1866 fprintf(stderr
, "urgent");
1869 fprintf(stderr
, "misc");
1871 case PF_DEBUG_NOISY
:
1872 fprintf(stderr
, "loud");
1875 fprintf(stderr
, "<invalid>");
1878 fprintf(stderr
, "'\n");
1883 pfctl_test_altqsupport(int dev
, int opts
)
1885 struct pfioc_altq pa
;
1887 if (ioctl(dev
, DIOCGETALTQS
, &pa
)) {
1888 if (errno
== ENODEV
) {
1889 if (!(opts
& PF_OPT_QUIET
))
1890 fprintf(stderr
, "No ALTQ support in kernel\n"
1891 "ALTQ related functions disabled\n");
1894 err(1, "DIOCGETALTQS");
1900 pfctl_show_anchors(int dev
, int opts
, char *anchorname
)
1902 struct pfioc_ruleset pr
;
1905 memset(&pr
, 0, sizeof(pr
));
1906 memcpy(pr
.path
, anchorname
, sizeof(pr
.path
));
1907 if (ioctl(dev
, DIOCGETRULESETS
, &pr
)) {
1908 if (errno
== EINVAL
)
1909 fprintf(stderr
, "Anchor '%s' not found.\n",
1912 err(1, "DIOCGETRULESETS");
1916 for (nr
= 0; nr
< mnr
; ++nr
) {
1917 char sub
[MAXPATHLEN
];
1920 if (ioctl(dev
, DIOCGETRULESET
, &pr
))
1921 err(1, "DIOCGETRULESET");
1922 if (!strcmp(pr
.name
, PF_RESERVED_ANCHOR
))
1926 strlcat(sub
, pr
.path
, sizeof(sub
));
1927 strlcat(sub
, "/", sizeof(sub
));
1929 strlcat(sub
, pr
.name
, sizeof(sub
));
1930 if (sub
[0] != '_' || (opts
& PF_OPT_VERBOSE
))
1931 printf(" %s\n", sub
);
1932 if ((opts
& PF_OPT_VERBOSE
) && pfctl_show_anchors(dev
, opts
, sub
))
1939 pfctl_lookup_option(char *cmd
, const char **list
)
1941 if (cmd
!= NULL
&& *cmd
)
1942 for (; *list
; list
++)
1943 if (!strncmp(cmd
, *list
, strlen(cmd
)))
1949 main(int argc
, char *argv
[])
1953 int mode
= O_RDONLY
;
1955 int optimize
= PF_OPTIMIZE_BASIC
;
1956 char anchorname
[MAXPATHLEN
];
1963 while ((ch
= getopt(argc
, argv
,
1964 "a:AdD:eqf:F:ghi:k:K:mnNOo:p:rRs:t:T:vx:z")) != -1) {
1970 opts
|= PF_OPT_DISABLE
;
1974 if (pfctl_cmdline_symset(optarg
) < 0)
1975 warnx("could not parse macro definition %s",
1979 opts
|= PF_OPT_ENABLE
;
1983 opts
|= PF_OPT_QUIET
;
1986 clearopt
= pfctl_lookup_option(optarg
, clearopt_list
);
1987 if (clearopt
== NULL
) {
1988 warnx("Unknown flush modifier '%s'", optarg
);
1997 if (state_killers
>= 2) {
1998 warnx("can only specify -k twice");
2002 state_kill
[state_killers
++] = optarg
;
2006 if (src_node_killers
>= 2) {
2007 warnx("can only specify -K twice");
2011 src_node_kill
[src_node_killers
++] = optarg
;
2015 opts
|= PF_OPT_MERGE
;
2018 opts
|= PF_OPT_NOACTION
;
2021 loadopt
|= PFCTL_FLAG_NAT
;
2024 opts
|= PF_OPT_USEDNS
;
2031 opts
|= PF_OPT_DEBUG
;
2034 loadopt
|= PFCTL_FLAG_ALTQ
;
2037 loadopt
|= PFCTL_FLAG_FILTER
;
2040 optiopt
= pfctl_lookup_option(optarg
, optiopt_list
);
2041 if (optiopt
== NULL
) {
2042 warnx("Unknown optimization '%s'", optarg
);
2045 opts
|= PF_OPT_OPTIMIZE
;
2048 loadopt
|= PFCTL_FLAG_OPTION
;
2054 showopt
= pfctl_lookup_option(optarg
, showopt_list
);
2055 if (showopt
== NULL
) {
2056 warnx("Unknown show modifier '%s'", optarg
);
2064 tblcmdopt
= pfctl_lookup_option(optarg
, tblcmdopt_list
);
2065 if (tblcmdopt
== NULL
) {
2066 warnx("Unknown table command '%s'", optarg
);
2071 if (opts
& PF_OPT_VERBOSE
)
2072 opts
|= PF_OPT_VERBOSE2
;
2073 opts
|= PF_OPT_VERBOSE
;
2076 debugopt
= pfctl_lookup_option(optarg
, debugopt_list
);
2077 if (debugopt
== NULL
) {
2078 warnx("Unknown debug level '%s'", optarg
);
2084 opts
|= PF_OPT_CLRRULECTRS
;
2095 if (tblcmdopt
!= NULL
) {
2100 loadopt
|= PFCTL_FLAG_TABLE
;
2103 mode
= strchr("acdefkrz", ch
) ? O_RDWR
: O_RDONLY
;
2104 } else if (argc
!= optind
) {
2105 warnx("unknown command line argument: %s ...", argv
[optind
]);
2112 if ((path
= calloc(1, MAXPATHLEN
)) == NULL
)
2113 errx(1, "pfctl: calloc");
2114 memset(anchorname
, 0, sizeof(anchorname
));
2115 if (anchoropt
!= NULL
) {
2116 int len
= strlen(anchoropt
);
2118 if (anchoropt
[len
- 1] == '*') {
2119 if (len
>= 2 && anchoropt
[len
- 2] == '/')
2120 anchoropt
[len
- 2] = '\0';
2122 anchoropt
[len
- 1] = '\0';
2123 opts
|= PF_OPT_RECURSE
;
2125 if (strlcpy(anchorname
, anchoropt
,
2126 sizeof(anchorname
)) >= sizeof(anchorname
))
2127 errx(1, "anchor name '%s' too long",
2129 loadopt
&= PFCTL_FLAG_FILTER
|PFCTL_FLAG_NAT
|PFCTL_FLAG_TABLE
;
2132 if ((opts
& PF_OPT_NOACTION
) == 0) {
2133 dev_fd
= open(pf_device
, mode
);
2135 err(1, "%s", pf_device
);
2136 altqsupport
= pfctl_test_altqsupport(dev_fd
, opts
);
2138 dev_fd
= open(pf_device
, O_RDONLY
);
2140 opts
|= PF_OPT_DUMMYACTION
;
2141 /* turn off options */
2142 opts
&= ~ (PF_OPT_DISABLE
| PF_OPT_ENABLE
);
2143 clearopt
= showopt
= debugopt
= NULL
;
2147 if (opts
& PF_OPT_DISABLE
)
2148 if (pfctl_disable(dev_fd
, opts
))
2151 if (showopt
!= NULL
) {
2154 pfctl_show_anchors(dev_fd
, opts
, anchorname
);
2157 pfctl_load_fingerprints(dev_fd
, opts
);
2158 pfctl_show_rules(dev_fd
, path
, opts
, PFCTL_SHOW_RULES
,
2162 pfctl_load_fingerprints(dev_fd
, opts
);
2163 pfctl_show_rules(dev_fd
, path
, opts
, PFCTL_SHOW_LABELS
,
2167 pfctl_load_fingerprints(dev_fd
, opts
);
2168 pfctl_show_nat(dev_fd
, opts
, anchorname
);
2171 pfctl_show_altq(dev_fd
, ifaceopt
, opts
,
2172 opts
& PF_OPT_VERBOSE2
);
2175 pfctl_show_states(dev_fd
, ifaceopt
, opts
);
2178 pfctl_show_src_nodes(dev_fd
, opts
);
2181 pfctl_show_status(dev_fd
, opts
);
2184 pfctl_show_timeouts(dev_fd
, opts
);
2187 pfctl_show_limits(dev_fd
, opts
);
2190 opts
|= PF_OPT_SHOWALL
;
2191 pfctl_load_fingerprints(dev_fd
, opts
);
2193 pfctl_show_nat(dev_fd
, opts
, anchorname
);
2194 pfctl_show_rules(dev_fd
, path
, opts
, 0, anchorname
, 0);
2195 pfctl_show_altq(dev_fd
, ifaceopt
, opts
, 0);
2196 pfctl_show_states(dev_fd
, ifaceopt
, opts
);
2197 pfctl_show_src_nodes(dev_fd
, opts
);
2198 pfctl_show_status(dev_fd
, opts
);
2199 pfctl_show_rules(dev_fd
, path
, opts
, 1, anchorname
, 0);
2200 pfctl_show_timeouts(dev_fd
, opts
);
2201 pfctl_show_limits(dev_fd
, opts
);
2202 pfctl_show_tables(anchorname
, opts
);
2203 pfctl_show_fingerprints(opts
);
2206 pfctl_show_tables(anchorname
, opts
);
2209 pfctl_load_fingerprints(dev_fd
, opts
);
2210 pfctl_show_fingerprints(opts
);
2213 pfctl_show_ifaces(ifaceopt
, opts
);
2218 if ((opts
& PF_OPT_CLRRULECTRS
) && showopt
== NULL
)
2219 pfctl_show_rules(dev_fd
, path
, opts
, PFCTL_SHOW_NOTHING
,
2222 if (clearopt
!= NULL
) {
2223 if (anchorname
[0] == '_' || strstr(anchorname
, "/_") != NULL
)
2224 errx(1, "anchor names beginning with '_' cannot "
2225 "be modified from the command line");
2227 switch (*clearopt
) {
2229 pfctl_clear_rules(dev_fd
, opts
, anchorname
);
2232 pfctl_clear_nat(dev_fd
, opts
, anchorname
);
2235 pfctl_clear_altq(dev_fd
, opts
);
2238 pfctl_clear_states(dev_fd
, ifaceopt
, opts
);
2241 pfctl_clear_src_nodes(dev_fd
, opts
);
2244 pfctl_clear_stats(dev_fd
, opts
);
2247 pfctl_clear_rules(dev_fd
, opts
, anchorname
);
2248 pfctl_clear_nat(dev_fd
, opts
, anchorname
);
2249 pfctl_clear_tables(anchorname
, opts
);
2251 pfctl_clear_altq(dev_fd
, opts
);
2252 pfctl_clear_states(dev_fd
, ifaceopt
, opts
);
2253 pfctl_clear_src_nodes(dev_fd
, opts
);
2254 pfctl_clear_stats(dev_fd
, opts
);
2255 pfctl_clear_fingerprints(dev_fd
, opts
);
2256 pfctl_clear_interface_flags(dev_fd
, opts
);
2260 pfctl_clear_fingerprints(dev_fd
, opts
);
2263 pfctl_clear_tables(anchorname
, opts
);
2268 pfctl_kill_states(dev_fd
, ifaceopt
, opts
);
2270 if (src_node_killers
)
2271 pfctl_kill_src_nodes(dev_fd
, ifaceopt
, opts
);
2273 if (tblcmdopt
!= NULL
) {
2274 error
= pfctl_command_tables(argc
, argv
, tableopt
,
2275 tblcmdopt
, rulesopt
, anchorname
, opts
);
2278 if (optiopt
!= NULL
) {
2284 optimize
|= PF_OPTIMIZE_BASIC
;
2288 optimize
|= PF_OPTIMIZE_PROFILE
;
2293 if (rulesopt
!= NULL
) {
2294 if (strcmp(rulesopt
, "-") == 0) {
2296 rulesopt
= __DECONST(char *, "stdin");
2298 if ((fin
= pfctl_fopen(rulesopt
, "r")) == NULL
)
2299 err(1, "%s", rulesopt
);
2302 if ((rulesopt
!= NULL
) && (loadopt
& PFCTL_FLAG_OPTION
) &&
2304 if (pfctl_clear_interface_flags(dev_fd
, opts
| PF_OPT_QUIET
))
2307 if (rulesopt
!= NULL
&& !(opts
& (PF_OPT_MERGE
|PF_OPT_NOACTION
)) &&
2308 !anchorname
[0] && (loadopt
& PFCTL_FLAG_OPTION
))
2309 if (pfctl_file_fingerprints(dev_fd
, opts
, PF_OSFP_FILE
))
2312 if (rulesopt
!= NULL
) {
2313 if (anchorname
[0] == '_' || strstr(anchorname
, "/_") != NULL
)
2314 errx(1, "anchor names beginning with '_' cannot "
2315 "be modified from the command line");
2316 if (pfctl_rules(dev_fd
, rulesopt
, fin
, opts
, optimize
,
2319 else if (!(opts
& PF_OPT_NOACTION
) &&
2320 (loadopt
& PFCTL_FLAG_TABLE
))
2321 warn_namespace_collision(NULL
);
2324 if (opts
& PF_OPT_ENABLE
)
2325 if (pfctl_enable(dev_fd
, opts
))
2328 if (debugopt
!= NULL
) {
2329 switch (*debugopt
) {
2331 pfctl_debug(dev_fd
, PF_DEBUG_NONE
, opts
);
2334 pfctl_debug(dev_fd
, PF_DEBUG_URGENT
, opts
);
2337 pfctl_debug(dev_fd
, PF_DEBUG_MISC
, opts
);
2340 pfctl_debug(dev_fd
, PF_DEBUG_NOISY
, opts
);