diff options
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 23 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 82 | ||||
-rw-r--r-- | usr.sbin/bgpd/printconf.c | 32 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 9 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_filter.c | 17 |
5 files changed, 127 insertions, 36 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index b43c5ec12cf..9a43575cc1c 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.97 2004/02/16 17:24:04 henning Exp $ */ +/* $OpenBSD: bgpd.h,v 1.98 2004/02/24 15:43:03 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -125,6 +125,15 @@ enum announce_type { ANNOUNCE_ALL }; +struct filter_set { + u_int8_t flags; + u_int32_t localpref; + u_int32_t med; + struct in_addr nexthop; + struct in6_addr nexthop6; + u_int8_t prepend; +}; + struct peer_config { u_int32_t id; u_int32_t groupid; @@ -139,6 +148,7 @@ struct peer_config { u_int8_t passive; u_int16_t holdtime; u_int16_t min_holdtime; + struct filter_set attrset; enum announce_type announce_type; char tcp_md5_key[TCP_MD5_KEY_LEN]; enum reconf_action reconf_action; @@ -316,6 +326,7 @@ enum as_spec { enum comp_ops { OP_NONE, OP_RANGE, + OP_XRANGE, OP_EQ, OP_NE, OP_LE, @@ -342,6 +353,7 @@ struct filter_match { u_int8_t len; } prefix; struct { + sa_family_t af; enum comp_ops op; u_int8_t len_min; u_int8_t len_max; @@ -352,15 +364,6 @@ struct filter_match { } as; }; -struct filter_set { - u_int8_t flags; - u_int32_t localpref; - u_int32_t med; - struct in_addr nexthop; - struct in6_addr nexthop6; - u_int8_t prepend; -}; - TAILQ_HEAD(filter_head, filter_rule); struct filter_rule { diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index cecddb5258a..cb77f09434d 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.57 2004/02/19 13:54:58 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.58 2004/02/24 15:43:03 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -115,9 +115,9 @@ typedef struct { %type <v.addr> address %type <v.u8> action quick direction %type <v.filter_peers> filter_peer -%type <v.filter_match> filter_match +%type <v.filter_match> filter_match prefixlenop %type <v.filter_set> filter_set filter_set_l filter_set_opt -%type <v.u8> unaryop filter_as +%type <v.u8> unaryop binaryop filter_as %% grammar : /* empty */ @@ -419,6 +419,10 @@ peeropts : REMOTEAS number { strtoul(s, NULL, 16); } } + | filter_set { + memcpy(&curpeer->conf.attrset, &$1, + sizeof(curpeer->conf.attrset)); + } ; filterrule : action quick direction filter_peer filter_match filter_set @@ -433,6 +437,20 @@ filterrule : action quick direction filter_peer filter_match filter_set if (expand_rule(&r, &$4, &$5, &$6) == -1) YYERROR; } + | action quick direction filter_peer filter_match + { + struct filter_rule r; + struct filter_set set; + + bzero(&r, sizeof(r)); + bzero(&set, sizeof(set)); + r.action = $1; + r.quick = $2; + r.dir = $3; + + if (expand_rule(&r, &$4, &$5, &set) == -1) + YYERROR; + } ; action : ALLOW { $$ = ACTION_ALLOW; } @@ -490,14 +508,26 @@ filter_match : /* empty */ { bzero(&$$, sizeof($$)); } } $$.prefix.len = $4; } - | PREFIXLEN unaryop number { + | PREFIX address '/' number PREFIXLEN prefixlenop { bzero(&$$, sizeof($$)); - if ($3 > 128) { - yyerror("prefixlen must be < 128"); + memcpy(&$$.prefix.addr, &$2, sizeof($$.prefix.addr)); + if ($4 > 32) { + yyerror("prefixlength must be <= 32"); + YYERROR; + } + $$.prefix.len = $4; + $$.prefixlen = $6.prefixlen; + $$.prefixlen.af = AF_INET; + if ($$.prefixlen.len_max > 32 || + $$.prefixlen.len_min > 32) { + yyerror("prefixlength must be <= 32"); YYERROR; } - $$.prefixlen.op = $2; - $$.prefixlen.len_min = $3; + } + | PREFIXLEN prefixlenop { + bzero(&$$, sizeof($$)); + $$.prefixlen = $2.prefixlen; + $$.prefixlen.af = AF_INET; } | filter_as number { bzero(&$$, sizeof($$)); @@ -510,16 +540,38 @@ filter_match : /* empty */ { bzero(&$$, sizeof($$)); } } ; +prefixlenop : unaryop number { + bzero(&$$, sizeof($$)); + if ($2 > 128) { + yyerror("prefixlen must be < 128"); + YYERROR; + } + $$.prefixlen.op = $1; + $$.prefixlen.len_min = $2; + } + | number binaryop number { + bzero(&$$, sizeof($$)); + if ($1 > 128 || $3 > 128) { + yyerror("prefixlen must be < 128"); + YYERROR; + } + if ($1 >= $3) { + yyerror("start prefixlen is bigger that end"); + YYERROR; + } + $$.prefixlen.op = $2; + $$.prefixlen.len_min = $1; + $$.prefixlen.len_max = $3; + } + ; + filter_as : AS { $$ = AS_ALL; } | SOURCEAS { $$ = AS_SOURCE; } | TRANSITAS { $$ = AS_TRANSIT; } ; -filter_set : /* empty */ { - bzero(&$$, sizeof($$)); - } - | SET filter_set_opt { $$ = $2; } - | SET "{" filter_set_l "}" { $$ = $3; } +filter_set : SET filter_set_opt { $$ = $2; } + | SET optnl "{" optnl filter_set_l optnl "}" { $$ = $5; } ; filter_set_l : filter_set_l comma filter_set_opt { @@ -577,6 +629,10 @@ unaryop : '=' { $$ = OP_EQ; } | '>' { $$ = OP_GT; } ; +binaryop : '-' { $$ = OP_RANGE; } + | '>' '<' { $$ = OP_XRANGE; } + ; + %% struct keywords { diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c index 281c88e0243..8caa4611c6c 100644 --- a/usr.sbin/bgpd/printconf.c +++ b/usr.sbin/bgpd/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.4 2004/02/09 23:16:46 henning Exp $ */ +/* $OpenBSD: printconf.c,v 1.5 2004/02/24 15:43:03 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -31,6 +31,12 @@ void print_op(enum comp_ops op) { switch (op) { + case OP_RANGE: + printf("-"); + break; + case OP_XRANGE: + printf("><"); + break; case OP_EQ: printf("="); break; @@ -124,6 +130,20 @@ print_peer(struct peer_config *p) printf("%s\tannounce ???\n", c); if (p->tcp_md5_key[0]) printf("%s\ttcp md5sig\n", c); + if (p->attrset.flags) { + printf("%s\tset {\n", c); + if (p->attrset.flags & SET_LOCALPREF) + printf("%s\t\tlocalpref %u\n", c, p->attrset.localpref); + if (p->attrset.flags & SET_MED) + printf("%s\t\tmed %u\n", c, p->attrset.med); + if (p->attrset.flags & SET_NEXTHOP) + printf("%s\t\tnexthop %s\n", + c, inet_ntoa(p->attrset.nexthop)); + if (p->attrset.flags & SET_PREPEND) + printf("%s\t\tprepend-self %u\n", + c, p->attrset.prepend); + printf("%s\t}\n", c); + } printf("%s}\n", c); if (p->group[0]) printf("}\n"); @@ -175,10 +195,12 @@ print_rule(struct peer *peer_l, struct filter_rule *r) r->match.prefix.len); if (r->match.prefixlen.op) { - if (r->match.prefixlen.op == OP_RANGE) - printf("prefixlen %u - %u ", r->match.prefixlen.len_min, - r->match.prefixlen.len_max); - else { + if (r->match.prefixlen.op == OP_RANGE || + r->match.prefixlen.op == OP_XRANGE) { + printf("prefixlen %u ", r->match.prefixlen.len_min); + print_op(r->match.prefixlen.op); + printf(" %u ", r->match.prefixlen.len_max); + } else { printf("prefixlen "); print_op(r->match.prefixlen.op); printf(" %u ", r->match.prefixlen.len_min); diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 3f6194bfebf..36f65314729 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.84 2004/02/23 17:19:26 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.85 2004/02/24 15:43:03 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -455,7 +455,10 @@ rde_update_dispatch(struct imsg *imsg) attr_optfree(&attrs); return (0); } - + + /* apply default overrides */ + rde_apply_set(&attrs, &peer->conf.attrset); + /* parse nlri prefix */ while (nlri_len > 0) { if ((pos = rde_update_get_prefix(p, nlri_len, &prefix, @@ -476,7 +479,7 @@ rde_update_dispatch(struct imsg *imsg) p += pos; nlri_len -= pos; - + /* input filter */ /* * XXX we need to copy attrs befor calling the filter diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c index b6e10347188..7423fbf63e2 100644 --- a/usr.sbin/bgpd/rde_filter.c +++ b/usr.sbin/bgpd/rde_filter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_filter.c,v 1.1 2004/02/19 23:07:00 claudio Exp $ */ +/* $OpenBSD: rde_filter.c,v 1.2 2004/02/24 15:43:03 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -110,6 +110,9 @@ rde_filter_match(struct filter_rule *f, struct attr_flags *attrs, case OP_RANGE: return ((plen >= f->match.prefixlen.len_min) && (plen <= f->match.prefixlen.len_max)); + case OP_XRANGE: + return ((plen < f->match.prefixlen.len_min) || + (plen > f->match.prefixlen.len_max)); case OP_EQ: return (plen == f->match.prefixlen.len_min); case OP_NE: @@ -126,16 +129,20 @@ rde_filter_match(struct filter_rule *f, struct attr_flags *attrs, /* NOTREACHED */ } else if (f->match.prefixlen.op != OP_NONE) { /* only prefixlen without a prefix */ - /* - * XXX IPv4 and IPv6 will cause trouble here. - * XXX need to store the af. - */ + + if (f->match.prefixlen.af != prefix->af) + /* don't use IPv4 rules for IPv6 and vice versa */ + return (0); + switch (f->match.prefixlen.op) { case OP_NONE: fatalx("internal filter bug"); case OP_RANGE: return ((plen >= f->match.prefixlen.len_min) && (plen <= f->match.prefixlen.len_max)); + case OP_XRANGE: + return ((plen < f->match.prefixlen.len_min) || + (plen > f->match.prefixlen.len_max)); case OP_EQ: return (plen == f->match.prefixlen.len_min); case OP_NE: |