GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/pfctl/pfctl.c Lines: 534 1368 39.0 %
Date: 2017-11-13 Branches: 357 1019 35.0 %

Line Branch Exec Source
1
/*	$OpenBSD: pfctl.c,v 1.350 2017/09/26 20:23:32 sashan 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.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
55
#include <syslog.h>
56
57
#include "pfctl_parser.h"
58
#include "pfctl.h"
59
60
void	 usage(void);
61
int	 pfctl_enable(int, int);
62
int	 pfctl_disable(int, int);
63
void	 pfctl_clear_queues(struct pf_qihead *);
64
void	 pfctl_clear_stats(int, const char *, int);
65
void	 pfctl_clear_interface_flags(int, int);
66
void	 pfctl_clear_rules(int, int, char *);
67
void	 pfctl_clear_src_nodes(int, int);
68
void	 pfctl_clear_states(int, const char *, int);
69
void	 pfctl_addrprefix(char *, struct pf_addr *);
70
void	 pfctl_kill_src_nodes(int, const char *, int);
71
void	 pfctl_net_kill_states(int, const char *, int, int);
72
void	 pfctl_label_kill_states(int, const char *, int, int);
73
void	 pfctl_id_kill_states(int, int);
74
void	 pfctl_key_kill_states(int, const char *, int, int);
75
int	 pfctl_parse_host(char *, struct pf_rule_addr *);
76
void	 pfctl_init_options(struct pfctl *);
77
int	 pfctl_load_options(struct pfctl *);
78
int	 pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
79
int	 pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int);
80
int	 pfctl_load_debug(struct pfctl *, unsigned int);
81
int	 pfctl_load_logif(struct pfctl *, char *);
82
int	 pfctl_load_hostid(struct pfctl *, unsigned int);
83
int	 pfctl_load_reassembly(struct pfctl *, u_int32_t);
84
void	 pfctl_print_rule_counters(struct pf_rule *, int);
85
int	 pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int,
86
	    long);
87
int	 pfctl_show_src_nodes(int, int);
88
int	 pfctl_show_states(int, const char *, int, long);
89
int	 pfctl_show_status(int, int);
90
int	 pfctl_show_timeouts(int, int);
91
int	 pfctl_show_limits(int, int);
92
void	 pfctl_debug(int, u_int32_t, int);
93
int	 pfctl_show_anchors(int, int, char *);
94
int	 pfctl_ruleset_trans(struct pfctl *, char *, struct pf_anchor *);
95
u_int	 pfctl_find_childqs(struct pfctl_qsitem *);
96
void	 pfctl_load_queue(struct pfctl *, u_int32_t, struct pfctl_qsitem *);
97
int	 pfctl_load_queues(struct pfctl *);
98
u_int	 pfctl_leafqueue_check(char *);
99
u_int	 pfctl_check_qassignments(struct pf_ruleset *);
100
int	 pfctl_load_ruleset(struct pfctl *, char *, struct pf_ruleset *, int);
101
int	 pfctl_load_rule(struct pfctl *, char *, struct pf_rule *, int);
102
const char	*pfctl_lookup_option(char *, const char **);
103
void	pfctl_state_store(int, const char *);
104
void	pfctl_state_load(int, const char *);
105
106
struct pf_anchor_global	 pf_anchors;
107
struct pf_anchor	 pf_main_anchor;
108
109
const char	*clearopt;
110
char		*rulesopt;
111
const char	*showopt;
112
const char	*debugopt;
113
char		*anchoropt;
114
const char	*optiopt = NULL;
115
char		*pf_device = "/dev/pf";
116
char		*ifaceopt;
117
char		*tableopt;
118
const char	*tblcmdopt;
119
int		 src_node_killers;
120
char		*src_node_kill[2];
121
int		 state_killers;
122
char		*state_kill[2];
123
124
int		 dev = -1;
125
int		 first_title = 1;
126
int		 labels = 0;
127
128
#define INDENT(d, o)	do {						\
129
				if (o) {				\
130
					int i;				\
131
					for (i=0; i < d; i++)		\
132
						printf("  ");		\
133
				}					\
134
			} while (0)					\
135
136
137
static const struct {
138
	const char	*name;
139
	int		index;
140
} pf_limits[] = {
141
	{ "states",		PF_LIMIT_STATES },
142
	{ "src-nodes",		PF_LIMIT_SRC_NODES },
143
	{ "frags",		PF_LIMIT_FRAGS },
144
	{ "tables",		PF_LIMIT_TABLES },
145
	{ "table-entries",	PF_LIMIT_TABLE_ENTRIES },
146
	{ NULL,			0 }
147
};
148
149
struct pf_hint {
150
	const char	*name;
151
	int		timeout;
152
};
153
static const struct pf_hint pf_hint_normal[] = {
154
	{ "tcp.first",		2 * 60 },
155
	{ "tcp.opening",	30 },
156
	{ "tcp.established",	24 * 60 * 60 },
157
	{ "tcp.closing",	15 * 60 },
158
	{ "tcp.finwait",	45 },
159
	{ "tcp.closed",		90 },
160
	{ "tcp.tsdiff",		30 },
161
	{ NULL,			0 }
162
};
163
static const struct pf_hint pf_hint_satellite[] = {
164
	{ "tcp.first",		3 * 60 },
165
	{ "tcp.opening",	30 + 5 },
166
	{ "tcp.established",	24 * 60 * 60 },
167
	{ "tcp.closing",	15 * 60 + 5 },
168
	{ "tcp.finwait",	45 + 5 },
169
	{ "tcp.closed",		90 + 5 },
170
	{ "tcp.tsdiff",		60 },
171
	{ NULL,			0 }
172
};
173
static const struct pf_hint pf_hint_conservative[] = {
174
	{ "tcp.first",		60 * 60 },
175
	{ "tcp.opening",	15 * 60 },
176
	{ "tcp.established",	5 * 24 * 60 * 60 },
177
	{ "tcp.closing",	60 * 60 },
178
	{ "tcp.finwait",	10 * 60 },
179
	{ "tcp.closed",		3 * 60 },
180
	{ "tcp.tsdiff",		60 },
181
	{ NULL,			0 }
182
};
183
static const struct pf_hint pf_hint_aggressive[] = {
184
	{ "tcp.first",		30 },
185
	{ "tcp.opening",	5 },
186
	{ "tcp.established",	5 * 60 * 60 },
187
	{ "tcp.closing",	60 },
188
	{ "tcp.finwait",	30 },
189
	{ "tcp.closed",		30 },
190
	{ "tcp.tsdiff",		10 },
191
	{ NULL,			0 }
192
};
193
194
static const struct {
195
	const char *name;
196
	const struct pf_hint *hint;
197
} pf_hints[] = {
198
	{ "normal",		pf_hint_normal },
199
	{ "satellite",		pf_hint_satellite },
200
	{ "high-latency",	pf_hint_satellite },
201
	{ "conservative",	pf_hint_conservative },
202
	{ "aggressive",		pf_hint_aggressive },
203
	{ NULL,			NULL }
204
};
205
206
static const char *clearopt_list[] = {
207
	"rules", "Sources", "states", "info", "Tables", "osfp", "all", NULL
208
};
209
210
static const char *showopt_list[] = {
211
	"queue", "rules", "Anchors", "Sources", "states", "info",
212
	"Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
213
	"all", NULL
214
};
215
216
static const char *tblcmdopt_list[] = {
217
	"kill", "flush", "add", "delete", "replace", "show",
218
	"test", "zero", "expire", NULL
219
};
220
221
static const char *debugopt_list[] = {
222
	"debug", "info", "notice", "warning",
223
	"error", "crit", "alert", "emerg",
224
	NULL
225
};
226
227
static const char *optiopt_list[] = {
228
	"none", "basic", "profile", NULL
229
};
230
231
struct pf_qihead qspecs = TAILQ_HEAD_INITIALIZER(qspecs);
232
struct pf_qihead rootqs = TAILQ_HEAD_INITIALIZER(rootqs);
233
234
235
__dead void
236
usage(void)
237
{
238
	extern char *__progname;
239
240
	fprintf(stderr, "usage: %s [-deghNnPqrvz] ", __progname);
241
	fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]");
242
	fprintf(stderr, " [-f file]\n");
243
	fprintf(stderr, "\t[-i interface] [-K key] [-k key] [-L statefile]");
244
	fprintf(stderr, " [-o level]\n");
245
	fprintf(stderr, "\t[-p device] [-S statefile] [-s modifier [-R id]]\n");
246
	fprintf(stderr, "\t[-t table -T command [address ...]]");
247
	fprintf(stderr, " [-V rdomain] [-x level]\n");
248
	exit(1);
249
}
250
251
int
252
pfctl_enable(int dev, int opts)
253
{
254
	if (ioctl(dev, DIOCSTART)) {
255
		if (errno == EEXIST)
256
			errx(1, "pf already enabled");
257
		else
258
			err(1, "DIOCSTART");
259
	}
260
	if ((opts & PF_OPT_QUIET) == 0)
261
		fprintf(stderr, "pf enabled\n");
262
263
	return (0);
264
}
265
266
int
267
pfctl_disable(int dev, int opts)
268
{
269
	if (ioctl(dev, DIOCSTOP)) {
270
		if (errno == ENOENT)
271
			errx(1, "pf not enabled");
272
		else
273
			err(1, "DIOCSTOP");
274
	}
275
	if ((opts & PF_OPT_QUIET) == 0)
276
		fprintf(stderr, "pf disabled\n");
277
278
	return (0);
279
}
280
281
void
282
pfctl_clear_stats(int dev, const char *iface, int opts)
283
{
284
	struct pfioc_iface pi;
285
286
	memset(&pi, 0, sizeof(pi));
287
	if (iface != NULL && strlcpy(pi.pfiio_name, iface,
288
	    sizeof(pi.pfiio_name)) >= sizeof(pi.pfiio_name))
289
		errx(1, "invalid interface: %s", iface);
290
291
	if (ioctl(dev, DIOCCLRSTATUS, &pi))
292
		err(1, "DIOCCLRSTATUS");
293
	if ((opts & PF_OPT_QUIET) == 0) {
294
		fprintf(stderr, "pf: statistics cleared");
295
		if (iface != NULL)
296
			fprintf(stderr, " for interface %s", iface);
297
		fprintf(stderr, "\n");
298
	}
299
}
300
301
void
302
pfctl_clear_interface_flags(int dev, int opts)
303
{
304
558
	struct pfioc_iface	pi;
305
306
279
	if ((opts & PF_OPT_NOACTION) == 0) {
307
		bzero(&pi, sizeof(pi));
308
		pi.pfiio_flags = PFI_IFLAG_SKIP;
309
310
		if (ioctl(dev, DIOCCLRIFFLAG, &pi))
311
			err(1, "DIOCCLRIFFLAG");
312
		if ((opts & PF_OPT_QUIET) == 0)
313
			fprintf(stderr, "pf: interface flags reset\n");
314
	}
315
279
}
316
317
void
318
pfctl_clear_rules(int dev, int opts, char *anchorname)
319
{
320
344
	struct pfr_buffer t;
321
322
172
	memset(&t, 0, sizeof(t));
323
172
	t.pfrb_type = PFRB_TRANS;
324

344
	if (pfctl_add_trans(&t, PF_TRANS_RULESET, anchorname) ||
325
172
	    pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
326
172
	    pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
327
		err(1, "pfctl_clear_rules");
328
172
	if ((opts & PF_OPT_QUIET) == 0)
329
142
		fprintf(stderr, "rules cleared\n");
330
172
}
331
332
void
333
pfctl_clear_src_nodes(int dev, int opts)
334
{
335
	if (ioctl(dev, DIOCCLRSRCNODES))
336
		err(1, "DIOCCLRSRCNODES");
337
	if ((opts & PF_OPT_QUIET) == 0)
338
		fprintf(stderr, "source tracking entries cleared\n");
339
}
340
341
void
342
pfctl_clear_states(int dev, const char *iface, int opts)
343
{
344
	struct pfioc_state_kill psk;
345
346
	memset(&psk, 0, sizeof(psk));
347
	if (iface != NULL && strlcpy(psk.psk_ifname, iface,
348
	    sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
349
		errx(1, "invalid interface: %s", iface);
350
351
	if (ioctl(dev, DIOCCLRSTATES, &psk))
352
		err(1, "DIOCCLRSTATES");
353
	if ((opts & PF_OPT_QUIET) == 0)
354
		fprintf(stderr, "%d states cleared\n", psk.psk_killed);
355
}
356
357
void
358
pfctl_addrprefix(char *addr, struct pf_addr *mask)
359
{
360
	char *p;
361
	const char *errstr;
362
	int prefix, ret_ga, q, r;
363
	struct addrinfo hints, *res;
364
365
	if ((p = strchr(addr, '/')) == NULL)
366
		return;
367
368
	*p++ = '\0';
369
	prefix = strtonum(p, 0, 128, &errstr);
370
	if (errstr)
371
		errx(1, "prefix is %s: %s", errstr, p);
372
373
	bzero(&hints, sizeof(hints));
374
	/* prefix only with numeric addresses */
375
	hints.ai_flags |= AI_NUMERICHOST;
376
377
	if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) {
378
		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
379
		/* NOTREACHED */
380
	}
381
382
	if (res->ai_family == AF_INET && prefix > 32)
383
		errx(1, "prefix too long for AF_INET");
384
	else if (res->ai_family == AF_INET6 && prefix > 128)
385
		errx(1, "prefix too long for AF_INET6");
386
387
	q = prefix >> 3;
388
	r = prefix & 7;
389
	switch (res->ai_family) {
390
	case AF_INET:
391
		bzero(&mask->v4, sizeof(mask->v4));
392
		mask->v4.s_addr = htonl((u_int32_t)
393
		    (0xffffffffffULL << (32 - prefix)));
394
		break;
395
	case AF_INET6:
396
		bzero(&mask->v6, sizeof(mask->v6));
397
		if (q > 0)
398
			memset((void *)&mask->v6, 0xff, q);
399
		if (r > 0)
400
			*((u_char *)&mask->v6 + q) =
401
			    (0xff00 >> r) & 0xff;
402
		break;
403
	}
404
	freeaddrinfo(res);
405
}
406
407
void
408
pfctl_kill_src_nodes(int dev, const char *iface, int opts)
409
{
410
	struct pfioc_src_node_kill psnk;
411
	struct addrinfo *res[2], *resp[2];
412
	struct sockaddr last_src, last_dst;
413
	int killed, sources, dests;
414
	int ret_ga;
415
416
	killed = sources = dests = 0;
417
418
	memset(&psnk, 0, sizeof(psnk));
419
	memset(&psnk.psnk_src.addr.v.a.mask, 0xff,
420
	    sizeof(psnk.psnk_src.addr.v.a.mask));
421
	memset(&last_src, 0xff, sizeof(last_src));
422
	memset(&last_dst, 0xff, sizeof(last_dst));
423
424
	pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask);
425
426
	if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) {
427
		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
428
		/* NOTREACHED */
429
	}
430
	for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
431
		if (resp[0]->ai_addr == NULL)
432
			continue;
433
		/* We get lots of duplicates.  Catch the easy ones */
434
		if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
435
			continue;
436
		last_src = *(struct sockaddr *)resp[0]->ai_addr;
437
438
		psnk.psnk_af = resp[0]->ai_family;
439
		sources++;
440
441
		if (psnk.psnk_af == AF_INET)
442
			psnk.psnk_src.addr.v.a.addr.v4 =
443
			    ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
444
		else if (psnk.psnk_af == AF_INET6)
445
			psnk.psnk_src.addr.v.a.addr.v6 =
446
			    ((struct sockaddr_in6 *)resp[0]->ai_addr)->
447
			    sin6_addr;
448
		else
449
			errx(1, "Unknown address family %d", psnk.psnk_af);
450
451
		if (src_node_killers > 1) {
452
			dests = 0;
453
			memset(&psnk.psnk_dst.addr.v.a.mask, 0xff,
454
			    sizeof(psnk.psnk_dst.addr.v.a.mask));
455
			memset(&last_dst, 0xff, sizeof(last_dst));
456
			pfctl_addrprefix(src_node_kill[1],
457
			    &psnk.psnk_dst.addr.v.a.mask);
458
			if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL,
459
			    &res[1]))) {
460
				errx(1, "getaddrinfo: %s",
461
				    gai_strerror(ret_ga));
462
				/* NOTREACHED */
463
			}
464
			for (resp[1] = res[1]; resp[1];
465
			    resp[1] = resp[1]->ai_next) {
466
				if (resp[1]->ai_addr == NULL)
467
					continue;
468
				if (psnk.psnk_af != resp[1]->ai_family)
469
					continue;
470
471
				if (memcmp(&last_dst, resp[1]->ai_addr,
472
				    sizeof(last_dst)) == 0)
473
					continue;
474
				last_dst = *(struct sockaddr *)resp[1]->ai_addr;
475
476
				dests++;
477
478
				if (psnk.psnk_af == AF_INET)
479
					psnk.psnk_dst.addr.v.a.addr.v4 =
480
					    ((struct sockaddr_in *)resp[1]->
481
					    ai_addr)->sin_addr;
482
				else if (psnk.psnk_af == AF_INET6)
483
					psnk.psnk_dst.addr.v.a.addr.v6 =
484
					    ((struct sockaddr_in6 *)resp[1]->
485
					    ai_addr)->sin6_addr;
486
				else
487
					errx(1, "Unknown address family %d",
488
					    psnk.psnk_af);
489
490
				if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
491
					err(1, "DIOCKILLSRCNODES");
492
				killed += psnk.psnk_killed;
493
			}
494
			freeaddrinfo(res[1]);
495
		} else {
496
			if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
497
				err(1, "DIOCKILLSRCNODES");
498
			killed += psnk.psnk_killed;
499
		}
500
	}
501
502
	freeaddrinfo(res[0]);
503
504
	if ((opts & PF_OPT_QUIET) == 0)
505
		fprintf(stderr, "killed %d src nodes from %d sources and %d "
506
		    "destinations\n", killed, sources, dests);
507
}
508
509
void
510
pfctl_net_kill_states(int dev, const char *iface, int opts, int rdomain)
511
{
512
	struct pfioc_state_kill psk;
513
	struct addrinfo *res[2], *resp[2];
514
	struct sockaddr last_src, last_dst;
515
	int killed, sources, dests;
516
	int ret_ga;
517
518
	killed = sources = dests = 0;
519
520
	memset(&psk, 0, sizeof(psk));
521
	memset(&psk.psk_src.addr.v.a.mask, 0xff,
522
	    sizeof(psk.psk_src.addr.v.a.mask));
523
	memset(&last_src, 0xff, sizeof(last_src));
524
	memset(&last_dst, 0xff, sizeof(last_dst));
525
	if (iface != NULL && strlcpy(psk.psk_ifname, iface,
526
	    sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
527
		errx(1, "invalid interface: %s", iface);
528
529
	psk.psk_rdomain = rdomain;
530
531
	pfctl_addrprefix(state_kill[0], &psk.psk_src.addr.v.a.mask);
532
533
	if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) {
534
		errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
535
		/* NOTREACHED */
536
	}
537
	for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
538
		if (resp[0]->ai_addr == NULL)
539
			continue;
540
		/* We get lots of duplicates.  Catch the easy ones */
541
		if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0)
542
			continue;
543
		last_src = *(struct sockaddr *)resp[0]->ai_addr;
544
545
		psk.psk_af = resp[0]->ai_family;
546
		sources++;
547
548
		if (psk.psk_af == AF_INET)
549
			psk.psk_src.addr.v.a.addr.v4 =
550
			    ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
551
		else if (psk.psk_af == AF_INET6)
552
			psk.psk_src.addr.v.a.addr.v6 =
553
			    ((struct sockaddr_in6 *)resp[0]->ai_addr)->
554
			    sin6_addr;
555
		else
556
			errx(1, "Unknown address family %d", psk.psk_af);
557
558
		if (state_killers > 1) {
559
			dests = 0;
560
			memset(&psk.psk_dst.addr.v.a.mask, 0xff,
561
			    sizeof(psk.psk_dst.addr.v.a.mask));
562
			memset(&last_dst, 0xff, sizeof(last_dst));
563
			pfctl_addrprefix(state_kill[1],
564
			    &psk.psk_dst.addr.v.a.mask);
565
			if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL,
566
			    &res[1]))) {
567
				errx(1, "getaddrinfo: %s",
568
				    gai_strerror(ret_ga));
569
				/* NOTREACHED */
570
			}
571
			for (resp[1] = res[1]; resp[1];
572
			    resp[1] = resp[1]->ai_next) {
573
				if (resp[1]->ai_addr == NULL)
574
					continue;
575
				if (psk.psk_af != resp[1]->ai_family)
576
					continue;
577
578
				if (memcmp(&last_dst, resp[1]->ai_addr,
579
				    sizeof(last_dst)) == 0)
580
					continue;
581
				last_dst = *(struct sockaddr *)resp[1]->ai_addr;
582
583
				dests++;
584
585
				if (psk.psk_af == AF_INET)
586
					psk.psk_dst.addr.v.a.addr.v4 =
587
					    ((struct sockaddr_in *)resp[1]->
588
					    ai_addr)->sin_addr;
589
				else if (psk.psk_af == AF_INET6)
590
					psk.psk_dst.addr.v.a.addr.v6 =
591
					    ((struct sockaddr_in6 *)resp[1]->
592
					    ai_addr)->sin6_addr;
593
				else
594
					errx(1, "Unknown address family %d",
595
					    psk.psk_af);
596
597
				if (ioctl(dev, DIOCKILLSTATES, &psk))
598
					err(1, "DIOCKILLSTATES");
599
				killed += psk.psk_killed;
600
			}
601
			freeaddrinfo(res[1]);
602
		} else {
603
			if (ioctl(dev, DIOCKILLSTATES, &psk))
604
				err(1, "DIOCKILLSTATES");
605
			killed += psk.psk_killed;
606
		}
607
	}
608
609
	freeaddrinfo(res[0]);
610
611
	if ((opts & PF_OPT_QUIET) == 0)
612
		fprintf(stderr, "killed %d states from %d sources and %d "
613
		    "destinations\n", killed, sources, dests);
614
}
615
616
void
617
pfctl_label_kill_states(int dev, const char *iface, int opts, int rdomain)
618
{
619
	struct pfioc_state_kill psk;
620
621
	if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
622
		warnx("no label specified");
623
		usage();
624
	}
625
	memset(&psk, 0, sizeof(psk));
626
	if (iface != NULL && strlcpy(psk.psk_ifname, iface,
627
	    sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
628
		errx(1, "invalid interface: %s", iface);
629
630
	if (strlcpy(psk.psk_label, state_kill[1], sizeof(psk.psk_label)) >=
631
	    sizeof(psk.psk_label))
632
		errx(1, "label too long: %s", state_kill[1]);
633
634
	psk.psk_rdomain = rdomain;
635
636
	if (ioctl(dev, DIOCKILLSTATES, &psk))
637
		err(1, "DIOCKILLSTATES");
638
639
	if ((opts & PF_OPT_QUIET) == 0)
640
		fprintf(stderr, "killed %d states\n", psk.psk_killed);
641
}
642
643
void
644
pfctl_id_kill_states(int dev, int opts)
645
{
646
	struct pfioc_state_kill psk;
647
648
	if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
649
		warnx("no id specified");
650
		usage();
651
	}
652
653
	memset(&psk, 0, sizeof(psk));
654
	if ((sscanf(state_kill[1], "%llx/%x",
655
	    &psk.psk_pfcmp.id, &psk.psk_pfcmp.creatorid)) == 2)
656
		HTONL(psk.psk_pfcmp.creatorid);
657
	else if ((sscanf(state_kill[1], "%llx", &psk.psk_pfcmp.id)) == 1) {
658
		psk.psk_pfcmp.creatorid = 0;
659
	} else {
660
		warnx("wrong id format specified");
661
		usage();
662
	}
663
	if (psk.psk_pfcmp.id == 0) {
664
		warnx("cannot kill id 0");
665
		usage();
666
	}
667
668
	psk.psk_pfcmp.id = htobe64(psk.psk_pfcmp.id);
669
	if (ioctl(dev, DIOCKILLSTATES, &psk))
670
		err(1, "DIOCKILLSTATES");
671
672
	if ((opts & PF_OPT_QUIET) == 0)
673
		fprintf(stderr, "killed %d states\n", psk.psk_killed);
674
}
675
676
void
677
pfctl_key_kill_states(int dev, const char *iface, int opts, int rdomain)
678
{
679
	struct pfioc_state_kill psk;
680
	char *s, *token, *tokens[4];
681
	struct protoent *p;
682
	u_int i, sidx, didx;
683
684
	if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
685
		warnx("no key specified");
686
		usage();
687
	}
688
	memset(&psk, 0, sizeof(psk));
689
690
	if (iface != NULL && strlcpy(psk.psk_ifname, iface,
691
	    sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
692
		errx(1, "invalid interface: %s", iface);
693
694
	psk.psk_rdomain = rdomain;
695
696
	s = strdup(state_kill[1]);
697
	if (!s)
698
		errx(1, "pfctl_key_kill_states: strdup");
699
	i = 0;
700
	while ((token = strsep(&s, " \t")) != NULL)
701
		if (*token != '\0') {
702
			if (i < 4)
703
				tokens[i] = token;
704
			i++;
705
		}
706
	if (i != 4)
707
		errx(1, "pfctl_key_kill_states: key must be "
708
		    "\"protocol host1:port1 direction host2:port2\" format");
709
710
	if ((p = getprotobyname(tokens[0])) == NULL)
711
		errx(1, "invalid protocol: %s", tokens[0]);
712
	psk.psk_proto = p->p_proto;
713
714
	if (strcmp(tokens[2], "->") == 0) {
715
		sidx = 1;
716
		didx = 3;
717
	} else if (strcmp(tokens[2], "<-") == 0) {
718
		sidx = 3;
719
		didx = 1;
720
	} else
721
		errx(1, "invalid direction: %s", tokens[2]);
722
723
	if (pfctl_parse_host(tokens[sidx], &psk.psk_src) == -1)
724
		errx(1, "invalid host: %s", tokens[sidx]);
725
	if (pfctl_parse_host(tokens[didx], &psk.psk_dst) == -1)
726
		errx(1, "invalid host: %s", tokens[didx]);
727
728
	if (ioctl(dev, DIOCKILLSTATES, &psk))
729
		err(1, "DIOCKILLSTATES");
730
731
	if ((opts & PF_OPT_QUIET) == 0)
732
		fprintf(stderr, "killed %d states\n", psk.psk_killed);
733
}
734
735
int
736
pfctl_parse_host(char *str, struct pf_rule_addr *addr)
737
{
738
	char *s = NULL, *sbs, *sbe;
739
	struct addrinfo hints, *ai;
740
	struct sockaddr_in *sin4;
741
	struct sockaddr_in6 *sin6;
742
743
	s = strdup(str);
744
	if (!s)
745
		errx(1, "pfctl_parse_host: strdup");
746
747
	memset(&hints, 0, sizeof(hints));
748
	hints.ai_socktype = SOCK_DGRAM;	/* dummy */
749
	hints.ai_flags = AI_NUMERICHOST;
750
751
	if ((sbs = strchr(s, '[')) != NULL && (sbe = strrchr(s, ']')) != NULL) {
752
		hints.ai_family = AF_INET6;
753
		*(sbs++) = *sbe = '\0';
754
	} else if ((sbs = strchr(s, ':')) != NULL) {
755
		hints.ai_family = AF_INET;
756
		*(sbs++) = '\0';
757
	} else
758
		goto error;
759
760
	if (getaddrinfo(s, sbs, &hints, &ai) != 0)
761
		goto error;
762
763
	switch (ai->ai_family) {
764
	case AF_INET:
765
		sin4 = (struct sockaddr_in *)ai->ai_addr;
766
		addr->addr.v.a.addr.v4 = sin4->sin_addr;
767
		addr->port[0] = sin4->sin_port;
768
		break;
769
770
	case AF_INET6:
771
		sin6 = (struct sockaddr_in6 *)ai->ai_addr;
772
		addr->addr.v.a.addr.v6 = sin6->sin6_addr;
773
		addr->port[0] = sin6->sin6_port;
774
		break;
775
	}
776
	freeaddrinfo(ai);
777
	free(s);
778
779
	memset(&addr->addr.v.a.mask, 0xff, sizeof(struct pf_addr));
780
	addr->port_op = PF_OP_EQ;
781
	addr->addr.type = PF_ADDR_ADDRMASK;
782
783
	return (0);
784
785
 error:
786
	free(s);
787
	return (-1);
788
}
789
790
void
791
pfctl_print_rule_counters(struct pf_rule *rule, int opts)
792
{
793
2952
	if (opts & PF_OPT_DEBUG) {
794
1476
		const char *t[PF_SKIP_COUNT] = { "i", "d", "r", "f",
795
		    "p", "sa", "da", "sp", "dp" };
796
		int i;
797
798
1476
		printf("  [ Skip steps: ");
799
29520
		for (i = 0; i < PF_SKIP_COUNT; ++i) {
800
13284
			if (rule->skip[i].nr == rule->nr + 1)
801
				continue;
802
11027
			printf("%s=", t[i]);
803
11027
			if (rule->skip[i].nr == -1)
804
8256
				printf("end ");
805
			else
806
2771
				printf("%u ", rule->skip[i].nr);
807
		}
808
1476
		printf("]\n");
809
810
1476
		printf("  [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
811
1476
		    rule->qname, rule->qid, rule->pqname, rule->pqid);
812
1476
	}
813
1476
	if (opts & PF_OPT_VERBOSE) {
814
1476
		printf("  [ Evaluations: %-8llu  Packets: %-8llu  "
815
			    "Bytes: %-10llu  States: %-6u]\n",
816
1476
			    (unsigned long long)rule->evaluations,
817
2952
			    (unsigned long long)(rule->packets[0] +
818
1476
			    rule->packets[1]),
819
2952
			    (unsigned long long)(rule->bytes[0] +
820
2952
			    rule->bytes[1]), rule->states_cur);
821
1476
		if (!(opts & PF_OPT_DEBUG))
822
			printf("  [ Inserted: uid %lu pid %lu "
823
			    "State Creations: %-6u]\n",
824
			    (unsigned long)rule->cuid, (unsigned long)rule->cpid,
825
			    rule->states_tot);
826
	}
827
1476
}
828
829
void
830
pfctl_print_title(char *title)
831
{
832
	if (!first_title)
833
		printf("\n");
834
	first_title = 0;
835
	printf("%s\n", title);
836
}
837
838
int
839
pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
840
    char *anchorname, int depth, int wildcard, long shownr)
841
{
842
354
	struct pfioc_rule pr;
843
	u_int32_t nr, mnr, header = 0;
844
177
	int len = strlen(path), ret = 0;
845
	char *npath, *p;
846
847
	/*
848
	 * Truncate a trailing / and * on an anchorname before searching for
849
	 * the ruleset, this is syntactic sugar that doesn't actually make it
850
	 * to the kernel.
851
	 */
852

179
	if ((p = strrchr(anchorname, '/')) != NULL &&
853
8
	    p[1] == '*' && p[2] == '\0') {
854
2
		p[0] = '\0';
855
2
	}
856
857
177
	memset(&pr, 0, sizeof(pr));
858
177
	if (anchorname[0] == '/') {
859
2
		if ((npath = calloc(1, PATH_MAX)) == NULL)
860
			err(1, "calloc");
861
2
		strlcpy(npath, anchorname, PATH_MAX);
862
2
	} else {
863
175
		if (path[0])
864
33
			snprintf(&path[len], PATH_MAX - len, "/%s", anchorname);
865
		else
866
142
			snprintf(&path[len], PATH_MAX - len, "%s", anchorname);
867
		npath = path;
868
	}
869
870
177
	memcpy(pr.anchor, npath, sizeof(pr.anchor));
871
177
	if (opts & PF_OPT_SHOWALL) {
872
		pr.rule.action = PF_PASS;
873
		if (ioctl(dev, DIOCGETRULES, &pr)) {
874
			warn("DIOCGETRULES");
875
			ret = -1;
876
			goto error;
877
		}
878
		header++;
879
		if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header))
880
			pfctl_print_title("FILTER RULES:");
881
		else if (format == PFCTL_SHOW_LABELS && labels)
882
			pfctl_print_title("LABEL COUNTERS:");
883
	}
884
177
	if (opts & PF_OPT_CLRRULECTRS)
885
		pr.action = PF_GET_CLR_CNTR;
886
887
177
	pr.rule.action = PF_PASS;
888
177
	if (ioctl(dev, DIOCGETRULES, &pr)) {
889
		warn("DIOCGETRULES");
890
		ret = -1;
891
		goto error;
892
	}
893
894
177
	if (shownr < 0) {
895
177
		mnr = pr.nr;
896
		nr = 0;
897
177
	} else if (shownr < pr.nr) {
898
		nr = shownr;
899
		mnr = shownr + 1;
900
	} else {
901
		warnx("rule %ld not found", shownr);
902
		ret = -1;
903
		goto error;
904
	}
905
3306
	for (; nr < mnr; ++nr) {
906
1476
		pr.nr = nr;
907
1476
		if (ioctl(dev, DIOCGETRULE, &pr)) {
908
			warn("DIOCGETRULE");
909
			ret = -1;
910
			goto error;
911
		}
912
913
		/* anchor is the same for all rules in it */
914
1476
		if (pr.rule.anchor_wildcard == 0)
915
1472
			wildcard = 0;
916
917
2952
		switch (format) {
918
		case PFCTL_SHOW_LABELS:
919
			if (pr.rule.label[0]) {
920
				INDENT(depth, !(opts & PF_OPT_VERBOSE));
921
				printf("%s %llu %llu %llu %llu"
922
				    " %llu %llu %llu %llu\n",
923
				    pr.rule.label,
924
				    (unsigned long long)pr.rule.evaluations,
925
				    (unsigned long long)(pr.rule.packets[0] +
926
				    pr.rule.packets[1]),
927
				    (unsigned long long)(pr.rule.bytes[0] +
928
				    pr.rule.bytes[1]),
929
				    (unsigned long long)pr.rule.packets[0],
930
				    (unsigned long long)pr.rule.bytes[0],
931
				    (unsigned long long)pr.rule.packets[1],
932
				    (unsigned long long)pr.rule.bytes[1],
933
				    (unsigned long long)pr.rule.states_tot);
934
			}
935
			break;
936
		case PFCTL_SHOW_RULES:
937

1626
			if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
938
				labels = 1;
939

1476
			INDENT(depth, !(opts & PF_OPT_VERBOSE));
940
1476
			print_rule(&pr.rule, pr.anchor_call, opts);
941
942
			/*
943
			 * If this is an 'unnamed' brace notation anchor OR
944
			 * the user has explicitly requested recursion,
945
			 * print it recursively.
946
			 */
947

1495
       		        if (pr.anchor_call[0] &&
948
53
			    (((p = strrchr(pr.anchor_call, '/')) ?
949

86
			    p[1] == '_' : pr.anchor_call[0] == '_') ||
950
19
			    opts & PF_OPT_RECURSE)) {
951
35
				printf(" {\n");
952
35
				pfctl_print_rule_counters(&pr.rule, opts);
953
35
				pfctl_show_rules(dev, npath, opts, format,
954
35
				    pr.anchor_call, depth + 1,
955
35
				    pr.rule.anchor_wildcard, -1);
956

35
				INDENT(depth, !(opts & PF_OPT_VERBOSE));
957
35
				printf("}\n");
958
35
			} else {
959
1441
				printf("\n");
960
1441
				pfctl_print_rule_counters(&pr.rule, opts);
961
			}
962
			break;
963
		case PFCTL_SHOW_NOTHING:
964
			break;
965
		}
966
	}
967
968
	/*
969
	 * If this anchor was called with a wildcard path, go through
970
	 * the rulesets in the anchor rather than the rules.
971
	 */
972

179
	if (wildcard && (opts & PF_OPT_RECURSE)) {
973
2
		struct pfioc_ruleset	 prs;
974
		u_int32_t		 mnr, nr;
975
976
2
		memset(&prs, 0, sizeof(prs));
977
2
		memcpy(prs.path, npath, sizeof(prs.path));
978
2
		if (ioctl(dev, DIOCGETRULESETS, &prs)) {
979
			if (errno == EINVAL)
980
				fprintf(stderr, "Anchor '%s' "
981
				    "not found.\n", anchorname);
982
			else
983
				err(1, "DIOCGETRULESETS");
984
		}
985
2
		mnr = prs.nr;
986
987
4
		for (nr = 0; nr < mnr; ++nr) {
988
			prs.nr = nr;
989
			if (ioctl(dev, DIOCGETRULESET, &prs))
990
				err(1, "DIOCGETRULESET");
991
			INDENT(depth, !(opts & PF_OPT_VERBOSE));
992
			printf("anchor \"%s\" all {\n", prs.name);
993
			pfctl_show_rules(dev, npath, opts,
994
			    format, prs.name, depth + 1, 0, shownr);
995
			INDENT(depth, !(opts & PF_OPT_VERBOSE));
996
			printf("}\n");
997
		}
998
2
		path[len] = '\0';
999
		return (0);
1000
2
	}
1001
1002
 error:
1003
175
	if (path != npath)
1004
2
		free(npath);
1005
175
	path[len] = '\0';
1006
175
	return (ret);
1007
177
}
1008
1009
int
1010
pfctl_show_src_nodes(int dev, int opts)
1011
{
1012
	struct pfioc_src_nodes psn;
1013
	struct pf_src_node *p;
1014
	char *inbuf = NULL, *newinbuf = NULL;
1015
	unsigned int len = 0;
1016
	int i;
1017
1018
	memset(&psn, 0, sizeof(psn));
1019
	for (;;) {
1020
		psn.psn_len = len;
1021
		if (len) {
1022
			newinbuf = realloc(inbuf, len);
1023
			if (newinbuf == NULL)
1024
				err(1, "realloc");
1025
			psn.psn_buf = inbuf = newinbuf;
1026
		}
1027
		if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) {
1028
			warn("DIOCGETSRCNODES");
1029
			free(inbuf);
1030
			return (-1);
1031
		}
1032
		if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len)
1033
			break;
1034
		if (len == 0 && psn.psn_len == 0)
1035
			goto done;
1036
		if (len == 0 && psn.psn_len != 0)
1037
			len = psn.psn_len;
1038
		if (psn.psn_len == 0)
1039
			goto done;	/* no src_nodes */
1040
		len *= 2;
1041
	}
1042
	p = psn.psn_src_nodes;
1043
	if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL))
1044
		pfctl_print_title("SOURCE TRACKING NODES:");
1045
	for (i = 0; i < psn.psn_len; i += sizeof(*p)) {
1046
		print_src_node(p, opts);
1047
		p++;
1048
	}
1049
done:
1050
	free(inbuf);
1051
	return (0);
1052
}
1053
1054
int
1055
pfctl_show_states(int dev, const char *iface, int opts, long shownr)
1056
{
1057
	struct pfioc_states ps;
1058
	struct pfsync_state *p;
1059
	char *inbuf = NULL, *newinbuf = NULL;
1060
	unsigned int len = 0;
1061
	int i, dotitle = (opts & PF_OPT_SHOWALL);
1062
1063
	memset(&ps, 0, sizeof(ps));
1064
	for (;;) {
1065
		ps.ps_len = len;
1066
		if (len) {
1067
			newinbuf = realloc(inbuf, len);
1068
			if (newinbuf == NULL)
1069
				err(1, "realloc");
1070
			ps.ps_buf = inbuf = newinbuf;
1071
		}
1072
		if (ioctl(dev, DIOCGETSTATES, &ps) < 0) {
1073
			warn("DIOCGETSTATES");
1074
			free(inbuf);
1075
			return (-1);
1076
		}
1077
		if (ps.ps_len + sizeof(struct pfioc_states) < len)
1078
			break;
1079
		if (len == 0 && ps.ps_len == 0)
1080
			goto done;
1081
		if (len == 0 && ps.ps_len != 0)
1082
			len = ps.ps_len;
1083
		if (ps.ps_len == 0)
1084
			goto done;	/* no states */
1085
		len *= 2;
1086
	}
1087
	p = ps.ps_states;
1088
	for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) {
1089
		if (iface != NULL && strcmp(p->ifname, iface))
1090
			continue;
1091
		if (dotitle) {
1092
			pfctl_print_title("STATES:");
1093
			dotitle = 0;
1094
		}
1095
		if (shownr < 0 || ntohl(p->rule) == shownr)
1096
			print_state(p, opts);
1097
	}
1098
done:
1099
	free(inbuf);
1100
	return (0);
1101
}
1102
1103
int
1104
pfctl_show_status(int dev, int opts)
1105
{
1106
8
	struct pf_status status;
1107
1108
4
	if (ioctl(dev, DIOCGETSTATUS, &status)) {
1109
		warn("DIOCGETSTATUS");
1110
		return (-1);
1111
	}
1112
4
	if (opts & PF_OPT_SHOWALL)
1113
		pfctl_print_title("INFO:");
1114
4
	print_status(&status, opts);
1115
4
	return (0);
1116
4
}
1117
1118
int
1119
pfctl_show_timeouts(int dev, int opts)
1120
{
1121
	struct pfioc_tm pt;
1122
	int i;
1123
1124
	if (opts & PF_OPT_SHOWALL)
1125
		pfctl_print_title("TIMEOUTS:");
1126
	memset(&pt, 0, sizeof(pt));
1127
	for (i = 0; pf_timeouts[i].name; i++) {
1128
		pt.timeout = pf_timeouts[i].timeout;
1129
		if (ioctl(dev, DIOCGETTIMEOUT, &pt))
1130
			err(1, "DIOCGETTIMEOUT");
1131
		printf("%-20s %10d", pf_timeouts[i].name, pt.seconds);
1132
		if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START &&
1133
		    pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END)
1134
			printf(" states");
1135
		else
1136
			printf("s");
1137
		printf("\n");
1138
	}
1139
	return (0);
1140
1141
}
1142
1143
int
1144
pfctl_show_limits(int dev, int opts)
1145
{
1146
	struct pfioc_limit pl;
1147
	int i;
1148
1149
	if (opts & PF_OPT_SHOWALL)
1150
		pfctl_print_title("LIMITS:");
1151
	memset(&pl, 0, sizeof(pl));
1152
	for (i = 0; pf_limits[i].name; i++) {
1153
		pl.index = pf_limits[i].index;
1154
		if (ioctl(dev, DIOCGETLIMIT, &pl))
1155
			err(1, "DIOCGETLIMIT");
1156
		printf("%-13s ", pf_limits[i].name);
1157
		if (pl.limit == UINT_MAX)
1158
			printf("unlimited\n");
1159
		else
1160
			printf("hard limit %8u\n", pl.limit);
1161
	}
1162
	return (0);
1163
}
1164
1165
/* callbacks for rule/nat/rdr/addr */
1166
int
1167
pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
1168
{
1169
	struct pf_rule		*rule;
1170
	struct pf_ruleset	*rs;
1171
	char 			*p;
1172
1173
7138
	rs = &pf->anchor->ruleset;
1174

3700
	if (anchor_call[0] && r->anchor == NULL) {
1175
		/*
1176
		 * Don't make non-brace anchors part of the main anchor pool.
1177
		 */
1178
48
		if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL)
1179
			err(1, "pfctl_add_rule: calloc");
1180
1181
48
		pf_init_ruleset(&r->anchor->ruleset);
1182
48
		r->anchor->ruleset.anchor = r->anchor;
1183
96
		if (strlcpy(r->anchor->path, anchor_call,
1184
48
		    sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
1185
                        errx(1, "pfctl_add_rule: strlcpy");
1186
48
		if ((p = strrchr(anchor_call, '/')) != NULL) {
1187
24
			if (strlen(p) == 1)
1188
				errx(1, "pfctl_add_rule: bad anchor name %s",
1189
				    anchor_call);
1190
		} else
1191
			p = (char *)anchor_call;
1192
96
		if (strlcpy(r->anchor->name, p,
1193
48
		    sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
1194
                        errx(1, "pfctl_add_rule: strlcpy");
1195
	}
1196
1197
3569
	if ((rule = calloc(1, sizeof(*rule))) == NULL)
1198
		err(1, "calloc");
1199
3569
	bcopy(r, rule, sizeof(*rule));
1200
1201
3569
	TAILQ_INSERT_TAIL(rs->rules.active.ptr, rule, entries);
1202
3569
	return (0);
1203
}
1204
1205
int
1206
pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a)
1207
{
1208
416
	int osize = pf->trans->pfrb_size;
1209
1210
208
	if (pfctl_add_trans(pf->trans, PF_TRANS_RULESET, path))
1211
		return (3);
1212
208
	if (pfctl_add_trans(pf->trans, PF_TRANS_TABLE, path))
1213
		return (4);
1214
208
	if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize))
1215
		return (5);
1216
1217
208
	return (0);
1218
208
}
1219
1220
int
1221
pfctl_add_queue(struct pfctl *pf, struct pf_queuespec *q)
1222
{
1223
	struct pfctl_qsitem	*qi;
1224
1225
74
	if (pf->anchor->name[0]) {
1226
		printf("must not have queue definitions in an anchor\n");
1227
		return (1);
1228
	}
1229
1230
37
	if (q->parent[0] == '\0') {
1231
44
		TAILQ_FOREACH(qi, &rootqs, entries) {
1232
			if (strcmp(q->ifname, qi->qs.ifname))
1233
			    continue;
1234
			printf("A root queue is already defined on %s\n",
1235
			    qi->qs.ifname);
1236
			return (1);
1237
		}
1238
	}
1239
1240
37
	if ((qi = calloc(1, sizeof(*qi))) == NULL)
1241
		err(1, "calloc");
1242
37
	bcopy(q, &qi->qs, sizeof(qi->qs));
1243
37
	TAILQ_INIT(&qi->children);
1244
1245
37
	if (qi->qs.parent[0])
1246
15
		TAILQ_INSERT_TAIL(&qspecs, qi, entries);
1247
	else
1248
22
		TAILQ_INSERT_TAIL(&rootqs, qi, entries);
1249
1250
37
	return (0);
1251
37
}
1252
1253
struct pfctl_qsitem *
1254
pfctl_find_queue(char *what, struct pf_qihead *where)
1255
{
1256
	struct pfctl_qsitem *q;
1257
1258
53
	TAILQ_FOREACH(q, where, entries)
1259
3
		if (strcmp(q->qs.qname, what) == 0)
1260
2
			return (q);
1261
1262
15
	return (NULL);
1263
17
}
1264
1265
u_int
1266
pfctl_find_childqs(struct pfctl_qsitem *qi)
1267
{
1268
	struct pfctl_qsitem	*n, *p, *q;
1269
68
	u_int			 flags = qi->qs.flags;
1270
1271
132
	TAILQ_FOREACH(p, &qspecs, entries) {
1272
32
		if (strcmp(p->qs.parent, qi->qs.qname))
1273
			continue;
1274

14
		if (p->qs.ifname[0] && strcmp(p->qs.ifname, qi->qs.ifname))
1275
			continue;
1276
14
		if (++p->matches > 10000)
1277
			errx(1, "pfctl_find_childqs: excessive matches, loop?");
1278
1279
14
		if ((q = pfctl_find_queue(p->qs.qname, &qi->children)) == NULL) {
1280
			/* insert */
1281
14
			if ((n = calloc(1, sizeof(*n))) == NULL)
1282
				err(1, "calloc");
1283
14
			TAILQ_INIT(&n->children);
1284
14
			bcopy(&p->qs, &n->qs, sizeof(n->qs));
1285
14
			TAILQ_INSERT_TAIL(&qi->children, n, entries);
1286
14
		} else {
1287
			if ((q->qs.ifname[0] && p->qs.ifname[0]))
1288
				errx(1, "queue %s on %s respecified",
1289
				    q->qs.qname, q->qs.ifname);
1290
			if (!q->qs.ifname[0] && !p->qs.ifname[0])
1291
				errx(1, "queue %s respecified",
1292
				    q->qs.qname);
1293
			/* ifbound beats floating */
1294
			if (!q->qs.ifname[0])
1295
				bcopy(&p->qs, &q->qs, sizeof(q->qs));
1296
		}
1297
	}
1298
1299
96
	TAILQ_FOREACH(p, &qi->children, entries)
1300
14
		flags |= pfctl_find_childqs(p);
1301
1302
34
	if (!TAILQ_EMPTY(&qi->children)) {
1303
14
		if (qi->qs.flags & PFQS_DEFAULT)
1304
			errx(1, "default queue %s is not a leaf queue",
1305
			    qi->qs.qname);
1306
13
		if (qi->qs.flags & PFQS_FLOWQUEUE)
1307
			errx(1, "flow queue %s is not a leaf queue",
1308
			    qi->qs.qname);
1309
	}
1310
1311
32
	return (flags);
1312
}
1313
1314
void
1315
pfctl_load_queue(struct pfctl *pf, u_int32_t ticket, struct pfctl_qsitem *qi)
1316
{
1317
52
	struct pfioc_queue	 q;
1318
	struct pfctl_qsitem	*p;
1319
1320
26
	q.ticket = ticket;
1321
26
	bcopy(&qi->qs, &q.queue, sizeof(q.queue));
1322
26
	if ((pf->opts & PF_OPT_NOACTION) == 0)
1323
		if (ioctl(pf->dev, DIOCADDQUEUE, &q))
1324
			err(1, "DIOCADDQUEUE");
1325
26
	if (pf->opts & PF_OPT_VERBOSE)
1326
26
		print_queuespec(&qi->qs);
1327
1328
72
	TAILQ_FOREACH(p, &qi->children, entries) {
1329
10
		strlcpy(p->qs.ifname, qi->qs.ifname, IFNAMSIZ);
1330
10
		pfctl_load_queue(pf, ticket, p);
1331
	}
1332
26
}
1333
1334
int
1335
pfctl_load_queues(struct pfctl *pf)
1336
{
1337
	struct pfctl_qsitem	*qi, *tempqi;
1338
	struct pf_queue_scspec	*rtsc, *lssc, *ulsc;
1339
	u_int32_t		 ticket;
1340
1341
680
	TAILQ_FOREACH(qi, &qspecs, entries) {
1342
11
		if (qi->matches == 0)
1343
			errx(1, "queue %s: parent %s not found", qi->qs.qname,
1344
			    qi->qs.parent);
1345
1346
11
		rtsc = &qi->qs.realtime;
1347
11
		lssc = &qi->qs.linkshare;
1348
11
		ulsc = &qi->qs.upperlimit;
1349
1350

33
		if (rtsc->m1.percent || rtsc->m2.percent ||
1351

22
		    lssc->m1.percent || lssc->m2.percent ||
1352
22
		    ulsc->m1.percent || ulsc->m2.percent)
1353
			errx(1, "only absolute bandwidth specs for now");
1354
1355
		/* Link sharing policy must be specified for child classes */
1356

12
		if (qi->qs.parent[0] != '\0' &&
1357
12
		    lssc->m1.absolute == 0 && lssc->m2.absolute == 0)
1358
			errx(1, "queue %s: no bandwidth was specified",
1359
			    qi->qs.qname);
1360
	}
1361
1362
219
	if ((pf->opts & PF_OPT_NOACTION) == 0)
1363
		ticket = pfctl_get_ticket(pf->trans, PF_TRANS_RULESET, "");
1364
1365
486
	TAILQ_FOREACH_SAFE(qi, &rootqs, entries, tempqi) {
1366
32
		TAILQ_REMOVE(&rootqs, qi, entries);
1367
16
		pfctl_load_queue(pf, ticket, qi);
1368
16
		TAILQ_INSERT_HEAD(&rootqs, qi, entries);
1369
	}
1370
1371
219
	return (0);
1372
}
1373
1374
void
1375
pfctl_clear_queues(struct pf_qihead *head)
1376
{
1377
	struct pfctl_qsitem *qi;
1378
1379
1494
	while ((qi = TAILQ_FIRST(head)) != NULL) {
1380
108
		TAILQ_REMOVE(head, qi, entries);
1381
36
		pfctl_clear_queues(&qi->children);
1382
36
		free(qi);
1383
	}
1384
474
}
1385
1386
u_int
1387
pfctl_leafqueue_check(char *qname)
1388
{
1389
	struct pfctl_qsitem	*qi;
1390

10944
	if (qname == NULL || qname[0] == 0)
1391
3647
		return (0);
1392
1393
4
	TAILQ_FOREACH(qi, &rootqs, entries) {
1394
1
		if (strcmp(qname, qi->qs.qname))
1395
			continue;
1396
		if (!TAILQ_EMPTY(&qi->children)) {
1397
			printf("queue %s: packets must be assigned to leaf "
1398
			    "queues only\n", qname);
1399
			return (1);
1400
		}
1401
	}
1402
4
	TAILQ_FOREACH(qi, &qspecs, entries) {
1403
1
		if (strcmp(qname, qi->qs.qname))
1404
			continue;
1405
1
		if (!TAILQ_EMPTY(&qi->children)) {
1406
			printf("queue %s: packets must be assigned to leaf "
1407
			    "queues only\n", qname);
1408
			return (1);
1409
		}
1410
	}
1411
1
	return (0);
1412
3648
}
1413
1414
u_int
1415
pfctl_check_qassignments(struct pf_ruleset *rs)
1416
{
1417
	struct pf_rule		*r;
1418
	struct pfctl_qsitem	*qi;
1419
	u_int			 flags, errs = 0;
1420
1421
	/* main ruleset: need find_childqs to populate qi->children */
1422
590
	if (rs->anchor->path[0] == 0) {
1423
480
		TAILQ_FOREACH(qi, &rootqs, entries) {
1424
18
			flags = pfctl_find_childqs(qi);
1425

26
			if (!(qi->qs.flags & PFQS_ROOTCLASS) &&
1426
8
			    !TAILQ_EMPTY(&qi->children)) {
1427
				if (qi->qs.flags & PFQS_FLOWQUEUE)
1428
					errx(1, "root queue %s doesn't "
1429
					    "support hierarchy",
1430
					    qi->qs.qname);
1431
				else
1432
					errx(1, "no bandwidth was specified "
1433
					    "for root queue %s", qi->qs.qname);
1434
			}
1435

28
			if ((qi->qs.flags & PFQS_ROOTCLASS) &&
1436
10
			    !(flags & PFQS_DEFAULT))
1437
				errx(1, "no default queue specified");
1438
		}
1439
	}
1440
1441
4232
	TAILQ_FOREACH(r, rs->rules.active.ptr, entries) {
1442
1824
		if (r->anchor)
1443
72
			errs += pfctl_check_qassignments(&r->anchor->ruleset);
1444

3648
		if (pfctl_leafqueue_check(r->qname) ||
1445
1824
		    pfctl_leafqueue_check(r->pqname))
1446
			errs++;
1447
	}
1448
292
	return (errs);
1449
}
1450
1451
int
1452
pfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs,
1453
    int depth)
1454
{
1455
	struct pf_rule *r;
1456
1050
	int		error, len = strlen(path);
1457
	int		brace = 0;
1458
1459
525
	pf->anchor = rs->anchor;
1460
1461
525
	if (path[0])
1462
91
		snprintf(&path[len], PATH_MAX - len, "/%s", pf->anchor->name);
1463
	else
1464
434
		snprintf(&path[len], PATH_MAX - len, "%s", pf->anchor->path);
1465
1466
525
	if (depth) {
1467
131
		if (TAILQ_FIRST(rs->rules.active.ptr) != NULL) {
1468
			brace++;
1469
83
			if (pf->opts & PF_OPT_VERBOSE)
1470
47
				printf(" {\n");
1471

119
			if ((pf->opts & PF_OPT_NOACTION) == 0 &&
1472
36
			    (error = pfctl_ruleset_trans(pf,
1473
36
			    path, rs->anchor))) {
1474
				printf("pfctl_load_rulesets: "
1475
				    "pfctl_ruleset_trans %d\n", error);
1476
				goto error;
1477
			}
1478
48
		} else if (pf->opts & PF_OPT_VERBOSE)
1479
36
			printf("\n");
1480
1481
	}
1482
1483
525
	if (pf->optimize)
1484
126
		pfctl_optimize_ruleset(pf, rs);
1485
1486
7768
	while ((r = TAILQ_FIRST(rs->rules.active.ptr)) != NULL) {
1487
10077
		TAILQ_REMOVE(rs->rules.active.ptr, r, entries);
1488
3359
		if ((error = pfctl_load_rule(pf, path, r, depth)))
1489
			goto error;
1490
3359
		if (r->anchor) {
1491
131
			if ((error = pfctl_load_ruleset(pf, path,
1492
131
			    &r->anchor->ruleset, depth + 1)))
1493
				goto error;
1494
3228
		} else if (pf->opts & PF_OPT_VERBOSE)
1495
1782
			printf("\n");
1496
3359
		free(r);
1497
	}
1498

608
	if (brace && pf->opts & PF_OPT_VERBOSE) {
1499

436
		INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE));
1500
47
		printf("}\n");
1501
47
	}
1502
525
	path[len] = '\0';
1503
525
	return (0);
1504
1505
 error:
1506
	path[len] = '\0';
1507
	return (error);
1508
1509
525
}
1510
1511
int
1512
pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth)
1513
{
1514
	char			*name;
1515
6718
	struct pfioc_rule	pr;
1516
3359
	int			len = strlen(path);
1517
1518
3359
	bzero(&pr, sizeof(pr));
1519
	/* set up anchor before adding to path for anchor_call */
1520
3359
	if ((pf->opts & PF_OPT_NOACTION) == 0)
1521
1518
		pr.ticket = pfctl_get_ticket(pf->trans, PF_TRANS_RULESET, path);
1522
3359
	if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >= sizeof(pr.anchor))
1523
		errx(1, "pfctl_load_rule: strlcpy");
1524
1525
3359
	if (r->anchor) {
1526
131
		if (r->anchor->match) {
1527
83
			if (path[0])
1528
75
				snprintf(&path[len], PATH_MAX - len,
1529
				    "/%s", r->anchor->name);
1530
			else
1531
8
				snprintf(&path[len], PATH_MAX - len,
1532
				    "%s", r->anchor->name);
1533
83
			name = r->anchor->name;
1534
83
		} else
1535
48
			name = r->anchor->path;
1536
	} else
1537
		name = "";
1538
1539
3359
	if ((pf->opts & PF_OPT_NOACTION) == 0) {
1540
1518
		memcpy(&pr.rule, r, sizeof(pr.rule));
1541

1614
		if (r->anchor && strlcpy(pr.anchor_call, name,
1542
48
		    sizeof(pr.anchor_call)) >= sizeof(pr.anchor_call))
1543
			errx(1, "pfctl_load_rule: strlcpy");
1544
1518
		if (ioctl(pf->dev, DIOCADDRULE, &pr))
1545
			err(1, "DIOCADDRULE");
1546
	}
1547
1548
3359
	if (pf->opts & PF_OPT_VERBOSE) {
1549

7864
		INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2));
1550
1865
		print_rule(r, name, pf->opts);
1551
1865
	}
1552
3359
	path[len] = '\0';
1553
3359
	return (0);
1554
3359
}
1555
1556
int
1557
pfctl_rules(int dev, char *filename, int opts, int optimize,
1558
    char *anchorname, struct pfr_buffer *trans)
1559
{
1560
#define ERR(x) do { warn(x); goto _error; } while(0)
1561
#define ERRX(x) do { warnx(x); goto _error; } while(0)
1562
1563
908
	struct pfr_buffer	*t, buf;
1564
454
	struct pfctl		 pf;
1565
	struct pf_ruleset	*rs;
1566
454
	struct pfr_table	 trs;
1567
	char			*path = NULL;
1568
	int			 osize;
1569
	char			*p;
1570
1571
454
	bzero(&pf, sizeof(pf));
1572
454
	RB_INIT(&pf_anchors);
1573
454
	memset(&pf_main_anchor, 0, sizeof(pf_main_anchor));
1574
454
	pf_init_ruleset(&pf_main_anchor.ruleset);
1575
454
	if (trans == NULL) {
1576
453
		bzero(&buf, sizeof(buf));
1577
453
		buf.pfrb_type = PFRB_TRANS;
1578
		t = &buf;
1579
		osize = 0;
1580
453
	} else {
1581
		t = trans;
1582
1
		osize = t->pfrb_size;
1583
	}
1584
1585
454
	memset(&pf, 0, sizeof(pf));
1586
454
	memset(&trs, 0, sizeof(trs));
1587
454
	if ((path = calloc(1, PATH_MAX)) == NULL)
1588
		ERRX("pfctl_rules: calloc");
1589
908
	if (strlcpy(trs.pfrt_anchor, anchorname,
1590
454
	    sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor))
1591
		ERRX("pfctl_rules: strlcpy");
1592
454
	pf.dev = dev;
1593
454
	pf.opts = opts;
1594
454
	pf.optimize = optimize;
1595
1596
	/* non-brace anchor, create without resolving the path */
1597
454
	if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL)
1598
		ERRX("pfctl_rules: calloc");
1599
454
	rs = &pf.anchor->ruleset;
1600
454
	pf_init_ruleset(rs);
1601
454
	rs->anchor = pf.anchor;
1602
908
	if (strlcpy(pf.anchor->path, anchorname,
1603
454
	    sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path))
1604
		errx(1, "pfctl_add_rule: strlcpy");
1605
1606
454
	if ((p = strrchr(anchorname, '/')) != NULL) {
1607
32
		if (strlen(p) == 1)
1608
			errx(1, "pfctl_add_rule: bad anchor name %s",
1609
			    anchorname);
1610
	} else
1611
		p = anchorname;
1612
1613
908
	if (strlcpy(pf.anchor->name, p,
1614
454
	    sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name))
1615
		errx(1, "pfctl_add_rule: strlcpy");
1616
1617
1618
454
	pf.astack[0] = pf.anchor;
1619
454
	pf.asd = 0;
1620
454
	pf.trans = t;
1621
454
	pfctl_init_options(&pf);
1622
1623
454
	if ((opts & PF_OPT_NOACTION) == 0) {
1624
		/*
1625
		 * XXX For the time being we need to open transactions for
1626
		 * the main ruleset before parsing, because tables are still
1627
		 * loaded at parse time.
1628
		 */
1629
172
		if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor))
1630
			ERRX("pfctl_rules");
1631
172
		pf.astack[0]->ruleset.tticket =
1632
172
		    pfctl_get_ticket(t, PF_TRANS_TABLE, anchorname);
1633
172
	}
1634
1635
454
	if (parse_config(filename, &pf) < 0) {
1636
56
		if ((opts & PF_OPT_NOACTION) == 0)
1637
			ERRX("Syntax error in config file: "
1638
			    "pf rules not loaded");
1639
		else
1640
			goto _error;
1641
	}
1642
1643

837
	if (!anchorname[0] && (pfctl_check_qassignments(&pf.anchor->ruleset) ||
1644
219
	    pfctl_load_queues(&pf))) {
1645
		if ((opts & PF_OPT_NOACTION) == 0)
1646
			ERRX("Unable to load queues into kernel");
1647
		else
1648
			goto _error;
1649
	}
1650
1651
394
	if (pfctl_load_ruleset(&pf, path, rs, 0)) {
1652
		if ((opts & PF_OPT_NOACTION) == 0)
1653
			ERRX("Unable to load rules into kernel");
1654
		else
1655
			goto _error;
1656
	}
1657
1658
394
	free(path);
1659
	path = NULL;
1660
1661
	/* process "load anchor" directives that might have used queues */
1662
394
	if (!anchorname[0]) {
1663
219
		if (pfctl_load_anchors(dev, &pf, t) == -1)
1664
			ERRX("load anchors");
1665
219
		pfctl_clear_queues(&qspecs);
1666
219
		pfctl_clear_queues(&rootqs);
1667
219
	}
1668
1669

787
	if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) {
1670
172
		if (!anchorname[0])
1671
			if (pfctl_load_options(&pf))
1672
				goto _error;
1673
172
		if (pfctl_trans(dev, t, DIOCXCOMMIT, osize))
1674
			ERR("DIOCXCOMMIT");
1675
	}
1676
394
	return (0);
1677
1678
_error:
1679
56
	if (trans == NULL) {	/* main ruleset */
1680
56
		if ((opts & PF_OPT_NOACTION) == 0)
1681
			if (pfctl_trans(dev, t, DIOCXROLLBACK, osize))
1682
				err(1, "DIOCXROLLBACK");
1683
		exit(1);
1684
	} else {		/* sub ruleset */
1685
		free(path);
1686
		return (-1);
1687
	}
1688
1689
#undef ERR
1690
#undef ERRX
1691
394
}
1692
1693
FILE *
1694
pfctl_fopen(const char *name, const char *mode)
1695
{
1696
582
	struct stat	 st;
1697
	FILE		*fp;
1698
1699
291
	fp = fopen(name, mode);
1700
291
	if (fp == NULL)
1701
1
		return (NULL);
1702

870
	if (fstat(fileno(fp), &st)) {
1703
		fclose(fp);
1704
		return (NULL);
1705
	}
1706
290
	if (S_ISDIR(st.st_mode)) {
1707
		fclose(fp);
1708
		errno = EISDIR;
1709
		return (NULL);
1710
	}
1711
290
	return (fp);
1712
291
}
1713
1714
void
1715
pfctl_init_options(struct pfctl *pf)
1716
{
1717
908
	int64_t mem;
1718
454
	int mib[2], mcl;
1719
454
	size_t size;
1720
1721
454
	pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
1722
454
	pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
1723
454
	pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
1724
454
	pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
1725
454
	pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
1726
454
	pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
1727
454
	pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
1728
454
	pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
1729
454
	pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
1730
454
	pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
1731
454
	pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
1732
454
	pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
1733
454
	pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
1734
454
	pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
1735
454
	pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
1736
454
	pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
1737
454
	pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
1738
454
	pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
1739
454
	pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START;
1740
454
	pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
1741
1742
454
	pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT;
1743
1744
454
	mib[0] = CTL_KERN;
1745
454
	mib[1] = KERN_MAXCLUSTERS;
1746
454
	size = sizeof(mcl);
1747
454
	if (sysctl(mib, 2, &mcl, &size, NULL, 0) == -1)
1748
		err(1, "sysctl");
1749
454
	pf->limit[PF_LIMIT_FRAGS] = mcl / 4;
1750
1751
454
	pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT;
1752
454
	pf->limit[PF_LIMIT_TABLES] = PFR_KTABLE_HIWAT;
1753
454
	pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
1754
1755
454
	mib[0] = CTL_HW;
1756
454
	mib[1] = HW_PHYSMEM64;
1757
454
	size = sizeof(mem);
1758
454
	if (sysctl(mib, 2, &mem, &size, NULL, 0) == -1)
1759
		err(1, "sysctl");
1760
454
	if (mem <= 100*1024*1024)
1761
		pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT_SMALL;
1762
1763
454
	pf->debug = LOG_ERR;
1764
454
	pf->debug_set = 0;
1765
454
	pf->reassemble = PF_REASS_ENABLED;
1766
454
}
1767
1768
int
1769
pfctl_load_options(struct pfctl *pf)
1770
{
1771
	int i, error = 0;
1772
1773
	/* load limits */
1774
	for (i = 0; i < PF_LIMIT_MAX; i++)
1775
		if (pfctl_load_limit(pf, i, pf->limit[i]))
1776
			error = 1;
1777
1778
	/*
1779
	 * If we've set the states limit, but haven't explicitly set adaptive
1780
	 * timeouts, do it now with a start of 60% and end of 120%.
1781
	 */
1782
	if (pf->limit_set[PF_LIMIT_STATES] &&
1783
	    !pf->timeout_set[PFTM_ADAPTIVE_START] &&
1784
	    !pf->timeout_set[PFTM_ADAPTIVE_END]) {
1785
		pf->timeout[PFTM_ADAPTIVE_START] =
1786
			(pf->limit[PF_LIMIT_STATES] / 10) * 6;
1787
		pf->timeout_set[PFTM_ADAPTIVE_START] = 1;
1788
		pf->timeout[PFTM_ADAPTIVE_END] =
1789
			(pf->limit[PF_LIMIT_STATES] / 10) * 12;
1790
		pf->timeout_set[PFTM_ADAPTIVE_END] = 1;
1791
	}
1792
1793
	/* load timeouts */
1794
	for (i = 0; i < PFTM_MAX; i++)
1795
		if (pfctl_load_timeout(pf, i, pf->timeout[i]))
1796
			error = 1;
1797
1798
	/* load debug */
1799
	if (pf->debug_set && pfctl_load_debug(pf, pf->debug))
1800
		error = 1;
1801
1802
	/* load logif */
1803
	if (pf->ifname_set && pfctl_load_logif(pf, pf->ifname))
1804
		error = 1;
1805
1806
	/* load hostid */
1807
	if (pf->hostid_set && pfctl_load_hostid(pf, pf->hostid))
1808
		error = 1;
1809
1810
	/* load reassembly settings */
1811
	if (pf->reass_set && pfctl_load_reassembly(pf, pf->reassemble))
1812
		error = 1;
1813
1814
	return (error);
1815
}
1816
1817
int
1818
pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
1819
{
1820
	int i;
1821
1822
1823
72
	for (i = 0; pf_limits[i].name; i++) {
1824
28
		if (strcasecmp(opt, pf_limits[i].name) == 0) {
1825
16
			pf->limit[pf_limits[i].index] = limit;
1826
16
			pf->limit_set[pf_limits[i].index] = 1;
1827
16
			break;
1828
		}
1829
	}
1830
16
	if (pf_limits[i].name == NULL) {
1831
		warnx("Bad pool name.");
1832
		return (1);
1833
	}
1834
1835
16
	if (pf->opts & PF_OPT_VERBOSE)
1836
16
		printf("set limit %s %d\n", opt, limit);
1837
1838
16
	return (0);
1839
16
}
1840
1841
int
1842
pfctl_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, &pl)) {
1850
		if (errno == EBUSY)
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
1861
int
1862
pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
1863
{
1864
	int i;
1865
1866
1892
	for (i = 0; pf_timeouts[i].name; i++) {
1867
867
		if (strcasecmp(opt, pf_timeouts[i].name) == 0) {
1868
158
			pf->timeout[pf_timeouts[i].timeout] = seconds;
1869
158
			pf->timeout_set[pf_timeouts[i].timeout] = 1;
1870
158
			break;
1871
		}
1872
	}
1873
1874
158
	if (pf_timeouts[i].name == NULL) {
1875
		warnx("Bad timeout name.");
1876
		return (1);
1877
	}
1878
1879
1880
158
	if (pf->opts & PF_OPT_VERBOSE && ! quiet)
1881
46
		printf("set timeout %s %d\n", opt, seconds);
1882
1883
158
	return (0);
1884
158
}
1885
1886
int
1887
pfctl_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, &pt)) {
1895
		warnx("DIOCSETTIMEOUT");
1896
		return (1);
1897
	}
1898
	return (0);
1899
}
1900
1901
int
1902
pfctl_set_reassembly(struct pfctl *pf, int on, int nodf)
1903
{
1904
28
	pf->reass_set = 1;
1905
14
	if (on) {
1906
8
		pf->reassemble = PF_REASS_ENABLED;
1907
8
		if (nodf)
1908
6
			pf->reassemble |= PF_REASS_NODF;
1909
	} else {
1910
6
		pf->reassemble = 0;
1911
	}
1912
1913
14
	if (pf->opts & PF_OPT_VERBOSE)
1914
20
		printf("set reassemble %s %s\n", on ? "yes" : "no",
1915
10
		    nodf ? "no-df" : "");
1916
1917
14
	return (0);
1918
}
1919
1920
int
1921
pfctl_set_optimization(struct pfctl *pf, const char *opt)
1922
{
1923
	const struct pf_hint *hint;
1924
	int i, r;
1925
1926
112
	for (i = 0; pf_hints[i].name; i++)
1927
48
		if (strcasecmp(opt, pf_hints[i].name) == 0)
1928
			break;
1929
1930
16
	hint = pf_hints[i].hint;
1931
16
	if (hint == NULL) {
1932
		warnx("invalid state timeouts optimization");
1933
		return (1);
1934
	}
1935
1936
256
	for (i = 0; hint[i].name; i++)
1937
112
		if ((r = pfctl_set_timeout(pf, hint[i].name,
1938
112
		    hint[i].timeout, 1)))
1939
			return (r);
1940
1941
16
	if (pf->opts & PF_OPT_VERBOSE)
1942
16
		printf("set optimization %s\n", opt);
1943
1944
16
	return (0);
1945
16
}
1946
1947
int
1948
pfctl_set_logif(struct pfctl *pf, char *ifname)
1949
{
1950
20
	if (!strcmp(ifname, "none")) {
1951
4
		free(pf->ifname);
1952
4
		pf->ifname = NULL;
1953
4
	} else {
1954
6
		pf->ifname = strdup(ifname);
1955
6
		if (!pf->ifname)
1956
			errx(1, "pfctl_set_logif: strdup");
1957
	}
1958
10
	pf->ifname_set = 1;
1959
1960
10
	if (pf->opts & PF_OPT_VERBOSE)
1961
10
		printf("set loginterface %s\n", ifname);
1962
1963
10
	return (0);
1964
}
1965
1966
int
1967
pfctl_load_logif(struct pfctl *pf, char *ifname)
1968
{
1969
	struct pfioc_iface	pi;
1970
1971
	memset(&pi, 0, sizeof(pi));
1972
	if (ifname && strlcpy(pi.pfiio_name, ifname,
1973
	    sizeof(pi.pfiio_name)) >= sizeof(pi.pfiio_name)) {
1974
		warnx("pfctl_load_logif: strlcpy");
1975
		return (1);
1976
	}
1977
	if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) {
1978
		warnx("DIOCSETSTATUSIF");
1979
		return (1);
1980
	}
1981
	return (0);
1982
}
1983
1984
void
1985
pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
1986
{
1987
8
	HTONL(hostid);
1988
1989
4
	pf->hostid = hostid;
1990
4
	pf->hostid_set = 1;
1991
1992
4
	if (pf->opts & PF_OPT_VERBOSE)
1993
4
		printf("set hostid 0x%08x\n", ntohl(hostid));
1994
4
}
1995
1996
int
1997
pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid)
1998
{
1999
	if (ioctl(dev, DIOCSETHOSTID, &hostid)) {
2000
		warnx("DIOCSETHOSTID");
2001
		return (1);
2002
	}
2003
	return (0);
2004
}
2005
2006
int
2007
pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly)
2008
{
2009
	if (ioctl(dev, DIOCSETREASS, &reassembly)) {
2010
		warnx("DIOCSETREASS");
2011
		return (1);
2012
	}
2013
	return (0);
2014
}
2015
2016
int
2017
pfctl_set_debug(struct pfctl *pf, char *d)
2018
{
2019
	u_int32_t	level;
2020
	int		loglevel;
2021
2022
	if ((loglevel = string_to_loglevel(d)) >= 0)
2023
		level = loglevel;
2024
	else {
2025
		warnx("unknown debug level \"%s\"", d);
2026
		return (-1);
2027
	}
2028
	pf->debug = level;
2029
	pf->debug_set = 1;
2030
2031
	if ((pf->opts & PF_OPT_NOACTION) == 0)
2032
		if (ioctl(dev, DIOCSETDEBUG, &level))
2033
			err(1, "DIOCSETDEBUG");
2034
2035
	if (pf->opts & PF_OPT_VERBOSE)
2036
		printf("set debug %s\n", d);
2037
2038
	return (0);
2039
}
2040
2041
int
2042
pfctl_load_debug(struct pfctl *pf, unsigned int level)
2043
{
2044
	if (ioctl(pf->dev, DIOCSETDEBUG, &level)) {
2045
		warnx("DIOCSETDEBUG");
2046
		return (1);
2047
	}
2048
	return (0);
2049
}
2050
2051
int
2052
pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how)
2053
{
2054
	struct pfioc_iface	pi;
2055
2056
	bzero(&pi, sizeof(pi));
2057
2058
	pi.pfiio_flags = flags;
2059
2060
	if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >=
2061
	    sizeof(pi.pfiio_name))
2062
		errx(1, "pfctl_set_interface_flags: strlcpy");
2063
2064
	if ((pf->opts & PF_OPT_NOACTION) == 0) {
2065
		if (how == 0) {
2066
			if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi))
2067
				err(1, "DIOCCLRIFFLAG");
2068
		} else {
2069
			if (ioctl(pf->dev, DIOCSETIFFLAG, &pi))
2070
				err(1, "DIOCSETIFFLAG");
2071
		}
2072
	}
2073
	return (0);
2074
}
2075
2076
void
2077
pfctl_debug(int dev, u_int32_t level, int opts)
2078
{
2079
	struct pfr_buffer t;
2080
2081
	memset(&t, 0, sizeof(t));
2082
	t.pfrb_type = PFRB_TRANS;
2083
	if (pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
2084
	    ioctl(dev, DIOCSETDEBUG, &level) ||
2085
	    pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
2086
		err(1, "pfctl_debug ioctl");
2087
2088
	if ((opts & PF_OPT_QUIET) == 0)
2089
		fprintf(stderr, "debug level set to '%s'\n",
2090
		    loglevel_to_string(level));
2091
}
2092
2093
int
2094
pfctl_show_anchors(int dev, int opts, char *anchorname)
2095
{
2096
	struct pfioc_ruleset	 pr;
2097
	u_int32_t		 mnr, nr;
2098
2099
	memset(&pr, 0, sizeof(pr));
2100
	memcpy(pr.path, anchorname, sizeof(pr.path));
2101
	if (ioctl(dev, DIOCGETRULESETS, &pr)) {
2102
		if (errno == EINVAL)
2103
			fprintf(stderr, "Anchor '%s' not found.\n",
2104
			    anchorname);
2105
		else
2106
			err(1, "DIOCGETRULESETS");
2107
		return (-1);
2108
	}
2109
	mnr = pr.nr;
2110
	for (nr = 0; nr < mnr; ++nr) {
2111
		char sub[PATH_MAX];
2112
2113
		pr.nr = nr;
2114
		if (ioctl(dev, DIOCGETRULESET, &pr))
2115
			err(1, "DIOCGETRULESET");
2116
		if (!strcmp(pr.name, PF_RESERVED_ANCHOR))
2117
			continue;
2118
		sub[0] = 0;
2119
		if (pr.path[0]) {
2120
			strlcat(sub, pr.path, sizeof(sub));
2121
			strlcat(sub, "/", sizeof(sub));
2122
		}
2123
		strlcat(sub, pr.name, sizeof(sub));
2124
		if (sub[0] != '_' || (opts & PF_OPT_VERBOSE))
2125
			printf("  %s\n", sub);
2126
		if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub))
2127
			return (-1);
2128
	}
2129
	return (0);
2130
}
2131
2132
const char *
2133
pfctl_lookup_option(char *cmd, const char **list)
2134
{
2135
	const char *item = NULL;
2136

3162
	if (cmd != NULL && *cmd)
2137
13096
		for (; *list; list++)
2138
5494
			if (!strncmp(cmd, *list, strlen(cmd))) {
2139
1054
				if (item == NULL)
2140
1054
					item = *list;
2141
				else
2142
					errx(1, "%s is ambigious", cmd);
2143
1054
			}
2144
2145
1054
	return (item);
2146
}
2147
2148
2149
void
2150
pfctl_state_store(int dev, const char *file)
2151
{
2152
	FILE *f;
2153
	struct pfioc_states ps;
2154
	char *inbuf = NULL, *newinbuf = NULL;
2155
	unsigned int len = 0;
2156
	size_t n;
2157
2158
	f = fopen(file, "w");
2159
	if (f == NULL)
2160
		err(1, "open: %s", file);
2161
2162
	memset(&ps, 0, sizeof(ps));
2163
	for (;;) {
2164
		ps.ps_len = len;
2165
		if (len) {
2166
			newinbuf = realloc(inbuf, len);
2167
			if (newinbuf == NULL)
2168
				err(1, "realloc");
2169
			ps.ps_buf = inbuf = newinbuf;
2170
		}
2171
		if (ioctl(dev, DIOCGETSTATES, &ps) < 0)
2172
			err(1, "DIOCGETSTATES");
2173
2174
		if (ps.ps_len + sizeof(struct pfioc_states) < len)
2175
			break;
2176
		if (len == 0 && ps.ps_len == 0)
2177
			goto done;
2178
		if (len == 0 && ps.ps_len != 0)
2179
			len = ps.ps_len;
2180
		if (ps.ps_len == 0)
2181
			goto done;	/* no states */
2182
		len *= 2;
2183
	}
2184
2185
	n = ps.ps_len / sizeof(struct pfsync_state);
2186
	if (fwrite(inbuf, sizeof(struct pfsync_state), n, f) < n)
2187
		err(1, "fwrite");
2188
2189
done:
2190
	free(inbuf);
2191
	fclose(f);
2192
}
2193
2194
void
2195
pfctl_state_load(int dev, const char *file)
2196
{
2197
	FILE *f;
2198
	struct pfioc_state ps;
2199
2200
	f = fopen(file, "r");
2201
	if (f == NULL)
2202
		err(1, "open: %s", file);
2203
2204
	while (fread(&ps.state, sizeof(ps.state), 1, f) == 1) {
2205
		if (ioctl(dev, DIOCADDSTATE, &ps) < 0) {
2206
			switch (errno) {
2207
			case EEXIST:
2208
			case EINVAL:
2209
				break;
2210
			default:
2211
				err(1, "DIOCADDSTATE");
2212
			}
2213
		}
2214
	}
2215
2216
	fclose(f);
2217
}
2218
2219
int
2220
main(int argc, char *argv[])
2221
{
2222
	int	 error = 0;
2223
	int	 ch;
2224
	int	 mode = O_RDONLY;
2225
	int	 opts = 0;
2226
	int	 optimize = PF_OPTIMIZE_BASIC;
2227
	int	 level;
2228
	int	 rdomain = 0;
2229
1602
	char	 anchorname[PATH_MAX];
2230
	int	 anchor_wildcard = 0;
2231
	char	*path;
2232
	char	*lfile = NULL, *sfile = NULL;
2233
801
	const char *errstr;
2234
	long	 shownr = -1;
2235
2236
801
	if (argc < 2)
2237
		usage();
2238
2239
11796
	while ((ch = getopt(argc, argv,
2240
3932
	    "a:dD:eqf:F:ghi:k:K:L:Nno:Pp:R:rS:s:t:T:vV:x:z")) != -1) {
2241







3131
		switch (ch) {
2242
		case 'a':
2243
518
			anchoropt = optarg;
2244
518
			break;
2245
		case 'd':
2246
			opts |= PF_OPT_DISABLE;
2247
			mode = O_RDWR;
2248
			break;
2249
		case 'D':
2250
1
			if (pfctl_cmdline_symset(optarg) < 0)
2251
				warnx("could not parse macro definition %s",
2252
				    optarg);
2253
			break;
2254
		case 'e':
2255
			opts |= PF_OPT_ENABLE;
2256
			mode = O_RDWR;
2257
			break;
2258
		case 'q':
2259
30
			opts |= PF_OPT_QUIET;
2260
30
			break;
2261
		case 'F':
2262
173
			clearopt = pfctl_lookup_option(optarg, clearopt_list);
2263
173
			if (clearopt == NULL) {
2264
				warnx("Unknown flush modifier '%s'", optarg);
2265
				usage();
2266
			}
2267
			mode = O_RDWR;
2268
173
			break;
2269
		case 'i':
2270
			ifaceopt = optarg;
2271
			break;
2272
		case 'k':
2273
			if (state_killers >= 2) {
2274
				warnx("can only specify -k twice");
2275
				usage();
2276
				/* NOTREACHED */
2277
			}
2278
			state_kill[state_killers++] = optarg;
2279
			mode = O_RDWR;
2280
			break;
2281
		case 'K':
2282
			if (src_node_killers >= 2) {
2283
				warnx("can only specify -K twice");
2284
				usage();
2285
				/* NOTREACHED */
2286
			}
2287
			src_node_kill[src_node_killers++] = optarg;
2288
			mode = O_RDWR;
2289
			break;
2290
		case 'N':
2291
1
			opts |= PF_OPT_NODNS;
2292
1
			break;
2293
		case 'n':
2294
281
			opts |= PF_OPT_NOACTION;
2295
281
			break;
2296
		case 'r':
2297
			opts |= PF_OPT_USEDNS;
2298
			break;
2299
		case 'R':
2300
			shownr = strtonum(optarg, -1, LONG_MAX, &errstr);
2301
			if (errstr) {
2302
				warnx("invalid rule id: %s", errstr);
2303
				usage();
2304
			}
2305
			break;
2306
		case 'f':
2307
483
			rulesopt = optarg;
2308
			mode = O_RDWR;
2309
483
			break;
2310
		case 'g':
2311
142
			opts |= PF_OPT_DEBUG;
2312
142
			break;
2313
		case 'o':
2314
705
			optiopt = pfctl_lookup_option(optarg, optiopt_list);
2315
705
			if (optiopt == NULL) {
2316
				warnx("Unknown optimization '%s'", optarg);
2317
				usage();
2318
			}
2319
705
			opts |= PF_OPT_OPTIMIZE;
2320
705
			break;
2321
		case 'P':
2322
			opts |= PF_OPT_PORTNAMES;
2323
			break;
2324
		case 'p':
2325
			pf_device = optarg;
2326
			break;
2327
		case 's':
2328
146
			showopt = pfctl_lookup_option(optarg, showopt_list);
2329
146
			if (showopt == NULL) {
2330
				warnx("Unknown show modifier '%s'", optarg);
2331
				usage();
2332
			}
2333
			break;
2334
		case 't':
2335
30
			tableopt = optarg;
2336
30
			break;
2337
		case 'T':
2338
30
			tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list);
2339
30
			if (tblcmdopt == NULL) {
2340
				warnx("Unknown table command '%s'", optarg);
2341
				usage();
2342
			}
2343
			break;
2344
		case 'v':
2345
591
			if (opts & PF_OPT_VERBOSE)
2346
142
				opts |= PF_OPT_VERBOSE2;
2347
591
			opts |= PF_OPT_VERBOSE;
2348
591
			break;
2349
		case 'V':
2350
			rdomain = strtonum(optarg, 0, RT_TABLEID_MAX, &errstr);
2351
			if (errstr) {
2352
				warnx("Invalid rdomain: %s", errstr);
2353
				usage();
2354
			}
2355
			break;
2356
		case 'x':
2357
			debugopt = pfctl_lookup_option(optarg, debugopt_list);
2358
			if (debugopt == NULL) {
2359
				warnx("Unknown debug level '%s'", optarg);
2360
				usage();
2361
			}
2362
			mode = O_RDWR;
2363
			break;
2364
		case 'z':
2365
			opts |= PF_OPT_CLRRULECTRS;
2366
			mode = O_RDWR;
2367
			break;
2368
		case 'S':
2369
			sfile = optarg;
2370
			break;
2371
		case 'L':
2372
			mode = O_RDWR;
2373
			lfile = optarg;
2374
			break;
2375
		case 'h':
2376
			/* FALLTHROUGH */
2377
		default:
2378
			usage();
2379
			/* NOTREACHED */
2380
		}
2381
	}
2382
2383
801
	if (tblcmdopt != NULL) {
2384
30
		argc -= optind;
2385
30
		argv += optind;
2386
30
		ch = *tblcmdopt;
2387
30
		mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY;
2388
801
	} else if (argc != optind) {
2389
		warnx("unknown command line argument: %s ...", argv[optind]);
2390
		usage();
2391
		/* NOTREACHED */
2392
	}
2393
2394
801
	if ((path = calloc(1, PATH_MAX)) == NULL)
2395
		errx(1, "pfctl: calloc");
2396
801
	memset(anchorname, 0, sizeof(anchorname));
2397
801
	if (anchoropt != NULL) {
2398
518
		int len = strlen(anchoropt);
2399
2400
518
		if (anchoropt[len - 1] == '*') {
2401

142
			if (len >= 2 && anchoropt[len - 2] == '/') {
2402
71
				anchoropt[len - 2] = '\0';
2403
				anchor_wildcard = 1;
2404
71
			} else
2405
				anchoropt[len - 1] = '\0';
2406
71
			opts |= PF_OPT_RECURSE;
2407
71
		}
2408
1036
		if (strlcpy(anchorname, anchoropt,
2409
518
		    sizeof(anchorname)) >= sizeof(anchorname))
2410
			errx(1, "anchor name '%s' too long",
2411
			    anchoropt);
2412
518
	}
2413
2414
801
	if ((opts & PF_OPT_NOACTION) == 0) {
2415
520
		dev = open(pf_device, mode);
2416
520
		if (dev == -1)
2417
			err(1, "%s", pf_device);
2418
	} else {
2419
281
		dev = open(pf_device, O_RDONLY);
2420
281
		if (dev >= 0)
2421
281
			opts |= PF_OPT_DUMMYACTION;
2422
		/* turn off options */
2423
281
		opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE);
2424
281
		clearopt = showopt = debugopt = NULL;
2425
	}
2426
2427
801
	if (opts & PF_OPT_DISABLE)
2428
		if (pfctl_disable(dev, opts))
2429
			error = 1;
2430
2431
801
	if (showopt != NULL) {
2432



292
		switch (*showopt) {
2433
		case 'A':
2434
			pfctl_show_anchors(dev, opts, anchorname);
2435
			break;
2436
		case 'r':
2437
142
			pfctl_load_fingerprints(dev, opts);
2438
142
			pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES,
2439
			    anchorname, 0, anchor_wildcard, shownr);
2440
142
			break;
2441
		case 'l':
2442
			pfctl_load_fingerprints(dev, opts);
2443
			pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS,
2444
			    anchorname, 0, anchor_wildcard, shownr);
2445
			break;
2446
		case 'q':
2447
			pfctl_show_queues(dev, ifaceopt, opts,
2448
			    opts & PF_OPT_VERBOSE2);
2449
			break;
2450
		case 's':
2451
			pfctl_show_states(dev, ifaceopt, opts, shownr);
2452
			break;
2453
		case 'S':
2454
			pfctl_show_src_nodes(dev, opts);
2455
			break;
2456
		case 'i':
2457
4
			pfctl_show_status(dev, opts);
2458
4
			break;
2459
		case 't':
2460
			pfctl_show_timeouts(dev, opts);
2461
			break;
2462
		case 'm':
2463
			pfctl_show_limits(dev, opts);
2464
			break;
2465
		case 'a':
2466
			opts |= PF_OPT_SHOWALL;
2467
			pfctl_load_fingerprints(dev, opts);
2468
2469
			pfctl_show_rules(dev, path, opts, 0, anchorname,
2470
			    0, 0, -1);
2471
			pfctl_show_queues(dev, ifaceopt, opts,
2472
			    opts & PF_OPT_VERBOSE2);
2473
			pfctl_show_states(dev, ifaceopt, opts, -1);
2474
			pfctl_show_src_nodes(dev, opts);
2475
			pfctl_show_status(dev, opts);
2476
			pfctl_show_rules(dev, path, opts, 1, anchorname,
2477
			    0, 0, -1);
2478
			pfctl_show_timeouts(dev, opts);
2479
			pfctl_show_limits(dev, opts);
2480
			pfctl_show_tables(anchorname, opts);
2481
			pfctl_show_fingerprints(opts);
2482
			break;
2483
		case 'T':
2484
			pfctl_show_tables(anchorname, opts);
2485
			break;
2486
		case 'o':
2487
			pfctl_load_fingerprints(dev, opts);
2488
			pfctl_show_fingerprints(opts);
2489
			break;
2490
		case 'I':
2491
			pfctl_show_ifaces(ifaceopt, opts);
2492
			break;
2493
		}
2494
	}
2495
2496
801
	if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL)
2497
		pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING,
2498
		    anchorname, 0, 0, -1);
2499
2500
801
	if (clearopt != NULL) {
2501

344
		if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
2502
			errx(1, "anchor names beginning with '_' cannot "
2503
			    "be modified from the command line");
2504
2505


344
		switch (*clearopt) {
2506
		case 'r':
2507
172
			pfctl_clear_rules(dev, opts, anchorname);
2508
172
			break;
2509
		case 's':
2510
			pfctl_clear_states(dev, ifaceopt, opts);
2511
			break;
2512
		case 'S':
2513
			pfctl_clear_src_nodes(dev, opts);
2514
			break;
2515
		case 'i':
2516
			pfctl_clear_stats(dev, ifaceopt, opts);
2517
			break;
2518
		case 'a':
2519
			pfctl_clear_tables(anchorname, opts);
2520
			pfctl_clear_rules(dev, opts, anchorname);
2521
			if (ifaceopt && *ifaceopt) {
2522
				warnx("don't specify an interface with -Fall");
2523
				usage();
2524
				/* NOTREACHED */
2525
			}
2526
			if (!*anchorname) {
2527
				pfctl_clear_states(dev, ifaceopt, opts);
2528
				pfctl_clear_src_nodes(dev, opts);
2529
				pfctl_clear_stats(dev, ifaceopt, opts);
2530
				pfctl_clear_fingerprints(dev, opts);
2531
				pfctl_clear_interface_flags(dev, opts);
2532
			}
2533
			break;
2534
		case 'o':
2535
			pfctl_clear_fingerprints(dev, opts);
2536
			break;
2537
		case 'T':
2538
			pfctl_clear_tables(anchorname, opts);
2539
			break;
2540
		}
2541
	}
2542
801
	if (state_killers) {
2543
		if (!strcmp(state_kill[0], "label"))
2544
			pfctl_label_kill_states(dev, ifaceopt, opts, rdomain);
2545
		else if (!strcmp(state_kill[0], "id"))
2546
			pfctl_id_kill_states(dev, opts);
2547
		else if (!strcmp(state_kill[0], "key"))
2548
			pfctl_key_kill_states(dev, ifaceopt, opts, rdomain);
2549
		else
2550
			pfctl_net_kill_states(dev, ifaceopt, opts, rdomain);
2551
	}
2552
2553
801
	if (src_node_killers)
2554
		pfctl_kill_src_nodes(dev, ifaceopt, opts);
2555
2556
801
	if (tblcmdopt != NULL) {
2557
60
		error = pfctl_command_tables(argc, argv, tableopt,
2558
30
		    tblcmdopt, rulesopt, anchorname, opts);
2559
30
		rulesopt = NULL;
2560
30
	}
2561
801
	if (optiopt != NULL) {
2562

1410
		switch (*optiopt) {
2563
		case 'n':
2564
			optimize = 0;
2565
634
			break;
2566
		case 'b':
2567
			optimize |= PF_OPTIMIZE_BASIC;
2568
71
			break;
2569
		case 'o':
2570
		case 'p':
2571
			optimize |= PF_OPTIMIZE_PROFILE;
2572
			break;
2573
		}
2574
	}
2575
2576

1254
	if (rulesopt != NULL && !anchorname[0]) {
2577
279
		pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET);
2578
279
		if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE))
2579
			error = 1;
2580
	}
2581
2582
801
	if (rulesopt != NULL) {
2583

906
		if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
2584
			errx(1, "anchor names beginning with '_' cannot "
2585
			    "be modified from the command line");
2586
393
		if (pfctl_rules(dev, rulesopt, opts, optimize,
2587
		    anchorname, NULL))
2588
			error = 1;
2589
393
		else if (!(opts & PF_OPT_NOACTION))
2590
172
			warn_namespace_collision(NULL);
2591
	}
2592
2593
741
	if (opts & PF_OPT_ENABLE)
2594
		if (pfctl_enable(dev, opts))
2595
			error = 1;
2596
2597
741
	if (debugopt != NULL) {
2598
		if ((level = string_to_loglevel((char *)debugopt)) < 0) {
2599
			switch (*debugopt) {
2600
			case 'n':
2601
				level = LOG_CRIT;
2602
				break;
2603
			case 'u':
2604
				level = LOG_ERR;
2605
				break;
2606
			case 'm':
2607
				level = LOG_NOTICE;
2608
				break;
2609
			case 'l':
2610
				level = LOG_DEBUG;
2611
				break;
2612
			}
2613
		}
2614
		if (level >= 0)
2615
			pfctl_debug(dev, level, opts);
2616
	}
2617
2618
741
	if (sfile != NULL)
2619
		pfctl_state_store(dev, sfile);
2620
741
	if (lfile != NULL)
2621
		pfctl_state_load(dev, lfile);
2622
2623
	exit(error);
2624
}