diff options
author | Cedric Berger <cedric@cvs.openbsd.org> | 2003-01-09 10:40:46 +0000 |
---|---|---|
committer | Cedric Berger <cedric@cvs.openbsd.org> | 2003-01-09 10:40:46 +0000 |
commit | ef9a4fa0481b3db31c30b68a6257c7a03c593c18 (patch) | |
tree | 1f05dbe8255eb7156a2b2e4a4b80524c15b16b6e /sbin/pfctl | |
parent | f3ba1b333f3d2c3a0007a91bf2ec133aae943748 (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.y | 48 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.8 | 5 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 18 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.h | 7 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.h | 9 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_radix.c | 84 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_table.c | 114 |
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); +} |