aboutsummaryrefslogtreecommitdiff
path: root/sbin/pfctl/pfctl_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/pfctl/pfctl_table.c')
-rw-r--r--sbin/pfctl/pfctl_table.c167
1 files changed, 115 insertions, 52 deletions
diff --git a/sbin/pfctl/pfctl_table.c b/sbin/pfctl/pfctl_table.c
index db338fbe0876..f23a62f518e1 100644
--- a/sbin/pfctl/pfctl_table.c
+++ b/sbin/pfctl/pfctl_table.c
@@ -32,16 +32,14 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <net/if.h>
#include <net/pfvar.h>
-#include <arpa/inet.h>
#include <ctype.h>
#include <err.h>
@@ -59,10 +57,11 @@ __FBSDID("$FreeBSD$");
extern void usage(void);
static int pfctl_table(int, char *[], char *, const char *, char *,
const char *, int);
-static void print_table(struct pfr_table *, int, int);
-static void print_tstats(struct pfr_tstats *, int);
+static void print_table(const struct pfr_table *, int, int);
+static int print_tstats(const struct pfr_tstats *, int);
static int load_addr(struct pfr_buffer *, int, char *[], char *, int);
static void print_addrx(struct pfr_addr *, struct pfr_addr *, int);
+static int nonzero_astats(struct pfr_astats *);
static void print_astats(struct pfr_astats *, int);
static void radix_perror(void);
static void xprintf(int, const char *, ...);
@@ -91,7 +90,7 @@ static const char *istats_text[2][2][2] = {
table.pfrt_flags |= PFR_TFLAG_PERSIST; \
if ((!(opts & PF_OPT_NOACTION) || \
(opts & PF_OPT_DUMMYACTION)) && \
- (pfr_add_tables(&table, 1, &nadd, flags)) && \
+ (pfr_add_table(&table, &nadd, flags)) && \
(errno != EPERM)) { \
radix_perror(); \
goto _error; \
@@ -105,16 +104,18 @@ static const char *istats_text[2][2][2] = {
table.pfrt_flags &= ~PFR_TFLAG_PERSIST; \
} while(0)
-int
-pfctl_clear_tables(const char *anchor, int opts)
+void
+pfctl_do_clear_tables(const char *anchor, int opts)
{
- return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts);
+ if (pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts))
+ exit(1);
}
-int
+void
pfctl_show_tables(const char *anchor, int opts)
{
- return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts);
+ if (pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts))
+ exit(1);
}
int
@@ -159,39 +160,42 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
if (!strcmp(command, "-F")) {
if (argc || file != NULL)
usage();
- RVTEST(pfr_clr_tables(&table, &ndel, flags));
+ RVTEST(pfctl_clear_tables(pfh, &table, &ndel, flags));
xprintf(opts, "%d tables deleted", ndel);
} else if (!strcmp(command, "-s")) {
b.pfrb_type = (opts & PF_OPT_VERBOSE2) ?
PFRB_TSTATS : PFRB_TABLES;
if (argc || file != NULL)
usage();
- for (;;) {
- pfr_buf_grow(&b, b.pfrb_size);
- b.pfrb_size = b.pfrb_msize;
- if (opts & PF_OPT_VERBOSE2)
- RVTEST(pfr_get_tstats(&table,
- b.pfrb_caddr, &b.pfrb_size, flags));
- else
- RVTEST(pfr_get_tables(&table,
- b.pfrb_caddr, &b.pfrb_size, flags));
- if (b.pfrb_size <= b.pfrb_msize)
- break;
- }
if ((opts & PF_OPT_SHOWALL) && b.pfrb_size > 0)
pfctl_print_title("TABLES:");
- PFRB_FOREACH(p, &b)
- if (opts & PF_OPT_VERBOSE2)
- print_tstats(p, opts & PF_OPT_DEBUG);
- else
+ if (opts & PF_OPT_VERBOSE2) {
+ uintptr_t arg = opts & PF_OPT_DEBUG;
+ pfctl_get_tstats(pfh, &table,
+ (pfctl_get_tstats_fn)print_tstats, (void *)arg);
+ } else {
+ for (;;) {
+ pfr_buf_grow(&b, b.pfrb_size);
+ b.pfrb_size = b.pfrb_msize;
+ RVTEST(pfr_get_tables(&table,
+ b.pfrb_caddr, &b.pfrb_size, flags));
+ if (b.pfrb_size <= b.pfrb_msize)
+ break;
+ }
+
+ if ((opts & PF_OPT_SHOWALL) && b.pfrb_size > 0)
+ pfctl_print_title("TABLES:");
+
+ PFRB_FOREACH(p, &b)
print_table(p, opts & PF_OPT_VERBOSE,
opts & PF_OPT_DEBUG);
+ }
} else if (!strcmp(command, "kill")) {
if (argc || file != NULL)
usage();
- RVTEST(pfr_del_tables(&table, 1, &ndel, flags));
+ RVTEST(pfr_del_table(&table, &ndel, flags));
xprintf(opts, "%d table deleted", ndel);
} else if (!strcmp(command, "flush")) {
if (argc || file != NULL)
@@ -296,6 +300,36 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
print_addrx(a, NULL,
opts & PF_OPT_USEDNS);
+ } else if (!strcmp(command, "reset")) {
+ struct pfr_astats *as;
+
+ b.pfrb_type = PFRB_ASTATS;
+ b2.pfrb_type = PFRB_ADDRS;
+ if (argc || file != NULL)
+ usage();
+ do {
+ pfr_buf_grow(&b, b.pfrb_size);
+ b.pfrb_size = b.pfrb_msize;
+ RVTEST(pfr_get_astats(&table, b.pfrb_caddr,
+ &b.pfrb_size, flags));
+ } while (b.pfrb_size > b.pfrb_msize);
+ PFRB_FOREACH(as, &b) {
+ as->pfras_a.pfra_fback = 0;
+ if (nonzero_astats(as))
+ if (pfr_buf_add(&b2, &as->pfras_a))
+ err(1, "duplicate buffer");
+ }
+
+ if (opts & PF_OPT_VERBOSE)
+ flags |= PFR_FLAG_FEEDBACK;
+ RVTEST(pfr_clr_astats(&table, b2.pfrb_caddr, b2.pfrb_size,
+ &nzero, flags));
+ xprintf(opts, "%d/%d stats cleared", nzero, b.pfrb_size);
+ if (opts & PF_OPT_VERBOSE)
+ PFRB_FOREACH(a, &b2)
+ if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
+ print_addrx(a, NULL,
+ opts & PF_OPT_USEDNS);
} else if (!strcmp(command, "show")) {
b.pfrb_type = (opts & PF_OPT_VERBOSE) ?
PFRB_ASTATS : PFRB_ADDRS;
@@ -347,11 +381,24 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
}
if (nmatch < b.pfrb_size)
rv = 2;
+ } else if (!strcmp(command, "zero") && (argc || file != NULL)) {
+ b.pfrb_type = PFRB_ADDRS;
+ if (load_addr(&b, argc, argv, file, 0))
+ goto _error;
+ if (opts & PF_OPT_VERBOSE)
+ flags |= PFR_FLAG_FEEDBACK;
+ RVTEST(pfr_clr_astats(&table, b.pfrb_caddr, b.pfrb_size,
+ &nzero, flags));
+ xprintf(opts, "%d/%d addresses cleared", nzero, b.pfrb_size);
+ if (opts & PF_OPT_VERBOSE)
+ PFRB_FOREACH(a, &b)
+ if (opts & PF_OPT_VERBOSE2 ||
+ a->pfra_fback != PFR_FB_NONE)
+ print_addrx(a, NULL,
+ opts & PF_OPT_USEDNS);
} else if (!strcmp(command, "zero")) {
- if (argc || file != NULL)
- usage();
flags |= PFR_FLAG_ADDRSTOO;
- RVTEST(pfr_clr_tstats(&table, 1, &nzero, flags));
+ RVTEST(pfctl_clear_tstats(pfh, &table, &nzero, flags));
xprintf(opts, "%d table/stats cleared", nzero);
} else
warnx("pfctl_table: unknown command '%s'", command);
@@ -366,7 +413,7 @@ _cleanup:
}
void
-print_table(struct pfr_table *ta, int verbose, int debug)
+print_table(const struct pfr_table *ta, int verbose, int debug)
{
if (!debug && !(ta->pfrt_flags & PFR_TFLAG_ACTIVE))
return;
@@ -387,14 +434,14 @@ print_table(struct pfr_table *ta, int verbose, int debug)
puts(ta->pfrt_name);
}
-void
-print_tstats(struct pfr_tstats *ts, int debug)
+int
+print_tstats(const struct pfr_tstats *ts, int debug)
{
time_t time = ts->pfrts_tzero;
int dir, op;
if (!debug && !(ts->pfrts_flags & PFR_TFLAG_ACTIVE))
- return;
+ return (0);
print_table(&ts->pfrts_t, 1, debug);
printf("\tAddresses: %d\n", ts->pfrts_cnt);
printf("\tCleared: %s", ctime(&time));
@@ -410,6 +457,8 @@ print_tstats(struct pfr_tstats *ts, int debug)
stats_text[dir][op],
(unsigned long long)ts->pfrts_packets[dir][op],
(unsigned long long)ts->pfrts_bytes[dir][op]);
+
+ return (0);
}
int
@@ -455,25 +504,42 @@ print_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns)
printf("\t nomatch");
if (dns && ad->pfra_net == hostnet) {
char host[NI_MAXHOST];
- union sockaddr_union sa;
+ struct sockaddr_storage ss;
strlcpy(host, "?", sizeof(host));
- bzero(&sa, sizeof(sa));
- sa.sa.sa_family = ad->pfra_af;
- if (sa.sa.sa_family == AF_INET) {
- sa.sa.sa_len = sizeof(sa.sin);
- sa.sin.sin_addr = ad->pfra_ip4addr;
+ bzero(&ss, sizeof(ss));
+ ss.ss_family = ad->pfra_af;
+ if (ss.ss_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
+
+ sin->sin_len = sizeof(*sin);
+ sin->sin_addr = ad->pfra_ip4addr;
} else {
- sa.sa.sa_len = sizeof(sa.sin6);
- sa.sin6.sin6_addr = ad->pfra_ip6addr;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
+
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_addr = ad->pfra_ip6addr;
}
- if (getnameinfo(&sa.sa, sa.sa.sa_len, host, sizeof(host),
- NULL, 0, NI_NAMEREQD) == 0)
+ if (getnameinfo((struct sockaddr *)&ss, ss.ss_len, host,
+ sizeof(host), NULL, 0, NI_NAMEREQD) == 0)
printf("\t(%s)", host);
}
printf("\n");
}
+int
+nonzero_astats(struct pfr_astats *as)
+{
+ uint64_t s = 0;
+
+ for (int dir = 0; dir < PFR_DIR_MAX; dir++)
+ for (int op = 0; op < PFR_OP_ADDR_MAX; op++)
+ s |= as->pfras_packets[dir][op] |
+ as->pfras_bytes[dir][op];
+
+ return (!!s);
+}
+
void
print_astats(struct pfr_astats *as, int dns)
{
@@ -580,12 +646,11 @@ xprintf(int opts, const char *fmt, ...)
/* interface stuff */
-int
+void
pfctl_show_ifaces(const char *filter, int opts)
{
struct pfr_buffer b;
struct pfi_kif *p;
- int i = 0;
bzero(&b, sizeof(b));
b.pfrb_type = PFRB_IFACES;
@@ -594,17 +659,15 @@ pfctl_show_ifaces(const char *filter, int opts)
b.pfrb_size = b.pfrb_msize;
if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size)) {
radix_perror();
- return (1);
+ exit(1);
}
if (b.pfrb_size <= b.pfrb_msize)
break;
- i++;
}
if (opts & PF_OPT_SHOWALL)
pfctl_print_title("INTERFACES:");
PFRB_FOREACH(p, &b)
print_iface(p, opts);
- return (0);
}
void