xref: /dragonfly/usr.sbin/pfctl/pfctl_table.c (revision a14160bc)
1ed1f0be2SJan Lentfer /*	$OpenBSD: pfctl_table.c,v 1.68 2008/06/21 10:34:08 mcbride Exp $ */
295cc27f0SJoerg Sonnenberger 
395cc27f0SJoerg Sonnenberger /*
495cc27f0SJoerg Sonnenberger  * Copyright (c) 2002 Cedric Berger
595cc27f0SJoerg Sonnenberger  * All rights reserved.
695cc27f0SJoerg Sonnenberger  *
795cc27f0SJoerg Sonnenberger  * Redistribution and use in source and binary forms, with or without
895cc27f0SJoerg Sonnenberger  * modification, are permitted provided that the following conditions
995cc27f0SJoerg Sonnenberger  * are met:
1095cc27f0SJoerg Sonnenberger  *
1195cc27f0SJoerg Sonnenberger  *    - Redistributions of source code must retain the above copyright
1295cc27f0SJoerg Sonnenberger  *      notice, this list of conditions and the following disclaimer.
1395cc27f0SJoerg Sonnenberger  *    - Redistributions in binary form must reproduce the above
1495cc27f0SJoerg Sonnenberger  *      copyright notice, this list of conditions and the following
1595cc27f0SJoerg Sonnenberger  *      disclaimer in the documentation and/or other materials provided
1695cc27f0SJoerg Sonnenberger  *      with the distribution.
1795cc27f0SJoerg Sonnenberger  *
1895cc27f0SJoerg Sonnenberger  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1995cc27f0SJoerg Sonnenberger  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2095cc27f0SJoerg Sonnenberger  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2195cc27f0SJoerg Sonnenberger  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2295cc27f0SJoerg Sonnenberger  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2395cc27f0SJoerg Sonnenberger  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2495cc27f0SJoerg Sonnenberger  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2595cc27f0SJoerg Sonnenberger  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2695cc27f0SJoerg Sonnenberger  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2795cc27f0SJoerg Sonnenberger  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2895cc27f0SJoerg Sonnenberger  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2995cc27f0SJoerg Sonnenberger  * POSSIBILITY OF SUCH DAMAGE.
30*a14160bcSMatthew Dillon  *
3195cc27f0SJoerg Sonnenberger  */
3295cc27f0SJoerg Sonnenberger 
3395cc27f0SJoerg Sonnenberger #include <sys/types.h>
3495cc27f0SJoerg Sonnenberger #include <sys/ioctl.h>
3595cc27f0SJoerg Sonnenberger #include <sys/socket.h>
3695cc27f0SJoerg Sonnenberger 
3795cc27f0SJoerg Sonnenberger #include <net/if.h>
3895cc27f0SJoerg Sonnenberger #include <net/pf/pfvar.h>
3995cc27f0SJoerg Sonnenberger #include <arpa/inet.h>
4095cc27f0SJoerg Sonnenberger 
4195cc27f0SJoerg Sonnenberger #include <ctype.h>
4295cc27f0SJoerg Sonnenberger #include <err.h>
4395cc27f0SJoerg Sonnenberger #include <errno.h>
4495cc27f0SJoerg Sonnenberger #include <netdb.h>
4595cc27f0SJoerg Sonnenberger #include <stdarg.h>
4695cc27f0SJoerg Sonnenberger #include <stdio.h>
4795cc27f0SJoerg Sonnenberger #include <stdlib.h>
4895cc27f0SJoerg Sonnenberger #include <string.h>
4995cc27f0SJoerg Sonnenberger #include <time.h>
5095cc27f0SJoerg Sonnenberger 
5195cc27f0SJoerg Sonnenberger #include "pfctl_parser.h"
5295cc27f0SJoerg Sonnenberger #include "pfctl.h"
5395cc27f0SJoerg Sonnenberger 
5495cc27f0SJoerg Sonnenberger extern void	usage(void);
5595cc27f0SJoerg Sonnenberger static int	pfctl_table(int, char *[], char *, const char *, char *,
5670224baaSJan Lentfer 		    const char *, int);
5795cc27f0SJoerg Sonnenberger static void	print_table(const struct pfr_table *, int, int);
5895cc27f0SJoerg Sonnenberger static void	print_tstats(const struct pfr_tstats *, int);
5995cc27f0SJoerg Sonnenberger static int	load_addr(struct pfr_buffer *, int, char *[], char *, int);
6095cc27f0SJoerg Sonnenberger static void	print_addrx(const struct pfr_addr *, const struct pfr_addr *,
6195cc27f0SJoerg Sonnenberger 			    int);
6295cc27f0SJoerg Sonnenberger static void	print_astats(const struct pfr_astats *, int);
6395cc27f0SJoerg Sonnenberger static void	radix_perror(void);
64b58f1e66SSascha Wildner static void	xprintf(int, const char *, ...) __printflike(2, 3);
6570224baaSJan Lentfer static void	print_iface(const struct pfi_kif *, int);
6695cc27f0SJoerg Sonnenberger 
6795cc27f0SJoerg Sonnenberger static const char	*stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = {
6895cc27f0SJoerg Sonnenberger 	{ "In/Block:",	"In/Pass:",	"In/XPass:" },
6995cc27f0SJoerg Sonnenberger 	{ "Out/Block:",	"Out/Pass:",	"Out/XPass:" }
7095cc27f0SJoerg Sonnenberger };
7195cc27f0SJoerg Sonnenberger 
7295cc27f0SJoerg Sonnenberger static const char	*istats_text[2][2][2] = {
7395cc27f0SJoerg Sonnenberger 	{ { "In4/Pass:", "In4/Block:" }, { "Out4/Pass:", "Out4/Block:" } },
7495cc27f0SJoerg Sonnenberger 	{ { "In6/Pass:", "In6/Block:" }, { "Out6/Pass:", "Out6/Block:" } }
7595cc27f0SJoerg Sonnenberger };
7695cc27f0SJoerg Sonnenberger 
7795cc27f0SJoerg Sonnenberger #define RVTEST(fct) do {				\
7895cc27f0SJoerg Sonnenberger 		if ((!(opts & PF_OPT_NOACTION) ||	\
7995cc27f0SJoerg Sonnenberger 		    (opts & PF_OPT_DUMMYACTION)) &&	\
8095cc27f0SJoerg Sonnenberger 		    (fct)) {				\
8195cc27f0SJoerg Sonnenberger 			radix_perror();			\
8295cc27f0SJoerg Sonnenberger 			goto _error;			\
8395cc27f0SJoerg Sonnenberger 		}					\
8495cc27f0SJoerg Sonnenberger 	} while (0)
8595cc27f0SJoerg Sonnenberger 
8695cc27f0SJoerg Sonnenberger #define CREATE_TABLE do {						\
8795cc27f0SJoerg Sonnenberger 		table.pfrt_flags |= PFR_TFLAG_PERSIST;			\
8870224baaSJan Lentfer 		if ((!(opts & PF_OPT_NOACTION) ||			\
8970224baaSJan Lentfer 		    (opts & PF_OPT_DUMMYACTION)) &&			\
9070224baaSJan Lentfer 		    (pfr_add_tables(&table, 1, &nadd, flags)) &&	\
9170224baaSJan Lentfer 		    (errno != EPERM)) {					\
9270224baaSJan Lentfer 			radix_perror();					\
9370224baaSJan Lentfer 			goto _error;					\
9470224baaSJan Lentfer 		}							\
9595cc27f0SJoerg Sonnenberger 		if (nadd) {						\
9695cc27f0SJoerg Sonnenberger 			warn_namespace_collision(table.pfrt_name);	\
9795cc27f0SJoerg Sonnenberger 			xprintf(opts, "%d table created", nadd);	\
9895cc27f0SJoerg Sonnenberger 			if (opts & PF_OPT_NOACTION)			\
9995cc27f0SJoerg Sonnenberger 				return (0);				\
10095cc27f0SJoerg Sonnenberger 		}							\
10195cc27f0SJoerg Sonnenberger 		table.pfrt_flags &= ~PFR_TFLAG_PERSIST;			\
10295cc27f0SJoerg Sonnenberger 	} while(0)
10395cc27f0SJoerg Sonnenberger 
10495cc27f0SJoerg Sonnenberger int
pfctl_clear_tables(const char * anchor,int opts)10570224baaSJan Lentfer pfctl_clear_tables(const char *anchor, int opts)
10695cc27f0SJoerg Sonnenberger {
10770224baaSJan Lentfer 	return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts);
10895cc27f0SJoerg Sonnenberger }
10995cc27f0SJoerg Sonnenberger 
11095cc27f0SJoerg Sonnenberger int
pfctl_show_tables(const char * anchor,int opts)11170224baaSJan Lentfer pfctl_show_tables(const char *anchor, int opts)
11295cc27f0SJoerg Sonnenberger {
11370224baaSJan Lentfer 	return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts);
11495cc27f0SJoerg Sonnenberger }
11595cc27f0SJoerg Sonnenberger 
11695cc27f0SJoerg Sonnenberger int
pfctl_command_tables(int argc,char * argv[],char * tname,const char * command,char * file,const char * anchor,int opts)11795cc27f0SJoerg Sonnenberger pfctl_command_tables(int argc, char *argv[], char *tname,
11870224baaSJan Lentfer     const char *command, char *file, const char *anchor, int opts)
11995cc27f0SJoerg Sonnenberger {
12095cc27f0SJoerg Sonnenberger 	if (tname == NULL || command == NULL)
12195cc27f0SJoerg Sonnenberger 		usage();
12270224baaSJan Lentfer 	return pfctl_table(argc, argv, tname, command, file, anchor, opts);
12395cc27f0SJoerg Sonnenberger }
12495cc27f0SJoerg Sonnenberger 
12595cc27f0SJoerg Sonnenberger int
pfctl_table(int argc,char * argv[],char * tname,const char * command,char * file,const char * anchor,int opts)12695cc27f0SJoerg Sonnenberger pfctl_table(int argc, char *argv[], char *tname, const char *command,
12770224baaSJan Lentfer     char *file, const char *anchor, int opts)
12895cc27f0SJoerg Sonnenberger {
12995cc27f0SJoerg Sonnenberger 	struct pfr_table	 table;
13095cc27f0SJoerg Sonnenberger 	struct pfr_buffer	 b, b2;
13195cc27f0SJoerg Sonnenberger 	const struct pfr_addr	*a, *a2;
13295cc27f0SJoerg Sonnenberger 	int			 nadd = 0, ndel = 0, nchange = 0, nzero = 0;
13395cc27f0SJoerg Sonnenberger 	int			 rv = 0, flags = 0, nmatch = 0;
13495cc27f0SJoerg Sonnenberger 	const void		*p;
13595cc27f0SJoerg Sonnenberger 
13695cc27f0SJoerg Sonnenberger 	if (command == NULL)
13795cc27f0SJoerg Sonnenberger 		usage();
13895cc27f0SJoerg Sonnenberger 	if (opts & PF_OPT_NOACTION)
13995cc27f0SJoerg Sonnenberger 		flags |= PFR_FLAG_DUMMY;
14095cc27f0SJoerg Sonnenberger 
14195cc27f0SJoerg Sonnenberger 	bzero(&b, sizeof(b));
14295cc27f0SJoerg Sonnenberger 	bzero(&b2, sizeof(b2));
14395cc27f0SJoerg Sonnenberger 	bzero(&table, sizeof(table));
14495cc27f0SJoerg Sonnenberger 	if (tname != NULL) {
14595cc27f0SJoerg Sonnenberger 		if (strlen(tname) >= PF_TABLE_NAME_SIZE)
14695cc27f0SJoerg Sonnenberger 			usage();
14795cc27f0SJoerg Sonnenberger 		if (strlcpy(table.pfrt_name, tname,
14895cc27f0SJoerg Sonnenberger 		    sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name))
14995cc27f0SJoerg Sonnenberger 			errx(1, "pfctl_table: strlcpy");
15095cc27f0SJoerg Sonnenberger 	}
15195cc27f0SJoerg Sonnenberger 	if (strlcpy(table.pfrt_anchor, anchor,
15270224baaSJan Lentfer 	    sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor))
15395cc27f0SJoerg Sonnenberger 		errx(1, "pfctl_table: strlcpy");
15495cc27f0SJoerg Sonnenberger 
15595cc27f0SJoerg Sonnenberger 	if (!strcmp(command, "-F")) {
15695cc27f0SJoerg Sonnenberger 		if (argc || file != NULL)
15795cc27f0SJoerg Sonnenberger 			usage();
15895cc27f0SJoerg Sonnenberger 		RVTEST(pfr_clr_tables(&table, &ndel, flags));
15995cc27f0SJoerg Sonnenberger 		xprintf(opts, "%d tables deleted", ndel);
16095cc27f0SJoerg Sonnenberger 	} else if (!strcmp(command, "-s")) {
16195cc27f0SJoerg Sonnenberger 		b.pfrb_type = (opts & PF_OPT_VERBOSE2) ?
16295cc27f0SJoerg Sonnenberger 		    PFRB_TSTATS : PFRB_TABLES;
16395cc27f0SJoerg Sonnenberger 		if (argc || file != NULL)
16495cc27f0SJoerg Sonnenberger 			usage();
16595cc27f0SJoerg Sonnenberger 		for (;;) {
16695cc27f0SJoerg Sonnenberger 			pfr_buf_grow(&b, b.pfrb_size);
16795cc27f0SJoerg Sonnenberger 			b.pfrb_size = b.pfrb_msize;
16895cc27f0SJoerg Sonnenberger 			if (opts & PF_OPT_VERBOSE2)
16995cc27f0SJoerg Sonnenberger 				RVTEST(pfr_get_tstats(&table,
17095cc27f0SJoerg Sonnenberger 				    b.pfrb_caddr, &b.pfrb_size, flags));
17195cc27f0SJoerg Sonnenberger 			else
17295cc27f0SJoerg Sonnenberger 				RVTEST(pfr_get_tables(&table,
17395cc27f0SJoerg Sonnenberger 				    b.pfrb_caddr, &b.pfrb_size, flags));
17495cc27f0SJoerg Sonnenberger 			if (b.pfrb_size <= b.pfrb_msize)
17595cc27f0SJoerg Sonnenberger 				break;
17695cc27f0SJoerg Sonnenberger 		}
17795cc27f0SJoerg Sonnenberger 
17870224baaSJan Lentfer 		if ((opts & PF_OPT_SHOWALL) && b.pfrb_size > 0)
17995cc27f0SJoerg Sonnenberger 			pfctl_print_title("TABLES:");
18095cc27f0SJoerg Sonnenberger 
18195cc27f0SJoerg Sonnenberger 		PFRB_FOREACH(p, &b)
18295cc27f0SJoerg Sonnenberger 			if (opts & PF_OPT_VERBOSE2)
18395cc27f0SJoerg Sonnenberger 				print_tstats(p, opts & PF_OPT_DEBUG);
18495cc27f0SJoerg Sonnenberger 			else
18595cc27f0SJoerg Sonnenberger 				print_table(p, opts & PF_OPT_VERBOSE,
18695cc27f0SJoerg Sonnenberger 				    opts & PF_OPT_DEBUG);
18795cc27f0SJoerg Sonnenberger 	} else if (!strcmp(command, "kill")) {
18895cc27f0SJoerg Sonnenberger 		if (argc || file != NULL)
18995cc27f0SJoerg Sonnenberger 			usage();
19095cc27f0SJoerg Sonnenberger 		RVTEST(pfr_del_tables(&table, 1, &ndel, flags));
19195cc27f0SJoerg Sonnenberger 		xprintf(opts, "%d table deleted", ndel);
19295cc27f0SJoerg Sonnenberger 	} else if (!strcmp(command, "flush")) {
19395cc27f0SJoerg Sonnenberger 		if (argc || file != NULL)
19495cc27f0SJoerg Sonnenberger 			usage();
19595cc27f0SJoerg Sonnenberger 		RVTEST(pfr_clr_addrs(&table, &ndel, flags));
19695cc27f0SJoerg Sonnenberger 		xprintf(opts, "%d addresses deleted", ndel);
19795cc27f0SJoerg Sonnenberger 	} else if (!strcmp(command, "add")) {
19895cc27f0SJoerg Sonnenberger 		b.pfrb_type = PFRB_ADDRS;
19995cc27f0SJoerg Sonnenberger 		if (load_addr(&b, argc, argv, file, 0))
20095cc27f0SJoerg Sonnenberger 			goto _error;
20195cc27f0SJoerg Sonnenberger 		CREATE_TABLE;
20295cc27f0SJoerg Sonnenberger 		if (opts & PF_OPT_VERBOSE)
20395cc27f0SJoerg Sonnenberger 			flags |= PFR_FLAG_FEEDBACK;
20495cc27f0SJoerg Sonnenberger 		RVTEST(pfr_add_addrs(&table, b.pfrb_caddr, b.pfrb_size,
20595cc27f0SJoerg Sonnenberger 		    &nadd, flags));
20695cc27f0SJoerg Sonnenberger 		xprintf(opts, "%d/%d addresses added", nadd, b.pfrb_size);
20795cc27f0SJoerg Sonnenberger 		if (opts & PF_OPT_VERBOSE)
20895cc27f0SJoerg Sonnenberger 			PFRB_FOREACH(a, &b)
20995cc27f0SJoerg Sonnenberger 				if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
21095cc27f0SJoerg Sonnenberger 					print_addrx(a, NULL,
21195cc27f0SJoerg Sonnenberger 					    opts & PF_OPT_USEDNS);
21295cc27f0SJoerg Sonnenberger 	} else if (!strcmp(command, "delete")) {
21395cc27f0SJoerg Sonnenberger 		b.pfrb_type = PFRB_ADDRS;
21495cc27f0SJoerg Sonnenberger 		if (load_addr(&b, argc, argv, file, 0))
21595cc27f0SJoerg Sonnenberger 			goto _error;
21695cc27f0SJoerg Sonnenberger 		if (opts & PF_OPT_VERBOSE)
21795cc27f0SJoerg Sonnenberger 			flags |= PFR_FLAG_FEEDBACK;
21895cc27f0SJoerg Sonnenberger 		RVTEST(pfr_del_addrs(&table, b.pfrb_caddr, b.pfrb_size,
21995cc27f0SJoerg Sonnenberger 		    &ndel, flags));
22095cc27f0SJoerg Sonnenberger 		xprintf(opts, "%d/%d addresses deleted", ndel, b.pfrb_size);
22195cc27f0SJoerg Sonnenberger 		if (opts & PF_OPT_VERBOSE)
22295cc27f0SJoerg Sonnenberger 			PFRB_FOREACH(a, &b)
22395cc27f0SJoerg Sonnenberger 				if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
22495cc27f0SJoerg Sonnenberger 					print_addrx(a, NULL,
22595cc27f0SJoerg Sonnenberger 					    opts & PF_OPT_USEDNS);
22695cc27f0SJoerg Sonnenberger 	} else if (!strcmp(command, "replace")) {
22795cc27f0SJoerg Sonnenberger 		b.pfrb_type = PFRB_ADDRS;
22895cc27f0SJoerg Sonnenberger 		if (load_addr(&b, argc, argv, file, 0))
22995cc27f0SJoerg Sonnenberger 			goto _error;
23095cc27f0SJoerg Sonnenberger 		CREATE_TABLE;
23195cc27f0SJoerg Sonnenberger 		if (opts & PF_OPT_VERBOSE)
23295cc27f0SJoerg Sonnenberger 			flags |= PFR_FLAG_FEEDBACK;
23395cc27f0SJoerg Sonnenberger 		for (;;) {
23495cc27f0SJoerg Sonnenberger 			int sz2 = b.pfrb_msize;
23595cc27f0SJoerg Sonnenberger 
23695cc27f0SJoerg Sonnenberger 			RVTEST(pfr_set_addrs(&table, b.pfrb_caddr, b.pfrb_size,
23795cc27f0SJoerg Sonnenberger 			    &sz2, &nadd, &ndel, &nchange, flags));
23895cc27f0SJoerg Sonnenberger 			if (sz2 <= b.pfrb_msize) {
23995cc27f0SJoerg Sonnenberger 				b.pfrb_size = sz2;
24095cc27f0SJoerg Sonnenberger 				break;
24195cc27f0SJoerg Sonnenberger 			} else
24295cc27f0SJoerg Sonnenberger 				pfr_buf_grow(&b, sz2);
24395cc27f0SJoerg Sonnenberger 		}
24495cc27f0SJoerg Sonnenberger 		if (nadd)
24595cc27f0SJoerg Sonnenberger 			xprintf(opts, "%d addresses added", nadd);
24695cc27f0SJoerg Sonnenberger 		if (ndel)
24795cc27f0SJoerg Sonnenberger 			xprintf(opts, "%d addresses deleted", ndel);
24895cc27f0SJoerg Sonnenberger 		if (nchange)
24995cc27f0SJoerg Sonnenberger 			xprintf(opts, "%d addresses changed", nchange);
25095cc27f0SJoerg Sonnenberger 		if (!nadd && !ndel && !nchange)
25195cc27f0SJoerg Sonnenberger 			xprintf(opts, "no changes");
25295cc27f0SJoerg Sonnenberger 		if (opts & PF_OPT_VERBOSE)
25395cc27f0SJoerg Sonnenberger 			PFRB_FOREACH(a, &b)
25495cc27f0SJoerg Sonnenberger 				if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
25595cc27f0SJoerg Sonnenberger 					print_addrx(a, NULL,
25695cc27f0SJoerg Sonnenberger 					    opts & PF_OPT_USEDNS);
25770224baaSJan Lentfer 	} else if (!strcmp(command, "expire")) {
25870224baaSJan Lentfer 		const char		*errstr;
25970224baaSJan Lentfer 		u_int			 lifetime;
26070224baaSJan Lentfer 
26170224baaSJan Lentfer 		b.pfrb_type = PFRB_ASTATS;
26270224baaSJan Lentfer 		b2.pfrb_type = PFRB_ADDRS;
26370224baaSJan Lentfer 		if (argc != 1 || file != NULL)
26470224baaSJan Lentfer 			usage();
26570224baaSJan Lentfer 		lifetime = strtonum(*argv, 0, UINT_MAX, &errstr);
26670224baaSJan Lentfer 		if (errstr)
26770224baaSJan Lentfer 			errx(1, "expiry time: %s", errstr);
26870224baaSJan Lentfer 		for (;;) {
26970224baaSJan Lentfer 			pfr_buf_grow(&b, b.pfrb_size);
27070224baaSJan Lentfer 			b.pfrb_size = b.pfrb_msize;
27170224baaSJan Lentfer 			RVTEST(pfr_get_astats(&table, b.pfrb_caddr,
27270224baaSJan Lentfer 			    &b.pfrb_size, flags));
27370224baaSJan Lentfer 			if (b.pfrb_size <= b.pfrb_msize)
27470224baaSJan Lentfer 				break;
27570224baaSJan Lentfer 		}
276ed1f0be2SJan Lentfer 		PFRB_FOREACH(p, &b) {
277ed1f0be2SJan Lentfer 			((struct pfr_astats *)p)->pfras_a.pfra_fback = 0;
27870224baaSJan Lentfer 			if (time(NULL) - ((struct pfr_astats *)p)->pfras_tzero >
27970224baaSJan Lentfer 			     lifetime)
28070224baaSJan Lentfer 				if (pfr_buf_add(&b2,
28170224baaSJan Lentfer 				    &((struct pfr_astats *)p)->pfras_a))
28270224baaSJan Lentfer 					err(1, "duplicate buffer");
283ed1f0be2SJan Lentfer 		}
28470224baaSJan Lentfer 
28570224baaSJan Lentfer 		if (opts & PF_OPT_VERBOSE)
28670224baaSJan Lentfer 			flags |= PFR_FLAG_FEEDBACK;
28770224baaSJan Lentfer 		RVTEST(pfr_del_addrs(&table, b2.pfrb_caddr, b2.pfrb_size,
28870224baaSJan Lentfer 		    &ndel, flags));
28970224baaSJan Lentfer 		xprintf(opts, "%d/%d addresses expired", ndel, b2.pfrb_size);
29070224baaSJan Lentfer 		if (opts & PF_OPT_VERBOSE)
29170224baaSJan Lentfer 			PFRB_FOREACH(a, &b2)
29270224baaSJan Lentfer 				if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
29370224baaSJan Lentfer 					print_addrx(a, NULL,
29470224baaSJan Lentfer 					    opts & PF_OPT_USEDNS);
29595cc27f0SJoerg Sonnenberger 	} else if (!strcmp(command, "show")) {
29695cc27f0SJoerg Sonnenberger 		b.pfrb_type = (opts & PF_OPT_VERBOSE) ?
29795cc27f0SJoerg Sonnenberger 			PFRB_ASTATS : PFRB_ADDRS;
29895cc27f0SJoerg Sonnenberger 		if (argc || file != NULL)
29995cc27f0SJoerg Sonnenberger 			usage();
30095cc27f0SJoerg Sonnenberger 		for (;;) {
30195cc27f0SJoerg Sonnenberger 			pfr_buf_grow(&b, b.pfrb_size);
30295cc27f0SJoerg Sonnenberger 			b.pfrb_size = b.pfrb_msize;
30395cc27f0SJoerg Sonnenberger 			if (opts & PF_OPT_VERBOSE)
30495cc27f0SJoerg Sonnenberger 				RVTEST(pfr_get_astats(&table, b.pfrb_caddr,
30595cc27f0SJoerg Sonnenberger 				    &b.pfrb_size, flags));
30695cc27f0SJoerg Sonnenberger 			else
30795cc27f0SJoerg Sonnenberger 				RVTEST(pfr_get_addrs(&table, b.pfrb_caddr,
30895cc27f0SJoerg Sonnenberger 				    &b.pfrb_size, flags));
30995cc27f0SJoerg Sonnenberger 			if (b.pfrb_size <= b.pfrb_msize)
31095cc27f0SJoerg Sonnenberger 				break;
31195cc27f0SJoerg Sonnenberger 		}
31295cc27f0SJoerg Sonnenberger 		PFRB_FOREACH(p, &b)
31395cc27f0SJoerg Sonnenberger 			if (opts & PF_OPT_VERBOSE)
31495cc27f0SJoerg Sonnenberger 				print_astats(p, opts & PF_OPT_USEDNS);
31595cc27f0SJoerg Sonnenberger 			else
31695cc27f0SJoerg Sonnenberger 				print_addrx(p, NULL, opts & PF_OPT_USEDNS);
31795cc27f0SJoerg Sonnenberger 	} else if (!strcmp(command, "test")) {
31895cc27f0SJoerg Sonnenberger 		b.pfrb_type = PFRB_ADDRS;
31995cc27f0SJoerg Sonnenberger 		b2.pfrb_type = PFRB_ADDRS;
32095cc27f0SJoerg Sonnenberger 
32195cc27f0SJoerg Sonnenberger 		if (load_addr(&b, argc, argv, file, 1))
32295cc27f0SJoerg Sonnenberger 			goto _error;
32395cc27f0SJoerg Sonnenberger 		if (opts & PF_OPT_VERBOSE2) {
32495cc27f0SJoerg Sonnenberger 			flags |= PFR_FLAG_REPLACE;
32595cc27f0SJoerg Sonnenberger 			PFRB_FOREACH(a, &b)
32695cc27f0SJoerg Sonnenberger 				if (pfr_buf_add(&b2, a))
32795cc27f0SJoerg Sonnenberger 					err(1, "duplicate buffer");
32895cc27f0SJoerg Sonnenberger 		}
32995cc27f0SJoerg Sonnenberger 		RVTEST(pfr_tst_addrs(&table, b.pfrb_caddr, b.pfrb_size,
33095cc27f0SJoerg Sonnenberger 		    &nmatch, flags));
33195cc27f0SJoerg Sonnenberger 		xprintf(opts, "%d/%d addresses match", nmatch, b.pfrb_size);
33270224baaSJan Lentfer 		if ((opts & PF_OPT_VERBOSE) && !(opts & PF_OPT_VERBOSE2))
33395cc27f0SJoerg Sonnenberger 			PFRB_FOREACH(a, &b)
33495cc27f0SJoerg Sonnenberger 				if (a->pfra_fback == PFR_FB_MATCH)
33595cc27f0SJoerg Sonnenberger 					print_addrx(a, NULL,
33695cc27f0SJoerg Sonnenberger 					    opts & PF_OPT_USEDNS);
33795cc27f0SJoerg Sonnenberger 		if (opts & PF_OPT_VERBOSE2) {
33895cc27f0SJoerg Sonnenberger 			a2 = NULL;
33995cc27f0SJoerg Sonnenberger 			PFRB_FOREACH(a, &b) {
34095cc27f0SJoerg Sonnenberger 				a2 = pfr_buf_next(&b2, a2);
34195cc27f0SJoerg Sonnenberger 				print_addrx(a2, a, opts & PF_OPT_USEDNS);
34295cc27f0SJoerg Sonnenberger 			}
34395cc27f0SJoerg Sonnenberger 		}
34495cc27f0SJoerg Sonnenberger 		if (nmatch < b.pfrb_size)
34595cc27f0SJoerg Sonnenberger 			rv = 2;
34695cc27f0SJoerg Sonnenberger 	} else if (!strcmp(command, "zero")) {
34795cc27f0SJoerg Sonnenberger 		if (argc || file != NULL)
34895cc27f0SJoerg Sonnenberger 			usage();
34995cc27f0SJoerg Sonnenberger 		flags |= PFR_FLAG_ADDRSTOO;
35095cc27f0SJoerg Sonnenberger 		RVTEST(pfr_clr_tstats(&table, 1, &nzero, flags));
35195cc27f0SJoerg Sonnenberger 		xprintf(opts, "%d table/stats cleared", nzero);
35295cc27f0SJoerg Sonnenberger 	} else
35395cc27f0SJoerg Sonnenberger 		warnx("pfctl_table: unknown command '%s'", command);
35495cc27f0SJoerg Sonnenberger 	goto _cleanup;
35595cc27f0SJoerg Sonnenberger 
35695cc27f0SJoerg Sonnenberger _error:
35795cc27f0SJoerg Sonnenberger 	rv = -1;
35895cc27f0SJoerg Sonnenberger _cleanup:
35995cc27f0SJoerg Sonnenberger 	pfr_buf_clear(&b);
36095cc27f0SJoerg Sonnenberger 	pfr_buf_clear(&b2);
36195cc27f0SJoerg Sonnenberger 	return (rv);
36295cc27f0SJoerg Sonnenberger }
36395cc27f0SJoerg Sonnenberger 
36495cc27f0SJoerg Sonnenberger void
print_table(const struct pfr_table * ta,int verbose,int debug)36595cc27f0SJoerg Sonnenberger print_table(const struct pfr_table *ta, int verbose, int debug)
36695cc27f0SJoerg Sonnenberger {
36795cc27f0SJoerg Sonnenberger 	if (!debug && !(ta->pfrt_flags & PFR_TFLAG_ACTIVE))
36895cc27f0SJoerg Sonnenberger 		return;
36995cc27f0SJoerg Sonnenberger 	if (verbose) {
370ed1f0be2SJan Lentfer 		printf("%c%c%c%c%c%c%c\t%s",
37195cc27f0SJoerg Sonnenberger 		    (ta->pfrt_flags & PFR_TFLAG_CONST) ? 'c' : '-',
37295cc27f0SJoerg Sonnenberger 		    (ta->pfrt_flags & PFR_TFLAG_PERSIST) ? 'p' : '-',
37395cc27f0SJoerg Sonnenberger 		    (ta->pfrt_flags & PFR_TFLAG_ACTIVE) ? 'a' : '-',
37495cc27f0SJoerg Sonnenberger 		    (ta->pfrt_flags & PFR_TFLAG_INACTIVE) ? 'i' : '-',
37595cc27f0SJoerg Sonnenberger 		    (ta->pfrt_flags & PFR_TFLAG_REFERENCED) ? 'r' : '-',
37695cc27f0SJoerg Sonnenberger 		    (ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-',
377ed1f0be2SJan Lentfer 		    (ta->pfrt_flags & PFR_TFLAG_COUNTERS) ? 'C' : '-',
37895cc27f0SJoerg Sonnenberger 		    ta->pfrt_name);
37995cc27f0SJoerg Sonnenberger 		if (ta->pfrt_anchor[0])
38095cc27f0SJoerg Sonnenberger 			printf("\t%s", ta->pfrt_anchor);
38195cc27f0SJoerg Sonnenberger 		puts("");
38295cc27f0SJoerg Sonnenberger 	} else
38395cc27f0SJoerg Sonnenberger 		puts(ta->pfrt_name);
38495cc27f0SJoerg Sonnenberger }
38595cc27f0SJoerg Sonnenberger 
38695cc27f0SJoerg Sonnenberger void
print_tstats(const struct pfr_tstats * ts,int debug)38795cc27f0SJoerg Sonnenberger print_tstats(const struct pfr_tstats *ts, int debug)
38895cc27f0SJoerg Sonnenberger {
38995cc27f0SJoerg Sonnenberger 	time_t	rtime = ts->pfrts_tzero;
39095cc27f0SJoerg Sonnenberger 	int	dir, op;
39195cc27f0SJoerg Sonnenberger 
39295cc27f0SJoerg Sonnenberger 	if (!debug && !(ts->pfrts_flags & PFR_TFLAG_ACTIVE))
39395cc27f0SJoerg Sonnenberger 		return;
39495cc27f0SJoerg Sonnenberger 	print_table(&ts->pfrts_t, 1, debug);
39595cc27f0SJoerg Sonnenberger 	printf("\tAddresses:   %d\n", ts->pfrts_cnt);
39695cc27f0SJoerg Sonnenberger 	printf("\tCleared:     %s", ctime(&rtime));
39795cc27f0SJoerg Sonnenberger 	printf("\tReferences:  [ Anchors: %-18d Rules: %-18d ]\n",
39895cc27f0SJoerg Sonnenberger 	    ts->pfrts_refcnt[PFR_REFCNT_ANCHOR],
39995cc27f0SJoerg Sonnenberger 	    ts->pfrts_refcnt[PFR_REFCNT_RULE]);
40095cc27f0SJoerg Sonnenberger 	printf("\tEvaluations: [ NoMatch: %-18llu Match: %-18llu ]\n",
40195cc27f0SJoerg Sonnenberger 	    (unsigned long long)ts->pfrts_nomatch,
40295cc27f0SJoerg Sonnenberger 	    (unsigned long long)ts->pfrts_match);
40395cc27f0SJoerg Sonnenberger 	for (dir = 0; dir < PFR_DIR_MAX; dir++)
40495cc27f0SJoerg Sonnenberger 		for (op = 0; op < PFR_OP_TABLE_MAX; op++)
40595cc27f0SJoerg Sonnenberger 			printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
40695cc27f0SJoerg Sonnenberger 			    stats_text[dir][op],
40795cc27f0SJoerg Sonnenberger 			    (unsigned long long)ts->pfrts_packets[dir][op],
40895cc27f0SJoerg Sonnenberger 			    (unsigned long long)ts->pfrts_bytes[dir][op]);
40995cc27f0SJoerg Sonnenberger }
41095cc27f0SJoerg Sonnenberger 
41195cc27f0SJoerg Sonnenberger int
load_addr(struct pfr_buffer * b,int argc,char * argv[],char * file,int nonetwork)41295cc27f0SJoerg Sonnenberger load_addr(struct pfr_buffer *b, int argc, char *argv[], char *file,
41395cc27f0SJoerg Sonnenberger     int nonetwork)
41495cc27f0SJoerg Sonnenberger {
41595cc27f0SJoerg Sonnenberger 	while (argc--)
41695cc27f0SJoerg Sonnenberger 		if (append_addr(b, *argv++, nonetwork)) {
41795cc27f0SJoerg Sonnenberger 			if (errno)
41895cc27f0SJoerg Sonnenberger 				warn("cannot decode %s", argv[-1]);
41995cc27f0SJoerg Sonnenberger 			return (-1);
42095cc27f0SJoerg Sonnenberger 		}
42195cc27f0SJoerg Sonnenberger 	if (pfr_buf_load(b, file, nonetwork, append_addr)) {
42295cc27f0SJoerg Sonnenberger 		warn("cannot load %s", file);
42395cc27f0SJoerg Sonnenberger 		return (-1);
42495cc27f0SJoerg Sonnenberger 	}
42595cc27f0SJoerg Sonnenberger 	return (0);
42695cc27f0SJoerg Sonnenberger }
42795cc27f0SJoerg Sonnenberger 
42895cc27f0SJoerg Sonnenberger void
print_addrx(const struct pfr_addr * ad,const struct pfr_addr * rad,int dns)42995cc27f0SJoerg Sonnenberger print_addrx(const struct pfr_addr *ad, const struct pfr_addr *rad, int dns)
43095cc27f0SJoerg Sonnenberger {
43195cc27f0SJoerg Sonnenberger 	char		ch, buf[256] = "{error}";
432ed1f0be2SJan Lentfer 	char		fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y', ' ' };
43395cc27f0SJoerg Sonnenberger 	unsigned int	fback, hostnet;
43495cc27f0SJoerg Sonnenberger 
43595cc27f0SJoerg Sonnenberger 	fback = (rad != NULL) ? rad->pfra_fback : ad->pfra_fback;
43695cc27f0SJoerg Sonnenberger 	ch = (fback < sizeof(fb)/sizeof(*fb)) ? fb[fback] : '?';
43795cc27f0SJoerg Sonnenberger 	hostnet = (ad->pfra_af == AF_INET6) ? 128 : 32;
43895cc27f0SJoerg Sonnenberger 	inet_ntop(ad->pfra_af, &ad->pfra_u, buf, sizeof(buf));
43995cc27f0SJoerg Sonnenberger 	printf("%c %c%s", ch, (ad->pfra_not?'!':' '), buf);
44095cc27f0SJoerg Sonnenberger 	if (ad->pfra_net < hostnet)
44195cc27f0SJoerg Sonnenberger 		printf("/%d", ad->pfra_net);
44295cc27f0SJoerg Sonnenberger 	if (rad != NULL && fback != PFR_FB_NONE) {
44395cc27f0SJoerg Sonnenberger 		if (strlcpy(buf, "{error}", sizeof(buf)) >= sizeof(buf))
44495cc27f0SJoerg Sonnenberger 			errx(1, "print_addrx: strlcpy");
44595cc27f0SJoerg Sonnenberger 		inet_ntop(rad->pfra_af, &rad->pfra_u, buf, sizeof(buf));
44695cc27f0SJoerg Sonnenberger 		printf("\t%c%s", (rad->pfra_not?'!':' '), buf);
44795cc27f0SJoerg Sonnenberger 		if (rad->pfra_net < hostnet)
44895cc27f0SJoerg Sonnenberger 			printf("/%d", rad->pfra_net);
44995cc27f0SJoerg Sonnenberger 	}
45095cc27f0SJoerg Sonnenberger 	if (rad != NULL && fback == PFR_FB_NONE)
45195cc27f0SJoerg Sonnenberger 		printf("\t nomatch");
45295cc27f0SJoerg Sonnenberger 	if (dns && ad->pfra_net == hostnet) {
45395cc27f0SJoerg Sonnenberger 		char hostname[NI_MAXHOST];
45495cc27f0SJoerg Sonnenberger 		union sockaddr_union sa;
45595cc27f0SJoerg Sonnenberger 
45695cc27f0SJoerg Sonnenberger 		strlcpy(hostname, "?", sizeof(hostname));
45795cc27f0SJoerg Sonnenberger 		bzero(&sa, sizeof(sa));
45895cc27f0SJoerg Sonnenberger 		sa.sa.sa_family = ad->pfra_af;
45995cc27f0SJoerg Sonnenberger 		if (sa.sa.sa_family == AF_INET) {
46095cc27f0SJoerg Sonnenberger 			sa.sa.sa_len = sizeof(sa.sin);
46195cc27f0SJoerg Sonnenberger 			sa.sin.sin_addr = ad->pfra_ip4addr;
46295cc27f0SJoerg Sonnenberger 		} else {
46395cc27f0SJoerg Sonnenberger 			sa.sa.sa_len = sizeof(sa.sin6);
46495cc27f0SJoerg Sonnenberger 			sa.sin6.sin6_addr = ad->pfra_ip6addr;
46595cc27f0SJoerg Sonnenberger 		}
46695cc27f0SJoerg Sonnenberger 		if (getnameinfo(&sa.sa, sa.sa.sa_len, hostname, sizeof(hostname),
46795cc27f0SJoerg Sonnenberger 		    NULL, 0, NI_NAMEREQD) == 0)
46895cc27f0SJoerg Sonnenberger 			printf("\t(%s)", hostname);
46995cc27f0SJoerg Sonnenberger 	}
47095cc27f0SJoerg Sonnenberger 	printf("\n");
47195cc27f0SJoerg Sonnenberger }
47295cc27f0SJoerg Sonnenberger 
47395cc27f0SJoerg Sonnenberger void
print_astats(const struct pfr_astats * as,int dns)47495cc27f0SJoerg Sonnenberger print_astats(const struct pfr_astats *as, int dns)
47595cc27f0SJoerg Sonnenberger {
47695cc27f0SJoerg Sonnenberger 	time_t	rtime = as->pfras_tzero;
47795cc27f0SJoerg Sonnenberger 	int	dir, op;
47895cc27f0SJoerg Sonnenberger 
47995cc27f0SJoerg Sonnenberger 	print_addrx(&as->pfras_a, NULL, dns);
48095cc27f0SJoerg Sonnenberger 	printf("\tCleared:     %s", ctime(&rtime));
481ed1f0be2SJan Lentfer  	if (as->pfras_a.pfra_fback == PFR_FB_NOCOUNT)
482ed1f0be2SJan Lentfer 		return;
48395cc27f0SJoerg Sonnenberger 	for (dir = 0; dir < PFR_DIR_MAX; dir++)
48495cc27f0SJoerg Sonnenberger 		for (op = 0; op < PFR_OP_ADDR_MAX; op++)
48595cc27f0SJoerg Sonnenberger 			printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
48695cc27f0SJoerg Sonnenberger 			    stats_text[dir][op],
48795cc27f0SJoerg Sonnenberger 			    (unsigned long long)as->pfras_packets[dir][op],
48895cc27f0SJoerg Sonnenberger 			    (unsigned long long)as->pfras_bytes[dir][op]);
48995cc27f0SJoerg Sonnenberger }
49095cc27f0SJoerg Sonnenberger 
49195cc27f0SJoerg Sonnenberger void
radix_perror(void)49295cc27f0SJoerg Sonnenberger radix_perror(void)
49395cc27f0SJoerg Sonnenberger {
49495cc27f0SJoerg Sonnenberger 	fprintf(stderr, "%s: %s.\n", getprogname(), pfr_strerror(errno));
49595cc27f0SJoerg Sonnenberger }
49695cc27f0SJoerg Sonnenberger 
49795cc27f0SJoerg Sonnenberger int
pfctl_define_table(char * name,int flags,int addrs,const char * anchor,struct pfr_buffer * ab,u_int32_t ticket)49895cc27f0SJoerg Sonnenberger pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
49970224baaSJan Lentfer     struct pfr_buffer *ab, u_int32_t ticket)
50095cc27f0SJoerg Sonnenberger {
50195cc27f0SJoerg Sonnenberger 	struct pfr_table tbl;
50295cc27f0SJoerg Sonnenberger 
50395cc27f0SJoerg Sonnenberger 	bzero(&tbl, sizeof(tbl));
50495cc27f0SJoerg Sonnenberger 	if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >=
50595cc27f0SJoerg Sonnenberger 	    sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor,
50670224baaSJan Lentfer 	    sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor))
50795cc27f0SJoerg Sonnenberger 		errx(1, "pfctl_define_table: strlcpy");
50895cc27f0SJoerg Sonnenberger 	tbl.pfrt_flags = flags;
50995cc27f0SJoerg Sonnenberger 
51095cc27f0SJoerg Sonnenberger 	return pfr_ina_define(&tbl, ab->pfrb_caddr, ab->pfrb_size, NULL,
51195cc27f0SJoerg Sonnenberger 	    NULL, ticket, addrs ? PFR_FLAG_ADDRSTOO : 0);
51295cc27f0SJoerg Sonnenberger }
51395cc27f0SJoerg Sonnenberger 
51495cc27f0SJoerg Sonnenberger void
warn_namespace_collision(const char * filter)51595cc27f0SJoerg Sonnenberger warn_namespace_collision(const char *filter)
51695cc27f0SJoerg Sonnenberger {
51795cc27f0SJoerg Sonnenberger 	struct pfr_buffer b;
51895cc27f0SJoerg Sonnenberger 	const struct pfr_table *t;
51970224baaSJan Lentfer 	const char *name = NULL, *lastcoll;
52095cc27f0SJoerg Sonnenberger 	int coll = 0;
52195cc27f0SJoerg Sonnenberger 
52295cc27f0SJoerg Sonnenberger 	bzero(&b, sizeof(b));
52395cc27f0SJoerg Sonnenberger 	b.pfrb_type = PFRB_TABLES;
52495cc27f0SJoerg Sonnenberger 	for (;;) {
52595cc27f0SJoerg Sonnenberger 		pfr_buf_grow(&b, b.pfrb_size);
52695cc27f0SJoerg Sonnenberger 		b.pfrb_size = b.pfrb_msize;
52795cc27f0SJoerg Sonnenberger 		if (pfr_get_tables(NULL, b.pfrb_caddr,
52895cc27f0SJoerg Sonnenberger 		    &b.pfrb_size, PFR_FLAG_ALLRSETS))
52995cc27f0SJoerg Sonnenberger 			err(1, "pfr_get_tables");
53095cc27f0SJoerg Sonnenberger 		if (b.pfrb_size <= b.pfrb_msize)
53195cc27f0SJoerg Sonnenberger 			break;
53295cc27f0SJoerg Sonnenberger 	}
53395cc27f0SJoerg Sonnenberger 	PFRB_FOREACH(t, &b) {
53495cc27f0SJoerg Sonnenberger 		if (!(t->pfrt_flags & PFR_TFLAG_ACTIVE))
53595cc27f0SJoerg Sonnenberger 			continue;
53695cc27f0SJoerg Sonnenberger 		if (filter != NULL && strcmp(filter, t->pfrt_name))
53795cc27f0SJoerg Sonnenberger 			continue;
53895cc27f0SJoerg Sonnenberger 		if (!t->pfrt_anchor[0])
53995cc27f0SJoerg Sonnenberger 			name = t->pfrt_name;
54095cc27f0SJoerg Sonnenberger 		else if (name != NULL && !strcmp(name, t->pfrt_name)) {
54195cc27f0SJoerg Sonnenberger 			coll++;
54295cc27f0SJoerg Sonnenberger 			lastcoll = name;
54395cc27f0SJoerg Sonnenberger 			name = NULL;
54495cc27f0SJoerg Sonnenberger 		}
54595cc27f0SJoerg Sonnenberger 	}
54695cc27f0SJoerg Sonnenberger 	if (coll == 1)
54795cc27f0SJoerg Sonnenberger 		warnx("warning: namespace collision with <%s> global table.",
54895cc27f0SJoerg Sonnenberger 		    lastcoll);
54995cc27f0SJoerg Sonnenberger 	else if (coll > 1)
55095cc27f0SJoerg Sonnenberger 		warnx("warning: namespace collisions with %d global tables.",
55195cc27f0SJoerg Sonnenberger 		    coll);
55295cc27f0SJoerg Sonnenberger 	pfr_buf_clear(&b);
55395cc27f0SJoerg Sonnenberger }
55495cc27f0SJoerg Sonnenberger 
55595cc27f0SJoerg Sonnenberger void
xprintf(int opts,const char * fmt,...)55695cc27f0SJoerg Sonnenberger xprintf(int opts, const char *fmt, ...)
55795cc27f0SJoerg Sonnenberger {
55895cc27f0SJoerg Sonnenberger 	va_list args;
55995cc27f0SJoerg Sonnenberger 
56095cc27f0SJoerg Sonnenberger 	if (opts & PF_OPT_QUIET)
56195cc27f0SJoerg Sonnenberger 		return;
56295cc27f0SJoerg Sonnenberger 
56395cc27f0SJoerg Sonnenberger 	va_start(args, fmt);
56495cc27f0SJoerg Sonnenberger 	vfprintf(stderr, fmt, args);
56595cc27f0SJoerg Sonnenberger 	va_end(args);
56695cc27f0SJoerg Sonnenberger 
56795cc27f0SJoerg Sonnenberger 	if (opts & PF_OPT_DUMMYACTION)
56895cc27f0SJoerg Sonnenberger 		fprintf(stderr, " (dummy).\n");
56995cc27f0SJoerg Sonnenberger 	else if (opts & PF_OPT_NOACTION)
57095cc27f0SJoerg Sonnenberger 		fprintf(stderr, " (syntax only).\n");
57195cc27f0SJoerg Sonnenberger 	else
57295cc27f0SJoerg Sonnenberger 		fprintf(stderr, ".\n");
57395cc27f0SJoerg Sonnenberger }
57495cc27f0SJoerg Sonnenberger 
57595cc27f0SJoerg Sonnenberger 
57695cc27f0SJoerg Sonnenberger /* interface stuff */
57795cc27f0SJoerg Sonnenberger 
57895cc27f0SJoerg Sonnenberger int
pfctl_show_ifaces(const char * filter,int opts)57995cc27f0SJoerg Sonnenberger pfctl_show_ifaces(const char *filter, int opts)
58095cc27f0SJoerg Sonnenberger {
58195cc27f0SJoerg Sonnenberger 	struct pfr_buffer	 b;
58270224baaSJan Lentfer 	const struct pfi_kif		*p;
58370224baaSJan Lentfer 	int			 i = 0;
58495cc27f0SJoerg Sonnenberger 
58595cc27f0SJoerg Sonnenberger 	bzero(&b, sizeof(b));
58695cc27f0SJoerg Sonnenberger 	b.pfrb_type = PFRB_IFACES;
58795cc27f0SJoerg Sonnenberger 	for (;;) {
58895cc27f0SJoerg Sonnenberger 		pfr_buf_grow(&b, b.pfrb_size);
58995cc27f0SJoerg Sonnenberger 		b.pfrb_size = b.pfrb_msize;
59070224baaSJan Lentfer 		if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size)) {
59195cc27f0SJoerg Sonnenberger 			radix_perror();
59295cc27f0SJoerg Sonnenberger 			return (1);
59395cc27f0SJoerg Sonnenberger 		}
59495cc27f0SJoerg Sonnenberger 		if (b.pfrb_size <= b.pfrb_msize)
59595cc27f0SJoerg Sonnenberger 			break;
59695cc27f0SJoerg Sonnenberger 		i++;
59795cc27f0SJoerg Sonnenberger 	}
59895cc27f0SJoerg Sonnenberger 	if (opts & PF_OPT_SHOWALL)
59995cc27f0SJoerg Sonnenberger 		pfctl_print_title("INTERFACES:");
60095cc27f0SJoerg Sonnenberger 	PFRB_FOREACH(p, &b)
60195cc27f0SJoerg Sonnenberger 		print_iface(p, opts);
60295cc27f0SJoerg Sonnenberger 	return (0);
60395cc27f0SJoerg Sonnenberger }
60495cc27f0SJoerg Sonnenberger 
60595cc27f0SJoerg Sonnenberger void
print_iface(const struct pfi_kif * p,int opts)60670224baaSJan Lentfer print_iface(const struct pfi_kif *p, int opts)
60795cc27f0SJoerg Sonnenberger {
60870224baaSJan Lentfer 	time_t	tzero = p->pfik_tzero;
60995cc27f0SJoerg Sonnenberger 	int	i, af, dir, act;
61095cc27f0SJoerg Sonnenberger 
61170224baaSJan Lentfer 	printf("%s", p->pfik_name);
61270224baaSJan Lentfer 	if (opts & PF_OPT_VERBOSE) {
61370224baaSJan Lentfer 		if (p->pfik_flags & PFI_IFLAG_SKIP)
61470224baaSJan Lentfer 			printf(" (skip)");
61570224baaSJan Lentfer 	}
61695cc27f0SJoerg Sonnenberger 	printf("\n");
61795cc27f0SJoerg Sonnenberger 
61895cc27f0SJoerg Sonnenberger 	if (!(opts & PF_OPT_VERBOSE2))
61995cc27f0SJoerg Sonnenberger 		return;
62095cc27f0SJoerg Sonnenberger 	printf("\tCleared:     %s", ctime(&tzero));
62195cc27f0SJoerg Sonnenberger 	printf("\tReferences:  [ States:  %-18d Rules: %-18d ]\n",
62270224baaSJan Lentfer 	    p->pfik_states, p->pfik_rules);
62395cc27f0SJoerg Sonnenberger 	for (i = 0; i < 8; i++) {
62495cc27f0SJoerg Sonnenberger 		af = (i>>2) & 1;
62595cc27f0SJoerg Sonnenberger 		dir = (i>>1) &1;
62695cc27f0SJoerg Sonnenberger 		act = i & 1;
62795cc27f0SJoerg Sonnenberger 		printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
62895cc27f0SJoerg Sonnenberger 		    istats_text[af][dir][act],
62970224baaSJan Lentfer 		    (unsigned long long)p->pfik_packets[af][dir][act],
63070224baaSJan Lentfer 		    (unsigned long long)p->pfik_bytes[af][dir][act]);
63195cc27f0SJoerg Sonnenberger 	}
63295cc27f0SJoerg Sonnenberger }
633