diff options
author | Cedric Berger <cedric@cvs.openbsd.org> | 2003-01-03 21:37:45 +0000 |
---|---|---|
committer | Cedric Berger <cedric@cvs.openbsd.org> | 2003-01-03 21:37:45 +0000 |
commit | 53b24bf74006b8fe01c11b5912d6fdd335766f47 (patch) | |
tree | 808cc224a9a0a135b48997ef94f531d0af7be38d /sbin | |
parent | 18e3159b84731971d6a6fd04b186575959c2ea35 (diff) |
Bring in userland code for accessing PF radix tables.
ok dhartmei@ mcbride@
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/pfctl/Makefile | 3 | ||||
-rw-r--r-- | sbin/pfctl/parse.y | 22 | ||||
-rw-r--r-- | sbin/pfctl/pf_print_state.c | 12 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.8 | 36 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 44 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_radix.c | 378 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_radix.h | 58 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_table.c | 591 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_table.h | 42 |
9 files changed, 1177 insertions, 9 deletions
diff --git a/sbin/pfctl/Makefile b/sbin/pfctl/Makefile index 4dfe8b38e6b..73c1a969f0a 100644 --- a/sbin/pfctl/Makefile +++ b/sbin/pfctl/Makefile @@ -1,7 +1,8 @@ -# $OpenBSD: Makefile,v 1.10 2002/12/06 16:16:15 henning Exp $ +# $OpenBSD: Makefile,v 1.11 2003/01/03 21:37:44 cedric Exp $ PROG= pfctl SRCS= pfctl.c parse.y pfctl_parser.c pf_print_state.c pfctl_altq.c +SRCS+= pfctl_radix.c pfctl_table.c CFLAGS+= -Wall -Wmissing-prototypes -Wno-uninitialized CFLAGS+= -Wstrict-prototypes YFLAGS= diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index a5d44e0ab29..e492ca7b282 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.272 2003/01/02 11:34:59 mcbride Exp $ */ +/* $OpenBSD: parse.y,v 1.273 2003/01/03 21:37:44 cedric Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -56,6 +56,7 @@ #include "pf_print_state.h" #include "pfctl_parser.h" +#include "pfctl_radix.h" #include "pfctl_altq.h" static struct pfctl *pf = NULL; @@ -1477,6 +1478,25 @@ xhost : '!' host { host : address | STRING '/' number { $$ = host($1, $3); } + | PORTUNARY STRING PORTUNARY { + struct pfr_table tbl; + int exists = 0; + + if ($1 != PF_OP_LT || $3 != PF_OP_GT) + YYERROR; + $$ = calloc(1, sizeof(struct node_host)); + if ($$ == NULL) + err(1, "host: calloc"); + $$->af = 0; + bzero(&tbl, sizeof(tbl)); + strlcpy(tbl.pfrt_name, $2, sizeof(tbl.pfrt_name)); + if (pfr_wrap_table(&tbl, &$$->addr, &exists, 0)) + err(1, "pfr_wrap_table"); + if (!exists) + fprintf(stderr, "warning: %s " + "table is not currently defined\n", + tbl.pfrt_name); + } ; number : STRING { diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c index 6f43cc3cf74..f6d8fe02e32 100644 --- a/sbin/pfctl/pf_print_state.c +++ b/sbin/pfctl/pf_print_state.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_print_state.c,v 1.14 2002/12/18 16:09:25 dhartmei Exp $ */ +/* $OpenBSD: pf_print_state.c,v 1.15 2003/01/03 21:37:44 cedric Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -53,6 +53,7 @@ #include <err.h> #include "pfctl_parser.h" +#include "pfctl_radix.h" #include "pf_print_state.h" void print_name(struct pf_addr *, struct pf_addr *, sa_family_t); @@ -62,6 +63,15 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af) { char buf[48]; + if (addr->mask.addr32[0] == PF_TABLE_MASK) { + struct pfr_table tbl = { "?" }; + + if (pfr_unwrap_table(&tbl, addr, 0)) + printf("<0x%08X>", addr->addr.addr32[0]); + else + printf("<%s>", tbl.pfrt_name); + return; + } if (addr->addr_dyn != NULL) printf("(%s)", addr->addr.pfa.ifname); else { diff --git a/sbin/pfctl/pfctl.8 b/sbin/pfctl/pfctl.8 index 3da745ffc7b..e77dd31c123 100644 --- a/sbin/pfctl/pfctl.8 +++ b/sbin/pfctl/pfctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pfctl.8,v 1.60 2002/12/15 16:52:35 margarida Exp $ +.\" $OpenBSD: pfctl.8,v 1.61 2003/01/03 21:37:44 cedric Exp $ .\" .\" Copyright (c) 2001 Kjell Wooding. All rights reserved. .\" @@ -39,6 +39,8 @@ .Op Fl k Ar host .Op Fl s Ar modifier .Op Fl x Ar level +.Op Fl t Ar table +.Op Fl T Ar command .Sh DESCRIPTION The .Nm @@ -120,7 +122,7 @@ rules, in that order. .It Fl F Ar modifier Flush one of the following. Modifier name may be abbreviated: -.Bl -tag -width "F rules " -compact +.Bl -tag -width "F tables " -compact .It Fl F Ar nat Flush the NAT rules. .It Fl F Ar queue @@ -131,6 +133,8 @@ Flush the filter rules. Flush the state table (NAT and filter). .It Fl F Ar info Flush the filter information (statistics that are not bound to rules). +.It Fl F Ar Tables +Flush the radix tables. .It Fl F Ar all Flush all of the above. .El @@ -168,7 +172,7 @@ Other rules and options are ignored. .It Fl s Ar modifier Show filter parameters. Modifier names may be abbreviated: -.Bl -tag -width "s rules " -compact +.Bl -tag -width "s timeouts " -compact .It Fl s Ar nat Show the currently loaded NAT rules. .It Fl s Ar queue @@ -199,9 +203,35 @@ useful for accounting. Show the current global timeouts. .It Fl s Ar memory Show the current pool memory hard limits. +.It Fl s Ar Tables +Show the list of radix tables. .It Fl s Ar all Show all of the above. .El +.It Fl t Ar table +Specify the name of the radix table. +.It Fl T Ar command +Specify the command to apply to the table. commands include: +.Bl -tag -width "T Replace " -compact +.It Fl T Ar create +Create a new table. +.It Fl T Ar kill +Kill a table. +.It Fl T Ar flush +Flush all addresses of a table. +.It Fl T Ar add +Add one or more addresses in a table. +.It Fl T Ar delete +Delete one or more addresses from a table. +.It Fl T Ar replace +Replace the addresses of the table. +.It Fl T Ar show +Show the content (addresses) of a table. +.It Fl T Ar test +Test if the given addresses match a table. +.It Fl T Ar zero +Clear all the statistics of a table. +.El .It Fl v Produce more verbose output. A second use of .Fl v diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 5615aa50575..2f1115908d1 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.c,v 1.117 2003/01/01 17:20:14 henning Exp $ */ +/* $OpenBSD: pfctl.c,v 1.118 2003/01/03 21:37:44 cedric Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -53,6 +53,8 @@ #include "pfctl_parser.h" #include "pf_print_state.h" #include "pfctl_altq.h" +#include "pfctl_table.h" +#include "pfctl_radix.h" void usage(void); int pfctl_enable(int, int); @@ -85,6 +87,8 @@ char *rulesopt; char *showopt; char *debugopt; char *anchoropt; +char *tableopt; +char *tblcmdopt; int state_killers; char *state_kill[2]; int loadopt = PFCTL_FLAG_ALL; @@ -166,6 +170,8 @@ usage(void) fprintf(stderr, "[-a anchor:ruleset] [-f file]\n"); fprintf(stderr, " "); fprintf(stderr, "[-F modifier] [-k host] [-s modifier] [-x level]\n"); + fprintf(stderr, " "); + fprintf(stderr, "[-t table [-T command [addresses]*]]\n"); exit(1); } @@ -1240,11 +1246,13 @@ main(int argc, char *argv[]) int ch; int mode = O_RDONLY; int opts = 0; + int dummy = 0; if (argc < 2) usage(); - while ((ch = getopt(argc, argv, "a:Adeqf:F:hk:nNOrRs:vx:z")) != -1) { + while ((ch = getopt(argc, argv, "a:Adeqf:F:hk:nNOrRs:t:T:vx:z")) != + -1) { switch (ch) { case 'a': anchoropt = optarg; @@ -1302,6 +1310,12 @@ main(int argc, char *argv[]) case 's': showopt = optarg; break; + case 't': + tableopt = optarg; + break; + case 'T': + tblcmdopt = optarg; + break; case 'v': if (opts & PF_OPT_VERBOSE) opts |= PF_OPT_VERBOSE2; @@ -1323,7 +1337,16 @@ main(int argc, char *argv[]) } } - if (argc != optind) { + if (tableopt != NULL || tblcmdopt != NULL) { + argc -= optind; + argv += optind; + ch = (tblcmdopt != NULL) ? *tblcmdopt : 0; + mode = strchr("acdfkrz", ch) ? O_RDWR : O_RDONLY; + if (opts & PF_OPT_NOACTION) { + opts &= ~PF_OPT_NOACTION; + dummy = PF_OPT_NOACTION; + } + } else if (argc != optind) { warnx("unknown command line argument: %s ...", argv[optind]); usage(); /* NOTREACHED */ @@ -1367,6 +1390,7 @@ main(int argc, char *argv[]) if (dev == -1) err(1, "open(\"/dev/pf\")"); altqsupport = pfctl_test_altqsupport(dev); + pfr_set_fd(dev); } else { /* turn off options */ opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); @@ -1401,6 +1425,10 @@ main(int argc, char *argv[]) pfctl_clear_altq(dev, opts); pfctl_clear_states(dev, opts); pfctl_clear_stats(dev, opts); + pfctl_clear_tables(opts); + break; + case 'T': + pfctl_clear_tables(opts); break; default: warnx("Unknown flush modifier '%s'", clearopt); @@ -1410,6 +1438,12 @@ main(int argc, char *argv[]) if (state_killers) pfctl_kill_states(dev, opts); + if (tableopt != NULL || tblcmdopt != NULL) { + error = pfctl_command_tables(argc, argv, tableopt, + tblcmdopt, rulesopt, opts | dummy); + rulesopt = NULL; + } + if (rulesopt != NULL) if (pfctl_rules(dev, rulesopt, opts)) error = 1; @@ -1452,6 +1486,10 @@ main(int argc, char *argv[]) pfctl_show_rules(dev, opts, 1); pfctl_show_timeouts(dev); pfctl_show_limits(dev); + pfctl_show_tables(opts); + break; + case 'T': + pfctl_show_tables(opts); break; default: warnx("Unknown show modifier '%s'", showopt); diff --git a/sbin/pfctl/pfctl_radix.c b/sbin/pfctl/pfctl_radix.c new file mode 100644 index 00000000000..d84cb433c7b --- /dev/null +++ b/sbin/pfctl/pfctl_radix.c @@ -0,0 +1,378 @@ +/* $OpenBSD: pfctl_radix.c,v 1.1 2003/01/03 21:37:44 cedric Exp $ */ + +/* + * Copyright (c) 2002 Cedric Berger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <netinet/in.h> +#include <net/pfvar.h> + +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> + +#include "pfctl_radix.h" + +#define RETURN_EINVAL \ + do { \ + errno = EINVAL; \ + return (-1); \ + } while (0) + +static int _pfr_dev = -1; + +static int +_pfr_ioctl(unsigned long op, void *buf) +{ + if (_pfr_dev < 0) + return (_pfr_dev); + return (ioctl(_pfr_dev, op, buf)); +} + +void +pfr_set_fd(int fd) +{ + _pfr_dev = fd; +} + +int +pfr_get_fd(void) +{ + return _pfr_dev; +} + +int +pfr_clr_tables(int *ndel, int flags) +{ + struct pfioc_table io; + + bzero(&io, sizeof io); + io.pfrio_flags = flags; + if (_pfr_ioctl(DIOCRCLRTABLES, &io)) + return (-1); + if (ndel != NULL) + *ndel = io.pfrio_ndel; + return (0); +} + +int +pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags) +{ + struct pfioc_table io; + + if (size < 0 || (size && tbl == NULL)) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_buffer = tbl; + io.pfrio_size = size; + if (_pfr_ioctl(DIOCRADDTABLES, &io)) + return (-1); + if (nadd != NULL) + *nadd = io.pfrio_nadd; + return (0); +} + +int +pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags) +{ + struct pfioc_table io; + + if (size < 0 || (size && tbl == NULL)) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_buffer = tbl; + io.pfrio_size = size; + if (_pfr_ioctl(DIOCRDELTABLES, &io)) + return (-1); + if (ndel != NULL) + *ndel = io.pfrio_ndel; + return (0); +} + +int +pfr_get_tables(struct pfr_table *tbl, int *size, int flags) +{ + struct pfioc_table io; + + if (size == NULL || *size < 0 || (*size && tbl == NULL)) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_buffer = tbl; + io.pfrio_size = *size; + if (_pfr_ioctl(DIOCRGETTABLES, &io)) + return (-1); + *size = io.pfrio_size; + return (0); +} + +int +pfr_get_tstats(struct pfr_tstats *tbl, int *size, int flags) +{ + struct pfioc_table io; + + if (size == NULL || *size < 0 || (*size && tbl == NULL)) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_buffer = tbl; + io.pfrio_size = *size; + if (_pfr_ioctl(DIOCRGETTSTATS, &io)) + return (-1); + *size = io.pfrio_size; + return (0); +} + +int +pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags) +{ + struct pfioc_table io; + + if (tbl == NULL) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_table = *tbl; + if (_pfr_ioctl(DIOCRSETADDRS, &io)) + return (-1); + if (ndel != NULL) + *ndel = io.pfrio_ndel; + return (0); +} + +int +pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, + int *nadd, int flags) +{ + struct pfioc_table io; + + if (tbl == NULL || size < 0 || (size && addr == NULL)) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_table = *tbl; + io.pfrio_buffer = addr; + io.pfrio_size = size; + if (_pfr_ioctl(DIOCRADDADDRS, &io)) + return (-1); + if (nadd != NULL) + *nadd = io.pfrio_nadd; + return (0); +} + +int +pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, + int *ndel, int flags) +{ + struct pfioc_table io; + + if (tbl == NULL || size < 0 || (size && addr == NULL)) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_table = *tbl; + io.pfrio_buffer = addr; + io.pfrio_size = size; + if (_pfr_ioctl(DIOCRDELADDRS, &io)) + return (-1); + if (ndel != NULL) + *ndel = io.pfrio_ndel; + return (0); +} + +int +pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, + int *size2, int *nadd, int *ndel, int *nchange, int flags) +{ + struct pfioc_table io; + + if (tbl == NULL || size < 0 || (size && addr == NULL)) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_table = *tbl; + io.pfrio_buffer = addr; + io.pfrio_size = size; + io.pfrio_size2 = (size2 != NULL) ? *size2 : 0; + if (_pfr_ioctl(DIOCRSETADDRS, &io)) + return (-1); + if (nadd != NULL) + *nadd = io.pfrio_nadd; + if (ndel != NULL) + *ndel = io.pfrio_ndel; + if (nchange != NULL) + *nchange = io.pfrio_nchange; + if (size2 != NULL) + *size2 = io.pfrio_size2; + return (0); +} + +int +pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size, + int flags) +{ + struct pfioc_table io; + + if (tbl == NULL || size == NULL || *size < 0 || (*size && addr == NULL)) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_table = *tbl; + io.pfrio_buffer = addr; + io.pfrio_size = *size; + if (_pfr_ioctl(DIOCRGETADDRS, &io)) + return (-1); + *size = io.pfrio_size; + return (0); +} + +int +pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size, + int flags) +{ + struct pfioc_table io; + + if (tbl == NULL || size == NULL || *size < 0 || (*size && addr == NULL)) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_table = *tbl; + io.pfrio_buffer = addr; + io.pfrio_size = *size; + if (_pfr_ioctl(DIOCRGETASTATS, &io)) + return (-1); + *size = io.pfrio_size; + return (0); +} + +int +pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size, + int *nzero, int flags) +{ + struct pfioc_table io; + + if (tbl == NULL || size < 0 || (size && addr == NULL)) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_table = *tbl; + io.pfrio_buffer = addr; + io.pfrio_size = size; + if (_pfr_ioctl(DIOCRCLRTSTATS, &io)) + return (-1); + if (nzero != NULL) + *nzero = io.pfrio_nzero; + return (0); +} + +int +pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags) +{ + struct pfioc_table io; + + if (size < 0 || (size && !tbl)) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_buffer = tbl; + io.pfrio_size = size; + if (_pfr_ioctl(DIOCRCLRTSTATS, &io)) + return (-1); + if (nzero) + *nzero = io.pfrio_nzero; + return (0); +} + + +int +pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, + int *nmatch, int flags) +{ + struct pfioc_table io; + + if (tbl == NULL || size < 0 || (size && addr == NULL)) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_table = *tbl; + io.pfrio_buffer = addr; + io.pfrio_size = size; + if (_pfr_ioctl(DIOCRTSTADDRS, &io)) + return (-1); + if (nmatch) + *nmatch = io.pfrio_nmatch; + return (0); +} + +int +pfr_wrap_table(struct pfr_table *tbl, struct pf_addr_wrap *wrap, + int *exists, int flags) +{ + struct pfioc_table io; + + if (tbl == NULL) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_table = *tbl; + io.pfrio_buffer = wrap; + io.pfrio_size = wrap ? 1 : 0; + io.pfrio_exists = exists ? 1 : 0; + if (_pfr_ioctl(DIOCRWRAPTABLE, &io)) + return (-1); + if (exists) + *exists = io.pfrio_exists; + return (0); +} + +int +pfr_unwrap_table(struct pfr_table *tbl, struct pf_addr_wrap *wrap, int flags) +{ + struct pfioc_table io; + + if (wrap == NULL) + RETURN_EINVAL; + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_buffer = wrap; + io.pfrio_size = 1; + if (_pfr_ioctl(DIOCRUNWRTABLE, &io)) + return (-1); + if (tbl != NULL) + *tbl = io.pfrio_table; + return (0); +} diff --git a/sbin/pfctl/pfctl_radix.h b/sbin/pfctl/pfctl_radix.h new file mode 100644 index 00000000000..084eb87b01d --- /dev/null +++ b/sbin/pfctl/pfctl_radix.h @@ -0,0 +1,58 @@ +/* $OpenBSD: pfctl_radix.h,v 1.1 2003/01/03 21:37:44 cedric Exp $ */ + +/* + * Copyright (c) 2002 Cedric Berger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _PFCTL_RADIX_H_ +#define _PFCTL_RADIX_H_ + +#include <net/pfvar.h> + +void pfr_set_fd(int); +int pfr_get_fd(void); +int pfr_clr_tables(int *ndel, int); +int pfr_add_tables(struct pfr_table *, int, int *, int); +int pfr_del_tables(struct pfr_table *, int, int *, int); +int pfr_get_tables(struct pfr_table *, int *, int); +int pfr_get_tstats(struct pfr_tstats *, int *, int); +int pfr_clr_tstats(struct pfr_table *, int, int *, int); +int pfr_clr_addrs(struct pfr_table *, int *, int); +int pfr_add_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int); +int pfr_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int); +int pfr_set_addrs(struct pfr_table *, struct pfr_addr *, int, int *, + int *, int *, int *, int); +int pfr_get_addrs(struct pfr_table *, struct pfr_addr *, int *, int); +int pfr_get_astats(struct pfr_table *, struct pfr_astats *, int *, int); +int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *, int); +int pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int); +int pfr_wrap_table(struct pfr_table *, struct pf_addr_wrap *, int *, int); +int pfr_unwrap_table(struct pfr_table *, struct pf_addr_wrap *, int); + +#endif /* _PFCTL_RADIX_H_ */ diff --git a/sbin/pfctl/pfctl_table.c b/sbin/pfctl/pfctl_table.c new file mode 100644 index 00000000000..00eb8f3a7dd --- /dev/null +++ b/sbin/pfctl/pfctl_table.c @@ -0,0 +1,591 @@ +/* $OpenBSD: pfctl_table.c,v 1.1 2003/01/03 21:37:44 cedric Exp $ */ + +/* + * Copyright (c) 2002 Cedric Berger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <netinet/in.h> +#include <net/pfvar.h> +#include <arpa/inet.h> + +#include <err.h> +#include <errno.h> +#include <time.h> +#include <fcntl.h> +#include <limits.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> +#include <assert.h> + +#include "pfctl_table.h" +#include "pfctl_radix.h" +#include "pfctl_parser.h" +#include "pf_print_state.h" + + +#define _BUF_SIZE 256 + +extern void usage(void); +static int _pfctl_table(int, char *[], char *, char *, char *, int); +static void _grow_buffer(int, int); +static void _print_table(struct pfr_table *); +static void _print_tstats(struct pfr_tstats *); +static void _load_addr(int, char *[], char *, int); +static int _next_token(char [_BUF_SIZE], FILE *); +static void _append_addr(char *, int); +static void _print_addr(struct pfr_addr *, struct pfr_addr *, int); +static void _print_astats(struct pfr_astats *, int); +static void _perror(void); + + +static union { + caddr_t caddr; + struct pfr_table *tables; + struct pfr_addr *addrs; + struct pfr_tstats *tstats; + struct pfr_astats *astats; +} buffer, buffer2; + +static int size, msize; +extern char *__progname; + +static char *commands[] = { + "-F", /* pfctl -F tables: flush all tables */ + "-s", /* pfctl -s tables: show all tables */ + "create", /* create a new table */ + "kill", /* kill a table */ + "flush", /* flush all addresses of a table */ + "add", /* add one or more addresses in a table */ + "delete", /* delete one or more addresses from a table */ + "replace", /* replace the addresses of the table */ + "show", /* show the content (addresses) of a table */ + "test", /* test if the given addresses match a table */ + "zero", /* clear all the statistics of a table */ + NULL +}; + +static char *stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = { + { "In/Block:", "In/Pass:", "In/XPass:" }, + { "Out/Block:", "Out/Pass:", "Out/XPass:" } +}; + + +#define DUMMY ((flags & PFR_FLAG_DUMMY)?" (dummy)":"") +#define RVTEST(fct) \ + do { int rv = fct; if (rv) \ + { _perror(); return (1); } \ + } while (0) + +int +pfctl_clear_tables(int opts) +{ + return _pfctl_table(0, NULL, NULL, "-F", NULL, opts); +} + +int +pfctl_show_tables(int opts) +{ + return _pfctl_table(0, NULL, NULL, "-s", NULL, opts); +} + +int +pfctl_command_tables(int argc, char *argv[], char *tname, + char *command, char *file, int opts) +{ + if (tname == NULL || command == NULL) + usage(); + return _pfctl_table(argc, argv, tname, command, file, opts); +} + +int +_pfctl_table(int argc, char *argv[], char *tname, char *command, + char *file, int opts) +{ + struct pfr_table table; + char **p; + int nadd = 0, ndel = 0, nchange = 0, nzero = 0; + int i, flags = 0, nmatch = 0; + + for (p = commands; *p != NULL; p++) + if (!strncmp(command, *p, strlen(command))) + break; + if (*p == NULL) + usage(); + if (opts & PF_OPT_NOACTION) + flags |= PFR_FLAG_DUMMY; + bzero(&table, sizeof(table)); + if (tname != NULL) { + if (strlen(tname) >= PF_TABLE_NAME_SIZE) + usage(); + strlcpy(table.pfrt_name, tname, PF_TABLE_NAME_SIZE); + } + if (!strcmp(*p, "-F")) { + if (argc || file != NULL) + usage(); + RVTEST(pfr_clr_tables(&ndel, flags)); + if (!(opts & PF_OPT_QUIET)) + fprintf(stderr, "%d tables deleted%s.\n", ndel, + DUMMY); + } + if (!strcmp(*p, "-s")) { + if (argc || file != NULL) + usage(); + for (;;) { + if (opts & PF_OPT_VERBOSE) { + _grow_buffer(sizeof(struct pfr_tstats), size); + size = msize; + RVTEST(pfr_get_tstats(buffer.tstats, &size, + flags)); + } else { + _grow_buffer(sizeof(struct pfr_table), size); + size = msize; + RVTEST(pfr_get_tables(buffer.tables, &size, + flags)); + } + if (size <= msize) + break; + } + for (i = 0; i < size; i++) + if (opts & PF_OPT_VERBOSE) + _print_tstats(buffer.tstats+i); + else + _print_table(buffer.tables+i); + } + if (!strcmp(*p, "create")) { + if (argc || file != NULL) + usage(); + RVTEST(pfr_add_tables(&table, 1, &nadd, flags)); + if (!(opts & PF_OPT_QUIET)) + fprintf(stderr, "%d table added%s.\n", nadd, DUMMY); + } + if (!strcmp(*p, "kill")) { + if (argc || file != NULL) + usage(); + RVTEST(pfr_del_tables(&table, 1, &ndel, flags)); + if (!(opts & PF_OPT_QUIET)) + fprintf(stderr, "%d table deleted%s.\n", ndel, DUMMY); + } + if (!strcmp(*p, "flush")) { + if (argc || file != NULL) + usage(); + RVTEST(pfr_clr_addrs(&table, &ndel, flags)); + if (!(opts & PF_OPT_QUIET)) + fprintf(stderr, "%d addresses deleted%s.\n", ndel, + DUMMY); + } + if (!strcmp(*p, "add")) { + _load_addr(argc, argv, file, 0); + if (opts & PF_OPT_VERBOSE) + flags |= PFR_FLAG_FEEDBACK; + RVTEST(pfr_add_addrs(&table, buffer.addrs, size, &nadd, + flags)); + if (!(opts & PF_OPT_QUIET)) + fprintf(stderr, "%d/%d addresses added%s.\n", nadd, + size, DUMMY); + if (opts & PF_OPT_VERBOSE) + for (i = 0; i < size; i++) + if ((opts & PF_OPT_VERBOSE2) || + buffer.addrs[i].pfra_fback) + _print_addr(buffer.addrs+i, NULL, + opts & PF_OPT_USEDNS); + } + if (!strcmp(*p, "delete")) { + _load_addr(argc, argv, file, 0); + if (opts & PF_OPT_VERBOSE) + flags |= PFR_FLAG_FEEDBACK; + RVTEST(pfr_del_addrs(&table, buffer.addrs, size, &nadd, + flags)); + if (!(opts & PF_OPT_QUIET)) + fprintf(stderr, "%d/%d addresses deleted%s.\n", nadd, + size, DUMMY); + if (opts & PF_OPT_VERBOSE) + for (i = 0; i < size; i++) + if ((opts & PF_OPT_VERBOSE2) || + buffer.addrs[i].pfra_fback) + _print_addr(buffer.addrs+i, NULL, + opts & PF_OPT_USEDNS); + } + if (!strcmp(*p, "replace")) { + _load_addr(argc, argv, file, 0); + if (opts & PF_OPT_VERBOSE) + flags |= PFR_FLAG_FEEDBACK; + for(;;) { + int size2 = msize; + + RVTEST(pfr_set_addrs(&table, buffer.addrs, size, + &size2, &nadd, &ndel, &nchange, flags)); + if (size2 <= msize) { + size = size2; + break; + } else + _grow_buffer(sizeof(struct pfr_addr), size2); + } + if (!(opts & PF_OPT_QUIET)) { + if (nadd) + fprintf(stderr, "%d addresses added%s.\n", + nadd, DUMMY); + if (ndel) + fprintf(stderr, "%d addresses deleted%s.\n", + ndel, DUMMY); + if (nchange) + fprintf(stderr, "%d addresses changed%s.\n", + nchange, DUMMY); + if (!nadd && !ndel && !nchange) + fprintf(stderr, "no changes%s.\n", DUMMY); + } + if (opts & PF_OPT_VERBOSE) + for (i = 0; i < size; i++) + if ((opts & PF_OPT_VERBOSE2) || + buffer.addrs[i].pfra_fback) + _print_addr(buffer.addrs+i, NULL, + opts & PF_OPT_USEDNS); + } + if (!strcmp(*p, "show")) { + if (argc || file != NULL) + usage(); + for (;;) { + if (opts & PF_OPT_VERBOSE) { + _grow_buffer(sizeof(struct pfr_astats), size); + size = msize; + RVTEST(pfr_get_astats(&table, buffer.astats, + &size, flags)); + } else { + _grow_buffer(sizeof(struct pfr_addr), size); + size = msize; + RVTEST(pfr_get_addrs(&table, buffer.addrs, + &size, flags)); + } + if (size <= msize) + break; + } + for (i = 0; i < size; i++) + if (opts & PF_OPT_VERBOSE) { + _print_astats(buffer.astats+i, + opts & PF_OPT_USEDNS); + } else { + _print_addr(buffer.addrs+i, NULL, + opts & PF_OPT_USEDNS); + } + } + if (!strcmp(*p, "test")) { + _load_addr(argc, argv, file, 1); + if (opts & PF_OPT_VERBOSE2) { + flags |= PFR_FLAG_REPLACE; + buffer2.caddr = calloc(sizeof(buffer.addrs[0]), size); + if (buffer2.caddr == NULL) { + _perror(); + return 1; + } + memcpy(buffer2.addrs, buffer.addrs, size * + sizeof(buffer.addrs[0])); + } + RVTEST(pfr_tst_addrs(&table, buffer.addrs, size, &nmatch, + flags)); + if (!(opts & PF_OPT_QUIET)) + printf("%d/%d addresses match.\n", nmatch, size); + if (opts & PF_OPT_VERBOSE && !(opts & PF_OPT_VERBOSE2)) + for (i = 0; i < size; i++) + if (buffer.addrs[i].pfra_fback == PFR_FB_MATCH) + _print_addr(buffer.addrs+i, NULL, + opts & PF_OPT_USEDNS); + if (opts & PF_OPT_VERBOSE2) + for (i = 0; i < size; i++) + _print_addr(buffer2.addrs+i, buffer.addrs+i, + opts & PF_OPT_USEDNS); + if (nmatch < size) + return (2); + } + if (!strcmp(*p, "zero")) { + if (argc || file != NULL) + usage(); + flags |= PFR_FLAG_RECURSE; + RVTEST(pfr_clr_tstats(&table, 1, &nzero, flags)); + if (!(opts & PF_OPT_QUIET)) + fprintf(stderr, "%d table/stats cleared%s.\n", nzero, + DUMMY); + } + return (0); +} + +void +_grow_buffer(int bs, int minsize) +{ + assert(minsize == 0 || minsize > msize); + if (!msize) { + msize = minsize; + if (msize < 64) + msize = 64; + buffer.caddr = calloc(bs, msize); + } else { + int omsize = msize; + if (minsize == 0) + msize *= 2; + else + msize = minsize; + buffer.caddr = realloc(buffer.caddr, msize * bs); + if (buffer.caddr) + bzero(buffer.caddr + omsize * bs, (msize-omsize) * bs); + } + if (!buffer.caddr) { + perror(__progname); + exit(1); + } +} + +void +_print_table(struct pfr_table *ta) +{ + printf("%s\n", ta->pfrt_name); +} + +void +_print_tstats(struct pfr_tstats *ts) +{ + time_t time = ts->pfrts_tzero; + int dir, op; + + printf("%s\n", ts->pfrts_name); + printf("\tAddresses: %d\n", ts->pfrts_cnt); + printf("\tCleared: %s", ctime(&time)); + printf("\tEvaluations: [ NoMatch: %-18llu Match: %-18llu ]\n", + ts->pfrts_nomatch, ts->pfrts_match); + for (dir = 0; dir < PFR_DIR_MAX; dir++) + for (op = 0; op < PFR_OP_TABLE_MAX; op++) + printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n", + stats_text[dir][op], + ts->pfrts_packets[dir][op], + ts->pfrts_bytes[dir][op]); +} + +void +_load_addr(int argc, char *argv[], char *file, int nonetwork) +{ + FILE *fp; + char buf[_BUF_SIZE]; + + while (argc--) + _append_addr(*argv++, nonetwork); + if (file == NULL) + return; + if (!strcmp(file, "-")) + fp = stdin; + else { + fp = fopen(file, "r"); + if (fp == NULL) { + perror(__progname); + exit(1); + } + } + while (_next_token(buf, fp)) + _append_addr(buf, nonetwork); + fclose(fp); +} + +int +_next_token(char buf[_BUF_SIZE], FILE *fp) +{ + static char _next_ch = ' '; + int i = 0; + + for (;;) { + /* skip spaces */ + while (isspace(_next_ch) && !feof(fp)) + _next_ch = fgetc(fp); + /* remove from '#' until end of line */ + if (_next_ch == '#') + while (!feof(fp)) { + _next_ch = fgetc(fp); + if (_next_ch == '\n') + break; + } + else + break; + } + if (feof(fp)) { + _next_ch = ' '; + return (0); + } + do { + if (i < _BUF_SIZE) + buf[i++] = _next_ch; + _next_ch = fgetc(fp); + } while (!feof(fp) && !isspace(_next_ch)); + if (i >= _BUF_SIZE) { + fprintf(stderr, "%s: address too long (%d bytes)\n", + __progname, i); + exit(1); + } + buf[i] = '\0'; + return (1); +} + +void +_append_addr(char *s, int test) +{ + char buf[_BUF_SIZE], *p, *q; + struct addrinfo *res, *ai, hints = { 0, 0, SOCK_DGRAM }; + int not = (*s == '!'), net = -1, rv; + + if (strlen(s) >= _BUF_SIZE) { + fprintf(stderr, "%s: address too long (%ld bytes)\n", + __progname, (long)strlen(s)); + exit(1); + } + strlcpy(buf, s+not, sizeof(buf)); + p = strrchr(buf, '/'); + if (test && (not || p)) + fprintf(stderr, "%s: illegal test address: \"%s\"\n", + __progname, s); + if (p) { + net = strtol(p+1, &q, 0); + if (!q || *q) { + fprintf(stderr, "%s: illegal network: \"%s\"\n", + __progname, p+1); + exit(1); + } + *p++ = '\0'; + } + rv = getaddrinfo(buf, NULL, &hints, &res); + if (rv) { + fprintf(stderr, "%s: illegal address: \"%s\"\n", __progname, + buf); + exit(1); + } + for (ai = res; ai; ai = ai->ai_next) { + switch (ai->ai_family) { + case AF_INET: + if (net > 32) { + fprintf(stderr, "%s: network too big: %d\n", + __progname, net); + exit(1); + } + if (size >= msize) + _grow_buffer(sizeof(struct pfr_addr), 0); + buffer.addrs[size].pfra_ip4addr = + ((struct sockaddr_in *)ai->ai_addr)->sin_addr; + buffer.addrs[size].pfra_not = not; + buffer.addrs[size].pfra_net = (net >= 0) ? net : 32; + buffer.addrs[size].pfra_af = AF_INET; + size++; + break; + case AF_INET6: + if (net > 128) { + fprintf(stderr, "%s: network too big: %d\n", + __progname, net); + exit(1); + } + if (size >= msize) + _grow_buffer(sizeof(struct pfr_addr), 0); + buffer.addrs[size].pfra_ip6addr = + ((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; + buffer.addrs[size].pfra_not = not; + buffer.addrs[size].pfra_net = (net >= 0) ? net : 128; + buffer.addrs[size].pfra_af = AF_INET6; + size++; + break; + } + } + freeaddrinfo(res); +} + +void +_print_addr(struct pfr_addr *ad, struct pfr_addr *rad, int dns) +{ + char buf[_BUF_SIZE] = "{error}"; + const char fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ' }; + int fback, hostnet; + + fback = (rad != NULL) ? rad->pfra_fback : ad->pfra_fback; + hostnet = (ad->pfra_af == AF_INET6) ? 128 : 32; + inet_ntop(ad->pfra_af, &ad->pfra_u, buf, sizeof(buf)); + printf("%c %c%s", fb[fback], (ad->pfra_not?'!':' '), buf); + if (ad->pfra_net < hostnet) + printf("/%d", ad->pfra_net); + if (rad != NULL && fback != PFR_FB_NONE) { + strcpy(buf, "{error}"); + inet_ntop(rad->pfra_af, &rad->pfra_u, buf, sizeof(buf)); + printf("\t%c%s", (rad->pfra_not?'!':' '), buf); + if (rad->pfra_net < hostnet) + printf("/%d", rad->pfra_net); + } + if (rad != NULL && fback == PFR_FB_NONE) + printf("\t nomatch"); + if (dns && ad->pfra_net == hostnet) { + char host[NI_MAXHOST] = "?"; + union sockaddr_union sa; + int rv; + + sa.sa.sa_len = (ad->pfra_af == AF_INET) ? + sizeof(sa.sin) : sizeof(sa.sin6); + sa.sa.sa_family = ad->pfra_af; + if (ad->pfra_af == AF_INET) + sa.sin.sin_addr = ad->pfra_ip4addr; + else + sa.sin6.sin6_addr = ad->pfra_ip6addr; + rv = getnameinfo(&sa.sa, sa.sa.sa_len, host, sizeof(host), + NULL, 0, NI_NAMEREQD); + if (!rv) + printf("\t(%s)", host); + } + printf("\n"); +} + +void +_print_astats(struct pfr_astats *as, int dns) +{ + time_t time = as->pfras_tzero; + int dir, op; + + _print_addr(&as->pfras_a, NULL, dns); + printf("\tCleared: %s", ctime(&time)); + for (dir = 0; dir < PFR_DIR_MAX; dir++) + for (op = 0; op < PFR_OP_ADDR_MAX; op++) + printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n", + stats_text[dir][op], + as->pfras_packets[dir][op], + as->pfras_bytes[dir][op]); +} + +void +_perror(void) +{ + if (errno == ESRCH) + fprintf(stderr, "%s: Table does not exist.\n", __progname); + else + perror(__progname); +} diff --git a/sbin/pfctl/pfctl_table.h b/sbin/pfctl/pfctl_table.h new file mode 100644 index 00000000000..650438271cc --- /dev/null +++ b/sbin/pfctl/pfctl_table.h @@ -0,0 +1,42 @@ +/* $OpenBSD: pfctl_table.h,v 1.1 2003/01/03 21:37:44 cedric Exp $ */ + +/* + * Copyright (c) 2002 Cedric Berger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _PFCTL_TABLE_H_ +#define _PFCTL_TABLE_H_ + +#include <net/pfvar.h> + +int pfctl_clear_tables(int); +int pfctl_show_tables(int); +int pfctl_command_tables(int, char *[], char *, char *, char *, int); + +#endif /* _PFCTL_TABLE_H_ */ |