summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd/parse.y
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2004-03-11 17:12:52 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2004-03-11 17:12:52 +0000
commitb21c2c568e1f969a0ca76f191c92856223ff303d (patch)
treec7a28663b294b4c9aa62c2be89dee73c6ec3534d /usr.sbin/bgpd/parse.y
parent01eec010699fb17fab1f9d2ec7b12f15330fd2b9 (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.y55
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)
{