diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2018-09-29 08:11:12 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2018-09-29 08:11:12 +0000 |
commit | 3e707678d2170dade0d8c727c0d4467b3334a779 (patch) | |
tree | c48e07dd99920136ec89a730561e4182e0c2bab1 /usr.sbin/bgpd/parse.y | |
parent | d036d37464c59cd3ed85183b9251d7de0622e405 (diff) |
Implement origin validation in bgpd. This introduces two new tables, the
roa-set for RPKI based origin validation and a origin-set which allows to
lookup a source-as / prefix pair.
For RPKI a config can be built like this:
roa-set {
165.254.255.0/24 source-as 15562
193.0.0.0/21 maxlen 24 source-as 3333
}
deny from any ovs invalid
match from any ovs valid set community local-as:42
match from any ovs not-found set community local-as:43
Origin sets are similar but only match when the source-as / prefix pair is
valid.
match from any origin-set ARINDB set community local-as:44
Committing this now so that further work can be done in tree.
OK benno@, job@
Diffstat (limited to 'usr.sbin/bgpd/parse.y')
-rw-r--r-- | usr.sbin/bgpd/parse.y | 136 |
1 files changed, 112 insertions, 24 deletions
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index 43ecd4a3f30..9e2359f31a3 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.360 2018/09/27 13:48:00 benno Exp $ */ +/* $OpenBSD: parse.y,v 1.361 2018/09/29 08:11:11 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -92,8 +92,8 @@ static struct peer *peer_l, *peer_l_old; static struct peer *curpeer; static struct peer *curgroup; static struct rdomain *currdom; -static struct prefixset *curpset; -static struct prefixset *curroaset; +static struct prefixset *curpset, *curoset; +static struct prefixset_tree *curpsitree; static struct filter_head *filter_l; static struct filter_head *peerfilter_l; static struct filter_head *groupfilter_l; @@ -213,7 +213,8 @@ typedef struct { %token FROM TO ANY %token CONNECTED STATIC %token COMMUNITY EXTCOMMUNITY LARGECOMMUNITY DELETE -%token PREFIX PREFIXLEN PREFIXSET ROASET +%token PREFIX PREFIXLEN PREFIXSET +%token ROASET ORIGINSET OVS %token ASSET SOURCEAS TRANSITAS PEERAS MAXASLEN MAXASSEQ %token SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY SELF %token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ORIGIN PRIORITY @@ -226,7 +227,7 @@ typedef struct { %token <v.number> NUMBER %type <v.number> asnumber as4number as4number_any optnumber %type <v.number> espah family restart origincode nettype -%type <v.number> yesno inout restricted +%type <v.number> yesno inout restricted validity %type <v.string> string %type <v.addr> address %type <v.prefix> prefix addrspec @@ -253,6 +254,7 @@ grammar : /* empty */ | grammar as_set '\n' | grammar prefixset '\n' | grammar roa_set '\n' + | grammar origin_set '\n' | grammar conf_main '\n' | grammar rdomain '\n' | grammar neighbor '\n' @@ -432,7 +434,7 @@ prefixset : PREFIXSET STRING '{' optnl { } free($2); } prefixset_l optnl '}' { - SIMPLEQ_INSERT_TAIL(conf->prefixsets, curpset, entry); + SIMPLEQ_INSERT_TAIL(&conf->prefixsets, curpset, entry); curpset = NULL; } | PREFIXSET STRING '{' optnl '}' { @@ -441,7 +443,7 @@ prefixset : PREFIXSET STRING '{' optnl { YYERROR; } free($2); - SIMPLEQ_INSERT_TAIL(conf->prefixsets, curpset, entry); + SIMPLEQ_INSERT_TAIL(&conf->prefixsets, curpset, entry); curpset = NULL; } @@ -492,24 +494,35 @@ prefixset_item : prefix prefixlenop { } ; -roa_set : ROASET STRING '{' optnl { - if ((curroaset = new_prefix_set($2, 1)) == NULL) { +roa_set : ROASET '{' optnl { + curpsitree = &conf->roa; + } roa_set_l optnl '}' { + curpsitree = NULL; + } + | ROASET '{' optnl '}' /* nothing */ + ; + +origin_set : ORIGINSET STRING '{' optnl { + if ((curoset = new_prefix_set($2, 1)) == NULL) { free($2); YYERROR; } + curpsitree = &curoset->psitems; free($2); } roa_set_l optnl '}' { - SIMPLEQ_INSERT_TAIL(conf->roasets, curroaset, entry); - curroaset = NULL; + SIMPLEQ_INSERT_TAIL(&conf->originsets, curoset, entry); + curoset = NULL; + curpsitree = NULL; } - | ROASET STRING '{' optnl '}' { - if ((curroaset = new_prefix_set($2, 1)) == NULL) { + | ORIGINSET STRING '{' optnl '}' { + if ((curoset = new_prefix_set($2, 1)) == NULL) { free($2); YYERROR; } free($2); - SIMPLEQ_INSERT_TAIL(conf->roasets, curroaset, entry); - curroaset = NULL; + SIMPLEQ_INSERT_TAIL(&conf->originsets, curoset, entry); + curoset = NULL; + curpsitree = NULL; } ; @@ -864,7 +877,7 @@ network : NETWORK prefix filter_set { | NETWORK PREFIXSET STRING filter_set { struct prefixset *ps; struct network *n; - if ((ps = find_prefixset($3, conf->prefixsets)) + if ((ps = find_prefixset($3, &conf->prefixsets)) == NULL) { yyerror("prefix-set %s not defined", ps->name); free($3); @@ -2175,6 +2188,21 @@ filter_elm : filter_prefix_h { free($2); free($3); } + | EXTCOMMUNITY OVS STRING { + if (fmopts.m.ext_community.flags & + EXT_COMMUNITY_FLAG_VALID) { + yyerror("\"ext-community\" already specified"); + free($3); + YYERROR; + } + + if (parseextcommunity(&fmopts.m.ext_community, + "ovs", $3) == -1) { + free($3); + YYERROR; + } + free($3); + } | NEXTHOP address { if (fmopts.m.nexthop.flags) { yyerror("nexthop already specified"); @@ -2204,9 +2232,9 @@ filter_elm : filter_prefix_h { free($2); YYERROR; } - if ((ps = find_prefixset($2, conf->prefixsets)) + if ((ps = find_prefixset($2, &conf->prefixsets)) == NULL) { - yyerror("prefix-set not defined"); + yyerror("prefix-set '%s' not defined", $2); free($2); YYERROR; } @@ -2228,7 +2256,7 @@ filter_elm : filter_prefix_h { if ($3.op == OP_RANGE && ps->sflags & PREFIXSET_FLAG_OPS) { yyerror("prefix-set %s contains prefixlen " "operators and cannot be used with an " - "or-longer filter", ps->name); + "or-longer filter", $2); free($2); YYERROR; } @@ -2237,9 +2265,36 @@ filter_elm : filter_prefix_h { fmopts.m.prefixset.flags |= PREFIXSET_FLAG_LONGER; fmopts.m.prefixset.flags |= PREFIXSET_FLAG_FILTER; - fmopts.m.prefixset.ps = NULL; free($2); } + | ORIGINSET STRING { + if (fmopts.m.originset.name[0] != '\0') { + yyerror("origin-set filter already specified"); + free($2); + YYERROR; + } + if (find_prefixset($2, &conf->originsets) == NULL) { + yyerror("origin-set '%s' not defined", $2); + free($2); + YYERROR; + } + if (strlcpy(fmopts.m.originset.name, $2, + sizeof(fmopts.m.originset.name)) >= + sizeof(fmopts.m.originset.name)) { + yyerror("origin-set name too long"); + free($2); + YYERROR; + } + free($2); + } + | OVS validity { + if (fmopts.m.ovs.is_set) { + yyerror("ovs filter already specified"); + YYERROR; + } + fmopts.m.ovs.validity = $2; + fmopts.m.ovs.is_set = 1; + } ; prefixlenop : /* empty */ { bzero(&$$, sizeof($$)); } @@ -2647,6 +2702,22 @@ filter_set_opt : LOCALPREF NUMBER { free($3); free($4); } + | EXTCOMMUNITY delete OVS STRING { + if (($$ = calloc(1, sizeof(struct filter_set))) == NULL) + fatal(NULL); + if ($2) + $$->type = ACTION_DEL_EXT_COMMUNITY; + else + $$->type = ACTION_SET_EXT_COMMUNITY; + + if (parseextcommunity(&$$->action.ext_community, + "ovs", $4) == -1) { + free($4); + free($$); + YYERROR; + } + free($4); + } | ORIGIN origincode { if (($$ = calloc(1, sizeof(struct filter_set))) == NULL) fatal(NULL); @@ -2655,7 +2726,7 @@ filter_set_opt : LOCALPREF NUMBER { } ; -origincode : string { +origincode : STRING { if (!strcmp($1, "egp")) $$ = ORIGIN_EGP; else if (!strcmp($1, "igp")) @@ -2670,6 +2741,21 @@ origincode : string { free($1); }; +validity : STRING { + if (!strcmp($1, "not-found")) + $$ = ROA_NOTFOUND; + else if (!strcmp($1, "invalid")) + $$ = ROA_INVALID; + else if (!strcmp($1, "valid")) + $$ = ROA_VALID; + else { + yyerror("unknown validity \"%s\"", $1); + free($1); + YYERROR; + } + free($1); + }; + optnl : /* empty */ | '\n' optnl ; @@ -2798,7 +2884,9 @@ lookup(char *s) { "on", ON}, { "or-longer", LONGER}, { "origin", ORIGIN}, + { "origin-set", ORIGINSET}, { "out", OUT}, + { "ovs", OVS}, { "passive", PASSIVE}, { "password", PASSWORD}, { "peer-as", PEERAS}, @@ -4287,12 +4375,12 @@ static struct prefixset * new_prefix_set(char *name, int is_roa) { const char *type = "prefix-set"; - struct prefixset_head *sets = conf->prefixsets; + struct prefixset_head *sets = &conf->prefixsets; struct prefixset *pset; if (is_roa) { type = "roa-set"; - sets = conf->roasets; + sets = &conf->originsets; } if (find_prefixset(name, sets) != NULL) { @@ -4321,7 +4409,7 @@ add_roa_set(struct prefixset_item *npsi, u_int32_t as, u_int8_t max) /* no prefixlen option in this tree */ npsi->p.op = OP_NONE; npsi->p.len_max = npsi->p.len_min = npsi->p.len; - psi = RB_INSERT(prefixset_tree, &curroaset->psitems, npsi); + psi = RB_INSERT(prefixset_tree, curpsitree, npsi); if (psi == NULL) psi = npsi; |