diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2004-03-11 17:12:52 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2004-03-11 17:12:52 +0000 |
commit | b21c2c568e1f969a0ca76f191c92856223ff303d (patch) | |
tree | c7a28663b294b4c9aa62c2be89dee73c6ec3534d /usr.sbin/bgpd/parse.y | |
parent | 01eec010699fb17fab1f9d2ec7b12f15330fd2b9 (diff) |
Add basic support for communities. Currently it is only possible to filter
on communities, e.g match from any community 24640:* set localpref 666
OK henning@
Diffstat (limited to 'usr.sbin/bgpd/parse.y')
-rw-r--r-- | usr.sbin/bgpd/parse.y | 55 |
1 files changed, 46 insertions, 9 deletions
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index 56922153782..c30a1db47f3 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.75 2004/03/10 11:40:33 henning Exp $ */ +/* $OpenBSD: parse.y,v 1.76 2004/03/11 17:12:51 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -81,6 +81,7 @@ struct sym { int symset(const char *, const char *, int); char *symget(const char *); int atoul(char *, u_long *); +int getcommunity(char *); typedef struct { union { @@ -111,11 +112,11 @@ typedef struct { %token ALLOW DENY MATCH %token QUICK %token FROM TO ANY -%token PREFIX PREFIXLEN SOURCEAS TRANSITAS +%token PREFIX PREFIXLEN SOURCEAS TRANSITAS COMMUNITY %token SET LOCALPREF MED NEXTHOP PREPEND %token ERROR %token <v.string> STRING -%type <v.number> number asnumber optnumber yesno inout +%type <v.number> number asnumber optnumber cnumber yesno inout %type <v.string> string %type <v.addr> address %type <v.prefix> prefix @@ -625,15 +626,32 @@ filter_match : /* empty */ { bzero(&$$, sizeof($$)); } $$.prefixlen = $2.prefixlen; $$.prefixlen.af = AF_INET; } - | filter_as number { + | filter_as asnumber { bzero(&$$, sizeof($$)); - if ($2 > 0xffff) { - yyerror("AS out of range, max %u", 0xffff); - YYERROR; - } $$.as.as = $2; $$.as.type = $1; } + | COMMUNITY STRING { + char *p; + int i; + + bzero(&$$, sizeof($$)); + if ((p = strchr($2, ':')) == NULL) { + yyerror("Bad community syntax"); + YYERROR; + } + *p++ = 0; + if ((i = getcommunity($2)) == COMMUNITY_ERROR) + YYERROR; + if (i == 0 || i == USHRT_MAX) { + yyerror("Bad community as number"); + YYERROR; + } + $$.community.as = i; + if ((i = getcommunity(p)) == COMMUNITY_ERROR) + YYERROR; + $$.community.type = i; + } ; prefixlenop : unaryop number { @@ -771,6 +789,7 @@ lookup(char *s) { "announce", ANNOUNCE}, { "any", ANY}, { "capabilities", CAPABILITIES}, + { "community", COMMUNITY}, { "deny", DENY}, { "descr", DESCR}, { "dump", DUMP}, @@ -992,7 +1011,7 @@ top: x != '!' && x != '=' && x != '/' && x != '#' && \ x != ',')) - if (isalnum(c) || c == ':' || c == '_') { + if (isalnum(c) || c == ':' || c == '_' || c == '*') { do { *p++ = c; if ((unsigned)(p-buf) >= sizeof(buf)) { @@ -1184,6 +1203,24 @@ atoul(char *s, u_long *ulvalp) return (0); } +int +getcommunity(char *s) +{ + u_long ulval; + + if (strcmp(s, "*") == 0) + return (COMMUNITY_ANY); + if (atoul(s, &ulval) == -1) { + yyerror("\"%s\" is not a number", s); + return (COMMUNITY_ERROR); + } + if (ulval > USHRT_MAX) { + yyerror("Community too big: max %u", USHRT_MAX); + return (COMMUNITY_ERROR); + } + return (ulval); +} + struct peer * alloc_peer(void) { |