Bug Summary

File:src/sbin/pfctl/pfctl.c
Warning:line 704, column 8
Potential leak of memory pointed to by 'token'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pfctl.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/pfctl/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sbin/pfctl -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -Wno-uninitialized -fdebug-compilation-dir=/usr/src/sbin/pfctl/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/sbin/pfctl/pfctl.c
1/* $OpenBSD: pfctl.c,v 1.392 2023/10/26 16:26:01 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2001 Daniel Hartmeier
5 * Copyright (c) 2002 - 2013 Henning Brauer <henning@openbsd.org>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * - Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include <sys/types.h>
35#include <sys/ioctl.h>
36#include <sys/socket.h>
37#include <sys/stat.h>
38
39#include <net/if.h>
40#include <netinet/in.h>
41#include <net/pfvar.h>
42#include <arpa/inet.h>
43#include <sys/sysctl.h>
44
45#include <err.h>
46#include <errno(*__errno()).h>
47#include <fcntl.h>
48#include <limits.h>
49#include <netdb.h>
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53#include <unistd.h>
54#include <syslog.h>
55#include <stdarg.h>
56#include <libgen.h>
57
58#include "pfctl_parser.h"
59#include "pfctl.h"
60
61void usage(void);
62int pfctl_enable(int, int);
63int pfctl_disable(int, int);
64void pfctl_clear_queues(struct pf_qihead *);
65void pfctl_clear_stats(int, const char *, int);
66void pfctl_clear_interface_flags(int, int);
67int pfctl_clear_rules(int, int, char *);
68void pfctl_clear_src_nodes(int, int);
69void pfctl_clear_states(int, const char *, int);
70struct addrinfo *
71 pfctl_addrprefix(char *, struct pf_addr *, int);
72void pfctl_kill_src_nodes(int, int);
73void pfctl_net_kill_states(int, const char *, int, int);
74void pfctl_label_kill_states(int, const char *, int, int);
75void pfctl_id_kill_states(int, int);
76void pfctl_key_kill_states(int, const char *, int, int);
77int pfctl_parse_host(char *, struct pf_rule_addr *);
78void pfctl_init_options(struct pfctl *);
79int pfctl_load_options(struct pfctl *);
80int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
81int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int);
82int pfctl_load_debug(struct pfctl *, unsigned int);
83int pfctl_load_logif(struct pfctl *, char *);
84int pfctl_load_hostid(struct pfctl *, unsigned int);
85int pfctl_load_reassembly(struct pfctl *, u_int32_t);
86int pfctl_load_syncookies(struct pfctl *, u_int8_t);
87int pfctl_set_synflwats(struct pfctl *, u_int32_t, u_int32_t);
88void pfctl_print_rule_counters(struct pf_rule *, int);
89int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int,
90 long);
91int pfctl_show_src_nodes(int, int);
92int pfctl_show_states(int, const char *, int, long);
93int pfctl_show_status(int, int);
94int pfctl_show_timeouts(int, int);
95int pfctl_show_limits(int, int);
96void pfctl_debug(int, u_int32_t, int);
97int pfctl_show_anchors(int, int, char *);
98int pfctl_ruleset_trans(struct pfctl *, char *, struct pf_anchor *);
99u_int pfctl_find_childqs(struct pfctl_qsitem *);
100void pfctl_load_queue(struct pfctl *, u_int32_t, struct pfctl_qsitem *);
101int pfctl_load_queues(struct pfctl *);
102u_int pfctl_leafqueue_check(char *);
103u_int pfctl_check_qassignments(struct pf_ruleset *);
104int pfctl_load_ruleset(struct pfctl *, char *, struct pf_ruleset *, int);
105int pfctl_load_rule(struct pfctl *, char *, struct pf_rule *, int);
106const char *pfctl_lookup_option(char *, const char **);
107void pfctl_state_store(int, const char *);
108void pfctl_state_load(int, const char *);
109void pfctl_reset(int, int);
110int pfctl_walk_show(int, struct pfioc_ruleset *, void *);
111int pfctl_walk_get(int, struct pfioc_ruleset *, void *);
112int pfctl_walk_anchors(int, int, const char *,
113 int(*)(int, struct pfioc_ruleset *, void *), void *);
114struct pfr_anchors *
115 pfctl_get_anchors(int, const char *, int);
116int pfctl_recurse(int, int, const char *,
117 int(*)(int, int, struct pfr_anchoritem *));
118int pfctl_call_clearrules(int, int, struct pfr_anchoritem *);
119int pfctl_call_cleartables(int, int, struct pfr_anchoritem *);
120int pfctl_call_clearanchors(int, int, struct pfr_anchoritem *);
121
122const char *clearopt;
123char *rulesopt;
124const char *showopt;
125const char *debugopt;
126char *anchoropt;
127const char *optiopt = NULL((void *)0);
128char *pf_device = "/dev/pf";
129char *ifaceopt;
130char *tableopt;
131const char *tblcmdopt;
132int src_node_killers;
133char *src_node_kill[2];
134int state_killers;
135char *state_kill[2];
136
137int dev = -1;
138int first_title = 1;
139int labels = 0;
140int exit_val = 0;
141
142#define INDENT(d, o)do { if (o) { int i; for (i=0; i < d; i++) printf(" "); }
} while (0)
do { \
143 if (o) { \
144 int i; \
145 for (i=0; i < d; i++) \
146 printf(" "); \
147 } \
148 } while (0) \
149
150
151static const struct {
152 const char *name;
153 int index;
154} pf_limits[] = {
155 { "states", PF_LIMIT_STATES },
156 { "src-nodes", PF_LIMIT_SRC_NODES },
157 { "frags", PF_LIMIT_FRAGS },
158 { "tables", PF_LIMIT_TABLES },
159 { "table-entries", PF_LIMIT_TABLE_ENTRIES },
160 { "pktdelay-pkts", PF_LIMIT_PKTDELAY_PKTS },
161 { "anchors", PF_LIMIT_ANCHORS },
162 { NULL((void *)0), 0 }
163};
164
165struct pf_hint {
166 const char *name;
167 int timeout;
168};
169static const struct pf_hint pf_hint_normal[] = {
170 { "tcp.first", 2 * 60 },
171 { "tcp.opening", 30 },
172 { "tcp.established", 24 * 60 * 60 },
173 { "tcp.closing", 15 * 60 },
174 { "tcp.finwait", 45 },
175 { "tcp.closed", 90 },
176 { "tcp.tsdiff", 30 },
177 { NULL((void *)0), 0 }
178};
179static const struct pf_hint pf_hint_satellite[] = {
180 { "tcp.first", 3 * 60 },
181 { "tcp.opening", 30 + 5 },
182 { "tcp.established", 24 * 60 * 60 },
183 { "tcp.closing", 15 * 60 + 5 },
184 { "tcp.finwait", 45 + 5 },
185 { "tcp.closed", 90 + 5 },
186 { "tcp.tsdiff", 60 },
187 { NULL((void *)0), 0 }
188};
189static const struct pf_hint pf_hint_conservative[] = {
190 { "tcp.first", 60 * 60 },
191 { "tcp.opening", 15 * 60 },
192 { "tcp.established", 5 * 24 * 60 * 60 },
193 { "tcp.closing", 60 * 60 },
194 { "tcp.finwait", 10 * 60 },
195 { "tcp.closed", 3 * 60 },
196 { "tcp.tsdiff", 60 },
197 { NULL((void *)0), 0 }
198};
199static const struct pf_hint pf_hint_aggressive[] = {
200 { "tcp.first", 30 },
201 { "tcp.opening", 5 },
202 { "tcp.established", 5 * 60 * 60 },
203 { "tcp.closing", 60 },
204 { "tcp.finwait", 30 },
205 { "tcp.closed", 30 },
206 { "tcp.tsdiff", 10 },
207 { NULL((void *)0), 0 }
208};
209
210static const struct {
211 const char *name;
212 const struct pf_hint *hint;
213} pf_hints[] = {
214 { "normal", pf_hint_normal },
215 { "satellite", pf_hint_satellite },
216 { "high-latency", pf_hint_satellite },
217 { "conservative", pf_hint_conservative },
218 { "aggressive", pf_hint_aggressive },
219 { NULL((void *)0), NULL((void *)0) }
220};
221
222static const char *clearopt_list[] = {
223 "rules", "Sources", "states", "info", "Tables", "osfp", "Reset",
224 "all", NULL((void *)0)
225};
226
227static const char *showopt_list[] = {
228 "queue", "rules", "Anchors", "Sources", "states", "info",
229 "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
230 "all", NULL((void *)0)
231};
232
233static const char *tblcmdopt_list[] = {
234 "kill", "flush", "add", "delete", "replace", "show",
235 "test", "zero", "expire", NULL((void *)0)
236};
237
238static const char *debugopt_list[] = {
239 "debug", "info", "notice", "warning",
240 "error", "crit", "alert", "emerg",
241 NULL((void *)0)
242};
243
244static const char *optiopt_list[] = {
245 "none", "basic", "profile", NULL((void *)0)
246};
247
248struct pf_qihead qspecs = TAILQ_HEAD_INITIALIZER(qspecs){ ((void *)0), &(qspecs).tqh_first };
249struct pf_qihead rootqs = TAILQ_HEAD_INITIALIZER(rootqs){ ((void *)0), &(rootqs).tqh_first };
250
251__dead__attribute__((__noreturn__)) void
252usage(void)
253{
254 extern char *__progname;
255
256 fprintf(stderr(&__sF[2]), "usage: %s [-deghNnPqrvz] ", __progname);
257 fprintf(stderr(&__sF[2]), "[-a anchor] [-D macro=value] [-F modifier]");
258 fprintf(stderr(&__sF[2]), " [-f file]\n");
259 fprintf(stderr(&__sF[2]), "\t[-i interface] [-K key] [-k key] [-L statefile]");
260 fprintf(stderr(&__sF[2]), " [-o level]\n");
261 fprintf(stderr(&__sF[2]), "\t[-p device] [-S statefile] [-s modifier [-R id]]\n");
262 fprintf(stderr(&__sF[2]), "\t[-t table -T command [address ...]]");
263 fprintf(stderr(&__sF[2]), " [-V rdomain] [-x level]\n");
264 exit(1);
265}
266
267void
268pfctl_err(int opts, int eval, const char *fmt, ...)
269{
270 va_list ap;
271
272 va_start(ap, fmt)__builtin_va_start((ap), fmt);
273
274 if ((opts & PF_OPT_IGNFAIL0x10000) == 0)
275 verr(eval, fmt, ap);
276 else
277 vwarn(fmt, ap);
278
279 va_end(ap)__builtin_va_end((ap));
280
281 exit_val = eval;
282}
283
284void
285pfctl_errx(int opts, int eval, const char *fmt, ...)
286{
287 va_list ap;
288
289 va_start(ap, fmt)__builtin_va_start((ap), fmt);
290
291 if ((opts & PF_OPT_IGNFAIL0x10000) == 0)
292 verrx(eval, fmt, ap);
293 else
294 vwarnx(fmt, ap);
295
296 va_end(ap)__builtin_va_end((ap));
297
298 exit_val = eval;
299}
300
301int
302pfctl_enable(int dev, int opts)
303{
304 if (ioctl(dev, DIOCSTART((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('D')) << 8) | ((1)))
) == -1) {
305 if (errno(*__errno()) == EEXIST17)
306 errx(1, "pf already enabled");
307 else
308 err(1, "DIOCSTART");
309 }
310 if ((opts & PF_OPT_QUIET0x00010) == 0)
311 fprintf(stderr(&__sF[2]), "pf enabled\n");
312
313 return (0);
314}
315
316int
317pfctl_disable(int dev, int opts)
318{
319 if (ioctl(dev, DIOCSTOP((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('D')) << 8) | ((2)))
) == -1) {
320 if (errno(*__errno()) == ENOENT2)
321 errx(1, "pf not enabled");
322 else
323 err(1, "DIOCSTOP");
324 }
325 if ((opts & PF_OPT_QUIET0x00010) == 0)
326 fprintf(stderr(&__sF[2]), "pf disabled\n");
327
328 return (0);
329}
330
331void
332pfctl_clear_stats(int dev, const char *iface, int opts)
333{
334 struct pfioc_iface pi;
335
336 memset(&pi, 0, sizeof(pi));
337 if (iface != NULL((void *)0) && strlcpy(pi.pfiio_name, iface,
338 sizeof(pi.pfiio_name)) >= sizeof(pi.pfiio_name))
339 pfctl_errx(opts, 1, "invalid interface: %s", iface);
340
341 if (ioctl(dev, DIOCCLRSTATUS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((22)))
, &pi) == -1)
342 pfctl_err(opts, 1, "DIOCCLRSTATUS");
343 if ((opts & PF_OPT_QUIET0x00010) == 0) {
344 fprintf(stderr(&__sF[2]), "pf: statistics cleared");
345 if (iface != NULL((void *)0))
346 fprintf(stderr(&__sF[2]), " for interface %s", iface);
347 fprintf(stderr(&__sF[2]), "\n");
348 }
349}
350
351void
352pfctl_clear_interface_flags(int dev, int opts)
353{
354 struct pfioc_iface pi;
355
356 if ((opts & PF_OPT_NOACTION0x00008) == 0) {
357 bzero(&pi, sizeof(pi));
358 pi.pfiio_flags = PFI_IFLAG_SKIP0x0100;
359
360 if (ioctl(dev, DIOCCLRIFFLAG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((90)))
, &pi) == -1)
361 pfctl_err(opts, 1, "DIOCCLRIFFLAG");
362 if ((opts & PF_OPT_QUIET0x00010) == 0)
363 fprintf(stderr(&__sF[2]), "pf: interface flags reset\n");
364 }
365}
366
367int
368pfctl_clear_rules(int dev, int opts, char *anchorname)
369{
370 struct pfr_buffer t;
371
372 memset(&t, 0, sizeof(t));
373 t.pfrb_type = PFRB_TRANS;
374 if (pfctl_add_trans(&t, PF_TRANS_RULESET, anchorname) ||
375 pfctl_trans(dev, &t, DIOCXBEGIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_trans) & 0x1fff) << 16) | ((('D')) <<
8) | ((81)))
, 0) ||
376 pfctl_trans(dev, &t, DIOCXCOMMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_trans) & 0x1fff) << 16) | ((('D')) <<
8) | ((82)))
, 0)) {
377 pfctl_err(opts, 1, "%s", __func__);
378 return (1);
379 } else if ((opts & PF_OPT_QUIET0x00010) == 0)
380 fprintf(stderr(&__sF[2]), "rules cleared\n");
381
382 return (0);
383}
384
385void
386pfctl_clear_src_nodes(int dev, int opts)
387{
388 if (ioctl(dev, DIOCCLRSRCNODES((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('D')) << 8) | ((85)))
) == -1)
389 pfctl_err(opts, 1, "DIOCCLRSRCNODES");
390 if ((opts & PF_OPT_QUIET0x00010) == 0)
391 fprintf(stderr(&__sF[2]), "source tracking entries cleared\n");
392}
393
394void
395pfctl_clear_states(int dev, const char *iface, int opts)
396{
397 struct pfioc_state_kill psk;
398
399 memset(&psk, 0, sizeof(psk));
400 if (iface != NULL((void *)0) && strlcpy(psk.psk_ifname, iface,
401 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
402 pfctl_errx(opts, 1, "invalid interface: %s", iface);
403
404 if (ioctl(dev, DIOCCLRSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state_kill) & 0x1fff) << 16) | ((('D'
)) << 8) | ((18)))
, &psk) == -1)
405 pfctl_err(opts, 1, "DIOCCLRSTATES");
406 if ((opts & PF_OPT_QUIET0x00010) == 0)
407 fprintf(stderr(&__sF[2]), "%d states cleared\n", psk.psk_killed);
408}
409
410struct addrinfo *
411pfctl_addrprefix(char *addr, struct pf_addr *mask, int numeric)
412{
413 char *p;
414 const char *errstr;
415 int prefix, ret_ga, q, r;
416 struct addrinfo hints, *res;
417
418 bzero(&hints, sizeof(hints));
419 hints.ai_socktype = SOCK_DGRAM2; /* dummy */
420 if (numeric)
421 hints.ai_flags = AI_NUMERICHOST4;
422
423 if ((p = strchr(addr, '/')) != NULL((void *)0)) {
424 *p++ = '\0';
425 /* prefix only with numeric addresses */
426 hints.ai_flags |= AI_NUMERICHOST4;
427 }
428
429 if ((ret_ga = getaddrinfo(addr, NULL((void *)0), &hints, &res))) {
430 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
431 /* NOTREACHED */
432 }
433
434 if (p == NULL((void *)0))
435 return res;
436
437 prefix = strtonum(p, 0, res->ai_family == AF_INET624 ? 128 : 32, &errstr);
438 if (errstr)
439 errx(1, "prefix is %s: %s", errstr, p);
440
441 q = prefix >> 3;
442 r = prefix & 7;
443 switch (res->ai_family) {
444 case AF_INET2:
445 bzero(&mask->v4pfa.v4, sizeof(mask->v4pfa.v4));
446 mask->v4pfa.v4.s_addr = htonl((u_int32_t)(__uint32_t)(__builtin_constant_p((u_int32_t) (0xffffffffffULL
<< (32 - prefix))) ? (__uint32_t)(((__uint32_t)((u_int32_t
) (0xffffffffffULL << (32 - prefix))) & 0xff) <<
24 | ((__uint32_t)((u_int32_t) (0xffffffffffULL << (32
- prefix))) & 0xff00) << 8 | ((__uint32_t)((u_int32_t
) (0xffffffffffULL << (32 - prefix))) & 0xff0000) >>
8 | ((__uint32_t)((u_int32_t) (0xffffffffffULL << (32 -
prefix))) & 0xff000000) >> 24) : __swap32md((u_int32_t
) (0xffffffffffULL << (32 - prefix))))
447 (0xffffffffffULL << (32 - prefix)))(__uint32_t)(__builtin_constant_p((u_int32_t) (0xffffffffffULL
<< (32 - prefix))) ? (__uint32_t)(((__uint32_t)((u_int32_t
) (0xffffffffffULL << (32 - prefix))) & 0xff) <<
24 | ((__uint32_t)((u_int32_t) (0xffffffffffULL << (32
- prefix))) & 0xff00) << 8 | ((__uint32_t)((u_int32_t
) (0xffffffffffULL << (32 - prefix))) & 0xff0000) >>
8 | ((__uint32_t)((u_int32_t) (0xffffffffffULL << (32 -
prefix))) & 0xff000000) >> 24) : __swap32md((u_int32_t
) (0xffffffffffULL << (32 - prefix))))
;
448 break;
449 case AF_INET624:
450 bzero(&mask->v6pfa.v6, sizeof(mask->v6pfa.v6));
451 if (q > 0)
452 memset((void *)&mask->v6pfa.v6, 0xff, q);
453 if (r > 0)
454 *((u_char *)&mask->v6pfa.v6 + q) =
455 (0xff00 >> r) & 0xff;
456 break;
457 }
458
459 return res;
460}
461
462void
463pfctl_kill_src_nodes(int dev, int opts)
464{
465 struct pfioc_src_node_kill psnk;
466 struct addrinfo *res[2], *resp[2];
467 struct sockaddr last_src, last_dst;
468 int killed, sources, dests;
469
470 killed = sources = dests = 0;
471
472 memset(&psnk, 0, sizeof(psnk));
473 memset(&psnk.psnk_src.addr.v.a.mask, 0xff,
474 sizeof(psnk.psnk_src.addr.v.a.mask));
475 memset(&last_src, 0xff, sizeof(last_src));
476 memset(&last_dst, 0xff, sizeof(last_dst));
477
478 res[0] = pfctl_addrprefix(src_node_kill[0],
479 &psnk.psnk_src.addr.v.a.mask, (opts & PF_OPT_NODNS0x01000));
480
481 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
482 if (resp[0]->ai_addr == NULL((void *)0))
483 continue;
484 /* We get lots of duplicates. Catch the easy ones */
485 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
486 continue;
487 last_src = *(struct sockaddr *)resp[0]->ai_addr;
488
489 psnk.psnk_af = resp[0]->ai_family;
490 sources++;
491
492 copy_satopfaddr(&psnk.psnk_src.addr.v.a.addr, resp[0]->ai_addr);
493
494 if (src_node_killers > 1) {
495 dests = 0;
496 memset(&psnk.psnk_dst.addr.v.a.mask, 0xff,
497 sizeof(psnk.psnk_dst.addr.v.a.mask));
498 memset(&last_dst, 0xff, sizeof(last_dst));
499 res[1] = pfctl_addrprefix(src_node_kill[1],
500 &psnk.psnk_dst.addr.v.a.mask,
501 (opts & PF_OPT_NODNS0x01000));
502 for (resp[1] = res[1]; resp[1];
503 resp[1] = resp[1]->ai_next) {
504 if (resp[1]->ai_addr == NULL((void *)0))
505 continue;
506 if (psnk.psnk_af != resp[1]->ai_family)
507 continue;
508
509 if (memcmp(&last_dst, resp[1]->ai_addr,
510 sizeof(last_dst)) == 0)
511 continue;
512 last_dst = *(struct sockaddr *)resp[1]->ai_addr;
513
514 dests++;
515
516 copy_satopfaddr(&psnk.psnk_src.addr.v.a.addr,
517 resp[1]->ai_addr);
518
519 if (ioctl(dev, DIOCKILLSRCNODES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_src_node_kill) & 0x1fff) << 16) | (((
'D')) << 8) | ((91)))
, &psnk) == -1)
520 err(1, "DIOCKILLSRCNODES");
521 killed += psnk.psnk_killed;
522 }
523 freeaddrinfo(res[1]);
524 } else {
525 if (ioctl(dev, DIOCKILLSRCNODES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_src_node_kill) & 0x1fff) << 16) | (((
'D')) << 8) | ((91)))
, &psnk) == -1)
526 err(1, "DIOCKILLSRCNODES");
527 killed += psnk.psnk_killed;
528 }
529 }
530
531 freeaddrinfo(res[0]);
532
533 if ((opts & PF_OPT_QUIET0x00010) == 0)
534 fprintf(stderr(&__sF[2]), "killed %d src nodes from %d sources and %d "
535 "destinations\n", killed, sources, dests);
536}
537
538void
539pfctl_net_kill_states(int dev, const char *iface, int opts, int rdomain)
540{
541 struct pfioc_state_kill psk;
542 struct addrinfo *res[2], *resp[2];
543 struct sockaddr last_src, last_dst;
544 int killed, sources, dests;
545
546 killed = sources = dests = 0;
547
548 memset(&psk, 0, sizeof(psk));
549 memset(&psk.psk_src.addr.v.a.mask, 0xff,
550 sizeof(psk.psk_src.addr.v.a.mask));
551 memset(&last_src, 0xff, sizeof(last_src));
552 memset(&last_dst, 0xff, sizeof(last_dst));
553 if (iface != NULL((void *)0) && strlcpy(psk.psk_ifname, iface,
554 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
555 errx(1, "invalid interface: %s", iface);
556
557 psk.psk_rdomain = rdomain;
558
559 res[0] = pfctl_addrprefix(state_kill[0],
560 &psk.psk_src.addr.v.a.mask, (opts & PF_OPT_NODNS0x01000));
561
562 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
563 if (resp[0]->ai_addr == NULL((void *)0))
564 continue;
565 /* We get lots of duplicates. Catch the easy ones */
566 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
567 continue;
568 last_src = *(struct sockaddr *)resp[0]->ai_addr;
569
570 psk.psk_af = resp[0]->ai_family;
571 sources++;
572
573 copy_satopfaddr(&psk.psk_src.addr.v.a.addr, resp[0]->ai_addr);
574
575 if (state_killers > 1) {
576 dests = 0;
577 memset(&psk.psk_dst.addr.v.a.mask, 0xff,
578 sizeof(psk.psk_dst.addr.v.a.mask));
579 memset(&last_dst, 0xff, sizeof(last_dst));
580 res[1] = pfctl_addrprefix(state_kill[1],
581 &psk.psk_dst.addr.v.a.mask,
582 (opts & PF_OPT_NODNS0x01000));
583 for (resp[1] = res[1]; resp[1];
584 resp[1] = resp[1]->ai_next) {
585 if (resp[1]->ai_addr == NULL((void *)0))
586 continue;
587 if (psk.psk_af != resp[1]->ai_family)
588 continue;
589
590 if (memcmp(&last_dst, resp[1]->ai_addr,
591 sizeof(last_dst)) == 0)
592 continue;
593 last_dst = *(struct sockaddr *)resp[1]->ai_addr;
594
595 dests++;
596
597 copy_satopfaddr(&psk.psk_src.addr.v.a.addr,
598 resp[1]->ai_addr);
599
600 if (ioctl(dev, DIOCKILLSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state_kill) & 0x1fff) << 16) | ((('D'
)) << 8) | ((41)))
, &psk) == -1)
601 err(1, "DIOCKILLSTATES");
602 killed += psk.psk_killed;
603 }
604 freeaddrinfo(res[1]);
605 } else {
606 if (ioctl(dev, DIOCKILLSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state_kill) & 0x1fff) << 16) | ((('D'
)) << 8) | ((41)))
, &psk) == -1)
607 err(1, "DIOCKILLSTATES");
608 killed += psk.psk_killed;
609 }
610 }
611
612 freeaddrinfo(res[0]);
613
614 if ((opts & PF_OPT_QUIET0x00010) == 0)
615 fprintf(stderr(&__sF[2]), "killed %d states from %d sources and %d "
616 "destinations\n", killed, sources, dests);
617}
618
619void
620pfctl_label_kill_states(int dev, const char *iface, int opts, int rdomain)
621{
622 struct pfioc_state_kill psk;
623
624 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
625 warnx("no label specified");
626 usage();
627 }
628 memset(&psk, 0, sizeof(psk));
629 if (iface != NULL((void *)0) && strlcpy(psk.psk_ifname, iface,
630 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
631 errx(1, "invalid interface: %s", iface);
632
633 if (strlcpy(psk.psk_label, state_kill[1], sizeof(psk.psk_label)) >=
634 sizeof(psk.psk_label))
635 errx(1, "label too long: %s", state_kill[1]);
636
637 psk.psk_rdomain = rdomain;
638
639 if (ioctl(dev, DIOCKILLSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state_kill) & 0x1fff) << 16) | ((('D'
)) << 8) | ((41)))
, &psk) == -1)
640 err(1, "DIOCKILLSTATES");
641
642 if ((opts & PF_OPT_QUIET0x00010) == 0)
643 fprintf(stderr(&__sF[2]), "killed %d states\n", psk.psk_killed);
644}
645
646void
647pfctl_id_kill_states(int dev, int opts)
648{
649 struct pfioc_state_kill psk;
650
651 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
652 warnx("no id specified");
653 usage();
654 }
655
656 memset(&psk, 0, sizeof(psk));
657 if ((sscanf(state_kill[1], "%llx/%x",
658 &psk.psk_pfcmp.id, &psk.psk_pfcmp.creatorid)) == 2)
659 HTONL(psk.psk_pfcmp.creatorid)(psk.psk_pfcmp.creatorid) = (__uint32_t)(__builtin_constant_p
((u_int32_t)(psk.psk_pfcmp.creatorid)) ? (__uint32_t)(((__uint32_t
)((u_int32_t)(psk.psk_pfcmp.creatorid)) & 0xff) << 24
| ((__uint32_t)((u_int32_t)(psk.psk_pfcmp.creatorid)) & 0xff00
) << 8 | ((__uint32_t)((u_int32_t)(psk.psk_pfcmp.creatorid
)) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(psk
.psk_pfcmp.creatorid)) & 0xff000000) >> 24) : __swap32md
((u_int32_t)(psk.psk_pfcmp.creatorid)))
;
660 else if ((sscanf(state_kill[1], "%llx", &psk.psk_pfcmp.id)) == 1) {
661 psk.psk_pfcmp.creatorid = 0;
662 } else {
663 warnx("wrong id format specified");
664 usage();
665 }
666 if (psk.psk_pfcmp.id == 0) {
667 warnx("cannot kill id 0");
668 usage();
669 }
670
671 psk.psk_pfcmp.id = htobe64(psk.psk_pfcmp.id)(__uint64_t)(__builtin_constant_p(psk.psk_pfcmp.id) ? (__uint64_t
)((((__uint64_t)(psk.psk_pfcmp.id) & 0xff) << 56) |
((__uint64_t)(psk.psk_pfcmp.id) & 0xff00ULL) << 40
| ((__uint64_t)(psk.psk_pfcmp.id) & 0xff0000ULL) <<
24 | ((__uint64_t)(psk.psk_pfcmp.id) & 0xff000000ULL) <<
8 | ((__uint64_t)(psk.psk_pfcmp.id) & 0xff00000000ULL) >>
8 | ((__uint64_t)(psk.psk_pfcmp.id) & 0xff0000000000ULL)
>> 24 | ((__uint64_t)(psk.psk_pfcmp.id) & 0xff000000000000ULL
) >> 40 | ((__uint64_t)(psk.psk_pfcmp.id) & 0xff00000000000000ULL
) >> 56) : __swap64md(psk.psk_pfcmp.id))
;
672 if (ioctl(dev, DIOCKILLSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state_kill) & 0x1fff) << 16) | ((('D'
)) << 8) | ((41)))
, &psk) == -1)
673 err(1, "DIOCKILLSTATES");
674
675 if ((opts & PF_OPT_QUIET0x00010) == 0)
676 fprintf(stderr(&__sF[2]), "killed %d states\n", psk.psk_killed);
677}
678
679void
680pfctl_key_kill_states(int dev, const char *iface, int opts, int rdomain)
681{
682 struct pfioc_state_kill psk;
683 char *s, *token, *tokens[4];
684 struct protoent *p;
685 u_int i, sidx, didx;
686
687 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
29
Assuming 'state_killers' is equal to 2
30
Assuming the condition is false
31
Taking false branch
688 warnx("no key specified");
689 usage();
690 }
691 memset(&psk, 0, sizeof(psk));
692
693 if (iface != NULL((void *)0) && strlcpy(psk.psk_ifname, iface,
32
Assuming 'iface' is equal to NULL
694 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
695 errx(1, "invalid interface: %s", iface);
696
697 psk.psk_rdomain = rdomain;
698
699 s = strdup(state_kill[1]);
33
Memory is allocated
700 if (!s)
34
Assuming 's' is non-null
35
Taking false branch
701 errx(1, "pfctl_key_kill_states: strdup");
702 i = 0;
703 while ((token = strsep(&s, " \t")) != NULL((void *)0))
36
Loop condition is true. Entering loop body
39
Assuming the condition is true
40
Loop condition is true. Entering loop body
704 if (*token != '\0') {
37
Assuming the condition is false
38
Taking false branch
41
Potential leak of memory pointed to by 'token'
705 if (i < 4)
706 tokens[i] = token;
707 i++;
708 }
709 if (i != 4)
710 errx(1, "pfctl_key_kill_states: key must be "
711 "\"protocol host1:port1 direction host2:port2\" format");
712
713 if ((p = getprotobyname(tokens[0])) == NULL((void *)0))
714 errx(1, "invalid protocol: %s", tokens[0]);
715 psk.psk_proto = p->p_proto;
716
717 if (strcmp(tokens[2], "->") == 0) {
718 sidx = 1;
719 didx = 3;
720 } else if (strcmp(tokens[2], "<-") == 0) {
721 sidx = 3;
722 didx = 1;
723 } else
724 errx(1, "invalid direction: %s", tokens[2]);
725
726 if (pfctl_parse_host(tokens[sidx], &psk.psk_src) == -1)
727 errx(1, "invalid host: %s", tokens[sidx]);
728 if (pfctl_parse_host(tokens[didx], &psk.psk_dst) == -1)
729 errx(1, "invalid host: %s", tokens[didx]);
730
731 if (ioctl(dev, DIOCKILLSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state_kill) & 0x1fff) << 16) | ((('D'
)) << 8) | ((41)))
, &psk) == -1)
732 err(1, "DIOCKILLSTATES");
733
734 if ((opts & PF_OPT_QUIET0x00010) == 0)
735 fprintf(stderr(&__sF[2]), "killed %d states\n", psk.psk_killed);
736}
737
738int
739pfctl_parse_host(char *str, struct pf_rule_addr *addr)
740{
741 char *s = NULL((void *)0), *sbs, *sbe;
742 struct addrinfo hints, *ai;
743
744 s = strdup(str);
745 if (!s)
746 errx(1, "pfctl_parse_host: strdup");
747
748 memset(&hints, 0, sizeof(hints));
749 hints.ai_socktype = SOCK_DGRAM2; /* dummy */
750 hints.ai_flags = AI_NUMERICHOST4;
751
752 if ((sbs = strchr(s, '[')) != NULL((void *)0) && (sbe = strrchr(s, ']')) != NULL((void *)0)) {
753 hints.ai_family = AF_INET624;
754 *(sbs++) = *sbe = '\0';
755 } else if ((sbs = strchr(s, ':')) != NULL((void *)0)) {
756 hints.ai_family = AF_INET2;
757 *(sbs++) = '\0';
758 } else
759 goto error;
760
761 if (getaddrinfo(s, sbs, &hints, &ai) != 0)
762 goto error;
763
764 copy_satopfaddr(&addr->addr.v.a.addr, ai->ai_addr);
765 addr->port[0] = ai->ai_family == AF_INET624 ?
766 ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port :
767 ((struct sockaddr_in *)ai->ai_addr)->sin_port;
768
769 freeaddrinfo(ai);
770 free(s);
771
772 memset(&addr->addr.v.a.mask, 0xff, sizeof(struct pf_addr));
773 addr->port_op = PF_OP_EQ;
774 addr->addr.type = PF_ADDR_ADDRMASK;
775
776 return (0);
777
778 error:
779 free(s);
780 return (-1);
781}
782
783void
784pfctl_print_rule_counters(struct pf_rule *rule, int opts)
785{
786 if ((rule->rule_flag & PFRULE_EXPIRED0x00400000) &&
787 !(opts & (PF_OPT_VERBOSE20x00080 | PF_OPT_DEBUG0x00200)))
788 return;
789
790 if (opts & PF_OPT_DEBUG0x00200) {
791 const char *t[PF_SKIP_COUNT9] = { "i", "d", "r", "f",
792 "p", "sa", "da", "sp", "dp" };
793 int i;
794
795 printf(" [ Skip steps: ");
796 for (i = 0; i < PF_SKIP_COUNT9; ++i) {
797 if (rule->skip[i].nr == rule->nr + 1)
798 continue;
799 printf("%s=", t[i]);
800 if (rule->skip[i].nr == -1)
801 printf("end ");
802 else
803 printf("%u ", rule->skip[i].nr);
804 }
805 printf("]\n");
806
807 printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
808 rule->qname, rule->qid, rule->pqname, rule->pqid);
809 }
810 if (opts & PF_OPT_VERBOSE0x00004) {
811 printf(" [ Evaluations: %-8llu Packets: %-8llu "
812 "Bytes: %-10llu States: %-6u]\n",
813 (unsigned long long)rule->evaluations,
814 (unsigned long long)(rule->packets[0] +
815 rule->packets[1]),
816 (unsigned long long)(rule->bytes[0] +
817 rule->bytes[1]), rule->states_cur);
818 if (!(opts & PF_OPT_DEBUG0x00200))
819 printf(" [ Inserted: uid %lu pid %lu "
820 "State Creations: %-6u]\n",
821 (unsigned long)rule->cuid, (unsigned long)rule->cpid,
822 rule->states_tot);
823 }
824}
825
826void
827pfctl_print_title(char *title)
828{
829 if (!first_title)
830 printf("\n");
831 first_title = 0;
832 printf("%s\n", title);
833}
834
835int
836pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
837 char *anchorname, int depth, int wildcard, long shownr)
838{
839 struct pfioc_rule pr;
840 u_int32_t header = 0;
841 int len = strlen(path), ret = 0;
842 char *npath, *p;
843
844 if (depth > PF_ANCHOR_STACK_MAX64) {
845 warnx("%s: max stack depth exceeded for %s", __func__, path);
846 return (-1);
847 }
848
849 /*
850 * Truncate a trailing / and * on an anchorname before searching for
851 * the ruleset, this is syntactic sugar that doesn't actually make it
852 * to the kernel.
853 */
854 if ((p = strrchr(anchorname, '/')) != NULL((void *)0) &&
855 p[1] == '*' && p[2] == '\0') {
856 p[0] = '\0';
857 }
858
859 memset(&pr, 0, sizeof(pr));
860 if (anchorname[0] == '/') {
861 if ((npath = calloc(1, PATH_MAX1024)) == NULL((void *)0))
862 err(1, "calloc");
863 strlcpy(npath, anchorname, PATH_MAX1024);
864 } else {
865 if (path[0])
866 snprintf(&path[len], PATH_MAX1024 - len, "/%s", anchorname);
867 else
868 snprintf(&path[len], PATH_MAX1024 - len, "%s", anchorname);
869 npath = path;
870 }
871
872 memcpy(pr.anchor, npath, sizeof(pr.anchor));
873 if (opts & PF_OPT_SHOWALL0x00400) {
874 pr.rule.action = PF_PASS;
875 if (ioctl(dev, DIOCGETRULES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_rule) & 0x1fff) << 16) | ((('D')) <<
8) | ((6)))
, &pr) == -1) {
876 warnx("%s", pf_strerror(errno(*__errno())));
877 ret = -1;
878 goto error;
879 }
880 header++;
881 if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header))
882 pfctl_print_title("FILTER RULES:");
883 else if (format == PFCTL_SHOW_LABELS && labels)
884 pfctl_print_title("LABEL COUNTERS:");
885 }
886 if (opts & PF_OPT_CLRRULECTRS0x00020)
887 pr.action = PF_GET_CLR_CNTR;
888
889 pr.rule.action = PF_PASS;
890 if (ioctl(dev, DIOCGETRULES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_rule) & 0x1fff) << 16) | ((('D')) <<
8) | ((6)))
, &pr) == -1) {
891 warnx("%s", pf_strerror(errno(*__errno())));
892 ret = -1;
893 goto error;
894 }
895
896 while (ioctl(dev, DIOCGETRULE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_rule) & 0x1fff) << 16) | ((('D')) <<
8) | ((7)))
, &pr) != -1) {
897 if (shownr != -1 && shownr != pr.nr)
898 continue;
899
900 /* anchor is the same for all rules in it */
901 if (pr.rule.anchor_wildcard == 0)
902 wildcard = 0;
903
904 switch (format) {
905 case PFCTL_SHOW_LABELS:
906 if (pr.rule.label[0]) {
907 INDENT(depth, !(opts & PF_OPT_VERBOSE))do { if (!(opts & 0x00004)) { int i; for (i=0; i < depth
; i++) printf(" "); } } while (0)
;
908 printf("%s %llu %llu %llu %llu"
909 " %llu %llu %llu %llu\n",
910 pr.rule.label,
911 (unsigned long long)pr.rule.evaluations,
912 (unsigned long long)(pr.rule.packets[0] +
913 pr.rule.packets[1]),
914 (unsigned long long)(pr.rule.bytes[0] +
915 pr.rule.bytes[1]),
916 (unsigned long long)pr.rule.packets[0],
917 (unsigned long long)pr.rule.bytes[0],
918 (unsigned long long)pr.rule.packets[1],
919 (unsigned long long)pr.rule.bytes[1],
920 (unsigned long long)pr.rule.states_tot);
921 }
922 break;
923 case PFCTL_SHOW_RULES:
924 if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL0x00400))
925 labels = 1;
926 INDENT(depth, !(opts & PF_OPT_VERBOSE))do { if (!(opts & 0x00004)) { int i; for (i=0; i < depth
; i++) printf(" "); } } while (0)
;
927 print_rule(&pr.rule, pr.anchor_call, opts);
928
929 /*
930 * If this is an 'unnamed' brace notation anchor OR
931 * the user has explicitly requested recursion,
932 * print it recursively.
933 */
934 if (pr.anchor_call[0] &&
935 (((p = strrchr(pr.anchor_call, '/')) ?
936 p[1] == '_' : pr.anchor_call[0] == '_') ||
937 opts & PF_OPT_RECURSE0x04000)) {
938 printf(" {\n");
939 pfctl_print_rule_counters(&pr.rule, opts);
940 pfctl_show_rules(dev, npath, opts, format,
941 pr.anchor_call, depth + 1,
942 pr.rule.anchor_wildcard, -1);
943 INDENT(depth, !(opts & PF_OPT_VERBOSE))do { if (!(opts & 0x00004)) { int i; for (i=0; i < depth
; i++) printf(" "); } } while (0)
;
944 printf("}\n");
945 } else {
946 if ((pr.rule.rule_flag & PFRULE_EXPIRED0x00400000) &&
947 !(opts & (PF_OPT_VERBOSE20x00080 | PF_OPT_DEBUG0x00200)))
948 break;
949 printf("\n");
950 pfctl_print_rule_counters(&pr.rule, opts);
951 }
952 break;
953 case PFCTL_SHOW_NOTHING:
954 break;
955 }
956 errno(*__errno()) = 0;
957 }
958
959 if (errno(*__errno()) != 0 && errno(*__errno()) != ENOENT2) {
960 warn("DIOCGETRULE");
961 ret = -1;
962 goto error;
963 }
964
965 /*
966 * If this anchor was called with a wildcard path, go through
967 * the rulesets in the anchor rather than the rules.
968 */
969 if (wildcard && (opts & PF_OPT_RECURSE0x04000)) {
970 struct pfioc_ruleset prs;
971 u_int32_t mnr, nr;
972
973 memset(&prs, 0, sizeof(prs));
974 memcpy(prs.path, npath, sizeof(prs.path));
975 if (ioctl(dev, DIOCGETRULESETS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_ruleset) & 0x1fff) << 16) | ((('D')) <<
8) | ((58)))
, &prs) == -1)
976 errx(1, "%s", pf_strerror(errno(*__errno())));
977 mnr = prs.nr;
978
979 for (nr = 0; nr < mnr; ++nr) {
980 prs.nr = nr;
981 if (ioctl(dev, DIOCGETRULESET(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_ruleset) & 0x1fff) << 16) | ((('D')) <<
8) | ((59)))
, &prs) == -1)
982 errx(1, "%s", pf_strerror(errno(*__errno())));
983 INDENT(depth, !(opts & PF_OPT_VERBOSE))do { if (!(opts & 0x00004)) { int i; for (i=0; i < depth
; i++) printf(" "); } } while (0)
;
984 printf("anchor \"%s\" all {\n", prs.name);
985 pfctl_show_rules(dev, npath, opts,
986 format, prs.name, depth + 1, 0, shownr);
987 INDENT(depth, !(opts & PF_OPT_VERBOSE))do { if (!(opts & 0x00004)) { int i; for (i=0; i < depth
; i++) printf(" "); } } while (0)
;
988 printf("}\n");
989 }
990 path[len] = '\0';
991 return (0);
992 }
993
994 error:
995 if (path != npath)
996 free(npath);
997 path[len] = '\0';
998 return (ret);
999}
1000
1001int
1002pfctl_show_src_nodes(int dev, int opts)
1003{
1004 struct pfioc_src_nodes psn;
1005 struct pf_src_node *p;
1006 char *inbuf = NULL((void *)0), *newinbuf = NULL((void *)0);
1007 size_t i, len = 0;
1008
1009 memset(&psn, 0, sizeof(psn));
1010 for (;;) {
1011 psn.psn_len = len;
1012 if (len) {
1013 newinbuf = realloc(inbuf, len);
1014 if (newinbuf == NULL((void *)0))
1015 err(1, "realloc");
1016 psn.psn_bufpsn_u.psu_buf = inbuf = newinbuf;
1017 }
1018 if (ioctl(dev, DIOCGETSRCNODES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_src_nodes) & 0x1fff) << 16) | ((('D')
) << 8) | ((84)))
, &psn) == -1) {
1019 warn("DIOCGETSRCNODES");
1020 free(inbuf);
1021 return (-1);
1022 }
1023 if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len)
1024 break;
1025 if (len == 0 && psn.psn_len == 0)
1026 goto done;
1027 if (len == 0 && psn.psn_len != 0)
1028 len = psn.psn_len;
1029 if (psn.psn_len == 0)
1030 goto done; /* no src_nodes */
1031 len *= 2;
1032 }
1033 p = psn.psn_src_nodespsn_u.psu_src_nodes;
1034 if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL0x00400))
1035 pfctl_print_title("SOURCE TRACKING NODES:");
1036 for (i = 0; i < psn.psn_len; i += sizeof(*p)) {
1037 print_src_node(p, opts);
1038 p++;
1039 }
1040done:
1041 free(inbuf);
1042 return (0);
1043}
1044
1045int
1046pfctl_show_states(int dev, const char *iface, int opts, long shownr)
1047{
1048 struct pfioc_states ps;
1049 struct pfsync_state *p;
1050 char *inbuf = NULL((void *)0), *newinbuf = NULL((void *)0);
1051 size_t i, len = 0;
1052 int dotitle = (opts & PF_OPT_SHOWALL0x00400);
1053
1054 memset(&ps, 0, sizeof(ps));
1055 for (;;) {
1056 ps.ps_len = len;
1057 if (len) {
1058 newinbuf = realloc(inbuf, len);
1059 if (newinbuf == NULL((void *)0))
1060 err(1, "realloc");
1061 ps.ps_bufps_u.psu_buf = inbuf = newinbuf;
1062 }
1063 if (ioctl(dev, DIOCGETSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_states) & 0x1fff) << 16) | ((('D')) <<
8) | ((25)))
, &ps) == -1) {
1064 warn("DIOCGETSTATES");
1065 free(inbuf);
1066 return (-1);
1067 }
1068 if (ps.ps_len + sizeof(struct pfioc_states) < len)
1069 break;
1070 if (len == 0 && ps.ps_len == 0)
1071 goto done;
1072 if (len == 0 && ps.ps_len != 0)
1073 len = ps.ps_len;
1074 if (ps.ps_len == 0)
1075 goto done; /* no states */
1076 len *= 2;
1077 }
1078 p = ps.ps_statesps_u.psu_states;
1079 for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) {
1080 if (iface != NULL((void *)0) && strcmp(p->ifname, iface))
1081 continue;
1082 if (dotitle) {
1083 pfctl_print_title("STATES:");
1084 dotitle = 0;
1085 }
1086 if (shownr < 0 || ntohl(p->rule)(__uint32_t)(__builtin_constant_p(p->rule) ? (__uint32_t)(
((__uint32_t)(p->rule) & 0xff) << 24 | ((__uint32_t
)(p->rule) & 0xff00) << 8 | ((__uint32_t)(p->
rule) & 0xff0000) >> 8 | ((__uint32_t)(p->rule) &
0xff000000) >> 24) : __swap32md(p->rule))
== shownr)
1087 print_state(p, opts);
1088 }
1089done:
1090 free(inbuf);
1091 return (0);
1092}
1093
1094int
1095pfctl_show_status(int dev, int opts)
1096{
1097 struct pf_status status;
1098 struct pfctl_watermarks wats;
1099 struct pfioc_synflwats iocwats;
1100
1101 if (ioctl(dev, DIOCGETSTATUS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pf_status) & 0x1fff) << 16) | ((('D')) <<
8) | ((21)))
, &status) == -1) {
1102 warn("DIOCGETSTATUS");
1103 return (-1);
1104 }
1105 if (ioctl(dev, DIOCGETSYNFLWATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_synflwats) & 0x1fff) << 16) | ((('D')
) << 8) | ((99)))
, &iocwats) == -1) {
1106 warn("DIOCGETSYNFLWATS");
1107 return (-1);
1108 }
1109 wats.hi = iocwats.hiwat;
1110 wats.lo = iocwats.lowat;
1111 if (opts & PF_OPT_SHOWALL0x00400)
1112 pfctl_print_title("INFO:");
1113 print_status(&status, &wats, opts);
1114 return (0);
1115}
1116
1117int
1118pfctl_show_timeouts(int dev, int opts)
1119{
1120 struct pfioc_tm pt;
1121 int i;
1122
1123 if (opts & PF_OPT_SHOWALL0x00400)
1124 pfctl_print_title("TIMEOUTS:");
1125 memset(&pt, 0, sizeof(pt));
1126 for (i = 0; pf_timeouts[i].name; i++) {
1127 pt.timeout = pf_timeouts[i].timeout;
1128 if (ioctl(dev, DIOCGETTIMEOUT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_tm) & 0x1fff) << 16) | ((('D')) <<
8) | ((30)))
, &pt) == -1)
1129 err(1, "DIOCGETTIMEOUT");
1130 printf("%-20s %10d", pf_timeouts[i].name, pt.seconds);
1131 if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START &&
1132 pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END)
1133 printf(" states");
1134 else
1135 printf("s");
1136 printf("\n");
1137 }
1138 return (0);
1139
1140}
1141
1142int
1143pfctl_show_limits(int dev, int opts)
1144{
1145 struct pfioc_limit pl;
1146 int i;
1147
1148 if (opts & PF_OPT_SHOWALL0x00400)
1149 pfctl_print_title("LIMITS:");
1150 memset(&pl, 0, sizeof(pl));
1151 for (i = 0; pf_limits[i].name; i++) {
1152 pl.index = pf_limits[i].index;
1153 if (ioctl(dev, DIOCGETLIMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_limit) & 0x1fff) << 16) | ((('D')) <<
8) | ((39)))
, &pl) == -1)
1154 err(1, "DIOCGETLIMIT");
1155 printf("%-13s ", pf_limits[i].name);
1156 if (pl.limit == UINT_MAX0xffffffffU)
1157 printf("unlimited\n");
1158 else
1159 printf("hard limit %8u\n", pl.limit);
1160 }
1161 return (0);
1162}
1163
1164/* callbacks for rule/nat/rdr/addr */
1165void
1166pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
1167{
1168 struct pf_rule *rule;
1169 struct pf_ruleset *rs;
1170
1171 rs = &pf->anchor->ruleset;
1172
1173 if ((rule = calloc(1, sizeof(*rule))) == NULL((void *)0))
1174 err(1, "calloc");
1175 bcopy(r, rule, sizeof(*rule));
1176
1177 TAILQ_INSERT_TAIL(rs->rules.active.ptr, rule, entries)do { (rule)->entries.tqe_next = ((void *)0); (rule)->entries
.tqe_prev = (rs->rules.active.ptr)->tqh_last; *(rs->
rules.active.ptr)->tqh_last = (rule); (rs->rules.active
.ptr)->tqh_last = &(rule)->entries.tqe_next; } while
(0)
;
1178}
1179
1180int
1181pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a)
1182{
1183 int osize = pf->trans->pfrb_size;
1184
1185 if (pfctl_add_trans(pf->trans, PF_TRANS_RULESET, path))
1186 return (3);
1187 if (pfctl_add_trans(pf->trans, PF_TRANS_TABLE, path))
1188 return (4);
1189 if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_trans) & 0x1fff) << 16) | ((('D')) <<
8) | ((81)))
, osize))
1190 return (5);
1191
1192 return (0);
1193}
1194
1195int
1196pfctl_add_queue(struct pfctl *pf, struct pf_queuespec *q)
1197{
1198 struct pfctl_qsitem *qi;
1199
1200 if (pf->anchor->name[0]) {
1201 printf("must not have queue definitions in an anchor\n");
1202 return (1);
1203 }
1204
1205 if (q->parent[0] == '\0') {
1206 TAILQ_FOREACH(qi, &rootqs, entries)for((qi) = ((&rootqs)->tqh_first); (qi) != ((void *)0)
; (qi) = ((qi)->entries.tqe_next))
{
1207 if (strcmp(q->ifname, qi->qs.ifname))
1208 continue;
1209 printf("A root queue is already defined on %s\n",
1210 qi->qs.ifname);
1211 return (1);
1212 }
1213 }
1214
1215 if ((qi = calloc(1, sizeof(*qi))) == NULL((void *)0))
1216 err(1, "calloc");
1217 bcopy(q, &qi->qs, sizeof(qi->qs));
1218 TAILQ_INIT(&qi->children)do { (&qi->children)->tqh_first = ((void *)0); (&
qi->children)->tqh_last = &(&qi->children)->
tqh_first; } while (0)
;
1219
1220 if (qi->qs.parent[0])
1221 TAILQ_INSERT_TAIL(&qspecs, qi, entries)do { (qi)->entries.tqe_next = ((void *)0); (qi)->entries
.tqe_prev = (&qspecs)->tqh_last; *(&qspecs)->tqh_last
= (qi); (&qspecs)->tqh_last = &(qi)->entries.tqe_next
; } while (0)
;
1222 else
1223 TAILQ_INSERT_TAIL(&rootqs, qi, entries)do { (qi)->entries.tqe_next = ((void *)0); (qi)->entries
.tqe_prev = (&rootqs)->tqh_last; *(&rootqs)->tqh_last
= (qi); (&rootqs)->tqh_last = &(qi)->entries.tqe_next
; } while (0)
;
1224
1225 return (0);
1226}
1227
1228struct pfctl_qsitem *
1229pfctl_find_queue(char *what, struct pf_qihead *where)
1230{
1231 struct pfctl_qsitem *q;
1232
1233 TAILQ_FOREACH(q, where, entries)for((q) = ((where)->tqh_first); (q) != ((void *)0); (q) = (
(q)->entries.tqe_next))
1234 if (strcmp(q->qs.qname, what) == 0)
1235 return (q);
1236
1237 return (NULL((void *)0));
1238}
1239
1240u_int
1241pfctl_find_childqs(struct pfctl_qsitem *qi)
1242{
1243 struct pfctl_qsitem *n, *p, *q;
1244 u_int flags = qi->qs.flags;
1245
1246 TAILQ_FOREACH(p, &qspecs, entries)for((p) = ((&qspecs)->tqh_first); (p) != ((void *)0); (
p) = ((p)->entries.tqe_next))
{
1247 if (strcmp(p->qs.parent, qi->qs.qname))
1248 continue;
1249 if (p->qs.ifname[0] && strcmp(p->qs.ifname, qi->qs.ifname))
1250 continue;
1251 if (++p->matches > 10000)
1252 errx(1, "pfctl_find_childqs: excessive matches, loop?");
1253
1254 if ((q = pfctl_find_queue(p->qs.qname, &qi->children)) == NULL((void *)0)) {
1255 /* insert */
1256 if ((n = calloc(1, sizeof(*n))) == NULL((void *)0))
1257 err(1, "calloc");
1258 TAILQ_INIT(&n->children)do { (&n->children)->tqh_first = ((void *)0); (&
n->children)->tqh_last = &(&n->children)->
tqh_first; } while (0)
;
1259 bcopy(&p->qs, &n->qs, sizeof(n->qs));
1260 TAILQ_INSERT_TAIL(&qi->children, n, entries)do { (n)->entries.tqe_next = ((void *)0); (n)->entries.
tqe_prev = (&qi->children)->tqh_last; *(&qi->
children)->tqh_last = (n); (&qi->children)->tqh_last
= &(n)->entries.tqe_next; } while (0)
;
1261 } else {
1262 if ((q->qs.ifname[0] && p->qs.ifname[0]))
1263 errx(1, "queue %s on %s respecified",
1264 q->qs.qname, q->qs.ifname);
1265 if (!q->qs.ifname[0] && !p->qs.ifname[0])
1266 errx(1, "queue %s respecified",
1267 q->qs.qname);
1268 /* ifbound beats floating */
1269 if (!q->qs.ifname[0])
1270 bcopy(&p->qs, &q->qs, sizeof(q->qs));
1271 }
1272 }
1273
1274 TAILQ_FOREACH(p, &qi->children, entries)for((p) = ((&qi->children)->tqh_first); (p) != ((void
*)0); (p) = ((p)->entries.tqe_next))
1275 flags |= pfctl_find_childqs(p);
1276
1277 if (!TAILQ_EMPTY(&qi->children)(((&qi->children)->tqh_first) == ((void *)0))) {
1278 if (qi->qs.flags & PFQS_DEFAULT0x1000)
1279 errx(1, "default queue %s is not a leaf queue",
1280 qi->qs.qname);
1281 if (qi->qs.flags & PFQS_FLOWQUEUE0x0001)
1282 errx(1, "flow queue %s is not a leaf queue",
1283 qi->qs.qname);
1284 }
1285
1286 return (flags);
1287}
1288
1289void
1290pfctl_load_queue(struct pfctl *pf, u_int32_t ticket, struct pfctl_qsitem *qi)
1291{
1292 struct pfioc_queue q;
1293 struct pfctl_qsitem *p;
1294
1295 q.ticket = ticket;
1296 bcopy(&qi->qs, &q.queue, sizeof(q.queue));
1297 if ((pf->opts & PF_OPT_NOACTION0x00008) == 0)
1298 if (ioctl(pf->dev, DIOCADDQUEUE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_queue) & 0x1fff) << 16) | ((('D')) <<
8) | ((93)))
, &q) == -1)
1299 err(1, "DIOCADDQUEUE");
1300 if (pf->opts & PF_OPT_VERBOSE0x00004)
1301 print_queuespec(&qi->qs);
1302
1303 TAILQ_FOREACH(p, &qi->children, entries)for((p) = ((&qi->children)->tqh_first); (p) != ((void
*)0); (p) = ((p)->entries.tqe_next))
{
1304 strlcpy(p->qs.ifname, qi->qs.ifname, IFNAMSIZ16);
1305 pfctl_load_queue(pf, ticket, p);
1306 }
1307}
1308
1309int
1310pfctl_load_queues(struct pfctl *pf)
1311{
1312 struct pfctl_qsitem *qi, *tempqi;
1313 struct pf_queue_scspec *rtsc, *lssc, *ulsc;
1314 u_int32_t ticket;
1315
1316 TAILQ_FOREACH(qi, &qspecs, entries)for((qi) = ((&qspecs)->tqh_first); (qi) != ((void *)0)
; (qi) = ((qi)->entries.tqe_next))
{
1317 if (qi->matches == 0)
1318 errx(1, "queue %s: parent %s not found", qi->qs.qname,
1319 qi->qs.parent);
1320
1321 rtsc = &qi->qs.realtime;
1322 lssc = &qi->qs.linkshare;
1323 ulsc = &qi->qs.upperlimit;
1324
1325 if (rtsc->m1.percent || rtsc->m2.percent ||
1326 lssc->m1.percent || lssc->m2.percent ||
1327 ulsc->m1.percent || ulsc->m2.percent)
1328 errx(1, "only absolute bandwidth specs for now");
1329
1330 /* Link sharing policy must be specified for child classes */
1331 if (qi->qs.parent[0] != '\0' &&
1332 lssc->m1.absolute == 0 && lssc->m2.absolute == 0)
1333 errx(1, "queue %s: no bandwidth was specified",
1334 qi->qs.qname);
1335 }
1336
1337 if ((pf->opts & PF_OPT_NOACTION0x00008) == 0)
1338 ticket = pfctl_get_ticket(pf->trans, PF_TRANS_RULESET, "");
1339
1340 TAILQ_FOREACH_SAFE(qi, &rootqs, entries, tempqi)for ((qi) = ((&rootqs)->tqh_first); (qi) != ((void *)0
) && ((tempqi) = ((qi)->entries.tqe_next), 1); (qi
) = (tempqi))
{
1341 TAILQ_REMOVE(&rootqs, qi, entries)do { if (((qi)->entries.tqe_next) != ((void *)0)) (qi)->
entries.tqe_next->entries.tqe_prev = (qi)->entries.tqe_prev
; else (&rootqs)->tqh_last = (qi)->entries.tqe_prev
; *(qi)->entries.tqe_prev = (qi)->entries.tqe_next; ; ;
} while (0)
;
1342 pfctl_load_queue(pf, ticket, qi);
1343 TAILQ_INSERT_HEAD(&rootqs, qi, entries)do { if (((qi)->entries.tqe_next = (&rootqs)->tqh_first
) != ((void *)0)) (&rootqs)->tqh_first->entries.tqe_prev
= &(qi)->entries.tqe_next; else (&rootqs)->tqh_last
= &(qi)->entries.tqe_next; (&rootqs)->tqh_first
= (qi); (qi)->entries.tqe_prev = &(&rootqs)->tqh_first
; } while (0)
;
1344 }
1345
1346 return (0);
1347}
1348
1349void
1350pfctl_clear_queues(struct pf_qihead *head)
1351{
1352 struct pfctl_qsitem *qi;
1353
1354 while ((qi = TAILQ_FIRST(head)((head)->tqh_first)) != NULL((void *)0)) {
1355 TAILQ_REMOVE(head, qi, entries)do { if (((qi)->entries.tqe_next) != ((void *)0)) (qi)->
entries.tqe_next->entries.tqe_prev = (qi)->entries.tqe_prev
; else (head)->tqh_last = (qi)->entries.tqe_prev; *(qi)
->entries.tqe_prev = (qi)->entries.tqe_next; ; ; } while
(0)
;
1356 pfctl_clear_queues(&qi->children);
1357 free(qi);
1358 }
1359}
1360
1361u_int
1362pfctl_leafqueue_check(char *qname)
1363{
1364 struct pfctl_qsitem *qi;
1365 if (qname == NULL((void *)0) || qname[0] == 0)
1366 return (0);
1367
1368 TAILQ_FOREACH(qi, &rootqs, entries)for((qi) = ((&rootqs)->tqh_first); (qi) != ((void *)0)
; (qi) = ((qi)->entries.tqe_next))
{
1369 if (strcmp(qname, qi->qs.qname))
1370 continue;
1371 if (!TAILQ_EMPTY(&qi->children)(((&qi->children)->tqh_first) == ((void *)0))) {
1372 printf("queue %s: packets must be assigned to leaf "
1373 "queues only\n", qname);
1374 return (1);
1375 }
1376 }
1377 TAILQ_FOREACH(qi, &qspecs, entries)for((qi) = ((&qspecs)->tqh_first); (qi) != ((void *)0)
; (qi) = ((qi)->entries.tqe_next))
{
1378 if (strcmp(qname, qi->qs.qname))
1379 continue;
1380 if (!TAILQ_EMPTY(&qi->children)(((&qi->children)->tqh_first) == ((void *)0))) {
1381 printf("queue %s: packets must be assigned to leaf "
1382 "queues only\n", qname);
1383 return (1);
1384 }
1385 }
1386 return (0);
1387}
1388
1389u_int
1390pfctl_check_qassignments(struct pf_ruleset *rs)
1391{
1392 struct pf_rule *r;
1393 struct pfctl_qsitem *qi;
1394 u_int flags, errs = 0;
1395
1396 /* main ruleset: need find_childqs to populate qi->children */
1397 if (rs->anchor->path[0] == 0) {
1398 TAILQ_FOREACH(qi, &rootqs, entries)for((qi) = ((&rootqs)->tqh_first); (qi) != ((void *)0)
; (qi) = ((qi)->entries.tqe_next))
{
1399 flags = pfctl_find_childqs(qi);
1400 if (!(qi->qs.flags & PFQS_ROOTCLASS0x0002) &&
1401 !TAILQ_EMPTY(&qi->children)(((&qi->children)->tqh_first) == ((void *)0))) {
1402 if (qi->qs.flags & PFQS_FLOWQUEUE0x0001)
1403 errx(1, "root queue %s doesn't "
1404 "support hierarchy",
1405 qi->qs.qname);
1406 else
1407 errx(1, "no bandwidth was specified "
1408 "for root queue %s", qi->qs.qname);
1409 }
1410 if ((qi->qs.flags & PFQS_ROOTCLASS0x0002) &&
1411 !(flags & PFQS_DEFAULT0x1000))
1412 errx(1, "no default queue specified");
1413 }
1414 }
1415
1416 TAILQ_FOREACH(r, rs->rules.active.ptr, entries)for((r) = ((rs->rules.active.ptr)->tqh_first); (r) != (
(void *)0); (r) = ((r)->entries.tqe_next))
{
1417 if (r->anchor)
1418 errs += pfctl_check_qassignments(&r->anchor->ruleset);
1419 if (pfctl_leafqueue_check(r->qname) ||
1420 pfctl_leafqueue_check(r->pqname))
1421 errs++;
1422 }
1423 return (errs);
1424}
1425
1426int
1427pfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs,
1428 int depth)
1429{
1430 struct pf_rule *r;
1431 int error, len = strlen(path);
1432 int brace = 0;
1433 unsigned int rno = 0;
1434
1435 pf->anchor = rs->anchor;
1436
1437 if (path[0])
1438 snprintf(&path[len], PATH_MAX1024 - len, "/%s", pf->anchor->name);
1439 else
1440 snprintf(&path[len], PATH_MAX1024 - len, "%s", pf->anchor->path);
1441
1442 if (depth) {
1443 if (TAILQ_FIRST(rs->rules.active.ptr)((rs->rules.active.ptr)->tqh_first) != NULL((void *)0)) {
1444 brace++;
1445 if (pf->opts & PF_OPT_VERBOSE0x00004)
1446 printf(" {\n");
1447 if ((pf->opts & PF_OPT_NOACTION0x00008) == 0 &&
1448 (error = pfctl_ruleset_trans(pf,
1449 path, rs->anchor))) {
1450 printf("pfctl_load_ruleset: "
1451 "pfctl_ruleset_trans %d\n", error);
1452 goto error;
1453 }
1454 } else if (pf->opts & PF_OPT_VERBOSE0x00004)
1455 printf("\n");
1456 }
1457
1458 if (pf->optimize)
1459 pfctl_optimize_ruleset(pf, rs);
1460
1461 while ((r = TAILQ_FIRST(rs->rules.active.ptr)((rs->rules.active.ptr)->tqh_first)) != NULL((void *)0)) {
1462 TAILQ_REMOVE(rs->rules.active.ptr, r, entries)do { if (((r)->entries.tqe_next) != ((void *)0)) (r)->entries
.tqe_next->entries.tqe_prev = (r)->entries.tqe_prev; else
(rs->rules.active.ptr)->tqh_last = (r)->entries.tqe_prev
; *(r)->entries.tqe_prev = (r)->entries.tqe_next; ; ; }
while (0)
;
1463 pfctl_expand_label_nr(r, rno);
1464 rno++;
1465 if ((error = pfctl_load_rule(pf, path, r, depth)))
1466 goto error;
1467 if (r->anchor) {
1468 if ((error = pfctl_load_ruleset(pf, path,
1469 &r->anchor->ruleset, depth + 1)))
1470 goto error;
1471 } else if (pf->opts & PF_OPT_VERBOSE0x00004)
1472 printf("\n");
1473 free(r);
1474 }
1475 if (brace && pf->opts & PF_OPT_VERBOSE0x00004) {
1476 INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE))do { if ((pf->opts & 0x00004)) { int i; for (i=0; i <
depth - 1; i++) printf(" "); } } while (0)
;
1477 printf("}\n");
1478 }
1479 path[len] = '\0';
1480 return (0);
1481
1482 error:
1483 path[len] = '\0';
1484 return (error);
1485
1486}
1487
1488int
1489pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth)
1490{
1491 char *name;
1492 struct pfioc_rule pr;
1493 int len = strlen(path);
1494
1495 bzero(&pr, sizeof(pr));
1496 /* set up anchor before adding to path for anchor_call */
1497 if ((pf->opts & PF_OPT_NOACTION0x00008) == 0)
1498 pr.ticket = pfctl_get_ticket(pf->trans, PF_TRANS_RULESET, path);
1499 if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >= sizeof(pr.anchor))
1500 errx(1, "pfctl_load_rule: strlcpy");
1501
1502 if (r->anchor) {
1503 if (r->anchor->match) {
1504 if (path[0])
1505 snprintf(&path[len], PATH_MAX1024 - len,
1506 "/%s", r->anchor->name);
1507 else
1508 snprintf(&path[len], PATH_MAX1024 - len,
1509 "%s", r->anchor->name);
1510 name = r->anchor->name;
1511 } else
1512 name = r->anchor->path;
1513 } else
1514 name = "";
1515
1516 if ((pf->opts & PF_OPT_NOACTION0x00008) == 0) {
1517 memcpy(&pr.rule, r, sizeof(pr.rule));
1518 if (r->anchor && strlcpy(pr.anchor_call, name,
1519 sizeof(pr.anchor_call)) >= sizeof(pr.anchor_call))
1520 errx(1, "pfctl_load_rule: strlcpy");
1521 if (ioctl(pf->dev, DIOCADDRULE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_rule) & 0x1fff) << 16) | ((('D')) <<
8) | ((4)))
, &pr) == -1)
1522 err(1, "DIOCADDRULE");
1523 }
1524
1525 if (pf->opts & PF_OPT_VERBOSE0x00004) {
1526 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2))do { if (!(pf->opts & 0x00080)) { int i; for (i=0; i <
depth; i++) printf(" "); } } while (0)
;
1527 print_rule(r, name, pf->opts);
1528 }
1529 path[len] = '\0';
1530 return (0);
1531}
1532
1533int
1534pfctl_rules(int dev, char *filename, int opts, int optimize,
1535 char *anchorname, struct pfr_buffer *trans)
1536{
1537#define ERR(x) do { warn(x); goto _error; } while(0)
1538#define ERRX(x) do { warnx(x); goto _error; } while(0)
1539
1540 struct pfr_buffer *t, buf;
1541 struct pfctl pf;
1542 struct pf_ruleset *rs;
1543 struct pfr_table trs;
1544 char *path = NULL((void *)0);
1545 int osize;
1546 char *p;
1547
1548 RB_INIT(&pf_anchors)do { (&pf_anchors)->rbh_root = ((void *)0); } while (0
)
;
1549 memset(&pf_main_anchor, 0, sizeof(pf_main_anchor));
1550 pf_init_ruleset(&pf_main_anchor.ruleset);
1551 if (trans == NULL((void *)0)) {
1552 bzero(&buf, sizeof(buf));
1553 buf.pfrb_type = PFRB_TRANS;
1554 t = &buf;
1555 osize = 0;
1556 } else {
1557 t = trans;
1558 osize = t->pfrb_size;
1559 }
1560
1561 memset(&pf, 0, sizeof(pf));
1562 memset(&trs, 0, sizeof(trs));
1563 if ((path = calloc(1, PATH_MAX1024)) == NULL((void *)0))
1564 ERRX("pfctl_rules: calloc");
1565 if (strlcpy(trs.pfrt_anchor, anchorname,
1566 sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor))
1567 ERRX("pfctl_rules: strlcpy");
1568 pf.dev = dev;
1569 pf.opts = opts;
1570 pf.optimize = optimize;
1571
1572 /* non-brace anchor, create without resolving the path */
1573 if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL((void *)0))
1574 ERRX("pfctl_rules: calloc");
1575 rs = &pf.anchor->ruleset;
1576 pf_init_ruleset(rs);
1577 rs->anchor = pf.anchor;
1578 if (strlcpy(pf.anchor->path, anchorname,
1579 sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path))
1580 errx(1, "%s: strlcpy", __func__);
1581
1582 if ((p = strrchr(anchorname, '/')) != NULL((void *)0)) {
1583 if (strlen(p) == 1)
1584 errx(1, "%s: bad anchor name %s", __func__, anchorname);
1585 } else
1586 p = anchorname;
1587
1588 if (strlcpy(pf.anchor->name, p,
1589 sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name))
1590 errx(1, "%s: strlcpy", __func__);
1591
1592 pf.astack[0] = pf.anchor;
1593 pf.asd = 0;
1594 pf.trans = t;
1595 pfctl_init_options(&pf);
1596
1597 if ((opts & PF_OPT_NOACTION0x00008) == 0) {
1598 /*
1599 * XXX For the time being we need to open transactions for
1600 * the main ruleset before parsing, because tables are still
1601 * loaded at parse time.
1602 */
1603 if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor))
1604 ERRX("pfctl_rules");
1605 pf.astack[0]->ruleset.tticket =
1606 pfctl_get_ticket(t, PF_TRANS_TABLE, anchorname);
1607 }
1608
1609 if (parse_config(filename, &pf) < 0) {
1610 if ((opts & PF_OPT_NOACTION0x00008) == 0)
1611 ERRX("Syntax error in config file: "
1612 "pf rules not loaded");
1613 else
1614 goto _error;
1615 }
1616
1617 if (!anchorname[0] && (pfctl_check_qassignments(&pf.anchor->ruleset) ||
1618 pfctl_load_queues(&pf))) {
1619 if ((opts & PF_OPT_NOACTION0x00008) == 0)
1620 ERRX("Unable to load queues into kernel");
1621 else
1622 goto _error;
1623 }
1624
1625 if (pfctl_load_ruleset(&pf, path, rs, 0)) {
1626 if ((opts & PF_OPT_NOACTION0x00008) == 0)
1627 ERRX("Unable to load rules into kernel");
1628 else
1629 goto _error;
1630 }
1631
1632 free(path);
1633 path = NULL((void *)0);
1634
1635 if (trans == NULL((void *)0)) {
1636 /*
1637 * process "load anchor" directives that might have used queues
1638 */
1639 if (pfctl_load_anchors(dev, &pf, t) == -1)
1640 ERRX("load anchors");
1641 pfctl_clear_queues(&qspecs);
1642 pfctl_clear_queues(&rootqs);
1643
1644 if ((opts & PF_OPT_NOACTION0x00008) == 0) {
1645 if (!anchorname[0] && pfctl_load_options(&pf))
1646 goto _error;
1647 if (pfctl_trans(dev, t, DIOCXCOMMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_trans) & 0x1fff) << 16) | ((('D')) <<
8) | ((82)))
, osize))
1648 ERR("DIOCXCOMMIT");
1649 }
1650 }
1651 return (0);
1652
1653_error:
1654 if (trans == NULL((void *)0)) { /* main ruleset */
1655 if ((opts & PF_OPT_NOACTION0x00008) == 0)
1656 if (pfctl_trans(dev, t, DIOCXROLLBACK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_trans) & 0x1fff) << 16) | ((('D')) <<
8) | ((83)))
, osize))
1657 err(1, "DIOCXROLLBACK");
1658 exit(1);
1659 } else { /* sub ruleset */
1660 free(path);
1661 return (-1);
1662 }
1663
1664#undef ERR
1665#undef ERRX
1666}
1667
1668FILE *
1669pfctl_fopen(const char *name, const char *mode)
1670{
1671 struct stat st;
1672 FILE *fp;
1673
1674 fp = fopen(name, mode);
1675 if (fp == NULL((void *)0))
1676 return (NULL((void *)0));
1677 if (fstat(fileno(fp)(!__isthreaded ? ((fp)->_file) : (fileno)(fp)), &st) == -1) {
1678 fclose(fp);
1679 return (NULL((void *)0));
1680 }
1681 if (S_ISDIR(st.st_mode)((st.st_mode & 0170000) == 0040000)) {
1682 fclose(fp);
1683 errno(*__errno()) = EISDIR21;
1684 return (NULL((void *)0));
1685 }
1686 return (fp);
1687}
1688
1689void
1690pfctl_init_options(struct pfctl *pf)
1691{
1692 int64_t mem;
1693 int mib[2], mcl;
1694 size_t size;
1695
1696 pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL120;
1697 pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL30;
1698 pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL24*60*60;
1699 pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL15 * 60;
1700 pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL45;
1701 pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL90;
1702 pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL60;
1703 pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL30;
1704 pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL60;
1705 pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL20;
1706 pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL10;
1707 pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL60;
1708 pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL30;
1709 pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL60;
1710 pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL60;
1711 pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL10;
1712 pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL0;
1713 pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL30;
1714 pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START60000;
1715 pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END120000;
1716
1717 pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT100000;
1718
1719 pf->syncookieswat[0] = PF_SYNCOOKIES_LOWATPCT25/2;
1720 pf->syncookieswat[1] = PF_SYNCOOKIES_HIWATPCT25;
1721
1722 mib[0] = CTL_KERN1;
1723 mib[1] = KERN_MAXCLUSTERS67;
1724 size = sizeof(mcl);
1725 if (sysctl(mib, 2, &mcl, &size, NULL((void *)0), 0) == -1)
1726 err(1, "sysctl");
1727 pf->limit[PF_LIMIT_FRAGS] = mcl / 4;
1728
1729 pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT10000;
1730 pf->limit[PF_LIMIT_TABLES] = PFR_KTABLE_HIWAT1000;
1731 pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT200000;
1732 pf->limit[PF_LIMIT_PKTDELAY_PKTS] = PF_PKTDELAY_MAXPKTS10000;
1733 pf->limit[PF_LIMIT_ANCHORS] = PF_ANCHOR_HIWAT512;
1734
1735 mib[0] = CTL_HW6;
1736 mib[1] = HW_PHYSMEM6419;
1737 size = sizeof(mem);
1738 if (sysctl(mib, 2, &mem, &size, NULL((void *)0), 0) == -1)
1739 err(1, "sysctl");
1740 if (mem <= 100*1024*1024)
1741 pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT_SMALL100000;
1742
1743 pf->debug = LOG_ERR3;
1744 pf->debug_set = 0;
1745 pf->reassemble = PF_REASS_ENABLED0x01;
1746}
1747
1748int
1749pfctl_load_options(struct pfctl *pf)
1750{
1751 int i, error = 0;
1752
1753 /* load limits */
1754 for (i = 0; i < PF_LIMIT_MAX; i++)
1755 if (pfctl_load_limit(pf, i, pf->limit[i]))
1756 error = 1;
1757
1758 /*
1759 * If we've set the states limit, but haven't explicitly set adaptive
1760 * timeouts, do it now with a start of 60% and end of 120%.
1761 */
1762 if (pf->limit_set[PF_LIMIT_STATES] &&
1763 !pf->timeout_set[PFTM_ADAPTIVE_START] &&
1764 !pf->timeout_set[PFTM_ADAPTIVE_END]) {
1765 pf->timeout[PFTM_ADAPTIVE_START] =
1766 (pf->limit[PF_LIMIT_STATES] / 10) * 6;
1767 pf->timeout_set[PFTM_ADAPTIVE_START] = 1;
1768 pf->timeout[PFTM_ADAPTIVE_END] =
1769 (pf->limit[PF_LIMIT_STATES] / 10) * 12;
1770 pf->timeout_set[PFTM_ADAPTIVE_END] = 1;
1771 }
1772
1773 /* load timeouts */
1774 for (i = 0; i < PFTM_MAX; i++)
1775 if (pfctl_load_timeout(pf, i, pf->timeout[i]))
1776 error = 1;
1777
1778 /* load debug */
1779 if (pf->debug_set && pfctl_load_debug(pf, pf->debug))
1780 error = 1;
1781
1782 /* load logif */
1783 if (pf->ifname_set && pfctl_load_logif(pf, pf->ifname))
1784 error = 1;
1785
1786 /* load hostid */
1787 if (pf->hostid_set && pfctl_load_hostid(pf, pf->hostid))
1788 error = 1;
1789
1790 /* load reassembly settings */
1791 if (pf->reass_set && pfctl_load_reassembly(pf, pf->reassemble))
1792 error = 1;
1793
1794 /* load syncookies settings */
1795 if (pf->syncookies_set && pfctl_load_syncookies(pf, pf->syncookies))
1796 error = 1;
1797 if (pf->syncookieswat_set) {
1798 struct pfioc_limit pl;
1799 unsigned curlim;
1800
1801 if (pf->limit_set[PF_LIMIT_STATES])
1802 curlim = pf->limit[PF_LIMIT_STATES];
1803 else {
1804 memset(&pl, 0, sizeof(pl));
1805 pl.index = pf_limits[PF_LIMIT_STATES].index;
1806 if (ioctl(dev, DIOCGETLIMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_limit) & 0x1fff) << 16) | ((('D')) <<
8) | ((39)))
, &pl) == -1)
1807 err(1, "DIOCGETLIMIT");
1808 curlim = pl.limit;
1809 }
1810 if (pfctl_set_synflwats(pf, curlim * pf->syncookieswat[0]/100,
1811 curlim * pf->syncookieswat[1]/100))
1812 error = 1;
1813 }
1814
1815 return (error);
1816}
1817
1818int
1819pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
1820{
1821 int i;
1822
1823 for (i = 0; pf_limits[i].name; i++) {
1824 if (strcasecmp(opt, pf_limits[i].name) == 0) {
1825 pf->limit[pf_limits[i].index] = limit;
1826 pf->limit_set[pf_limits[i].index] = 1;
1827 break;
1828 }
1829 }
1830 if (pf_limits[i].name == NULL((void *)0)) {
1831 warnx("Bad pool name.");
1832 return (1);
1833 }
1834
1835 if (pf->opts & PF_OPT_VERBOSE0x00004)
1836 printf("set limit %s %d\n", opt, limit);
1837
1838 return (0);
1839}
1840
1841int
1842pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit)
1843{
1844 struct pfioc_limit pl;
1845
1846 memset(&pl, 0, sizeof(pl));
1847 pl.index = index;
1848 pl.limit = limit;
1849 if (ioctl(pf->dev, DIOCSETLIMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_limit) & 0x1fff) << 16) | ((('D')) <<
8) | ((40)))
, &pl) == -1) {
1850 if (errno(*__errno()) == EBUSY16)
1851 warnx("Current pool size exceeds requested %s limit %u",
1852 pf_limits[index].name, limit);
1853 else
1854 warnx("Cannot set %s limit to %u",
1855 pf_limits[index].name, limit);
1856 return (1);
1857 }
1858 return (0);
1859}
1860
1861int
1862pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
1863{
1864 int i;
1865
1866 for (i = 0; pf_timeouts[i].name; i++) {
1867 if (strcasecmp(opt, pf_timeouts[i].name) == 0) {
1868 pf->timeout[pf_timeouts[i].timeout] = seconds;
1869 pf->timeout_set[pf_timeouts[i].timeout] = 1;
1870 break;
1871 }
1872 }
1873
1874 if (pf_timeouts[i].name == NULL((void *)0)) {
1875 warnx("Bad timeout name.");
1876 return (1);
1877 }
1878
1879
1880 if (pf->opts & PF_OPT_VERBOSE0x00004 && ! quiet)
1881 printf("set timeout %s %d\n", opt, seconds);
1882
1883 return (0);
1884}
1885
1886int
1887pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds)
1888{
1889 struct pfioc_tm pt;
1890
1891 memset(&pt, 0, sizeof(pt));
1892 pt.timeout = timeout;
1893 pt.seconds = seconds;
1894 if (ioctl(pf->dev, DIOCSETTIMEOUT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_tm) & 0x1fff) << 16) | ((('D')) <<
8) | ((29)))
, &pt) == -1) {
1895 warnx("DIOCSETTIMEOUT");
1896 return (1);
1897 }
1898 return (0);
1899}
1900
1901int
1902pfctl_set_synflwats(struct pfctl *pf, u_int32_t lowat, u_int32_t hiwat)
1903{
1904 struct pfioc_synflwats ps;
1905
1906 memset(&ps, 0, sizeof(ps));
1907 ps.hiwat = hiwat;
1908 ps.lowat = lowat;
1909
1910 if (ioctl(pf->dev, DIOCSETSYNFLWATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_synflwats) & 0x1fff) << 16) | ((('D')
) << 8) | ((97)))
, &ps) == -1) {
1911 warnx("Cannot set synflood detection watermarks");
1912 return (1);
1913 }
1914 return (0);
1915}
1916
1917int
1918pfctl_set_reassembly(struct pfctl *pf, int on, int nodf)
1919{
1920 pf->reass_set = 1;
1921 if (on) {
1922 pf->reassemble = PF_REASS_ENABLED0x01;
1923 if (nodf)
1924 pf->reassemble |= PF_REASS_NODF0x02;
1925 } else {
1926 pf->reassemble = 0;
1927 }
1928
1929 if (pf->opts & PF_OPT_VERBOSE0x00004)
1930 printf("set reassemble %s %s\n", on ? "yes" : "no",
1931 nodf ? "no-df" : "");
1932
1933 return (0);
1934}
1935
1936int
1937pfctl_set_syncookies(struct pfctl *pf, u_int8_t val, struct pfctl_watermarks *w)
1938{
1939 if (val != PF_SYNCOOKIES_ADAPTIVE2 && w != NULL((void *)0)) {
1940 warnx("syncookies start/end only apply to adaptive");
1941 return (1);
1942 }
1943 if (val == PF_SYNCOOKIES_ADAPTIVE2 && w != NULL((void *)0)) {
1944 if (!w->hi)
1945 w->hi = PF_SYNCOOKIES_HIWATPCT25;
1946 if (!w->lo)
1947 w->lo = w->hi / 2;
1948 if (w->lo >= w->hi) {
1949 warnx("start must be higher than end");
1950 return (1);
1951 }
1952 pf->syncookieswat[0] = w->lo;
1953 pf->syncookieswat[1] = w->hi;
1954 pf->syncookieswat_set = 1;
1955 }
1956
1957 if (pf->opts & PF_OPT_VERBOSE0x00004) {
1958 if (val == PF_SYNCOOKIES_NEVER0)
1959 printf("set syncookies never\n");
1960 else if (val == PF_SYNCOOKIES_ALWAYS1)
1961 printf("set syncookies always\n");
1962 else if (val == PF_SYNCOOKIES_ADAPTIVE2) {
1963 if (pf->syncookieswat_set)
1964 printf("set syncookies adaptive (start %u%%, "
1965 "end %u%%)\n", pf->syncookieswat[1],
1966 pf->syncookieswat[0]);
1967 else
1968 printf("set syncookies adaptive\n");
1969 } else { /* cannot happen */
1970 warnx("king bula ate all syncookies");
1971 return (1);
1972 }
1973 }
1974
1975 pf->syncookies_set = 1;
1976 pf->syncookies = val;
1977 return (0);
1978}
1979
1980int
1981pfctl_set_optimization(struct pfctl *pf, const char *opt)
1982{
1983 const struct pf_hint *hint;
1984 int i, r;
1985
1986 for (i = 0; pf_hints[i].name; i++)
1987 if (strcasecmp(opt, pf_hints[i].name) == 0)
1988 break;
1989
1990 hint = pf_hints[i].hint;
1991 if (hint == NULL((void *)0)) {
1992 warnx("invalid state timeouts optimization");
1993 return (1);
1994 }
1995
1996 for (i = 0; hint[i].name; i++)
1997 if ((r = pfctl_set_timeout(pf, hint[i].name,
1998 hint[i].timeout, 1)))
1999 return (r);
2000
2001 if (pf->opts & PF_OPT_VERBOSE0x00004)
2002 printf("set optimization %s\n", opt);
2003
2004 return (0);
2005}
2006
2007int
2008pfctl_set_logif(struct pfctl *pf, char *ifname)
2009{
2010 if (!strcmp(ifname, "none")) {
2011 free(pf->ifname);
2012 pf->ifname = NULL((void *)0);
2013 } else {
2014 pf->ifname = strdup(ifname);
2015 if (!pf->ifname)
2016 errx(1, "pfctl_set_logif: strdup");
2017 }
2018 pf->ifname_set = 1;
2019
2020 if (pf->opts & PF_OPT_VERBOSE0x00004)
2021 printf("set loginterface %s\n", ifname);
2022
2023 return (0);
2024}
2025
2026int
2027pfctl_load_logif(struct pfctl *pf, char *ifname)
2028{
2029 struct pfioc_iface pi;
2030
2031 memset(&pi, 0, sizeof(pi));
2032 if (ifname && strlcpy(pi.pfiio_name, ifname,
2033 sizeof(pi.pfiio_name)) >= sizeof(pi.pfiio_name)) {
2034 warnx("pfctl_load_logif: strlcpy");
2035 return (1);
2036 }
2037 if (ioctl(pf->dev, DIOCSETSTATUSIF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((20)))
, &pi) == -1) {
2038 warnx("DIOCSETSTATUSIF");
2039 return (1);
2040 }
2041 return (0);
2042}
2043
2044void
2045pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
2046{
2047 HTONL(hostid)(hostid) = (__uint32_t)(__builtin_constant_p((u_int32_t)(hostid
)) ? (__uint32_t)(((__uint32_t)((u_int32_t)(hostid)) & 0xff
) << 24 | ((__uint32_t)((u_int32_t)(hostid)) & 0xff00
) << 8 | ((__uint32_t)((u_int32_t)(hostid)) & 0xff0000
) >> 8 | ((__uint32_t)((u_int32_t)(hostid)) & 0xff000000
) >> 24) : __swap32md((u_int32_t)(hostid)))
;
2048
2049 pf->hostid = hostid;
2050 pf->hostid_set = 1;
2051
2052 if (pf->opts & PF_OPT_VERBOSE0x00004)
2053 printf("set hostid 0x%08x\n", ntohl(hostid)(__uint32_t)(__builtin_constant_p(hostid) ? (__uint32_t)(((__uint32_t
)(hostid) & 0xff) << 24 | ((__uint32_t)(hostid) &
0xff00) << 8 | ((__uint32_t)(hostid) & 0xff0000) >>
8 | ((__uint32_t)(hostid) & 0xff000000) >> 24) : __swap32md
(hostid))
);
2054}
2055
2056int
2057pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid)
2058{
2059 if (ioctl(dev, DIOCSETHOSTID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int32_t) & 0x1fff) << 16) | ((('D')) << 8)
| ((86)))
, &hostid) == -1) {
2060 warnx("DIOCSETHOSTID");
2061 return (1);
2062 }
2063 return (0);
2064}
2065
2066int
2067pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly)
2068{
2069 if (ioctl(dev, DIOCSETREASS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int32_t) & 0x1fff) << 16) | ((('D')) << 8)
| ((92)))
, &reassembly) == -1) {
2070 warnx("DIOCSETREASS");
2071 return (1);
2072 }
2073 return (0);
2074}
2075
2076int
2077pfctl_load_syncookies(struct pfctl *pf, u_int8_t val)
2078{
2079 if (ioctl(dev, DIOCSETSYNCOOKIES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int8_t) & 0x1fff) << 16) | ((('D')) << 8) |
((98)))
, &val) == -1) {
2080 warnx("DIOCSETSYNCOOKIES");
2081 return (1);
2082 }
2083 return (0);
2084}
2085
2086int
2087pfctl_set_debug(struct pfctl *pf, char *d)
2088{
2089 u_int32_t level;
2090 int loglevel;
2091
2092 if ((loglevel = string_to_loglevel(d)) >= 0)
2093 level = loglevel;
2094 else {
2095 warnx("unknown debug level \"%s\"", d);
2096 return (-1);
2097 }
2098 pf->debug = level;
2099 pf->debug_set = 1;
2100
2101 if ((pf->opts & PF_OPT_NOACTION0x00008) == 0)
2102 if (ioctl(dev, DIOCSETDEBUG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int32_t) & 0x1fff) << 16) | ((('D')) << 8)
| ((24)))
, &level) == -1)
2103 err(1, "DIOCSETDEBUG");
2104
2105 if (pf->opts & PF_OPT_VERBOSE0x00004)
2106 printf("set debug %s\n", d);
2107
2108 return (0);
2109}
2110
2111int
2112pfctl_load_debug(struct pfctl *pf, unsigned int level)
2113{
2114 if (ioctl(pf->dev, DIOCSETDEBUG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int32_t) & 0x1fff) << 16) | ((('D')) << 8)
| ((24)))
, &level) == -1) {
2115 warnx("DIOCSETDEBUG");
2116 return (1);
2117 }
2118 return (0);
2119}
2120
2121int
2122pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how)
2123{
2124 struct pfioc_iface pi;
2125
2126 bzero(&pi, sizeof(pi));
2127
2128 pi.pfiio_flags = flags;
2129
2130 if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >=
2131 sizeof(pi.pfiio_name))
2132 errx(1, "pfctl_set_interface_flags: strlcpy");
2133
2134 if ((pf->opts & PF_OPT_NOACTION0x00008) == 0) {
2135 if (how == 0) {
2136 if (ioctl(pf->dev, DIOCCLRIFFLAG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((90)))
, &pi) == -1)
2137 err(1, "DIOCCLRIFFLAG");
2138 } else {
2139 if (ioctl(pf->dev, DIOCSETIFFLAG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_iface) & 0x1fff) << 16) | ((('D')) <<
8) | ((89)))
, &pi) == -1)
2140 err(1, "DIOCSETIFFLAG");
2141 }
2142 }
2143 return (0);
2144}
2145
2146void
2147pfctl_debug(int dev, u_int32_t level, int opts)
2148{
2149 struct pfr_buffer t;
2150
2151 memset(&t, 0, sizeof(t));
2152 t.pfrb_type = PFRB_TRANS;
2153 if (pfctl_trans(dev, &t, DIOCXBEGIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_trans) & 0x1fff) << 16) | ((('D')) <<
8) | ((81)))
, 0) ||
2154 ioctl(dev, DIOCSETDEBUG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(u_int32_t) & 0x1fff) << 16) | ((('D')) << 8)
| ((24)))
, &level) == -1||
2155 pfctl_trans(dev, &t, DIOCXCOMMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_trans) & 0x1fff) << 16) | ((('D')) <<
8) | ((82)))
, 0))
2156 err(1, "pfctl_debug ioctl");
2157
2158 if ((opts & PF_OPT_QUIET0x00010) == 0)
2159 fprintf(stderr(&__sF[2]), "debug level set to '%s'\n",
2160 loglevel_to_string(level));
2161}
2162
2163int
2164pfctl_walk_show(int opts, struct pfioc_ruleset *pr, void *warg)
2165{
2166 if (pr->path[0]) {
2167 if (pr->path[0] != '_' || (opts & PF_OPT_VERBOSE0x00004))
2168 printf(" %s/%s\n", pr->path, pr->name);
2169 } else if (pr->name[0] != '_' || (opts & PF_OPT_VERBOSE0x00004))
2170 printf(" %s\n", pr->name);
2171
2172 return (0);
2173}
2174
2175int
2176pfctl_walk_get(int opts, struct pfioc_ruleset *pr, void *warg)
2177{
2178 struct pfr_anchoritem *pfra;
2179 struct pfr_anchors *anchors;
2180 int e;
2181
2182 anchors = (struct pfr_anchors *) warg;
2183
2184 pfra = malloc(sizeof(*pfra));
2185 if (pfra == NULL((void *)0))
2186 err(1, "%s", __func__);
2187
2188 if (pr->path[0])
2189 e = asprintf(&pfra->pfra_anchorname, "%s/%s", pr->path,
2190 pr->name);
2191 else
2192 e = asprintf(&pfra->pfra_anchorname, "%s", pr->name);
2193
2194 if (e == -1)
2195 err(1, "%s", __func__);
2196
2197
2198 SLIST_INSERT_HEAD(anchors, pfra, pfra_sle)do { (pfra)->pfra_sle.sle_next = (anchors)->slh_first; (
anchors)->slh_first = (pfra); } while (0)
;
2199
2200 return (0);
2201}
2202
2203int
2204pfctl_walk_anchors(int dev, int opts, const char *anchor,
2205 int(walkf)(int, struct pfioc_ruleset *, void *), void *warg)
2206{
2207 struct pfioc_ruleset pr;
2208 u_int32_t mnr, nr;
2209
2210 memset(&pr, 0, sizeof(pr));
2211 strlcpy(pr.path, anchor, sizeof(pr.path));
2212 if (ioctl(dev, DIOCGETRULESETS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_ruleset) & 0x1fff) << 16) | ((('D')) <<
8) | ((58)))
, &pr) == -1)
2213 errx(1, "%s", pf_strerror(errno(*__errno())));
2214 mnr = pr.nr;
2215 for (nr = 0; nr < mnr; ++nr) {
2216 char sub[PATH_MAX1024];
2217
2218 pr.nr = nr;
2219 if (ioctl(dev, DIOCGETRULESET(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_ruleset) & 0x1fff) << 16) | ((('D')) <<
8) | ((59)))
, &pr) == -1)
2220 errx(1, "%s", pf_strerror(errno(*__errno())));
2221 if (!strcmp(pr.name, PF_RESERVED_ANCHOR"_pf"))
2222 continue;
2223 sub[0] = '\0';
2224
2225 if (walkf(opts, &pr, warg))
2226 return (-1);
2227
2228 if (pr.path[0])
2229 snprintf(sub, sizeof(sub), "%s/%s",
2230 pr.path, pr.name);
2231 else
2232 snprintf(sub, sizeof(sub), "%s",
2233 pr.name);
2234 if (pfctl_walk_anchors(dev, opts, sub, walkf, warg))
2235 return (-1);
2236 }
2237 return (0);
2238}
2239
2240int
2241pfctl_show_anchors(int dev, int opts, char *anchor)
2242{
2243 return (
2244 pfctl_walk_anchors(dev, opts, anchor, pfctl_walk_show, NULL((void *)0)));
2245}
2246
2247struct pfr_anchors *
2248pfctl_get_anchors(int dev, const char *anchor, int opts)
2249{
2250 struct pfioc_ruleset pr;
2251 static struct pfr_anchors anchors;
2252 char anchorbuf[PATH_MAX1024];
2253 char *n;
2254
2255 SLIST_INIT(&anchors){ ((&anchors)->slh_first) = ((void *)0); };
2256
2257 memset(&pr, 0, sizeof(pr));
2258 if (*anchor != '\0') {
2259 strlcpy(anchorbuf, anchor, sizeof(anchorbuf));
2260 n = dirname(anchorbuf);
2261 if (n[0] != '.' && n[1] != '\0')
2262 strlcpy(pr.path, n, sizeof(pr.path));
2263 strlcpy(anchorbuf, anchor, sizeof(anchorbuf));
2264 n = basename(anchorbuf);
2265 if (n != NULL((void *)0))
2266 strlcpy(pr.name, n, sizeof(pr.name));
2267 }
2268
2269 /* insert a root anchor first. */
2270 pfctl_walk_get(opts, &pr, &anchors);
2271
2272 if (pfctl_walk_anchors(dev, opts, anchor, pfctl_walk_get, &anchors))
2273 errx(1,
2274 "%s failed to retrieve list of anchors, can't continue",
2275 __func__);
2276
2277 return (&anchors);
2278}
2279
2280int
2281pfctl_call_cleartables(int dev, int opts, struct pfr_anchoritem *pfra)
2282{
2283 /*
2284 * PF_OPT_QUIET makes pfctl_clear_tables() to stop printing number of
2285 * tables cleared for given anchor.
2286 */
2287 opts |= PF_OPT_QUIET0x00010;
2288 return ((pfctl_clear_tables(pfra->pfra_anchorname, opts) == -1) ?
2289 1 : 0);
2290}
2291
2292int
2293pfctl_call_clearrules(int dev, int opts, struct pfr_anchoritem *pfra)
2294{
2295 /*
2296 * PF_OPT_QUIET makes pfctl_clear_rules() to stop printing a 'rules
2297 * cleared' message for every anchor it deletes.
2298 */
2299 opts |= PF_OPT_QUIET0x00010;
2300 return (pfctl_clear_rules(dev, opts, pfra->pfra_anchorname));
2301}
2302
2303int
2304pfctl_call_clearanchors(int dev, int opts, struct pfr_anchoritem *pfra)
2305{
2306 int rv = 0;
2307
2308 rv |= pfctl_call_cleartables(dev, opts, pfra);
2309 rv |= pfctl_call_clearrules(dev, opts, pfra);
2310
2311 return (rv);
2312}
2313
2314int
2315pfctl_recurse(int dev, int opts, const char *anchorname,
2316 int(*walkf)(int, int, struct pfr_anchoritem *))
2317{
2318 int rv = 0;
2319 struct pfr_anchors *anchors;
2320 struct pfr_anchoritem *pfra, *pfra_save;
2321
2322 anchors = pfctl_get_anchors(dev, anchorname, opts);
2323 /*
2324 * While traversing the list, pfctl_clear_*() must always return
2325 * so that failures on one anchor do not prevent clearing others.
2326 */
2327 opts |= PF_OPT_IGNFAIL0x10000;
2328 printf("Removing:\n");
2329 SLIST_FOREACH_SAFE(pfra, anchors, pfra_sle, pfra_save)for ((pfra) = ((anchors)->slh_first); (pfra) && ((
pfra_save) = ((pfra)->pfra_sle.sle_next), 1); (pfra) = (pfra_save
))
{
2330 printf(" %s\n", (*pfra->pfra_anchorname == '\0') ?
2331 "/" : pfra->pfra_anchorname);
2332 rv |= walkf(dev, opts, pfra);
2333 SLIST_REMOVE(anchors, pfra, pfr_anchoritem, pfra_sle)do { if ((anchors)->slh_first == (pfra)) { do { ((anchors)
)->slh_first = ((anchors))->slh_first->pfra_sle.sle_next
; } while (0); } else { struct pfr_anchoritem *curelm = (anchors
)->slh_first; while (curelm->pfra_sle.sle_next != (pfra
)) curelm = curelm->pfra_sle.sle_next; curelm->pfra_sle
.sle_next = curelm->pfra_sle.sle_next->pfra_sle.sle_next
; } ; } while (0)
;
2334 free(pfra->pfra_anchorname);
2335 free(pfra);
2336 }
2337
2338 return (rv);
2339}
2340
2341const char *
2342pfctl_lookup_option(char *cmd, const char **list)
2343{
2344 const char *item = NULL((void *)0);
2345
2346 if (cmd != NULL((void *)0) && *cmd)
2347 for (; *list; list++)
2348 if (!strncmp(cmd, *list, strlen(cmd))) {
2349 if (item == NULL((void *)0))
2350 item = *list;
2351 else
2352 errx(1, "%s is ambigious", cmd);
2353 }
2354
2355 return (item);
2356}
2357
2358
2359void
2360pfctl_state_store(int dev, const char *file)
2361{
2362 FILE *f;
2363 struct pfioc_states ps;
2364 char *inbuf = NULL((void *)0), *newinbuf = NULL((void *)0);
2365 size_t n, len = 0;
2366
2367 f = fopen(file, "w");
2368 if (f == NULL((void *)0))
2369 err(1, "open: %s", file);
2370
2371 memset(&ps, 0, sizeof(ps));
2372 for (;;) {
2373 ps.ps_len = len;
2374 if (len) {
2375 newinbuf = realloc(inbuf, len);
2376 if (newinbuf == NULL((void *)0))
2377 err(1, "realloc");
2378 ps.ps_bufps_u.psu_buf = inbuf = newinbuf;
2379 }
2380 if (ioctl(dev, DIOCGETSTATES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_states) & 0x1fff) << 16) | ((('D')) <<
8) | ((25)))
, &ps) == -1)
2381 err(1, "DIOCGETSTATES");
2382
2383 if (ps.ps_len + sizeof(struct pfioc_states) < len)
2384 break;
2385 if (len == 0 && ps.ps_len == 0)
2386 goto done;
2387 if (len == 0 && ps.ps_len != 0)
2388 len = ps.ps_len;
2389 if (ps.ps_len == 0)
2390 goto done; /* no states */
2391 len *= 2;
2392 }
2393
2394 n = ps.ps_len / sizeof(struct pfsync_state);
2395 if (fwrite(inbuf, sizeof(struct pfsync_state), n, f) < n)
2396 err(1, "fwrite");
2397
2398done:
2399 free(inbuf);
2400 fclose(f);
2401}
2402
2403void
2404pfctl_state_load(int dev, const char *file)
2405{
2406 FILE *f;
2407 struct pfioc_state ps;
2408
2409 f = fopen(file, "r");
2410 if (f == NULL((void *)0))
2411 err(1, "open: %s", file);
2412
2413 while (fread(&ps.state, sizeof(ps.state), 1, f) == 1) {
2414 if (ioctl(dev, DIOCADDSTATE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_state) & 0x1fff) << 16) | ((('D')) <<
8) | ((37)))
, &ps) == -1) {
2415 switch (errno(*__errno())) {
2416 case EEXIST17:
2417 case EINVAL22:
2418 break;
2419 default:
2420 err(1, "DIOCADDSTATE");
2421 }
2422 }
2423 }
2424
2425 fclose(f);
2426}
2427
2428void
2429pfctl_reset(int dev, int opts)
2430{
2431 struct pfctl pf;
2432 struct pfr_buffer t;
2433 int i;
2434
2435 memset(&pf, 0, sizeof(pf));
2436 pf.dev = dev;
2437 pfctl_init_options(&pf);
2438
2439 /* Force reset upon pfctl_load_options() */
2440 pf.debug_set = 1;
2441 pf.reass_set = 1;
2442 pf.syncookieswat_set = 1;
2443 pf.syncookies_set = 1;
2444 pf.ifname = strdup("none");
2445 if (pf.ifname == NULL((void *)0))
2446 err(1, "%s: strdup", __func__);
2447 pf.ifname_set = 1;
2448
2449 memset(&t, 0, sizeof(t));
2450 t.pfrb_type = PFRB_TRANS;
2451 if (pfctl_trans(dev, &t, DIOCXBEGIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_trans) & 0x1fff) << 16) | ((('D')) <<
8) | ((81)))
, 0))
2452 err(1, "%s: DIOCXBEGIN", __func__);
2453
2454 for (i = 0; pf_limits[i].name; i++)
2455 pf.limit_set[pf_limits[i].index] = 1;
2456
2457 for (i = 0; pf_timeouts[i].name; i++)
2458 pf.timeout_set[pf_timeouts[i].timeout] = 1;
2459
2460 pfctl_load_options(&pf);
2461
2462 if (pfctl_trans(dev, &t, DIOCXCOMMIT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct pfioc_trans) & 0x1fff) << 16) | ((('D')) <<
8) | ((82)))
, 0))
2463 err(1, "%s: DIOCXCOMMIT", __func__);
2464
2465 pfctl_clear_interface_flags(dev, opts);
2466}
2467
2468#ifndef REGRESS_NOMAIN
2469int
2470main(int argc, char *argv[])
2471{
2472 int ch;
2473 int mode = O_RDONLY0x0000;
2474 int opts = 0;
2475 int optimize = PF_OPTIMIZE_BASIC0x0001;
2476 int level;
2477 int rdomain = 0;
2478 char anchorname[PATH_MAX1024];
2479 int anchor_wildcard = 0;
2480 char *path;
2481 char *lfile = NULL((void *)0), *sfile = NULL((void *)0);
2482 const char *errstr;
2483 long shownr = -1;
2484
2485 if (argc < 2)
1
Assuming 'argc' is >= 2
2
Taking false branch
2486 usage();
2487
2488 while ((ch = getopt(argc, argv,
3
Assuming the condition is false
2489 "a:dD:eqf:F:ghi:k:K:L:Nno:Pp:R:rS:s:t:T:vV:x:z")) != -1) {
2490 switch (ch) {
2491 case 'a':
2492 anchoropt = optarg;
2493 break;
2494 case 'd':
2495 opts |= PF_OPT_DISABLE0x00001;
2496 mode = O_RDWR0x0002;
2497 break;
2498 case 'D':
2499 if (pfctl_cmdline_symset(optarg) < 0)
2500 warnx("could not parse macro definition %s",
2501 optarg);
2502 break;
2503 case 'e':
2504 opts |= PF_OPT_ENABLE0x00002;
2505 mode = O_RDWR0x0002;
2506 break;
2507 case 'q':
2508 opts |= PF_OPT_QUIET0x00010;
2509 break;
2510 case 'F':
2511 clearopt = pfctl_lookup_option(optarg, clearopt_list);
2512 if (clearopt == NULL((void *)0)) {
2513 warnx("Unknown flush modifier '%s'", optarg);
2514 usage();
2515 }
2516 mode = O_RDWR0x0002;
2517 break;
2518 case 'i':
2519 ifaceopt = optarg;
2520 break;
2521 case 'k':
2522 if (state_killers >= 2) {
2523 warnx("can only specify -k twice");
2524 usage();
2525 /* NOTREACHED */
2526 }
2527 state_kill[state_killers++] = optarg;
2528 mode = O_RDWR0x0002;
2529 break;
2530 case 'K':
2531 if (src_node_killers >= 2) {
2532 warnx("can only specify -K twice");
2533 usage();
2534 /* NOTREACHED */
2535 }
2536 src_node_kill[src_node_killers++] = optarg;
2537 mode = O_RDWR0x0002;
2538 break;
2539 case 'N':
2540 opts |= PF_OPT_NODNS0x01000;
2541 break;
2542 case 'n':
2543 opts |= PF_OPT_NOACTION0x00008;
2544 break;
2545 case 'r':
2546 opts |= PF_OPT_USEDNS0x00040;
2547 break;
2548 case 'R':
2549 shownr = strtonum(optarg, -1, LONG_MAX0x7fffffffffffffffL, &errstr);
2550 if (errstr) {
2551 warnx("invalid rule id: %s", errstr);
2552 usage();
2553 }
2554 break;
2555 case 'f':
2556 rulesopt = optarg;
2557 mode = O_RDWR0x0002;
2558 break;
2559 case 'g':
2560 opts |= PF_OPT_DEBUG0x00200;
2561 break;
2562 case 'o':
2563 optiopt = pfctl_lookup_option(optarg, optiopt_list);
2564 if (optiopt == NULL((void *)0)) {
2565 warnx("Unknown optimization '%s'", optarg);
2566 usage();
2567 }
2568 opts |= PF_OPT_OPTIMIZE0x00800;
2569 break;
2570 case 'P':
2571 opts |= PF_OPT_PORTNAMES0x08000;
2572 break;
2573 case 'p':
2574 pf_device = optarg;
2575 break;
2576 case 's':
2577 showopt = pfctl_lookup_option(optarg, showopt_list);
2578 if (showopt == NULL((void *)0)) {
2579 warnx("Unknown show modifier '%s'", optarg);
2580 usage();
2581 }
2582 break;
2583 case 't':
2584 tableopt = optarg;
2585 break;
2586 case 'T':
2587 tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list);
2588 if (tblcmdopt == NULL((void *)0)) {
2589 warnx("Unknown table command '%s'", optarg);
2590 usage();
2591 }
2592 break;
2593 case 'v':
2594 if (opts & PF_OPT_VERBOSE0x00004)
2595 opts |= PF_OPT_VERBOSE20x00080;
2596 opts |= PF_OPT_VERBOSE0x00004;
2597 break;
2598 case 'V':
2599 rdomain = strtonum(optarg, 0, RT_TABLEID_MAX255, &errstr);
2600 if (errstr) {
2601 warnx("Invalid rdomain: %s", errstr);
2602 usage();
2603 }
2604 break;
2605 case 'x':
2606 debugopt = pfctl_lookup_option(optarg, debugopt_list);
2607 if (debugopt == NULL((void *)0)) {
2608 warnx("Unknown debug level '%s'", optarg);
2609 usage();
2610 }
2611 mode = O_RDWR0x0002;
2612 break;
2613 case 'z':
2614 opts |= PF_OPT_CLRRULECTRS0x00020;
2615 mode = O_RDWR0x0002;
2616 break;
2617 case 'S':
2618 sfile = optarg;
2619 break;
2620 case 'L':
2621 mode = O_RDWR0x0002;
2622 lfile = optarg;
2623 break;
2624 case 'h':
2625 /* FALLTHROUGH */
2626 default:
2627 usage();
2628 /* NOTREACHED */
2629 }
2630 }
2631
2632 if ((opts & PF_OPT_NODNS0x01000) && (opts & PF_OPT_USEDNS0x00040))
2633 errx(1, "-N and -r are mutually exclusive");
2634
2635 if ((tblcmdopt == NULL((void *)0)) ^ (tableopt == NULL((void *)0)))
4
Assuming 'tblcmdopt' is not equal to NULL
5
Assuming 'tableopt' is not equal to NULL
6
Taking false branch
2636 usage();
2637
2638 if (tblcmdopt
6.1
'tblcmdopt' is not equal to NULL
!= NULL((void *)0)) {
7
Taking true branch
2639 argc -= optind;
2640 argv += optind;
2641 ch = *tblcmdopt;
2642 mode = strchr("st", ch) ? O_RDONLY0x0000 : O_RDWR0x0002;
8
Assuming the condition is false
9
'?' condition is false
2643 } else if (argc != optind) {
2644 warnx("unknown command line argument: %s ...", argv[optind]);
2645 usage();
2646 /* NOTREACHED */
2647 }
2648
2649 memset(anchorname, 0, sizeof(anchorname));
2650 if (anchoropt != NULL((void *)0)) {
10
Assuming 'anchoropt' is equal to NULL
11
Taking false branch
2651 if (anchoropt[0] == '\0')
2652 errx(1, "anchor name must not be empty");
2653 if (mode == O_RDONLY0x0000 && showopt == NULL((void *)0) && tblcmdopt == NULL((void *)0)) {
2654 warnx("anchors apply to -f, -F, -s, and -T only");
2655 usage();
2656 }
2657 if (mode == O_RDWR0x0002 && tblcmdopt == NULL((void *)0) &&
2658 (anchoropt[0] == '_' || strstr(anchoropt, "/_") != NULL((void *)0)))
2659 errx(1, "anchor names beginning with '_' cannot "
2660 "be modified from the command line");
2661 int len = strlen(anchoropt);
2662
2663 if (anchoropt[len - 1] == '*') {
2664 if (len >= 2 && anchoropt[len - 2] == '/') {
2665 anchoropt[len - 2] = '\0';
2666 anchor_wildcard = 1;
2667 } else
2668 anchoropt[len - 1] = '\0';
2669 opts |= PF_OPT_RECURSE0x04000;
2670 }
2671 if (strlcpy(anchorname, anchoropt,
2672 sizeof(anchorname)) >= sizeof(anchorname))
2673 errx(1, "anchor name '%s' too long",
2674 anchoropt);
2675 }
2676
2677 if ((opts & PF_OPT_NOACTION0x00008) == 0) {
12
Taking true branch
2678 dev = open(pf_device, mode);
2679 if (dev == -1)
13
Assuming the condition is false
14
Taking false branch
2680 err(1, "%s", pf_device);
2681 } else {
2682 dev = open(pf_device, O_RDONLY0x0000);
2683 if (dev >= 0)
2684 opts |= PF_OPT_DUMMYACTION0x00100;
2685 /* turn off options */
2686 opts &= ~ (PF_OPT_DISABLE0x00001 | PF_OPT_ENABLE0x00002);
2687 clearopt = showopt = debugopt = NULL((void *)0);
2688 }
2689
2690 if (opts & PF_OPT_DISABLE0x00001)
15
Taking false branch
2691 if (pfctl_disable(dev, opts))
2692 exit_val = 1;
2693
2694 if ((path = calloc(1, PATH_MAX1024)) == NULL((void *)0))
16
Assuming the condition is false
17
Taking false branch
2695 errx(1, "%s: calloc", __func__);
2696
2697 if (showopt != NULL((void *)0)) {
18
Assuming 'showopt' is equal to NULL
2698 switch (*showopt) {
2699 case 'A':
2700 pfctl_show_anchors(dev, opts, anchorname);
2701 break;
2702 case 'r':
2703 pfctl_load_fingerprints(dev, opts);
2704 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES,
2705 anchorname, 0, anchor_wildcard, shownr);
2706 break;
2707 case 'l':
2708 pfctl_load_fingerprints(dev, opts);
2709 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS,
2710 anchorname, 0, anchor_wildcard, shownr);
2711 break;
2712 case 'q':
2713 pfctl_show_queues(dev, ifaceopt, opts,
2714 opts & PF_OPT_VERBOSE20x00080);
2715 break;
2716 case 's':
2717 pfctl_show_states(dev, ifaceopt, opts, shownr);
2718 break;
2719 case 'S':
2720 pfctl_show_src_nodes(dev, opts);
2721 break;
2722 case 'i':
2723 pfctl_show_status(dev, opts);
2724 break;
2725 case 't':
2726 pfctl_show_timeouts(dev, opts);
2727 break;
2728 case 'm':
2729 pfctl_show_limits(dev, opts);
2730 break;
2731 case 'a':
2732 opts |= PF_OPT_SHOWALL0x00400;
2733 pfctl_load_fingerprints(dev, opts);
2734
2735 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES,
2736 anchorname, 0, 0, -1);
2737 pfctl_show_queues(dev, ifaceopt, opts,
2738 opts & PF_OPT_VERBOSE20x00080);
2739 pfctl_show_states(dev, ifaceopt, opts, -1);
2740 pfctl_show_src_nodes(dev, opts);
2741 pfctl_show_status(dev, opts);
2742 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS,
2743 anchorname, 0, 0, -1);
2744 pfctl_show_timeouts(dev, opts);
2745 pfctl_show_limits(dev, opts);
2746 pfctl_show_tables(anchorname, opts);
2747 pfctl_show_fingerprints(opts);
2748 break;
2749 case 'T':
2750 pfctl_show_tables(anchorname, opts);
2751 break;
2752 case 'o':
2753 pfctl_load_fingerprints(dev, opts);
2754 pfctl_show_fingerprints(opts);
2755 break;
2756 case 'I':
2757 pfctl_show_ifaces(ifaceopt, opts);
2758 break;
2759 }
2760 }
2761
2762 if ((opts & PF_OPT_CLRRULECTRS0x00020) && showopt == NULL((void *)0))
2763 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING,
2764 anchorname, 0, 0, -1);
2765
2766 if (clearopt != NULL((void *)0)) {
19
Assuming 'clearopt' is equal to NULL
20
Taking false branch
2767 switch (*clearopt) {
2768 case 'r':
2769 if (opts & PF_OPT_RECURSE0x04000)
2770 pfctl_recurse(dev, opts, anchorname,
2771 pfctl_call_clearrules);
2772 else
2773 pfctl_clear_rules(dev, opts, anchorname);
2774 break;
2775 case 's':
2776 pfctl_clear_states(dev, ifaceopt, opts);
2777 break;
2778 case 'S':
2779 pfctl_clear_src_nodes(dev, opts);
2780 break;
2781 case 'i':
2782 pfctl_clear_stats(dev, ifaceopt, opts);
2783 break;
2784 case 'a':
2785 if (ifaceopt) {
2786 warnx("don't specify an interface with -Fall");
2787 usage();
2788 /* NOTREACHED */
2789 }
2790 if (opts & PF_OPT_RECURSE0x04000)
2791 pfctl_recurse(dev, opts, anchorname,
2792 pfctl_call_clearanchors);
2793 else {
2794 pfctl_clear_tables(anchorname, opts);
2795 pfctl_clear_rules(dev, opts, anchorname);
2796 }
2797
2798 if (!*anchorname) {
2799 pfctl_clear_states(dev, ifaceopt, opts);
2800 pfctl_clear_src_nodes(dev, opts);
2801 pfctl_clear_stats(dev, ifaceopt, opts);
2802 pfctl_clear_fingerprints(dev, opts);
2803 pfctl_reset(dev, opts);
2804 }
2805 break;
2806 case 'o':
2807 pfctl_clear_fingerprints(dev, opts);
2808 break;
2809 case 'T':
2810 if ((opts & PF_OPT_RECURSE0x04000) == 0)
2811 pfctl_clear_tables(anchorname, opts);
2812 else
2813 pfctl_recurse(dev, opts, anchorname,
2814 pfctl_call_cleartables);
2815 break;
2816 case 'R':
2817 pfctl_reset(dev, opts);
2818 break;
2819 }
2820 }
2821 if (state_killers) {
21
Assuming 'state_killers' is not equal to 0
22
Taking true branch
2822 if (!strcmp(state_kill[0], "label"))
23
Assuming the condition is false
24
Taking false branch
2823 pfctl_label_kill_states(dev, ifaceopt, opts, rdomain);
2824 else if (!strcmp(state_kill[0], "id"))
25
Assuming the condition is false
26
Taking false branch
2825 pfctl_id_kill_states(dev, opts);
2826 else if (!strcmp(state_kill[0], "key"))
27
Taking true branch
2827 pfctl_key_kill_states(dev, ifaceopt, opts, rdomain);
28
Calling 'pfctl_key_kill_states'
2828 else
2829 pfctl_net_kill_states(dev, ifaceopt, opts, rdomain);
2830 }
2831
2832 if (src_node_killers)
2833 pfctl_kill_src_nodes(dev, opts);
2834
2835 if (tblcmdopt != NULL((void *)0)) {
2836 exit_val = pfctl_table(argc, argv, tableopt,
2837 tblcmdopt, rulesopt, anchorname, opts);
2838 rulesopt = NULL((void *)0);
2839 }
2840 if (optiopt != NULL((void *)0)) {
2841 switch (*optiopt) {
2842 case 'n':
2843 optimize = 0;
2844 break;
2845 case 'b':
2846 optimize |= PF_OPTIMIZE_BASIC0x0001;
2847 break;
2848 case 'o':
2849 case 'p':
2850 optimize |= PF_OPTIMIZE_PROFILE0x0002;
2851 break;
2852 }
2853 }
2854
2855 if (rulesopt != NULL((void *)0) && !anchorname[0]) {
2856 pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET0x00010);
2857 if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE"/etc/pf.os"))
2858 exit_val = 1;
2859 }
2860
2861 if (rulesopt != NULL((void *)0)) {
2862 if (pfctl_rules(dev, rulesopt, opts, optimize,
2863 anchorname, NULL((void *)0)))
2864 exit_val = 1;
2865 }
2866
2867 if (opts & PF_OPT_ENABLE0x00002)
2868 if (pfctl_enable(dev, opts))
2869 exit_val = 1;
2870
2871 if (debugopt != NULL((void *)0)) {
2872 if ((level = string_to_loglevel((char *)debugopt)) < 0) {
2873 switch (*debugopt) {
2874 case 'n':
2875 level = LOG_CRIT2;
2876 break;
2877 case 'u':
2878 level = LOG_ERR3;
2879 break;
2880 case 'm':
2881 level = LOG_NOTICE5;
2882 break;
2883 case 'l':
2884 level = LOG_DEBUG7;
2885 break;
2886 }
2887 }
2888 if (level >= 0)
2889 pfctl_debug(dev, level, opts);
2890 }
2891
2892 if (sfile != NULL((void *)0))
2893 pfctl_state_store(dev, sfile);
2894 if (lfile != NULL((void *)0))
2895 pfctl_state_load(dev, lfile);
2896
2897 exit(exit_val);
2898}
2899#endif /* REGRESS_NOMAIN */
2900
2901char *
2902pf_strerror(int errnum)
2903{
2904 switch (errnum) {
2905 case ESRCH3:
2906 return "Table does not exist";
2907 case EINVAL22:
2908 case ENOENT2:
2909 return "Anchor does not exist";
2910 default:
2911 return strerror(errnum);
2912 }
2913}