diff options
Diffstat (limited to 'sbin/pfctl')
-rw-r--r-- | sbin/pfctl/parse.y | 103 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.h | 5 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_optimize.c | 3 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 50 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.h | 3 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_radix.c | 11 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_table.c | 19 |
7 files changed, 155 insertions, 39 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index de30e7c443e..11ffd536617 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.605 2011/07/13 20:57:10 mcbride Exp $ */ +/* $OpenBSD: parse.y,v 1.606 2011/07/27 00:26:10 mcbride Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -380,6 +380,7 @@ typedef struct { int i; char *string; u_int rtableid; + u_int16_t weight; struct { u_int8_t b1; u_int8_t b2; @@ -451,6 +452,7 @@ int parseport(char *, struct range *r, int); %token SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID %token ANTISPOOF FOR INCLUDE MATCHES %token BITMASK RANDOM SOURCEHASH ROUNDROBIN LEASTSTATES STATICPORT PROBABILITY +%token WEIGHT %token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT %token QUEUE PRIORITY QLIMIT RTABLE RDOMAIN %token LOAD RULESET_OPTIMIZATION RTABLE RDOMAIN PRIO @@ -465,6 +467,7 @@ int parseport(char *, struct range *r, int); %type <v.number> number icmptype icmp6type uid gid %type <v.number> tos not yesno optnodf %type <v.probability> probability +%type <v.weight> optweight %type <v.i> dir af optimizer %type <v.i> sourcetrack flush unaryop statelock %type <v.b> action @@ -480,6 +483,7 @@ int parseport(char *, struct range *r, int); %type <v.fromto> fromto %type <v.peer> ipportspec from to %type <v.host> ipspec xhost host dynaddr host_list +%type <v.host> table_host_list tablespec %type <v.host> redir_host_list redirspec %type <v.host> route_host route_host_list routespec %type <v.os> os xos os_list @@ -1190,8 +1194,6 @@ table_opt : STRING { table_opts.flags |= PFR_TFLAG_PERSIST; else if (!strcmp($1, "counters")) table_opts.flags |= PFR_TFLAG_COUNTERS; - else if (!strcmp($1, "cost")) - table_opts.flags |= PFR_TFLAG_COST; else { yyerror("invalid table option '%s'", $1); free($1); @@ -1200,7 +1202,7 @@ table_opt : STRING { free($1); } | '{' optnl '}' { table_opts.init_addr = 1; } - | '{' optnl host_list '}' { + | '{' optnl table_host_list '}' { struct node_host *n; struct node_tinit *ti; @@ -1252,6 +1254,25 @@ table_opt : STRING { } ; +tablespec : xhost optweight { + if ($2 > 0) { + struct node_host *n; + for (n = $1; n != NULL; n = n->next) + n->weight = $2; + } + $$ = $1; + } + | '{' optnl table_host_list '}' { $$ = $3; } + ; + +table_host_list : tablespec optnl { $$ = $1; } + | table_host_list comma tablespec optnl { + $1->tail->next = $3; + $1->tail = $3->tail; + $$ = $1; + } + ; + altqif : ALTQ interface queue_opts QUEUE qassign { struct pf_altq a; @@ -2269,6 +2290,8 @@ filter_opt : USER uids { filter_opts.route.host = $2; filter_opts.route.rt = PF_DUPTO; filter_opts.route.pool_opts = $3.type | $3.opts; + memcpy(&filter_opts.rroute.pool_opts, &$3, + sizeof(filter_opts.rroute.pool_opts)); if ($3.key != NULL) filter_opts.route.key = $3.key; } @@ -2675,6 +2698,7 @@ ipspec : ANY { $$ = NULL; } | '{' optnl host_list '}' { $$ = $3; } ; + host_list : ipspec optnl { $$ = $1; } | host_list comma ipspec optnl { if ($1 == NULL) { @@ -2717,6 +2741,16 @@ xhost : not host { $$->tail = $$; } ; + +optweight : WEIGHT NUMBER { + if ($2 < 1 || $2 > USHRT_MAX) { + yyerror("weight out of range"); + YYERROR; + } + $$ = $2; + } + | /* empty */ { $$ = 0; } + ; host : STRING { if (($$ = host($1)) == NULL) { @@ -3572,22 +3606,39 @@ portstar : numberstring { } ; -redirspec : host { $$ = $1; } +redirspec : host optweight { + if ($2 > 0) { + struct node_host *n; + for (n = $1; n != NULL; n = n->next) + n->weight = $2; + } + $$ = $1; + } | '{' optnl redir_host_list '}' { $$ = $3; } ; -redir_host_list : host optnl { +redir_host_list : host optweight optnl { if ($1->addr.type != PF_ADDR_ADDRMASK) { free($1); yyerror("only addresses can be listed for" "redirection pools "); YYERROR; } + if ($2 > 0) { + struct node_host *n; + for (n = $1; n != NULL; n = n->next) + n->weight = $2; + } $$ = $1; } - | redir_host_list comma host optnl { + | redir_host_list comma host optweight optnl { $1->tail->next = $3; $1->tail = $3->tail; + if ($4 > 0) { + struct node_host *n; + for (n = $3; n != NULL; n = n->next) + n->weight = $4; + } $$ = $1; } ; @@ -3804,8 +3855,15 @@ route_host : STRING { } ; -route_host_list : route_host optnl { $$ = $1; } - | route_host_list comma route_host optnl { +route_host_list : route_host optweight optnl { + if ($2 > 0) { + struct node_host *n; + for (n = $1; n != NULL; n = n->next) + n->weight = $2; + } + $$ = $1; + } + | route_host_list comma route_host optweight optnl { if ($1->af == 0) $1->af = $3->af; if ($1->af != $3->af) { @@ -3815,11 +3873,23 @@ route_host_list : route_host optnl { $$ = $1; } } $1->tail->next = $3; $1->tail = $3->tail; + if ($4 > 0) { + struct node_host *n; + for (n = $3; n != NULL; n = n->next) + n->weight = $4; + } $$ = $1; } ; -routespec : route_host { $$ = $1; } +routespec : route_host optweight { + if ($2 > 0) { + struct node_host *n; + for (n = $1; n != NULL; n = n->next) + n->weight = $2; + } + $$ = $1; + } | '{' optnl route_host_list '}' { $$ = $3; } ; @@ -4057,7 +4127,7 @@ process_tabledef(char *name, struct table_opts *opts) ab.pfrb_type = PFRB_ADDRS; SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) { if (ti->file) - if (pfr_buf_load(&ab, ti->file, 0, append_addr)) { + if (pfr_buf_load(&ab, ti->file, 0)) { if (errno) yyerror("cannot load \"%s\": %s", ti->file, strerror(errno)); @@ -4576,8 +4646,8 @@ collapse_redirspec(struct pf_pool *rpool, struct pf_rule *r, return (0); } else { /* more than one address */ if (rs->pool_opts.type && - (rs->pool_opts.type != PF_POOL_ROUNDROBIN) && - (rs->pool_opts.type != PF_POOL_LEASTSTATES)) { + (rs->pool_opts.type != PF_POOL_ROUNDROBIN) && + (rs->pool_opts.type != PF_POOL_LEASTSTATES)) { yyerror("only round-robin or " "least-states valid for multiple " "translation or routing addresses"); @@ -4598,15 +4668,13 @@ collapse_redirspec(struct pf_pool *rpool, struct pf_rule *r, } memset(&ra, 0, sizeof(ra)); ra.addr = h->addr; + ra.weight = h->weight; if (add_opt_table(pf, &tbl, h->af, &ra, h->ifname)) return (1); - } + } } if (tbl) { - if (rs->pool_opts.type == PF_POOL_LEASTSTATES) - tbl->pt_flags |= PFR_TFLAG_COST; - if ((pf->opts & PF_OPT_NOACTION) == 0 && pf_opt_create_table(pf, tbl)) return (1); @@ -5150,6 +5218,7 @@ lookup(char *s) { "upperlimit", UPPERLIMIT}, { "urpf-failed", URPFFAILED}, { "user", USER}, + { "weight", WEIGHT}, }; const struct keywords *p; diff --git a/sbin/pfctl/pfctl.h b/sbin/pfctl/pfctl.h index ad17fbde8b7..87e0362dca0 100644 --- a/sbin/pfctl/pfctl.h +++ b/sbin/pfctl/pfctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.h,v 1.46 2010/11/12 13:14:41 claudio Exp $ */ +/* $OpenBSD: pfctl.h,v 1.47 2011/07/27 00:26:10 mcbride Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -69,8 +69,7 @@ void pfr_buf_clear(struct pfr_buffer *); int pfr_buf_add(struct pfr_buffer *, const void *); void *pfr_buf_next(struct pfr_buffer *, const void *); int pfr_buf_grow(struct pfr_buffer *, int); -int pfr_buf_load(struct pfr_buffer *, char *, int, - int (*)(struct pfr_buffer *, char *, int)); +int pfr_buf_load(struct pfr_buffer *, char *, int); char *pfr_strerror(int); int pfi_get_ifaces(const char *, struct pfi_kif *, int *); int pfi_clr_istats(const char *, int *, int); diff --git a/sbin/pfctl/pfctl_optimize.c b/sbin/pfctl/pfctl_optimize.c index 72959bfdc95..2a333565ad4 100644 --- a/sbin/pfctl/pfctl_optimize.c +++ b/sbin/pfctl/pfctl_optimize.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_optimize.c,v 1.28 2011/07/07 00:47:19 mcbride Exp $ */ +/* $OpenBSD: pfctl_optimize.c,v 1.29 2011/07/27 00:26:10 mcbride Exp $ */ /* * Copyright (c) 2004 Mike Frantzen <frantzen@openbsd.org> @@ -1231,6 +1231,7 @@ add_opt_table(struct pfctl *pf, struct pf_opt_tbl **tbl, sa_family_t af, node_host.af = af; node_host.addr = addr->addr; node_host.ifname = ifname; + node_host.weight = addr->weight; #ifdef OPT_DEBUG DEBUG("<%s> adding %s/%d", (*tbl)->pt_name, inet_ntop(af, diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 3e6d1064779..4ad8c50e9e9 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.278 2011/07/08 18:52:47 henning Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.279 2011/07/27 00:26:10 mcbride Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1092,8 +1092,6 @@ print_tabledef(const char *name, int flags, int addrs, printf(" persist"); if (flags & PFR_TFLAG_COUNTERS) printf(" counters"); - if (flags & PFR_TFLAG_COST) - printf(" cost"); SIMPLEQ_FOREACH(ti, nodes, entries) { if (ti->file) { printf(" file \"%s\"", ti->file); @@ -1450,7 +1448,6 @@ ifa_skip_if(const char *filter, struct node_host *p) return (p->ifname[n] < '0' || p->ifname[n] > '9'); } - struct node_host * host(const char *s) { @@ -1509,8 +1506,10 @@ host(const char *s) fprintf(stderr, "no IP address found for %s\n", s); return (NULL); } - for (n = h; n != NULL; n = n->next) + for (n = h; n != NULL; n = n->next) { n->addr.type = PF_ADDR_ADDRMASK; + n->weight = 0; + } return (h); } @@ -1702,9 +1701,41 @@ host_dns(const char *s, int v4mask, int v6mask) int append_addr(struct pfr_buffer *b, char *s, int test) { - char *r; + static int previous = 0; + static int expect = 0; + struct pfr_addr *a; struct node_host *h, *n; - int rv, not = 0; + char *r; + const char *errstr; + int rv, not = 0, i = 0; + u_int16_t weight; + + /* skip weight if given */ + if (strcmp(s, "weight") == 0) { + expect = 1; + return (1); /* expecting further call */ + } + + /* check if previous host is set */ + if (expect) { + /* parse and append load balancing weight */ + weight = strtonum(s, 1, USHRT_MAX, &errstr); + if (errstr) { + fprintf(stderr, "failed to convert weight %s\n", s); + return (-1); + } + if (previous != -1) { + PFRB_FOREACH(a, b) { + if (++i >= previous) { + a->pfra_weight = weight; + a->pfra_type = PFRKE_COST; + } + } + } + + expect = 0; + return (0); + } for (r = s; *r == '!'; r++) not = !not; @@ -1713,6 +1744,7 @@ append_addr(struct pfr_buffer *b, char *s, int test) return (-1); } rv = append_addr_host(b, n, test, not); + previous = b->pfrb_size; do { h = n; n = n->next; @@ -1744,6 +1776,10 @@ append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not) errx(1, "append_addr_host: strlcpy"); addr.pfra_type = PFRKE_ROUTE; } + if (n->weight > 0) { + addr.pfra_weight = n->weight; + addr.pfra_type = PFRKE_COST; + } switch (n->af) { case AF_INET: addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0]; diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h index 7d27dba9cf1..9359c4edff4 100644 --- a/sbin/pfctl/pfctl_parser.h +++ b/sbin/pfctl/pfctl_parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.h,v 1.96 2011/07/03 23:37:55 zinke Exp $ */ +/* $OpenBSD: pfctl_parser.h,v 1.97 2011/07/27 00:26:10 mcbride Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -117,6 +117,7 @@ struct node_host { sa_family_t af; u_int8_t not; u_int32_t ifindex; /* link-local IPv6 addrs */ + u_int16_t weight; /* load balancing weight */ char *ifname; u_int ifa_flags; struct node_host *next; diff --git a/sbin/pfctl/pfctl_radix.c b/sbin/pfctl/pfctl_radix.c index becd0305b83..1fced17e5c5 100644 --- a/sbin/pfctl/pfctl_radix.c +++ b/sbin/pfctl/pfctl_radix.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_radix.c,v 1.28 2007/12/05 12:01:47 chl Exp $ */ +/* $OpenBSD: pfctl_radix.c,v 1.29 2011/07/27 00:26:10 mcbride Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -46,6 +46,7 @@ #include <err.h> #include "pfctl.h" +#include "pfctl_parser.h" #define BUF_SIZE 256 @@ -505,12 +506,12 @@ pfr_buf_clear(struct pfr_buffer *b) } int -pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork, - int (*append_addr)(struct pfr_buffer *, char *, int)) +pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork) { FILE *fp; char buf[BUF_SIZE]; int rv; + int ev = 0; if (file == NULL) return (0); @@ -522,10 +523,12 @@ pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork, return (-1); } while ((rv = pfr_next_token(buf, fp)) == 1) - if (append_addr(b, buf, nonetwork)) { + if ((ev = append_addr(b, buf, nonetwork)) == -1) { rv = -1; break; } + if (ev == 1) /* expected further append_addr call */ + rv = -1; if (fp != stdin) fclose(fp); return (rv); diff --git a/sbin/pfctl/pfctl_table.c b/sbin/pfctl/pfctl_table.c index bbdc4e660db..002da62c708 100644 --- a/sbin/pfctl/pfctl_table.c +++ b/sbin/pfctl/pfctl_table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_table.c,v 1.70 2011/07/03 23:37:55 zinke Exp $ */ +/* $OpenBSD: pfctl_table.c,v 1.71 2011/07/27 00:26:10 mcbride Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -411,13 +411,18 @@ int load_addr(struct pfr_buffer *b, int argc, char *argv[], char *file, int nonetwork) { + int ev = 0; while (argc--) - if (append_addr(b, *argv++, nonetwork)) { + if ((ev = append_addr(b, *argv++, nonetwork)) == -1) { if (errno) warn("cannot decode %s", argv[-1]); return (-1); } - if (pfr_buf_load(b, file, nonetwork, append_addr)) { + if (ev == 1) { /* expected further append_addr call */ + warnx("failed to decode %s", argv[-1]); + return (-1); + } + if (pfr_buf_load(b, file, nonetwork)) { warn("cannot load %s", file); return (-1); } @@ -479,12 +484,14 @@ print_astats(struct pfr_astats *as, int dns) print_addrx(&as->pfras_a, NULL, dns); printf("\tCleared: %s", ctime(&time)); - if (as->pfras_a.pfra_type == PFRKE_COST) + if (as->pfras_a.pfra_states) printf("\tActive States: %d\n", as->pfras_a.pfra_states); - if (as->pfras_a.pfra_fback == PFR_FB_NOCOUNT) - return; + if (as->pfras_a.pfra_type == PFRKE_COST) + printf("\tWeight: %d\n", as->pfras_a.pfra_weight); if (as->pfras_a.pfra_ifname[0]) printf("\tInterface: %s\n", as->pfras_a.pfra_ifname); + if (as->pfras_a.pfra_fback == PFR_FB_NOCOUNT) + return; for (dir = 0; dir < PFR_DIR_MAX; dir++) for (op = 0; op < PFR_OP_ADDR_MAX; op++) printf("\t%-19s [ Packets: %-18llu Bytes: %-18llu ]\n", |