1 /* $OpenBSD: pfctl.c,v 1.277 2008/07/24 10:52:43 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>
38 #include <sys/endian.h>
41 #include <netinet/in.h>
42 #include <net/pf/pfvar.h>
43 #include <arpa/inet.h>
44 #include <net/altq/altq.h>
45 #include <sys/sysctl.h>
58 #include "pfctl_parser.h"
61 void usage(void) __dead2
;
62 int pfctl_enable(int, int);
63 int pfctl_disable(int, int);
64 int pfctl_clear_stats(int, int);
65 int pfctl_clear_interface_flags(int, int);
66 int pfctl_clear_rules(int, int, char *);
67 int pfctl_clear_nat(int, int, char *);
68 int pfctl_clear_altq(int, int);
69 int pfctl_clear_src_nodes(int, int);
70 int pfctl_clear_states(int, const char *, int);
71 void pfctl_addrprefix(char *, struct pf_addr
*);
72 int pfctl_kill_src_nodes(int, const char *, int);
73 int pfctl_net_kill_states(int, const char *, int);
74 int pfctl_label_kill_states(int, const char *, int);
75 int pfctl_id_kill_states(int, const char *, int);
76 void pfctl_init_options(struct pfctl
*);
77 int pfctl_load_options(struct pfctl
*);
78 int pfctl_load_limit(struct pfctl
*, unsigned int, unsigned int);
79 int pfctl_load_timeout(struct pfctl
*, unsigned int, unsigned int);
80 int pfctl_load_debug(struct pfctl
*, unsigned int);
81 int pfctl_load_logif(struct pfctl
*, char *);
82 int pfctl_load_hostid(struct pfctl
*, unsigned int);
83 int pfctl_get_pool(int, struct pf_pool
*, u_int32_t
, u_int32_t
, int,
85 void pfctl_print_rule_counters(struct pf_rule
*, int);
86 int pfctl_show_rules(int, char *, int, enum pfctl_show
, char *, int);
87 int pfctl_show_nat(int, int, char *);
88 int pfctl_show_src_nodes(int, int);
89 int pfctl_show_states(int, const char *, int);
90 int pfctl_show_status(int, int);
91 int pfctl_show_timeouts(int, int);
92 int pfctl_show_limits(int, int);
93 void pfctl_debug(int, u_int32_t
, int);
94 int pfctl_test_altqsupport(int, int);
95 int pfctl_show_anchors(int, int, char *);
96 int pfctl_ruleset_trans(struct pfctl
*, char *, struct pf_anchor
*);
97 int pfctl_load_ruleset(struct pfctl
*, char *,
98 struct pf_ruleset
*, int, int);
99 int pfctl_load_rule(struct pfctl
*, char *, struct pf_rule
*, int);
100 const char *pfctl_lookup_option(char *, const char **);
102 const char *clearopt
;
105 const char *debugopt
;
107 const char *optiopt
= NULL
;
108 const char *pf_device
= "/dev/pf";
111 const char *tblcmdopt
;
112 int src_node_killers
;
113 char *src_node_kill
[2];
123 #define INDENT(d, o) do { \
126 for (i=0; i < d; i++) \
132 static const struct {
136 { "states", PF_LIMIT_STATES
},
137 { "src-nodes", PF_LIMIT_SRC_NODES
},
138 { "frags", PF_LIMIT_FRAGS
},
139 { "tables", PF_LIMIT_TABLES
},
140 { "table-entries", PF_LIMIT_TABLE_ENTRIES
},
148 static const struct pf_hint pf_hint_normal
[] = {
149 { "tcp.first", 2 * 60 },
150 { "tcp.opening", 30 },
151 { "tcp.established", 24 * 60 * 60 },
152 { "tcp.closing", 15 * 60 },
153 { "tcp.finwait", 45 },
154 { "tcp.closed", 90 },
155 { "tcp.tsdiff", 30 },
158 static const struct pf_hint pf_hint_satellite
[] = {
159 { "tcp.first", 3 * 60 },
160 { "tcp.opening", 30 + 5 },
161 { "tcp.established", 24 * 60 * 60 },
162 { "tcp.closing", 15 * 60 + 5 },
163 { "tcp.finwait", 45 + 5 },
164 { "tcp.closed", 90 + 5 },
165 { "tcp.tsdiff", 60 },
168 static const struct pf_hint pf_hint_conservative
[] = {
169 { "tcp.first", 60 * 60 },
170 { "tcp.opening", 15 * 60 },
171 { "tcp.established", 5 * 24 * 60 * 60 },
172 { "tcp.closing", 60 * 60 },
173 { "tcp.finwait", 10 * 60 },
174 { "tcp.closed", 3 * 60 },
175 { "tcp.tsdiff", 60 },
178 static const struct pf_hint pf_hint_aggressive
[] = {
180 { "tcp.opening", 5 },
181 { "tcp.established", 5 * 60 * 60 },
182 { "tcp.closing", 60 },
183 { "tcp.finwait", 30 },
184 { "tcp.closed", 30 },
185 { "tcp.tsdiff", 10 },
189 static const struct {
191 const struct pf_hint
*hint
;
193 { "normal", pf_hint_normal
},
194 { "satellite", pf_hint_satellite
},
195 { "high-latency", pf_hint_satellite
},
196 { "conservative", pf_hint_conservative
},
197 { "aggressive", pf_hint_aggressive
},
201 static const char *clearopt_list
[] = {
202 "nat", "queue", "rules", "Sources",
203 "states", "info", "Tables", "osfp", "all", NULL
206 static const char *showopt_list
[] = {
207 "nat", "queue", "rules", "Anchors", "Sources", "states", "info",
208 "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
212 static const char *tblcmdopt_list
[] = {
213 "kill", "flush", "add", "delete", "load", "replace", "show",
214 "test", "zero", "expire", NULL
217 static const char *debugopt_list
[] = {
218 "none", "urgent", "misc", "loud", NULL
221 static const char *optiopt_list
[] = {
222 "none", "basic", "profile", NULL
228 fprintf(stderr
, "usage: %s [-AdeghmNnOqRrvz] ", getprogname());
229 fprintf(stderr
, "[-a anchor] [-D macro=value] [-F modifier]\n");
230 fprintf(stderr
, "\t[-f file] [-i interface] [-K host | network] ");
231 fprintf(stderr
, "[-k host | network | label | id]\n");
232 fprintf(stderr
, "\t[-o level] [-p device] [-s modifier]\n");
233 fprintf(stderr
, "\t[-t table -T command [address ...]] [-x level]\n");
238 pfctl_enable(int dev
, int opts
)
240 if (ioctl(dev
, DIOCSTART
)) {
242 errx(1, "pf already enabled");
246 if ((opts
& PF_OPT_QUIET
) == 0)
247 fprintf(stderr
, "pf enabled\n");
249 if (altqsupport
&& ioctl(dev
, DIOCSTARTALTQ
))
251 err(1, "DIOCSTARTALTQ");
257 pfctl_disable(int dev
, int opts
)
259 if (ioctl(dev
, DIOCSTOP
)) {
261 errx(1, "pf not enabled");
265 if ((opts
& PF_OPT_QUIET
) == 0)
266 fprintf(stderr
, "pf disabled\n");
268 if (altqsupport
&& ioctl(dev
, DIOCSTOPALTQ
))
270 err(1, "DIOCSTOPALTQ");
276 pfctl_clear_stats(int dev
, int opts
)
278 if (ioctl(dev
, DIOCCLRSTATUS
))
279 err(1, "DIOCCLRSTATUS");
280 if ((opts
& PF_OPT_QUIET
) == 0)
281 fprintf(stderr
, "pf: statistics cleared\n");
286 pfctl_clear_interface_flags(int dev
, int opts
)
288 struct pfioc_iface pi
;
290 if ((opts
& PF_OPT_NOACTION
) == 0) {
291 bzero(&pi
, sizeof(pi
));
292 pi
.pfiio_flags
= PFI_IFLAG_SKIP
;
294 if (ioctl(dev
, DIOCCLRIFFLAG
, &pi
))
295 err(1, "DIOCCLRIFFLAG");
296 if ((opts
& PF_OPT_QUIET
) == 0)
297 fprintf(stderr
, "pf: interface flags reset\n");
303 pfctl_clear_rules(int dev
, int opts
, char *anchorname
)
307 memset(&t
, 0, sizeof(t
));
308 t
.pfrb_type
= PFRB_TRANS
;
309 if (pfctl_add_trans(&t
, PF_RULESET_SCRUB
, anchorname
) ||
310 pfctl_add_trans(&t
, PF_RULESET_FILTER
, anchorname
) ||
311 pfctl_trans(dev
, &t
, DIOCXBEGIN
, 0) ||
312 pfctl_trans(dev
, &t
, DIOCXCOMMIT
, 0))
313 err(1, "pfctl_clear_rules");
314 if ((opts
& PF_OPT_QUIET
) == 0)
315 fprintf(stderr
, "rules cleared\n");
320 pfctl_clear_nat(int dev
, int opts
, char *anchorname
)
324 memset(&t
, 0, sizeof(t
));
325 t
.pfrb_type
= PFRB_TRANS
;
326 if (pfctl_add_trans(&t
, PF_RULESET_NAT
, anchorname
) ||
327 pfctl_add_trans(&t
, PF_RULESET_BINAT
, anchorname
) ||
328 pfctl_add_trans(&t
, PF_RULESET_RDR
, anchorname
) ||
329 pfctl_trans(dev
, &t
, DIOCXBEGIN
, 0) ||
330 pfctl_trans(dev
, &t
, DIOCXCOMMIT
, 0))
331 err(1, "pfctl_clear_nat");
332 if ((opts
& PF_OPT_QUIET
) == 0)
333 fprintf(stderr
, "nat cleared\n");
338 pfctl_clear_altq(int dev
, int opts
)
344 memset(&t
, 0, sizeof(t
));
345 t
.pfrb_type
= PFRB_TRANS
;
346 if (pfctl_add_trans(&t
, PF_RULESET_ALTQ
, "") ||
347 pfctl_trans(dev
, &t
, DIOCXBEGIN
, 0) ||
348 pfctl_trans(dev
, &t
, DIOCXCOMMIT
, 0))
349 err(1, "pfctl_clear_altq");
350 if ((opts
& PF_OPT_QUIET
) == 0)
351 fprintf(stderr
, "altq cleared\n");
356 pfctl_clear_src_nodes(int dev
, int opts
)
358 if (ioctl(dev
, DIOCCLRSRCNODES
))
359 err(1, "DIOCCLRSRCNODES");
360 if ((opts
& PF_OPT_QUIET
) == 0)
361 fprintf(stderr
, "source tracking entries cleared\n");
366 pfctl_clear_states(int dev
, const char *iface
, int opts
)
368 struct pfioc_state_kill psk
;
370 memset(&psk
, 0, sizeof(psk
));
371 if (iface
!= NULL
&& strlcpy(psk
.psk_ifname
, iface
,
372 sizeof(psk
.psk_ifname
)) >= sizeof(psk
.psk_ifname
))
373 errx(1, "invalid interface: %s", iface
);
375 if (ioctl(dev
, DIOCCLRSTATES
, &psk
))
376 err(1, "DIOCCLRSTATES");
377 if ((opts
& PF_OPT_QUIET
) == 0)
378 fprintf(stderr
, "%d states cleared\n", psk
.psk_killed
);
383 pfctl_addrprefix(char *addr
, struct pf_addr
*mask
)
387 int prefix
, ret_ga
, q
, r
;
388 struct addrinfo hints
, *res
;
390 if ((p
= strchr(addr
, '/')) == NULL
)
394 prefix
= strtonum(p
, 0, 128, &errstr
);
396 errx(1, "prefix is %s: %s", errstr
, p
);
398 bzero(&hints
, sizeof(hints
));
399 /* prefix only with numeric addresses */
400 hints
.ai_flags
|= AI_NUMERICHOST
;
402 if ((ret_ga
= getaddrinfo(addr
, NULL
, &hints
, &res
))) {
403 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga
));
407 if (res
->ai_family
== AF_INET
&& prefix
> 32)
408 errx(1, "prefix too long for AF_INET");
409 else if (res
->ai_family
== AF_INET6
&& prefix
> 128)
410 errx(1, "prefix too long for AF_INET6");
414 switch (res
->ai_family
) {
416 bzero(&mask
->v4
, sizeof(mask
->v4
));
417 mask
->v4
.s_addr
= htonl((u_int32_t
)
418 (0xffffffffffULL
<< (32 - prefix
)));
421 bzero(&mask
->v6
, sizeof(mask
->v6
));
423 memset((void *)&mask
->v6
, 0xff, q
);
425 *((u_char
*)&mask
->v6
+ q
) =
426 (0xff00 >> r
) & 0xff;
433 pfctl_kill_src_nodes(int dev
, const char *iface __unused
, int opts
)
435 struct pfioc_src_node_kill psnk
;
436 struct addrinfo
*res
[2], *resp
[2];
437 struct sockaddr last_src
, last_dst
;
438 int killed
, sources
, dests
;
441 killed
= sources
= dests
= 0;
443 memset(&psnk
, 0, sizeof(psnk
));
444 memset(&psnk
.psnk_src
.addr
.v
.a
.mask
, 0xff,
445 sizeof(psnk
.psnk_src
.addr
.v
.a
.mask
));
446 memset(&last_src
, 0xff, sizeof(last_src
));
447 memset(&last_dst
, 0xff, sizeof(last_dst
));
449 pfctl_addrprefix(src_node_kill
[0], &psnk
.psnk_src
.addr
.v
.a
.mask
);
451 if ((ret_ga
= getaddrinfo(src_node_kill
[0], NULL
, NULL
, &res
[0]))) {
452 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga
));
455 for (resp
[0] = res
[0]; resp
[0]; resp
[0] = resp
[0]->ai_next
) {
456 if (resp
[0]->ai_addr
== NULL
)
458 /* We get lots of duplicates. Catch the easy ones */
459 if (memcmp(&last_src
, resp
[0]->ai_addr
, sizeof(last_src
)) == 0)
461 last_src
= *(struct sockaddr
*)resp
[0]->ai_addr
;
463 psnk
.psnk_af
= resp
[0]->ai_family
;
466 if (psnk
.psnk_af
== AF_INET
)
467 psnk
.psnk_src
.addr
.v
.a
.addr
.v4
=
468 ((struct sockaddr_in
*)resp
[0]->ai_addr
)->sin_addr
;
469 else if (psnk
.psnk_af
== AF_INET6
)
470 psnk
.psnk_src
.addr
.v
.a
.addr
.v6
=
471 ((struct sockaddr_in6
*)resp
[0]->ai_addr
)->
474 errx(1, "Unknown address family %d", psnk
.psnk_af
);
476 if (src_node_killers
> 1) {
478 memset(&psnk
.psnk_dst
.addr
.v
.a
.mask
, 0xff,
479 sizeof(psnk
.psnk_dst
.addr
.v
.a
.mask
));
480 memset(&last_dst
, 0xff, sizeof(last_dst
));
481 pfctl_addrprefix(src_node_kill
[1],
482 &psnk
.psnk_dst
.addr
.v
.a
.mask
);
483 if ((ret_ga
= getaddrinfo(src_node_kill
[1], NULL
, NULL
,
485 errx(1, "getaddrinfo: %s",
486 gai_strerror(ret_ga
));
489 for (resp
[1] = res
[1]; resp
[1];
490 resp
[1] = resp
[1]->ai_next
) {
491 if (resp
[1]->ai_addr
== NULL
)
493 if (psnk
.psnk_af
!= resp
[1]->ai_family
)
496 if (memcmp(&last_dst
, resp
[1]->ai_addr
,
497 sizeof(last_dst
)) == 0)
499 last_dst
= *(struct sockaddr
*)resp
[1]->ai_addr
;
503 if (psnk
.psnk_af
== AF_INET
)
504 psnk
.psnk_dst
.addr
.v
.a
.addr
.v4
=
505 ((struct sockaddr_in
*)resp
[1]->
507 else if (psnk
.psnk_af
== AF_INET6
)
508 psnk
.psnk_dst
.addr
.v
.a
.addr
.v6
=
509 ((struct sockaddr_in6
*)resp
[1]->
512 errx(1, "Unknown address family %d",
515 if (ioctl(dev
, DIOCKILLSRCNODES
, &psnk
))
516 err(1, "DIOCKILLSRCNODES");
517 killed
+= psnk
.psnk_killed
;
519 freeaddrinfo(res
[1]);
521 if (ioctl(dev
, DIOCKILLSRCNODES
, &psnk
))
522 err(1, "DIOCKILLSRCNODES");
523 killed
+= psnk
.psnk_killed
;
527 freeaddrinfo(res
[0]);
529 if ((opts
& PF_OPT_QUIET
) == 0)
530 fprintf(stderr
, "killed %d src nodes from %d sources and %d "
531 "destinations\n", killed
, sources
, dests
);
536 pfctl_net_kill_states(int dev
, const char *iface
, int opts
)
538 struct pfioc_state_kill psk
;
539 struct addrinfo
*res
[2], *resp
[2];
540 struct sockaddr last_src
, last_dst
;
541 int killed
, sources
, dests
;
544 killed
= sources
= dests
= 0;
546 memset(&psk
, 0, sizeof(psk
));
547 memset(&psk
.psk_src
.addr
.v
.a
.mask
, 0xff,
548 sizeof(psk
.psk_src
.addr
.v
.a
.mask
));
549 memset(&last_src
, 0xff, sizeof(last_src
));
550 memset(&last_dst
, 0xff, sizeof(last_dst
));
551 if (iface
!= NULL
&& strlcpy(psk
.psk_ifname
, iface
,
552 sizeof(psk
.psk_ifname
)) >= sizeof(psk
.psk_ifname
))
553 errx(1, "invalid interface: %s", iface
);
555 pfctl_addrprefix(state_kill
[0], &psk
.psk_src
.addr
.v
.a
.mask
);
557 if ((ret_ga
= getaddrinfo(state_kill
[0], NULL
, NULL
, &res
[0]))) {
558 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga
));
561 for (resp
[0] = res
[0]; resp
[0]; resp
[0] = resp
[0]->ai_next
) {
562 if (resp
[0]->ai_addr
== NULL
)
564 /* We get lots of duplicates. Catch the easy ones */
565 if (memcmp(&last_src
, resp
[0]->ai_addr
, sizeof(last_src
)) == 0)
567 last_src
= *(struct sockaddr
*)resp
[0]->ai_addr
;
569 psk
.psk_af
= resp
[0]->ai_family
;
572 if (psk
.psk_af
== AF_INET
)
573 psk
.psk_src
.addr
.v
.a
.addr
.v4
=
574 ((struct sockaddr_in
*)resp
[0]->ai_addr
)->sin_addr
;
575 else if (psk
.psk_af
== AF_INET6
)
576 psk
.psk_src
.addr
.v
.a
.addr
.v6
=
577 ((struct sockaddr_in6
*)resp
[0]->ai_addr
)->
580 errx(1, "Unknown address family %d", psk
.psk_af
);
582 if (state_killers
> 1) {
584 memset(&psk
.psk_dst
.addr
.v
.a
.mask
, 0xff,
585 sizeof(psk
.psk_dst
.addr
.v
.a
.mask
));
586 memset(&last_dst
, 0xff, sizeof(last_dst
));
587 pfctl_addrprefix(state_kill
[1],
588 &psk
.psk_dst
.addr
.v
.a
.mask
);
589 if ((ret_ga
= getaddrinfo(state_kill
[1], NULL
, NULL
,
591 errx(1, "getaddrinfo: %s",
592 gai_strerror(ret_ga
));
595 for (resp
[1] = res
[1]; resp
[1];
596 resp
[1] = resp
[1]->ai_next
) {
597 if (resp
[1]->ai_addr
== NULL
)
599 if (psk
.psk_af
!= resp
[1]->ai_family
)
602 if (memcmp(&last_dst
, resp
[1]->ai_addr
,
603 sizeof(last_dst
)) == 0)
605 last_dst
= *(struct sockaddr
*)resp
[1]->ai_addr
;
609 if (psk
.psk_af
== AF_INET
)
610 psk
.psk_dst
.addr
.v
.a
.addr
.v4
=
611 ((struct sockaddr_in
*)resp
[1]->
613 else if (psk
.psk_af
== AF_INET6
)
614 psk
.psk_dst
.addr
.v
.a
.addr
.v6
=
615 ((struct sockaddr_in6
*)resp
[1]->
618 errx(1, "Unknown address family %d",
621 if (ioctl(dev
, DIOCKILLSTATES
, &psk
))
622 err(1, "DIOCKILLSTATES");
623 killed
+= psk
.psk_killed
;
625 freeaddrinfo(res
[1]);
627 if (ioctl(dev
, DIOCKILLSTATES
, &psk
))
628 err(1, "DIOCKILLSTATES");
629 killed
+= psk
.psk_killed
;
633 freeaddrinfo(res
[0]);
635 if ((opts
& PF_OPT_QUIET
) == 0)
636 fprintf(stderr
, "killed %d states from %d sources and %d "
637 "destinations\n", killed
, sources
, dests
);
642 pfctl_label_kill_states(int dev
, const char *iface
, int opts
)
644 struct pfioc_state_kill psk
;
646 if (state_killers
!= 2 || (strlen(state_kill
[1]) == 0)) {
647 warnx("no label specified");
650 memset(&psk
, 0, sizeof(psk
));
651 if (iface
!= NULL
&& strlcpy(psk
.psk_ifname
, iface
,
652 sizeof(psk
.psk_ifname
)) >= sizeof(psk
.psk_ifname
))
653 errx(1, "invalid interface: %s", iface
);
655 if (strlcpy(psk
.psk_label
, state_kill
[1], sizeof(psk
.psk_label
)) >=
656 sizeof(psk
.psk_label
))
657 errx(1, "label too long: %s", state_kill
[1]);
659 if (ioctl(dev
, DIOCKILLSTATES
, &psk
))
660 err(1, "DIOCKILLSTATES");
662 if ((opts
& PF_OPT_QUIET
) == 0)
663 fprintf(stderr
, "killed %d states\n", psk
.psk_killed
);
669 pfctl_id_kill_states(int dev
, const char *iface
, int opts
)
671 struct pfioc_state_kill psk
;
673 if (state_killers
!= 2 || (strlen(state_kill
[1]) == 0)) {
674 warnx("no id specified");
678 memset(&psk
, 0, sizeof(psk
));
679 if ((sscanf(state_kill
[1], "%" SCNx64
"/%x",
680 &psk
.psk_pfcmp
.id
, &psk
.psk_pfcmp
.creatorid
)) == 2)
681 psk
.psk_pfcmp
.creatorid
=htonl(psk
.psk_pfcmp
.creatorid
);
682 else if ((sscanf(state_kill
[1], "%" SCNx64
, &psk
.psk_pfcmp
.id
)) == 1) {
683 psk
.psk_pfcmp
.creatorid
= 0;
685 warnx("wrong id format specified");
688 if (psk
.psk_pfcmp
.id
== 0) {
689 warnx("cannot kill id 0");
693 psk
.psk_pfcmp
.id
= htobe64(psk
.psk_pfcmp
.id
);
694 if (ioctl(dev
, DIOCKILLSTATES
, &psk
))
695 err(1, "DIOCKILLSTATES");
697 if ((opts
& PF_OPT_QUIET
) == 0)
698 fprintf(stderr
, "killed %d states\n", psk
.psk_killed
);
704 pfctl_get_pool(int dev
, struct pf_pool
*pool
, u_int32_t nr
,
705 u_int32_t ticket
, int r_action
, char *anchorname
)
707 struct pfioc_pooladdr pp
;
708 struct pf_pooladdr
*pa
;
711 memset(&pp
, 0, sizeof(pp
));
712 memcpy(pp
.anchor
, anchorname
, sizeof(pp
.anchor
));
713 pp
.r_action
= r_action
;
716 if (ioctl(dev
, DIOCGETADDRS
, &pp
)) {
717 warn("DIOCGETADDRS");
721 TAILQ_INIT(&pool
->list
);
722 for (pnr
= 0; pnr
< mpnr
; ++pnr
) {
724 if (ioctl(dev
, DIOCGETADDR
, &pp
)) {
728 pa
= calloc(1, sizeof(struct pf_pooladdr
));
731 bcopy(&pp
.addr
, pa
, sizeof(struct pf_pooladdr
));
732 TAILQ_INSERT_TAIL(&pool
->list
, pa
, entries
);
739 pfctl_move_pool(struct pf_pool
*src
, struct pf_pool
*dst
)
741 struct pf_pooladdr
*pa
;
743 while ((pa
= TAILQ_FIRST(&src
->list
)) != NULL
) {
744 TAILQ_REMOVE(&src
->list
, pa
, entries
);
745 TAILQ_INSERT_TAIL(&dst
->list
, pa
, entries
);
750 pfctl_clear_pool(struct pf_pool
*pool
)
752 struct pf_pooladdr
*pa
;
754 while ((pa
= TAILQ_FIRST(&pool
->list
)) != NULL
) {
755 TAILQ_REMOVE(&pool
->list
, pa
, entries
);
761 pfctl_print_rule_counters(struct pf_rule
*rule
, int opts
)
763 if (opts
& PF_OPT_DEBUG
) {
764 const char *t
[PF_SKIP_COUNT
] = { "i", "d", "f",
765 "p", "sa", "sp", "da", "dp" };
768 printf(" [ Skip steps: ");
769 for (i
= 0; i
< PF_SKIP_COUNT
; ++i
) {
770 if (rule
->skip
[i
].nr
== rule
->nr
+ 1)
773 if (rule
->skip
[i
].nr
== (uint32_t)(-1))
776 printf("%u ", rule
->skip
[i
].nr
);
780 printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
781 rule
->qname
, rule
->qid
, rule
->pqname
, rule
->pqid
);
783 if (opts
& PF_OPT_VERBOSE
) {
784 printf(" [ Evaluations: %-8llu Packets: %-8llu "
785 "Bytes: %-10llu States: %-6u]\n",
786 (unsigned long long)rule
->evaluations
,
787 (unsigned long long)(rule
->packets
[0] +
789 (unsigned long long)(rule
->bytes
[0] +
790 rule
->bytes
[1]), rule
->states_cur
);
791 if (!(opts
& PF_OPT_DEBUG
))
792 printf(" [ Inserted: uid %u pid %u "
793 "State Creations: %-6u]\n",
794 (unsigned)rule
->cuid
, (unsigned)rule
->cpid
,
800 pfctl_print_title(const char *title
)
805 printf("%s\n", title
);
809 pfctl_show_rules(int dev
, char *path
, int opts
, enum pfctl_show format
,
810 char *anchorname
, int depth
)
812 struct pfioc_rule pr
;
813 u_int32_t nr
, mnr
, header
= 0;
814 int rule_numbers
= opts
& (PF_OPT_VERBOSE2
| PF_OPT_DEBUG
);
815 int len
= strlen(path
);
820 snprintf(&path
[len
], MAXPATHLEN
- len
, "/%s", anchorname
);
822 snprintf(&path
[len
], MAXPATHLEN
- len
, "%s", anchorname
);
824 memset(&pr
, 0, sizeof(pr
));
825 memcpy(pr
.anchor
, path
, sizeof(pr
.anchor
));
826 if (opts
& PF_OPT_SHOWALL
) {
827 pr
.rule
.action
= PF_PASS
;
828 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
829 warn("DIOCGETRULES");
834 pr
.rule
.action
= PF_SCRUB
;
835 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
836 warn("DIOCGETRULES");
839 if (opts
& PF_OPT_SHOWALL
) {
840 if (format
== PFCTL_SHOW_RULES
&& (pr
.nr
> 0 || header
))
841 pfctl_print_title("FILTER RULES:");
842 else if (format
== PFCTL_SHOW_LABELS
&& labels
)
843 pfctl_print_title("LABEL COUNTERS:");
846 if (opts
& PF_OPT_CLRRULECTRS
)
847 pr
.action
= PF_GET_CLR_CNTR
;
849 for (nr
= 0; nr
< mnr
; ++nr
) {
851 if (ioctl(dev
, DIOCGETRULE
, &pr
)) {
856 if (pfctl_get_pool(dev
, &pr
.rule
.rpool
,
857 nr
, pr
.ticket
, PF_SCRUB
, path
) != 0)
861 case PFCTL_SHOW_LABELS
:
863 case PFCTL_SHOW_RULES
:
864 if (pr
.rule
.label
[0] && (opts
& PF_OPT_SHOWALL
))
866 print_rule(&pr
.rule
, pr
.anchor_call
, rule_numbers
);
868 pfctl_print_rule_counters(&pr
.rule
, opts
);
870 case PFCTL_SHOW_NOTHING
:
873 pfctl_clear_pool(&pr
.rule
.rpool
);
875 pr
.rule
.action
= PF_PASS
;
876 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
877 warn("DIOCGETRULES");
881 for (nr
= 0; nr
< mnr
; ++nr
) {
883 if (ioctl(dev
, DIOCGETRULE
, &pr
)) {
888 if (pfctl_get_pool(dev
, &pr
.rule
.rpool
,
889 nr
, pr
.ticket
, PF_PASS
, path
) != 0)
893 case PFCTL_SHOW_LABELS
:
894 if (pr
.rule
.label
[0]) {
895 printf("%s %llu %llu %llu %llu"
896 " %llu %llu %llu %llu\n",
898 (unsigned long long)pr
.rule
.evaluations
,
899 (unsigned long long)(pr
.rule
.packets
[0] +
901 (unsigned long long)(pr
.rule
.bytes
[0] +
903 (unsigned long long)pr
.rule
.packets
[0],
904 (unsigned long long)pr
.rule
.bytes
[0],
905 (unsigned long long)pr
.rule
.packets
[1],
906 (unsigned long long)pr
.rule
.bytes
[1],
907 (unsigned long long)pr
.rule
.states_tot
);
910 case PFCTL_SHOW_RULES
:
912 if (pr
.rule
.label
[0] && (opts
& PF_OPT_SHOWALL
))
914 INDENT(depth
, !(opts
& PF_OPT_VERBOSE
));
915 if (pr
.anchor_call
[0] &&
916 ((((p
= strrchr(pr
.anchor_call
, '_')) != NULL
) &&
917 ((void *)p
== (void *)pr
.anchor_call
||
918 *(--p
) == '/')) || (opts
& PF_OPT_RECURSE
))) {
920 if ((p
= strrchr(pr
.anchor_call
, '/')) !=
924 p
= &pr
.anchor_call
[0];
926 p
= &pr
.anchor_call
[0];
928 print_rule(&pr
.rule
, p
, rule_numbers
);
933 pfctl_print_rule_counters(&pr
.rule
, opts
);
935 pfctl_show_rules(dev
, path
, opts
, format
,
937 INDENT(depth
, !(opts
& PF_OPT_VERBOSE
));
941 case PFCTL_SHOW_NOTHING
:
944 pfctl_clear_pool(&pr
.rule
.rpool
);
955 pfctl_show_nat(int dev
, int opts
, char *anchorname
)
957 struct pfioc_rule pr
;
959 static int nattype
[3] = { PF_NAT
, PF_RDR
, PF_BINAT
};
960 int i
, dotitle
= opts
& PF_OPT_SHOWALL
;
962 memset(&pr
, 0, sizeof(pr
));
963 memcpy(pr
.anchor
, anchorname
, sizeof(pr
.anchor
));
964 for (i
= 0; i
< 3; i
++) {
965 pr
.rule
.action
= nattype
[i
];
966 if (ioctl(dev
, DIOCGETRULES
, &pr
)) {
967 warn("DIOCGETRULES");
971 for (nr
= 0; nr
< mnr
; ++nr
) {
973 if (ioctl(dev
, DIOCGETRULE
, &pr
)) {
977 if (pfctl_get_pool(dev
, &pr
.rule
.rpool
, nr
,
978 pr
.ticket
, nattype
[i
], anchorname
) != 0)
981 pfctl_print_title("TRANSLATION RULES:");
984 print_rule(&pr
.rule
, pr
.anchor_call
,
985 opts
& PF_OPT_VERBOSE2
);
987 pfctl_print_rule_counters(&pr
.rule
, opts
);
988 pfctl_clear_pool(&pr
.rule
.rpool
);
995 pfctl_show_src_nodes(int dev
, int opts
)
997 struct pfioc_src_nodes psn
;
998 struct pf_src_node
*p
;
999 char *inbuf
= NULL
, *newinbuf
= NULL
;
1000 unsigned int len
= 0;
1003 memset(&psn
, 0, sizeof(psn
));
1007 newinbuf
= realloc(inbuf
, len
);
1008 if (newinbuf
== NULL
)
1010 psn
.psn_buf
= inbuf
= newinbuf
;
1012 if (ioctl(dev
, DIOCGETSRCNODES
, &psn
) < 0) {
1013 warn("DIOCGETSRCNODES");
1017 if (psn
.psn_len
+ sizeof(struct pfioc_src_nodes
) < len
)
1019 if (len
== 0 && psn
.psn_len
== 0)
1021 if (len
== 0 && psn
.psn_len
!= 0)
1023 if (psn
.psn_len
== 0)
1024 goto done
; /* no src_nodes */
1027 p
= psn
.psn_src_nodes
;
1028 if (psn
.psn_len
> 0 && (opts
& PF_OPT_SHOWALL
))
1029 pfctl_print_title("SOURCE TRACKING NODES:");
1030 for (i
= 0; i
< psn
.psn_len
; i
+= sizeof(*p
)) {
1031 print_src_node(p
, opts
);
1040 pfctl_show_states(int dev
, const char *iface
, int opts
)
1042 struct pfioc_states ps
;
1043 struct pfsync_state
*p
;
1044 char *inbuf
= NULL
, *newinbuf
= NULL
;
1045 unsigned int len
= 0;
1046 int i
, dotitle
= (opts
& PF_OPT_SHOWALL
);
1048 memset(&ps
, 0, sizeof(ps
));
1052 newinbuf
= realloc(inbuf
, len
);
1053 if (newinbuf
== NULL
)
1055 ps
.ps_buf
= inbuf
= newinbuf
;
1057 if (ioctl(dev
, DIOCGETSTATES
, &ps
) < 0) {
1058 warn("DIOCGETSTATES");
1062 if (ps
.ps_len
+ sizeof(struct pfioc_states
) < len
)
1064 if (len
== 0 && ps
.ps_len
== 0)
1066 if (len
== 0 && ps
.ps_len
!= 0)
1069 goto done
; /* no states */
1073 for (i
= 0; i
< ps
.ps_len
; i
+= sizeof(*p
), p
++) {
1074 if (iface
!= NULL
&& strcmp(p
->ifname
, iface
))
1077 pfctl_print_title("STATES:");
1080 print_state(p
, opts
);
1088 pfctl_show_status(int dev
, int opts
)
1090 struct pf_status status
;
1092 if (ioctl(dev
, DIOCGETSTATUS
, &status
)) {
1093 warn("DIOCGETSTATUS");
1096 if (opts
& PF_OPT_SHOWALL
)
1097 pfctl_print_title("INFO:");
1098 print_status(&status
, opts
);
1103 pfctl_show_timeouts(int dev
, int opts
)
1108 if (opts
& PF_OPT_SHOWALL
)
1109 pfctl_print_title("TIMEOUTS:");
1110 memset(&pt
, 0, sizeof(pt
));
1111 for (i
= 0; pf_timeouts
[i
].name
; i
++) {
1112 pt
.timeout
= pf_timeouts
[i
].timeout
;
1113 if (ioctl(dev
, DIOCGETTIMEOUT
, &pt
))
1114 err(1, "DIOCGETTIMEOUT");
1115 printf("%-20s %10d", pf_timeouts
[i
].name
, pt
.seconds
);
1116 if (pf_timeouts
[i
].timeout
>= PFTM_ADAPTIVE_START
&&
1117 pf_timeouts
[i
].timeout
<= PFTM_ADAPTIVE_END
)
1128 pfctl_show_limits(int dev
, int opts
)
1130 struct pfioc_limit pl
;
1133 if (opts
& PF_OPT_SHOWALL
)
1134 pfctl_print_title("LIMITS:");
1135 memset(&pl
, 0, sizeof(pl
));
1136 for (i
= 0; pf_limits
[i
].name
; i
++) {
1137 pl
.index
= pf_limits
[i
].index
;
1138 if (ioctl(dev
, DIOCGETLIMIT
, &pl
))
1139 err(1, "DIOCGETLIMIT");
1140 printf("%-13s ", pf_limits
[i
].name
);
1141 if (pl
.limit
== UINT_MAX
)
1142 printf("unlimited\n");
1144 printf("hard limit %8u\n", pl
.limit
);
1149 /* callbacks for rule/nat/rdr/addr */
1151 pfctl_add_pool(struct pfctl
*pf
, struct pf_pool
*p
, sa_family_t af
)
1153 struct pf_pooladdr
*pa
;
1155 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1156 if (ioctl(pf
->dev
, DIOCBEGINADDRS
, &pf
->paddr
))
1157 err(1, "DIOCBEGINADDRS");
1161 TAILQ_FOREACH(pa
, &p
->list
, entries
) {
1162 memcpy(&pf
->paddr
.addr
, pa
, sizeof(struct pf_pooladdr
));
1163 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1164 if (ioctl(pf
->dev
, DIOCADDADDR
, &pf
->paddr
))
1165 err(1, "DIOCADDADDR");
1172 pfctl_add_rule(struct pfctl
*pf
, struct pf_rule
*r
, const char *anchor_call
)
1175 struct pf_rule
*rule
;
1176 struct pf_ruleset
*rs
;
1179 rs_num
= pf_get_ruleset_number(r
->action
);
1180 if (rs_num
== PF_RULESET_MAX
)
1181 errx(1, "Invalid rule type %d", r
->action
);
1183 rs
= &pf
->anchor
->ruleset
;
1185 if (anchor_call
[0] && r
->anchor
== NULL
) {
1187 * Don't make non-brace anchors part of the main anchor pool.
1189 if ((r
->anchor
= calloc(1, sizeof(*r
->anchor
))) == NULL
)
1190 err(1, "pfctl_add_rule: calloc");
1192 pf_init_ruleset(&r
->anchor
->ruleset
);
1193 r
->anchor
->ruleset
.anchor
= r
->anchor
;
1194 if (strlcpy(r
->anchor
->path
, anchor_call
,
1195 sizeof(rule
->anchor
->path
)) >= sizeof(rule
->anchor
->path
))
1196 errx(1, "pfctl_add_rule: strlcpy");
1197 if ((p
= strrchr(anchor_call
, '/')) != NULL
) {
1199 err(1, "pfctl_add_rule: bad anchor name %s",
1202 p
= __DECONST(char *, anchor_call
);
1203 if (strlcpy(r
->anchor
->name
, p
,
1204 sizeof(rule
->anchor
->name
)) >= sizeof(rule
->anchor
->name
))
1205 errx(1, "pfctl_add_rule: strlcpy");
1208 if ((rule
= calloc(1, sizeof(*rule
))) == NULL
)
1210 bcopy(r
, rule
, sizeof(*rule
));
1211 TAILQ_INIT(&rule
->rpool
.list
);
1212 pfctl_move_pool(&r
->rpool
, &rule
->rpool
);
1214 TAILQ_INSERT_TAIL(rs
->rules
[rs_num
].active
.ptr
, rule
, entries
);
1219 pfctl_ruleset_trans(struct pfctl
*pf
, char *path
, struct pf_anchor
*a
)
1221 int osize
= pf
->trans
->pfrb_size
;
1223 if ((pf
->loadopt
& PFCTL_FLAG_NAT
) != 0) {
1224 if (pfctl_add_trans(pf
->trans
, PF_RULESET_NAT
, path
) ||
1225 pfctl_add_trans(pf
->trans
, PF_RULESET_BINAT
, path
) ||
1226 pfctl_add_trans(pf
->trans
, PF_RULESET_RDR
, path
))
1229 if (a
== pf
->astack
[0] && ((altqsupport
&&
1230 (pf
->loadopt
& PFCTL_FLAG_ALTQ
) != 0))) {
1231 if (pfctl_add_trans(pf
->trans
, PF_RULESET_ALTQ
, path
))
1234 if ((pf
->loadopt
& PFCTL_FLAG_FILTER
) != 0) {
1235 if (pfctl_add_trans(pf
->trans
, PF_RULESET_SCRUB
, path
) ||
1236 pfctl_add_trans(pf
->trans
, PF_RULESET_FILTER
, path
))
1239 if (pf
->loadopt
& PFCTL_FLAG_TABLE
)
1240 if (pfctl_add_trans(pf
->trans
, PF_RULESET_TABLE
, path
))
1242 if (pfctl_trans(pf
->dev
, pf
->trans
, DIOCXBEGIN
, osize
))
1249 pfctl_load_ruleset(struct pfctl
*pf
, char *path
, struct pf_ruleset
*rs
,
1250 int rs_num
, int depth
)
1253 int error
, len
= strlen(path
);
1256 pf
->anchor
= rs
->anchor
;
1259 snprintf(&path
[len
], MAXPATHLEN
- len
, "/%s", pf
->anchor
->name
);
1261 snprintf(&path
[len
], MAXPATHLEN
- len
, "%s", pf
->anchor
->name
);
1264 if (TAILQ_FIRST(rs
->rules
[rs_num
].active
.ptr
) != NULL
) {
1266 if (pf
->opts
& PF_OPT_VERBOSE
)
1268 if ((pf
->opts
& PF_OPT_NOACTION
) == 0 &&
1269 (error
= pfctl_ruleset_trans(pf
,
1270 path
, rs
->anchor
))) {
1271 printf("pfctl_load_rulesets: "
1272 "pfctl_ruleset_trans %d\n", error
);
1275 } else if (pf
->opts
& PF_OPT_VERBOSE
)
1280 if (pf
->optimize
&& rs_num
== PF_RULESET_FILTER
)
1281 pfctl_optimize_ruleset(pf
, rs
);
1283 while ((r
= TAILQ_FIRST(rs
->rules
[rs_num
].active
.ptr
)) != NULL
) {
1284 TAILQ_REMOVE(rs
->rules
[rs_num
].active
.ptr
, r
, entries
);
1285 if ((error
= pfctl_load_rule(pf
, path
, r
, depth
)))
1288 if ((error
= pfctl_load_ruleset(pf
, path
,
1289 &r
->anchor
->ruleset
, rs_num
, depth
+ 1)))
1291 } else if (pf
->opts
& PF_OPT_VERBOSE
)
1295 if (brace
&& pf
->opts
& PF_OPT_VERBOSE
) {
1296 INDENT(depth
- 1, (pf
->opts
& PF_OPT_VERBOSE
));
1309 pfctl_load_rule(struct pfctl
*pf
, char *path
, struct pf_rule
*r
, int depth
)
1311 u_int8_t rs_num
= pf_get_ruleset_number(r
->action
);
1313 struct pfioc_rule pr
;
1314 int len
= strlen(path
);
1316 bzero(&pr
, sizeof(pr
));
1317 /* set up anchor before adding to path for anchor_call */
1318 if ((pf
->opts
& PF_OPT_NOACTION
) == 0)
1319 pr
.ticket
= pfctl_get_ticket(pf
->trans
, rs_num
, path
);
1320 if (strlcpy(pr
.anchor
, path
, sizeof(pr
.anchor
)) >= sizeof(pr
.anchor
))
1321 errx(1, "pfctl_load_rule: strlcpy");
1324 if (r
->anchor
->match
) {
1326 snprintf(&path
[len
], MAXPATHLEN
- len
,
1327 "/%s", r
->anchor
->name
);
1329 snprintf(&path
[len
], MAXPATHLEN
- len
,
1330 "%s", r
->anchor
->name
);
1333 name
= r
->anchor
->path
;
1335 name
= __DECONST(char *, "");
1337 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1338 if (pfctl_add_pool(pf
, &r
->rpool
, r
->af
))
1340 pr
.pool_ticket
= pf
->paddr
.ticket
;
1341 memcpy(&pr
.rule
, r
, sizeof(pr
.rule
));
1342 if (r
->anchor
&& strlcpy(pr
.anchor_call
, name
,
1343 sizeof(pr
.anchor_call
)) >= sizeof(pr
.anchor_call
))
1344 errx(1, "pfctl_load_rule: strlcpy");
1345 if (ioctl(pf
->dev
, DIOCADDRULE
, &pr
))
1346 err(1, "DIOCADDRULE");
1349 if (pf
->opts
& PF_OPT_VERBOSE
) {
1350 INDENT(depth
, !(pf
->opts
& PF_OPT_VERBOSE2
));
1351 print_rule(r
, r
->anchor
? r
->anchor
->name
: "",
1352 pf
->opts
& PF_OPT_VERBOSE2
);
1355 pfctl_clear_pool(&r
->rpool
);
1360 pfctl_add_altq(struct pfctl
*pf
, struct pf_altq
*a
)
1363 (loadopt
& PFCTL_FLAG_ALTQ
) != 0) {
1364 memcpy(&pf
->paltq
->altq
, a
, sizeof(struct pf_altq
));
1365 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1366 if (ioctl(pf
->dev
, DIOCADDALTQ
, pf
->paltq
)) {
1368 errx(1, "qtype not configured");
1369 else if (errno
== ENODEV
)
1370 errx(1, "%s: driver does not support "
1373 err(1, "DIOCADDALTQ");
1376 pfaltq_store(&pf
->paltq
->altq
);
1382 pfctl_rules(int dev
, char *filename
, int opts
, int optimize
,
1383 char *anchorname
, struct pfr_buffer
*trans
)
1385 #define ERR(x) do { warn(x); goto _error; } while(0)
1386 #define ERRX(x) do { warnx(x); goto _error; } while(0)
1388 struct pfr_buffer
*t
, buf
;
1389 struct pfioc_altq pa
;
1391 struct pf_ruleset
*rs
;
1392 struct pfr_table trs
;
1396 RB_INIT(&pf_anchors
);
1397 memset(&pf_main_anchor
, 0, sizeof(pf_main_anchor
));
1398 pf_init_ruleset(&pf_main_anchor
.ruleset
);
1399 pf_main_anchor
.ruleset
.anchor
= &pf_main_anchor
;
1400 if (trans
== NULL
) {
1401 bzero(&buf
, sizeof(buf
));
1402 buf
.pfrb_type
= PFRB_TRANS
;
1407 osize
= t
->pfrb_size
;
1410 memset(&pa
, 0, sizeof(pa
));
1411 memset(&pf
, 0, sizeof(pf
));
1412 memset(&trs
, 0, sizeof(trs
));
1413 if ((path
= calloc(1, MAXPATHLEN
)) == NULL
)
1414 ERRX("pfctl_rules: calloc");
1415 if (strlcpy(trs
.pfrt_anchor
, anchorname
,
1416 sizeof(trs
.pfrt_anchor
)) >= sizeof(trs
.pfrt_anchor
))
1417 ERRX("pfctl_rules: strlcpy");
1420 pf
.optimize
= optimize
;
1421 pf
.loadopt
= loadopt
;
1423 /* non-brace anchor, create without resolving the path */
1424 if ((pf
.anchor
= calloc(1, sizeof(*pf
.anchor
))) == NULL
)
1425 ERRX("pfctl_rules: calloc");
1426 rs
= &pf
.anchor
->ruleset
;
1427 pf_init_ruleset(rs
);
1428 rs
->anchor
= pf
.anchor
;
1429 if (strlcpy(pf
.anchor
->path
, anchorname
,
1430 sizeof(pf
.anchor
->path
)) >= sizeof(pf
.anchor
->path
))
1431 errx(1, "pfctl_add_rule: strlcpy");
1432 if (strlcpy(pf
.anchor
->name
, anchorname
,
1433 sizeof(pf
.anchor
->name
)) >= sizeof(pf
.anchor
->name
))
1434 errx(1, "pfctl_add_rule: strlcpy");
1437 pf
.astack
[0] = pf
.anchor
;
1440 pf
.loadopt
&= ~PFCTL_FLAG_ALTQ
;
1443 pfctl_init_options(&pf
);
1445 if ((opts
& PF_OPT_NOACTION
) == 0) {
1447 * XXX For the time being we need to open transactions for
1448 * the main ruleset before parsing, because tables are still
1449 * loaded at parse time.
1451 if (pfctl_ruleset_trans(&pf
, anchorname
, pf
.anchor
))
1452 ERRX("pfctl_rules");
1453 if (altqsupport
&& (pf
.loadopt
& PFCTL_FLAG_ALTQ
))
1455 pfctl_get_ticket(t
, PF_RULESET_ALTQ
, anchorname
);
1456 if (pf
.loadopt
& PFCTL_FLAG_TABLE
)
1457 pf
.astack
[0]->ruleset
.tticket
=
1458 pfctl_get_ticket(t
, PF_RULESET_TABLE
, anchorname
);
1461 if (parse_config(filename
, &pf
) < 0) {
1462 if ((opts
& PF_OPT_NOACTION
) == 0)
1463 ERRX("Syntax error in config file: "
1464 "pf rules not loaded");
1469 if ((pf
.loadopt
& PFCTL_FLAG_FILTER
&&
1470 (pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_SCRUB
, 0))) ||
1471 (pf
.loadopt
& PFCTL_FLAG_NAT
&&
1472 (pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_NAT
, 0) ||
1473 pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_RDR
, 0) ||
1474 pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_BINAT
, 0))) ||
1475 (pf
.loadopt
& PFCTL_FLAG_FILTER
&&
1476 pfctl_load_ruleset(&pf
, path
, rs
, PF_RULESET_FILTER
, 0))) {
1477 if ((opts
& PF_OPT_NOACTION
) == 0)
1478 ERRX("Unable to load rules into kernel");
1483 if ((altqsupport
&& (pf
.loadopt
& PFCTL_FLAG_ALTQ
) != 0))
1484 if (check_commit_altq(dev
, opts
) != 0)
1485 ERRX("errors in altq config");
1487 /* process "load anchor" directives */
1489 if (pfctl_load_anchors(dev
, &pf
, t
) == -1)
1490 ERRX("load anchors");
1492 if (trans
== NULL
&& (opts
& PF_OPT_NOACTION
) == 0) {
1494 if (pfctl_load_options(&pf
))
1496 if (pfctl_trans(dev
, t
, DIOCXCOMMIT
, osize
))
1502 if (trans
== NULL
) { /* main ruleset */
1503 if ((opts
& PF_OPT_NOACTION
) == 0)
1504 if (pfctl_trans(dev
, t
, DIOCXROLLBACK
, osize
))
1505 err(1, "DIOCXROLLBACK");
1507 } else { /* sub ruleset */
1516 pfctl_fopen(const char *name
, const char *mode
)
1521 fp
= fopen(name
, mode
);
1524 if (fstat(fileno(fp
), &st
)) {
1528 if (S_ISDIR(st
.st_mode
)) {
1537 pfctl_init_options(struct pfctl
*pf
)
1543 pf
->timeout
[PFTM_TCP_FIRST_PACKET
] = PFTM_TCP_FIRST_PACKET_VAL
;
1544 pf
->timeout
[PFTM_TCP_OPENING
] = PFTM_TCP_OPENING_VAL
;
1545 pf
->timeout
[PFTM_TCP_ESTABLISHED
] = PFTM_TCP_ESTABLISHED_VAL
;
1546 pf
->timeout
[PFTM_TCP_CLOSING
] = PFTM_TCP_CLOSING_VAL
;
1547 pf
->timeout
[PFTM_TCP_FIN_WAIT
] = PFTM_TCP_FIN_WAIT_VAL
;
1548 pf
->timeout
[PFTM_TCP_CLOSED
] = PFTM_TCP_CLOSED_VAL
;
1549 pf
->timeout
[PFTM_UDP_FIRST_PACKET
] = PFTM_UDP_FIRST_PACKET_VAL
;
1550 pf
->timeout
[PFTM_UDP_SINGLE
] = PFTM_UDP_SINGLE_VAL
;
1551 pf
->timeout
[PFTM_UDP_MULTIPLE
] = PFTM_UDP_MULTIPLE_VAL
;
1552 pf
->timeout
[PFTM_ICMP_FIRST_PACKET
] = PFTM_ICMP_FIRST_PACKET_VAL
;
1553 pf
->timeout
[PFTM_ICMP_ERROR_REPLY
] = PFTM_ICMP_ERROR_REPLY_VAL
;
1554 pf
->timeout
[PFTM_OTHER_FIRST_PACKET
] = PFTM_OTHER_FIRST_PACKET_VAL
;
1555 pf
->timeout
[PFTM_OTHER_SINGLE
] = PFTM_OTHER_SINGLE_VAL
;
1556 pf
->timeout
[PFTM_OTHER_MULTIPLE
] = PFTM_OTHER_MULTIPLE_VAL
;
1557 pf
->timeout
[PFTM_FRAG
] = PFTM_FRAG_VAL
;
1558 pf
->timeout
[PFTM_INTERVAL
] = PFTM_INTERVAL_VAL
;
1559 pf
->timeout
[PFTM_SRC_NODE
] = PFTM_SRC_NODE_VAL
;
1560 pf
->timeout
[PFTM_TS_DIFF
] = PFTM_TS_DIFF_VAL
;
1561 pf
->timeout
[PFTM_ADAPTIVE_START
] = PFSTATE_ADAPT_START
;
1562 pf
->timeout
[PFTM_ADAPTIVE_END
] = PFSTATE_ADAPT_END
;
1564 pf
->limit
[PF_LIMIT_STATES
] = PFSTATE_HIWAT
;
1565 pf
->limit
[PF_LIMIT_FRAGS
] = PFFRAG_FRENT_HIWAT
;
1566 pf
->limit
[PF_LIMIT_SRC_NODES
] = PFSNODE_HIWAT
;
1567 pf
->limit
[PF_LIMIT_TABLES
] = PFR_KTABLE_HIWAT
;
1568 pf
->limit
[PF_LIMIT_TABLE_ENTRIES
] = PFR_KENTRY_HIWAT
;
1571 mib
[1] = HW_PHYSMEM
;
1573 if (sysctl(mib
, 2, &mem
, &size
, NULL
, 0) == -1)
1575 if (mem
<= 100*1024*1024)
1576 pf
->limit
[PF_LIMIT_TABLE_ENTRIES
] = PFR_KENTRY_HIWAT_SMALL
;
1578 pf
->debug
= PF_DEBUG_URGENT
;
1582 pfctl_load_options(struct pfctl
*pf
)
1586 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1590 for (i
= 0; i
< PF_LIMIT_MAX
; i
++) {
1591 if ((pf
->opts
& PF_OPT_MERGE
) && !pf
->limit_set
[i
])
1593 if (pfctl_load_limit(pf
, i
, pf
->limit
[i
]))
1598 * If we've set the limit, but haven't explicitly set adaptive
1599 * timeouts, do it now with a start of 60% and end of 120%.
1601 if (pf
->limit_set
[PF_LIMIT_STATES
] &&
1602 !pf
->timeout_set
[PFTM_ADAPTIVE_START
] &&
1603 !pf
->timeout_set
[PFTM_ADAPTIVE_END
]) {
1604 pf
->timeout
[PFTM_ADAPTIVE_START
] =
1605 (pf
->limit
[PF_LIMIT_STATES
] / 10) * 6;
1606 pf
->timeout_set
[PFTM_ADAPTIVE_START
] = 1;
1607 pf
->timeout
[PFTM_ADAPTIVE_END
] =
1608 (pf
->limit
[PF_LIMIT_STATES
] / 10) * 12;
1609 pf
->timeout_set
[PFTM_ADAPTIVE_END
] = 1;
1613 for (i
= 0; i
< PFTM_MAX
; i
++) {
1614 if ((pf
->opts
& PF_OPT_MERGE
) && !pf
->timeout_set
[i
])
1616 if (pfctl_load_timeout(pf
, i
, pf
->timeout
[i
]))
1621 if (!(pf
->opts
& PF_OPT_MERGE
) || pf
->debug_set
)
1622 if (pfctl_load_debug(pf
, pf
->debug
))
1626 if (!(pf
->opts
& PF_OPT_MERGE
) || pf
->ifname_set
)
1627 if (pfctl_load_logif(pf
, pf
->ifname
))
1631 if (!(pf
->opts
& PF_OPT_MERGE
) || pf
->hostid_set
)
1632 if (pfctl_load_hostid(pf
, pf
->hostid
))
1639 pfctl_set_limit(struct pfctl
*pf
, const char *opt
, unsigned int limit
)
1644 for (i
= 0; pf_limits
[i
].name
; i
++) {
1645 if (strcasecmp(opt
, pf_limits
[i
].name
) == 0) {
1646 pf
->limit
[pf_limits
[i
].index
] = limit
;
1647 pf
->limit_set
[pf_limits
[i
].index
] = 1;
1651 if (pf_limits
[i
].name
== NULL
) {
1652 warnx("Bad pool name.");
1656 if (pf
->opts
& PF_OPT_VERBOSE
)
1657 printf("set limit %s %d\n", opt
, limit
);
1663 pfctl_load_limit(struct pfctl
*pf
, unsigned int his_index
, unsigned int limit
)
1665 struct pfioc_limit pl
;
1667 memset(&pl
, 0, sizeof(pl
));
1668 pl
.index
= his_index
;
1670 if (ioctl(pf
->dev
, DIOCSETLIMIT
, &pl
)) {
1672 warnx("Current pool size exceeds requested hard limit");
1674 warnx("DIOCSETLIMIT");
1681 pfctl_set_timeout(struct pfctl
*pf
, const char *opt
, int seconds
, int quiet
)
1685 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1688 for (i
= 0; pf_timeouts
[i
].name
; i
++) {
1689 if (strcasecmp(opt
, pf_timeouts
[i
].name
) == 0) {
1690 pf
->timeout
[pf_timeouts
[i
].timeout
] = seconds
;
1691 pf
->timeout_set
[pf_timeouts
[i
].timeout
] = 1;
1696 if (pf_timeouts
[i
].name
== NULL
) {
1697 warnx("Bad timeout name.");
1702 if (pf
->opts
& PF_OPT_VERBOSE
&& ! quiet
)
1703 printf("set timeout %s %d\n", opt
, seconds
);
1709 pfctl_load_timeout(struct pfctl
*pf
, unsigned int timeout
, unsigned int seconds
)
1713 memset(&pt
, 0, sizeof(pt
));
1714 pt
.timeout
= timeout
;
1715 pt
.seconds
= seconds
;
1716 if (ioctl(pf
->dev
, DIOCSETTIMEOUT
, &pt
)) {
1717 warnx("DIOCSETTIMEOUT");
1724 pfctl_set_optimization(struct pfctl
*pf
, const char *opt
)
1726 const struct pf_hint
*hint
;
1729 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1732 for (i
= 0; pf_hints
[i
].name
; i
++)
1733 if (strcasecmp(opt
, pf_hints
[i
].name
) == 0)
1736 hint
= pf_hints
[i
].hint
;
1738 warnx("invalid state timeouts optimization");
1742 for (i
= 0; hint
[i
].name
; i
++)
1743 if ((r
= pfctl_set_timeout(pf
, hint
[i
].name
,
1744 hint
[i
].timeout
, 1)))
1747 if (pf
->opts
& PF_OPT_VERBOSE
)
1748 printf("set optimization %s\n", opt
);
1754 pfctl_set_logif(struct pfctl
*pf
, char *ifname
)
1757 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1760 if (!strcmp(ifname
, "none")) {
1764 pf
->ifname
= strdup(ifname
);
1766 errx(1, "pfctl_set_logif: strdup");
1770 if (pf
->opts
& PF_OPT_VERBOSE
)
1771 printf("set loginterface %s\n", ifname
);
1777 pfctl_load_logif(struct pfctl
*pf
, char *ifname
)
1781 memset(&pi
, 0, sizeof(pi
));
1782 if (ifname
&& strlcpy(pi
.ifname
, ifname
,
1783 sizeof(pi
.ifname
)) >= sizeof(pi
.ifname
)) {
1784 warnx("pfctl_load_logif: strlcpy");
1787 if (ioctl(pf
->dev
, DIOCSETSTATUSIF
, &pi
)) {
1788 warnx("DIOCSETSTATUSIF");
1795 pfctl_set_hostid(struct pfctl
*pf
, u_int32_t hostid
)
1797 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1800 hostid
= htonl(hostid
);
1802 pf
->hostid
= hostid
;
1805 if (pf
->opts
& PF_OPT_VERBOSE
)
1806 printf("set hostid 0x%08x\n", ntohl(hostid
));
1812 pfctl_load_hostid(struct pfctl
*pf __unused
, u_int32_t hostid
)
1814 if (ioctl(dev_fd
, DIOCSETHOSTID
, &hostid
)) {
1815 warnx("DIOCSETHOSTID");
1822 pfctl_set_debug(struct pfctl
*pf
, char *d
)
1826 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1829 if (!strcmp(d
, "none"))
1830 pf
->debug
= PF_DEBUG_NONE
;
1831 else if (!strcmp(d
, "urgent"))
1832 pf
->debug
= PF_DEBUG_URGENT
;
1833 else if (!strcmp(d
, "misc"))
1834 pf
->debug
= PF_DEBUG_MISC
;
1835 else if (!strcmp(d
, "loud"))
1836 pf
->debug
= PF_DEBUG_NOISY
;
1838 warnx("unknown debug level \"%s\"", d
);
1844 if ((pf
->opts
& PF_OPT_NOACTION
) == 0)
1845 if (ioctl(dev_fd
, DIOCSETDEBUG
, &level
))
1846 err(1, "DIOCSETDEBUG");
1848 if (pf
->opts
& PF_OPT_VERBOSE
)
1849 printf("set debug %s\n", d
);
1855 pfctl_load_debug(struct pfctl
*pf
, unsigned int level
)
1857 if (ioctl(pf
->dev
, DIOCSETDEBUG
, &level
)) {
1858 warnx("DIOCSETDEBUG");
1865 pfctl_set_interface_flags(struct pfctl
*pf
, char *ifname
, int flags
, int how
)
1867 struct pfioc_iface pi
;
1869 if ((loadopt
& PFCTL_FLAG_OPTION
) == 0)
1872 bzero(&pi
, sizeof(pi
));
1874 pi
.pfiio_flags
= flags
;
1876 if (strlcpy(pi
.pfiio_name
, ifname
, sizeof(pi
.pfiio_name
)) >=
1877 sizeof(pi
.pfiio_name
))
1878 errx(1, "pfctl_set_interface_flags: strlcpy");
1880 if ((pf
->opts
& PF_OPT_NOACTION
) == 0) {
1882 if (ioctl(pf
->dev
, DIOCCLRIFFLAG
, &pi
))
1883 err(1, "DIOCCLRIFFLAG");
1885 if (ioctl(pf
->dev
, DIOCSETIFFLAG
, &pi
))
1886 err(1, "DIOCSETIFFLAG");
1893 pfctl_debug(int dev
, u_int32_t level
, int opts
)
1895 if (ioctl(dev
, DIOCSETDEBUG
, &level
))
1896 err(1, "DIOCSETDEBUG");
1897 if ((opts
& PF_OPT_QUIET
) == 0) {
1898 fprintf(stderr
, "debug level set to '");
1901 fprintf(stderr
, "none");
1903 case PF_DEBUG_URGENT
:
1904 fprintf(stderr
, "urgent");
1907 fprintf(stderr
, "misc");
1909 case PF_DEBUG_NOISY
:
1910 fprintf(stderr
, "loud");
1913 fprintf(stderr
, "<invalid>");
1916 fprintf(stderr
, "'\n");
1921 pfctl_test_altqsupport(int dev
, int opts
)
1923 struct pfioc_altq pa
;
1925 if (ioctl(dev
, DIOCGETALTQS
, &pa
)) {
1926 if (errno
== ENODEV
) {
1927 if (!(opts
& PF_OPT_QUIET
))
1928 fprintf(stderr
, "No ALTQ support in kernel\n"
1929 "ALTQ related functions disabled\n");
1932 err(1, "DIOCGETALTQS");
1938 pfctl_show_anchors(int dev
, int opts
, char *anchorname
)
1940 struct pfioc_ruleset pr
;
1943 memset(&pr
, 0, sizeof(pr
));
1944 memcpy(pr
.path
, anchorname
, sizeof(pr
.path
));
1945 if (ioctl(dev
, DIOCGETRULESETS
, &pr
)) {
1946 if (errno
== EINVAL
)
1947 fprintf(stderr
, "Anchor '%s' not found.\n",
1950 err(1, "DIOCGETRULESETS");
1954 for (nr
= 0; nr
< mnr
; ++nr
) {
1955 char sub
[MAXPATHLEN
];
1958 if (ioctl(dev
, DIOCGETRULESET
, &pr
))
1959 err(1, "DIOCGETRULESET");
1960 if (!strcmp(pr
.name
, PF_RESERVED_ANCHOR
))
1964 strlcat(sub
, pr
.path
, sizeof(sub
));
1965 strlcat(sub
, "/", sizeof(sub
));
1967 strlcat(sub
, pr
.name
, sizeof(sub
));
1968 if (sub
[0] != '_' || (opts
& PF_OPT_VERBOSE
))
1969 printf(" %s\n", sub
);
1970 if ((opts
& PF_OPT_VERBOSE
) && pfctl_show_anchors(dev
, opts
, sub
))
1977 pfctl_lookup_option(char *cmd
, const char **list
)
1979 if (cmd
!= NULL
&& *cmd
)
1980 for (; *list
; list
++)
1981 if (!strncmp(cmd
, *list
, strlen(cmd
)))
1987 main(int argc
, char *argv
[])
1991 int mode
= O_RDONLY
;
1993 int optimize
= PF_OPTIMIZE_BASIC
;
1994 char anchorname
[MAXPATHLEN
];
2000 while ((ch
= getopt(argc
, argv
,
2001 "a:AdD:eqf:F:ghi:k:K:mnNOo:p:rRs:t:T:vx:z")) != -1) {
2007 opts
|= PF_OPT_DISABLE
;
2011 if (pfctl_cmdline_symset(optarg
) < 0)
2012 warnx("could not parse macro definition %s",
2016 opts
|= PF_OPT_ENABLE
;
2020 opts
|= PF_OPT_QUIET
;
2023 clearopt
= pfctl_lookup_option(optarg
, clearopt_list
);
2024 if (clearopt
== NULL
) {
2025 warnx("Unknown flush modifier '%s'", optarg
);
2034 if (state_killers
>= 2) {
2035 warnx("can only specify -k twice");
2039 state_kill
[state_killers
++] = optarg
;
2043 if (src_node_killers
>= 2) {
2044 warnx("can only specify -K twice");
2048 src_node_kill
[src_node_killers
++] = optarg
;
2052 opts
|= PF_OPT_MERGE
;
2055 opts
|= PF_OPT_NOACTION
;
2058 loadopt
|= PFCTL_FLAG_NAT
;
2061 opts
|= PF_OPT_USEDNS
;
2068 opts
|= PF_OPT_DEBUG
;
2071 loadopt
|= PFCTL_FLAG_ALTQ
;
2074 loadopt
|= PFCTL_FLAG_FILTER
;
2077 optiopt
= pfctl_lookup_option(optarg
, optiopt_list
);
2078 if (optiopt
== NULL
) {
2079 warnx("Unknown optimization '%s'", optarg
);
2082 opts
|= PF_OPT_OPTIMIZE
;
2085 loadopt
|= PFCTL_FLAG_OPTION
;
2091 showopt
= pfctl_lookup_option(optarg
, showopt_list
);
2092 if (showopt
== NULL
) {
2093 warnx("Unknown show modifier '%s'", optarg
);
2101 tblcmdopt
= pfctl_lookup_option(optarg
, tblcmdopt_list
);
2102 if (tblcmdopt
== NULL
) {
2103 warnx("Unknown table command '%s'", optarg
);
2108 if (opts
& PF_OPT_VERBOSE
)
2109 opts
|= PF_OPT_VERBOSE2
;
2110 opts
|= PF_OPT_VERBOSE
;
2113 debugopt
= pfctl_lookup_option(optarg
, debugopt_list
);
2114 if (debugopt
== NULL
) {
2115 warnx("Unknown debug level '%s'", optarg
);
2121 opts
|= PF_OPT_CLRRULECTRS
;
2132 if (tblcmdopt
!= NULL
) {
2137 loadopt
|= PFCTL_FLAG_TABLE
;
2140 mode
= strchr("acdefkrz", ch
) ? O_RDWR
: O_RDONLY
;
2141 } else if (argc
!= optind
) {
2142 warnx("unknown command line argument: %s ...", argv
[optind
]);
2149 if ((path
= calloc(1, MAXPATHLEN
)) == NULL
)
2150 errx(1, "pfctl: calloc");
2151 memset(anchorname
, 0, sizeof(anchorname
));
2152 if (anchoropt
!= NULL
) {
2153 int len
= strlen(anchoropt
);
2155 if (anchoropt
[len
- 1] == '*') {
2156 if (len
>= 2 && anchoropt
[len
- 2] == '/')
2157 anchoropt
[len
- 2] = '\0';
2159 anchoropt
[len
- 1] = '\0';
2160 opts
|= PF_OPT_RECURSE
;
2162 if (strlcpy(anchorname
, anchoropt
,
2163 sizeof(anchorname
)) >= sizeof(anchorname
))
2164 errx(1, "anchor name '%s' too long",
2166 loadopt
&= PFCTL_FLAG_FILTER
|PFCTL_FLAG_NAT
|PFCTL_FLAG_TABLE
;
2169 if ((opts
& PF_OPT_NOACTION
) == 0) {
2170 dev_fd
= open(pf_device
, mode
);
2172 err(1, "%s", pf_device
);
2173 altqsupport
= pfctl_test_altqsupport(dev_fd
, opts
);
2175 dev_fd
= open(pf_device
, O_RDONLY
);
2177 opts
|= PF_OPT_DUMMYACTION
;
2178 /* turn off options */
2179 opts
&= ~ (PF_OPT_DISABLE
| PF_OPT_ENABLE
);
2180 clearopt
= showopt
= debugopt
= NULL
;
2184 if (opts
& PF_OPT_DISABLE
)
2185 if (pfctl_disable(dev_fd
, opts
))
2188 if (showopt
!= NULL
) {
2191 pfctl_show_anchors(dev_fd
, opts
, anchorname
);
2194 pfctl_load_fingerprints(dev_fd
, opts
);
2195 pfctl_show_rules(dev_fd
, path
, opts
, PFCTL_SHOW_RULES
,
2199 pfctl_load_fingerprints(dev_fd
, opts
);
2200 pfctl_show_rules(dev_fd
, path
, opts
, PFCTL_SHOW_LABELS
,
2204 pfctl_load_fingerprints(dev_fd
, opts
);
2205 pfctl_show_nat(dev_fd
, opts
, anchorname
);
2208 pfctl_show_altq(dev_fd
, ifaceopt
, opts
,
2209 opts
& PF_OPT_VERBOSE2
);
2212 pfctl_show_states(dev_fd
, ifaceopt
, opts
);
2215 pfctl_show_src_nodes(dev_fd
, opts
);
2218 pfctl_show_status(dev_fd
, opts
);
2221 pfctl_show_timeouts(dev_fd
, opts
);
2224 pfctl_show_limits(dev_fd
, opts
);
2227 opts
|= PF_OPT_SHOWALL
;
2228 pfctl_load_fingerprints(dev_fd
, opts
);
2230 pfctl_show_nat(dev_fd
, opts
, anchorname
);
2231 pfctl_show_rules(dev_fd
, path
, opts
, 0, anchorname
, 0);
2232 pfctl_show_altq(dev_fd
, ifaceopt
, opts
, 0);
2233 pfctl_show_states(dev_fd
, ifaceopt
, opts
);
2234 pfctl_show_src_nodes(dev_fd
, opts
);
2235 pfctl_show_status(dev_fd
, opts
);
2236 pfctl_show_rules(dev_fd
, path
, opts
, 1, anchorname
, 0);
2237 pfctl_show_timeouts(dev_fd
, opts
);
2238 pfctl_show_limits(dev_fd
, opts
);
2239 pfctl_show_tables(anchorname
, opts
);
2240 pfctl_show_fingerprints(opts
);
2243 pfctl_show_tables(anchorname
, opts
);
2246 pfctl_load_fingerprints(dev_fd
, opts
);
2247 pfctl_show_fingerprints(opts
);
2250 pfctl_show_ifaces(ifaceopt
, opts
);
2255 if ((opts
& PF_OPT_CLRRULECTRS
) && showopt
== NULL
)
2256 pfctl_show_rules(dev_fd
, path
, opts
, PFCTL_SHOW_NOTHING
,
2259 if (clearopt
!= NULL
) {
2260 if (anchorname
[0] == '_' || strstr(anchorname
, "/_") != NULL
)
2261 errx(1, "anchor names beginning with '_' cannot "
2262 "be modified from the command line");
2264 switch (*clearopt
) {
2266 pfctl_clear_rules(dev_fd
, opts
, anchorname
);
2269 pfctl_clear_nat(dev_fd
, opts
, anchorname
);
2272 pfctl_clear_altq(dev_fd
, opts
);
2275 pfctl_clear_states(dev_fd
, ifaceopt
, opts
);
2278 pfctl_clear_src_nodes(dev_fd
, opts
);
2281 pfctl_clear_stats(dev_fd
, opts
);
2284 pfctl_clear_rules(dev_fd
, opts
, anchorname
);
2285 pfctl_clear_nat(dev_fd
, opts
, anchorname
);
2286 pfctl_clear_tables(anchorname
, opts
);
2288 pfctl_clear_altq(dev_fd
, opts
);
2289 pfctl_clear_states(dev_fd
, ifaceopt
, opts
);
2290 pfctl_clear_src_nodes(dev_fd
, opts
);
2291 pfctl_clear_stats(dev_fd
, opts
);
2292 pfctl_clear_fingerprints(dev_fd
, opts
);
2293 pfctl_clear_interface_flags(dev_fd
, opts
);
2297 pfctl_clear_fingerprints(dev_fd
, opts
);
2300 pfctl_clear_tables(anchorname
, opts
);
2304 if (state_killers
) {
2305 if (!strcmp(state_kill
[0], "label"))
2306 pfctl_label_kill_states(dev_fd
, ifaceopt
, opts
);
2307 else if (!strcmp(state_kill
[0], "id"))
2308 pfctl_id_kill_states(dev_fd
, ifaceopt
, opts
);
2310 pfctl_net_kill_states(dev_fd
, ifaceopt
, opts
);
2313 if (src_node_killers
)
2314 pfctl_kill_src_nodes(dev_fd
, ifaceopt
, opts
);
2316 if (tblcmdopt
!= NULL
) {
2317 error
= pfctl_command_tables(argc
, argv
, tableopt
,
2318 tblcmdopt
, rulesopt
, anchorname
, opts
);
2321 if (optiopt
!= NULL
) {
2327 optimize
|= PF_OPTIMIZE_BASIC
;
2331 optimize
|= PF_OPTIMIZE_PROFILE
;
2336 if ((rulesopt
!= NULL
) && (loadopt
& PFCTL_FLAG_OPTION
) &&
2338 if (pfctl_clear_interface_flags(dev_fd
, opts
| PF_OPT_QUIET
))
2341 if (rulesopt
!= NULL
&& !(opts
& (PF_OPT_MERGE
|PF_OPT_NOACTION
)) &&
2342 !anchorname
[0] && (loadopt
& PFCTL_FLAG_OPTION
))
2343 if (pfctl_file_fingerprints(dev_fd
, opts
, PF_OSFP_FILE
))
2346 if (rulesopt
!= NULL
) {
2347 if (anchorname
[0] == '_' || strstr(anchorname
, "/_") != NULL
)
2348 errx(1, "anchor names beginning with '_' cannot "
2349 "be modified from the command line");
2350 if (pfctl_rules(dev_fd
, rulesopt
, opts
, optimize
,
2353 else if (!(opts
& PF_OPT_NOACTION
) &&
2354 (loadopt
& PFCTL_FLAG_TABLE
))
2355 warn_namespace_collision(NULL
);
2358 if (opts
& PF_OPT_ENABLE
)
2359 if (pfctl_enable(dev_fd
, opts
))
2362 if (debugopt
!= NULL
) {
2363 switch (*debugopt
) {
2365 pfctl_debug(dev_fd
, PF_DEBUG_NONE
, opts
);
2368 pfctl_debug(dev_fd
, PF_DEBUG_URGENT
, opts
);
2371 pfctl_debug(dev_fd
, PF_DEBUG_MISC
, opts
);
2374 pfctl_debug(dev_fd
, PF_DEBUG_NOISY
, opts
);