summaryrefslogtreecommitdiff
path: root/sbin/pfctl
diff options
context:
space:
mode:
authorCedric Berger <cedric@cvs.openbsd.org>2003-01-09 10:40:46 +0000
committerCedric Berger <cedric@cvs.openbsd.org>2003-01-09 10:40:46 +0000
commitef9a4fa0481b3db31c30b68a6257c7a03c593c18 (patch)
tree1f05dbe8255eb7156a2b2e4a4b80524c15b16b6e /sbin/pfctl
parentf3ba1b333f3d2c3a0007a91bf2ec133aae943748 (diff)
Add support for active/inactive tablesets in the kernel.
Add table definition/initialisation construct in pfctl parser. Add and fix documentation for pf.4 and pf.conf.5. Tested on i386 and sparc64 by myself, macppc by Daniel. ok dhartmei@
Diffstat (limited to 'sbin/pfctl')
-rw-r--r--sbin/pfctl/parse.y48
-rw-r--r--sbin/pfctl/pfctl.85
-rw-r--r--sbin/pfctl/pfctl.c18
-rw-r--r--sbin/pfctl/pfctl.h7
-rw-r--r--sbin/pfctl/pfctl_parser.h9
-rw-r--r--sbin/pfctl/pfctl_radix.c84
-rw-r--r--sbin/pfctl/pfctl_table.c114
7 files changed, 261 insertions, 24 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 36bd1521efa..085d2d88498 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.282 2003/01/08 19:47:37 deraadt Exp $ */
+/* $OpenBSD: parse.y,v 1.283 2003/01/09 10:40:44 cedric Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -377,7 +377,7 @@ typedef struct {
%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
%token MINTTL ERROR ALLOWOPTS FASTROUTE ROUTETO DUPTO REPLYTO NO LABEL
-%token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP
+%token NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
%token FRAGNORM FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY
%token REQUIREORDER YES
@@ -390,7 +390,7 @@ typedef struct {
%token <v.i> PORTUNARY PORTBINARY
%type <v.interface> interface if_list if_item_not if_item
%type <v.number> number port icmptype icmp6type uid gid
-%type <v.number> tos
+%type <v.number> tos tableopts tableinit
%type <v.i> no dir log af fragcache
%type <v.i> staticport
%type <v.b> action flags flag blockspec
@@ -440,6 +440,7 @@ ruleset : /* empty */
| ruleset queuespec '\n'
| ruleset varset '\n'
| ruleset antispoof '\n'
+ | ruleset tabledef '\n'
| ruleset error '\n' { errors++; }
;
@@ -776,6 +777,46 @@ antispoof_iflst : if_item { $$ = $1; }
}
;
+tabledef : TABLE PORTUNARY STRING PORTUNARY tableopts tableinit {
+ if ($2 != PF_OP_LT || $4 != PF_OP_GT)
+ YYERROR;
+ if (strlen($3) >= PF_TABLE_NAME_SIZE)
+ YYERROR;
+ pfctl_define_table($3, $5, $6);
+ }
+ ;
+
+tableopts : /* empty */ { $$ = 0; }
+ | tableopts STRING {
+ $$ = $1;
+ if (!strcmp($2, "const"))
+ $$ |= PFR_TFLAG_CONST;
+ else if (!strcmp($2, "persist"))
+ $$ |= PFR_TFLAG_PERSIST;
+ else
+ YYERROR;
+ }
+
+tableinit : /* empty */ { $$ = 0; }
+ | '{' tableaddrs '}' { $$ = 1; }
+
+tableaddrs : /* empty */
+ | tableaddrs tableaddr comma
+
+tableaddr : STRING {
+ pfctl_append_addr($1, -1, 0);
+ }
+ | STRING '/' number {
+ pfctl_append_addr($1, $3, 0);
+ }
+ | '!' STRING {
+ pfctl_append_addr($2, -1, 1);
+ }
+ | '!' STRING '/' number {
+ pfctl_append_addr($2, $4, 1);
+ }
+ ;
+
altqif : ALTQ interface queue_opts QUEUE qassign {
struct pf_altq a;
@@ -3529,6 +3570,7 @@ lookup(char *s)
{ "set", SET},
{ "source-hash", SOURCEHASH},
{ "state", STATE},
+ { "table", TABLE},
{ "tbrsize", TBRSIZE},
{ "timeout", TIMEOUT},
{ "to", TO},
diff --git a/sbin/pfctl/pfctl.8 b/sbin/pfctl/pfctl.8
index e77dd31c123..cf1865803ff 100644
--- a/sbin/pfctl/pfctl.8
+++ b/sbin/pfctl/pfctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pfctl.8,v 1.61 2003/01/03 21:37:44 cedric Exp $
+.\" $OpenBSD: pfctl.8,v 1.62 2003/01/09 10:40:44 cedric Exp $
.\"
.\" Copyright (c) 2001 Kjell Wooding. All rights reserved.
.\"
@@ -231,6 +231,9 @@ Show the content (addresses) of a table.
Test if the given addresses match a table.
.It Fl T Ar zero
Clear all the statistics of a table.
+.It Fl T Ar load
+Load only the table definitions from pf.conf.
+Used in "pfctl -Tl -f pf.conf".
.El
.It Fl v
Produce more verbose output. A second use of
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index f7a9c2a138e..3e673c6a8cb 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.125 2003/01/07 01:04:33 henning Exp $ */
+/* $OpenBSD: pfctl.c,v 1.126 2003/01/09 10:40:44 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -974,7 +974,7 @@ pfctl_rules(int dev, char *filename, int opts)
if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_FILTER]))
err(1, "DIOCBEGINRULES");
}
-
+ pfctl_begin_table();
}
/* fill in callback data */
pf.dev = dev;
@@ -1013,6 +1013,7 @@ pfctl_rules(int dev, char *filename, int opts)
if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_FILTER]))
err(1, "DIOCCOMMITRULES");
}
+ pfctl_commit_table();
#if 0
if ((opts & PF_OPT_QUIET) == 0) {
fprintf(stderr, "%u nat entries loaded\n", n);
@@ -1340,10 +1341,15 @@ main(int argc, char *argv[])
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;
+ if (ch == 'l') {
+ loadopt = PFCTL_FLAG_TABLE;
+ tblcmdopt = NULL;
+ } else {
+ 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]);
diff --git a/sbin/pfctl/pfctl.h b/sbin/pfctl/pfctl.h
index 8111f407405..0d6f1f3161b 100644
--- a/sbin/pfctl/pfctl.h
+++ b/sbin/pfctl/pfctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.h,v 1.3 2003/01/07 00:21:08 dhartmei Exp $ */
+/* $OpenBSD: pfctl.h,v 1.4 2003/01/09 10:40:44 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -50,6 +50,11 @@ 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_set_tflags(struct pfr_table *, int, int, int, int *, int *, int);
+int pfr_ina_begin(int *, int *, int);
+int pfr_ina_commit(int, int *, int *, int);
+int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
+ int *, int, int);
int pfctl_clear_tables(int);
int pfctl_show_tables(int);
int pfctl_command_tables(int, char *[], char *, char *, char *, int);
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
index 8be11417b38..07fd09c1c24 100644
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.h,v 1.38 2003/01/04 00:01:34 deraadt Exp $ */
+/* $OpenBSD: pfctl_parser.h,v 1.39 2003/01/09 10:40:44 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -88,6 +88,11 @@ void print_status(struct pf_status *);
int eval_pfaltq(struct pfctl *, struct pf_altq *, u_int32_t, u_int16_t);
int eval_pfqueue(struct pfctl *, struct pf_altq *, u_int32_t, u_int16_t);
+void pfctl_begin_table(void);
+void pfctl_append_addr(char *, int, int);
+void pfctl_define_table(char *, int, int);
+void pfctl_commit_table(void);
+
struct icmptypeent {
char *name;
u_int8_t type;
@@ -114,7 +119,9 @@ struct pf_timeout {
#define PFCTL_FLAG_NAT 0x04
#define PFCTL_FLAG_OPTION 0x08
#define PFCTL_FLAG_ALTQ 0x10
+#define PFCTL_FLAG_TABLE 0x20
extern const struct pf_timeout pf_timeouts[];
+extern int loadopt;
#endif /* _PFCTL_PARSER_H_ */
diff --git a/sbin/pfctl/pfctl_radix.c b/sbin/pfctl/pfctl_radix.c
index d5fdb825dac..c8ed2c7a8e3 100644
--- a/sbin/pfctl/pfctl_radix.c
+++ b/sbin/pfctl/pfctl_radix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_radix.c,v 1.7 2003/01/07 00:21:08 dhartmei Exp $ */
+/* $OpenBSD: pfctl_radix.c,v 1.8 2003/01/09 10:40:44 cedric Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -315,6 +315,30 @@ pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
return (0);
}
+int
+pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
+ int *nchange, int *ndel, int flags)
+{
+ struct pfioc_table io;
+
+ if (size < 0 || (size && !tbl)) {
+ errno = EINVAL;
+ return -1;
+ }
+ bzero(&io, sizeof io);
+ io.pfrio_flags = flags;
+ io.pfrio_buffer = tbl;
+ io.pfrio_size = size;
+ io.pfrio_setflag = setflag;
+ io.pfrio_clrflag = clrflag;
+ if (ioctl(dev, DIOCRCLRTSTATS, &io))
+ return (-1);
+ if (nchange)
+ *nchange = io.pfrio_nchange;
+ if (ndel)
+ *ndel = io.pfrio_ndel;
+ return (0);
+}
int
pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
@@ -337,3 +361,61 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
*nmatch = io.pfrio_nmatch;
return (0);
}
+
+int
+pfr_ina_begin(int *ticket, int *ndel, int flags)
+{
+ struct pfioc_table io;
+
+ bzero(&io, sizeof io);
+ io.pfrio_flags = flags;
+ if (ioctl(dev, DIOCRINABEGIN, &io))
+ return (-1);
+ if (ndel != NULL)
+ *ndel = io.pfrio_ndel;
+ if (ticket != NULL)
+ *ticket = io.pfrio_ticket;
+ return (0);
+}
+
+int
+pfr_ina_commit(int ticket, int *nadd, int *nchange, int flags)
+{
+ struct pfioc_table io;
+
+ bzero(&io, sizeof io);
+ io.pfrio_flags = flags;
+ io.pfrio_ticket = ticket;
+ if (ioctl(dev, DIOCRINACOMMIT, &io))
+ return (-1);
+ if (nadd != NULL)
+ *nadd = io.pfrio_nadd;
+ if (nchange != NULL)
+ *nchange = io.pfrio_nchange;
+ return (0);
+}
+
+int
+pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
+ int *nadd, int *naddr, int ticket, int flags)
+{
+ struct pfioc_table io;
+
+ if (tbl == NULL || size < 0 || (size && addr == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+ bzero(&io, sizeof io);
+ io.pfrio_flags = flags;
+ io.pfrio_table = *tbl;
+ io.pfrio_buffer = addr;
+ io.pfrio_size = size;
+ io.pfrio_ticket = ticket;
+ if (ioctl(dev, DIOCRINADEFINE, &io))
+ return (-1);
+ if (nadd != NULL)
+ *nadd = io.pfrio_nadd;
+ if (naddr != NULL)
+ *naddr = io.pfrio_naddr;
+ return (0);
+}
diff --git a/sbin/pfctl/pfctl_table.c b/sbin/pfctl/pfctl_table.c
index 9957718b181..9100aab7c6b 100644
--- a/sbin/pfctl/pfctl_table.c
+++ b/sbin/pfctl/pfctl_table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_table.c,v 1.12 2003/01/07 00:21:08 dhartmei Exp $ */
+/* $OpenBSD: pfctl_table.c,v 1.13 2003/01/09 10:40:44 cedric Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -68,7 +68,7 @@ static void append_addr(char *, int);
static void print_addrx(struct pfr_addr *, struct pfr_addr *, int);
static void print_astats(struct pfr_astats *, int);
static void radix_perror(void);
-
+static void inactive_cleanup(void);
static union {
caddr_t caddr;
@@ -78,7 +78,7 @@ static union {
struct pfr_astats *astats;
} buffer, buffer2;
-static int size, msize;
+static int size, msize, ticket, inactive;
extern char *__progname;
static char *commands[] = {
@@ -165,7 +165,7 @@ pfctl_table(int argc, char *argv[], char *tname, char *command,
if (argc || file != NULL)
usage();
for (;;) {
- if (opts & PF_OPT_VERBOSE) {
+ if (opts & PF_OPT_VERBOSE2) {
grow_buffer(sizeof(struct pfr_tstats), size);
size = msize;
RVTEST(pfr_get_tstats(buffer.tstats, &size,
@@ -180,15 +180,16 @@ pfctl_table(int argc, char *argv[], char *tname, char *command,
break;
}
for (i = 0; i < size; i++)
- if (opts & PF_OPT_VERBOSE)
+ if (opts & PF_OPT_VERBOSE2)
print_tstats(buffer.tstats+i,
- opts & PF_OPT_VERBOSE2);
+ opts & PF_OPT_VERBOSE);
else
print_table(buffer.tables+i,
- opts & PF_OPT_VERBOSE2);
+ opts & PF_OPT_VERBOSE);
} else if (!strcmp(*p, "create")) {
if (argc || file != NULL)
usage();
+ table.pfrt_flags = PFR_TFLAG_PERSIST;
RVTEST(pfr_add_tables(&table, 1, &nadd, flags));
if (!(opts & PF_OPT_QUIET))
fprintf(stderr, "%d table added%s.\n", nadd, DUMMY);
@@ -239,7 +240,7 @@ pfctl_table(int argc, char *argv[], char *tname, char *command,
load_addr(argc, argv, file, 0);
if (opts & PF_OPT_VERBOSE)
flags |= PFR_FLAG_FEEDBACK;
- for(;;) {
+ for (;;) {
int size2 = msize;
RVTEST(pfr_set_addrs(&table, buffer.addrs, size,
@@ -325,7 +326,7 @@ pfctl_table(int argc, char *argv[], char *tname, char *command,
} else if (!strcmp(*p, "zero")) {
if (argc || file != NULL)
usage();
- flags |= PFR_FLAG_RECURSE;
+ flags |= PFR_FLAG_ADDRSTOO;
RVTEST(pfr_clr_tstats(&table, 1, &nzero, flags));
if (!(opts & PF_OPT_QUIET))
fprintf(stderr, "%d table/stats cleared%s.\n", nzero,
@@ -364,8 +365,16 @@ print_table(struct pfr_table *ta, int all)
{
if (!all && !(ta->pfrt_flags & PFR_TFLAG_ACTIVE))
return;
- printf(" %c%s\n", (ta->pfrt_flags & PFR_TFLAG_PERSIST)?'+':' ',
- ta->pfrt_name);
+ if (all) {
+ printf("%c%c%c%c%c\t%s\n",
+ (ta->pfrt_flags & PFR_TFLAG_CONST) ? 'c' : '-',
+ (ta->pfrt_flags & PFR_TFLAG_PERSIST) ? 'p' : '-',
+ (ta->pfrt_flags & PFR_TFLAG_ACTIVE) ? 'a' : '-',
+ (ta->pfrt_flags & PFR_TFLAG_INACTIVE) ? 'i' : '-',
+ (ta->pfrt_flags & PFR_TFLAG_REFERENCED) ? 'r' : '-',
+ ta->pfrt_name);
+ } else
+ puts(ta->pfrt_name);
}
void
@@ -590,3 +599,86 @@ radix_perror(void)
else
perror(__progname);
}
+
+void pfctl_begin_table(void)
+{
+ static int hookreg;
+ int rv;
+
+ if ((loadopt & (PFCTL_FLAG_TABLE | PFCTL_FLAG_ALL)) == 0)
+ return;
+ rv = pfr_ina_begin(&ticket, NULL, 0);
+ if (rv) {
+ radix_perror();
+ exit(1);
+ }
+ if (!hookreg) {
+ atexit(inactive_cleanup);
+ hookreg = 1;
+ }
+}
+
+void pfctl_append_addr(char *addr, int net, int neg)
+{
+ char *p = NULL;
+
+ if (net < 0 && !neg) {
+ append_addr(addr, 0);
+ return;
+ }
+ if (net >= 0 && !neg)
+ asprintf(&p, "%s/%d", addr, net);
+ else if (net < 0)
+ asprintf(&p, "!%s", addr);
+ else
+ asprintf(&p, "!%s/%d", addr, net);
+ if (p == NULL) {
+ radix_perror();
+ exit(1);
+ }
+ append_addr(p, 0);
+ free(p);
+}
+
+void pfctl_define_table(char *name, int flags, int addrs)
+{
+ struct pfr_table tbl;
+ int rv;
+
+ if ((loadopt & (PFCTL_FLAG_TABLE | PFCTL_FLAG_ALL)) == 0) {
+ size = 0;
+ return;
+ }
+ bzero(&tbl, sizeof(tbl));
+ strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name));
+ tbl.pfrt_flags = flags;
+
+ inactive = 1;
+ rv = pfr_ina_define(&tbl, buffer.addrs, size, NULL, NULL, ticket,
+ addrs ? PFR_FLAG_ADDRSTOO : 0);
+ if (rv) {
+ radix_perror();
+ exit(1);
+ }
+ size = 0;
+}
+
+void pfctl_commit_table(void)
+{
+ int rv;
+
+ if ((loadopt & (PFCTL_FLAG_TABLE | PFCTL_FLAG_ALL)) == 0)
+ return;
+ rv = pfr_ina_commit(ticket, NULL, NULL, 0);
+ if (rv) {
+ radix_perror();
+ exit(1);
+ }
+ inactive = 0;
+}
+
+void inactive_cleanup(void)
+{
+ if (inactive)
+ pfr_ina_begin(NULL, NULL, 0);
+}