diff options
-rw-r--r-- | usr.sbin/bgpd/parse.y | 163 |
1 files changed, 102 insertions, 61 deletions
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index 6ec38c18016..60843eac970 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.120 2004/07/27 13:27:42 henning Exp $ */ +/* $OpenBSD: parse.y,v 1.121 2004/07/27 20:26:59 henning Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -67,13 +67,23 @@ struct filter_peers_l { struct filter_peers p; }; +struct filter_prefix_l { + struct filter_prefix_l *next; + struct filter_prefix p; +}; + +struct filter_match_l { + struct filter_match m; + struct filter_prefix_l *prefix_l; +}; + struct peer *alloc_peer(void); struct peer *new_peer(void); struct peer *new_group(void); int add_mrtconfig(enum mrt_type, char *, time_t, struct peer *); int get_id(struct peer *); int expand_rule(struct filter_rule *, struct filter_peers_l *, - struct filter_match *, struct filter_set *); + struct filter_match_l *, struct filter_set *); int str2key(char *, char *, size_t); int neighbor_consistent(struct peer *); @@ -99,7 +109,9 @@ typedef struct { struct bgpd_addr addr; u_int8_t u8; struct filter_peers_l *filter_peers; - struct filter_match filter_match; + struct filter_match_l filter_match; + struct filter_prefix_l *filter_prefix; + struct filter_prefixlen prefixlen; struct filter_set filter_set; struct { struct bgpd_addr prefix; @@ -137,8 +149,10 @@ typedef struct { %type <v.prefix> prefix addrspec %type <v.u8> action quick direction %type <v.filter_peers> filter_peer filter_peer_l filter_peer_h -%type <v.filter_match> filter_match prefixlenop +%type <v.filter_match> filter_match +%type <v.prefixlen> prefixlenop %type <v.filter_set> filter_set filter_set_l filter_set_opt +%type <v.filter_prefix> filter_prefix filter_prefix_l filter_prefix_h %type <v.u8> unaryop binaryop filter_as %type <v.encspec> encspec; %% @@ -741,12 +755,14 @@ encspec : /* nada */ { filterrule : action quick direction filter_peer_h filter_match filter_set { - struct filter_rule r; + struct filter_rule r; + struct filter_prefix_l *l; - if ($5.prefix.addr.af && $5.prefix.addr.af != AF_INET) { - yyerror("king bula sez: AF_INET only for now"); - YYERROR; - } + for (l = $5.prefix_l; l != NULL; l = l->next) + if (l->p.addr.af && l->p.addr.af != AF_INET) { + yyerror("king bula sez: AF_INET only"); + YYERROR; + } bzero(&r, sizeof(r)); r.action = $1; @@ -830,47 +846,54 @@ filter_peer : ANY { } ; +filter_prefix_h : filter_prefix + | '{' filter_prefix_l '}' { $$ = $2; } + ; + +filter_prefix_l : filter_prefix { $$ = $1; } + | filter_prefix_l comma filter_prefix { + $3->next = $1; + $$ = $3; + } + ; + +filter_prefix : prefix { + if (($$ = calloc(1, sizeof(struct filter_prefix_l))) == + NULL) + fatal(NULL); + memcpy(&$$->p.addr, &$1.prefix, + sizeof($$->p.addr)); + $$->p.len = $1.len; + $$->next = NULL; + } + ; + filter_match : /* empty */ { bzero(&$$, sizeof($$)); } - | PREFIX prefix { - bzero(&$$, sizeof($$)); - memcpy(&$$.prefix.addr, &$2.prefix, - sizeof($$.prefix.addr)); - $$.prefix.len = $2.len; + | PREFIX filter_prefix_h { + $$.prefix_l = $2; } | PREFIX prefix PREFIXLEN prefixlenop { bzero(&$$, sizeof($$)); - memcpy(&$$.prefix.addr, &$2.prefix, - sizeof($$.prefix.addr)); - $$.prefix.len = $2.len; - $$.prefixlen = $4.prefixlen; - $$.prefixlen.af = $2.prefix.af; - if ($$.prefixlen.af == AF_INET) - if ($$.prefixlen.len_max > 32 || - $$.prefixlen.len_min > 32) { - yyerror("prefixlen must be <= 32"); - YYERROR; - } - if ($$.prefixlen.af == AF_INET6) - if ($$.prefixlen.len_max > 128 || - $$.prefixlen.len_min > 128) { - yyerror("prefixlen must be <= 128"); - YYERROR; - } + memcpy(&$$.m.prefix.addr, &$2.prefix, + sizeof($$.m.prefix.addr)); + $$.m.prefix.len = $2.len; + memcpy(&$$.m.prefixlen, &$4, sizeof($$.m.prefixlen)); + $$.m.prefixlen.af = $2.prefix.af; } | PREFIXLEN prefixlenop { bzero(&$$, sizeof($$)); - $$.prefixlen = $2.prefixlen; - $$.prefixlen.af = AF_INET; + memcpy(&$$.m.prefixlen, &$2, sizeof($$.m.prefixlen)); + $$.m.prefixlen.af = AF_INET; } | filter_as asnumber { bzero(&$$, sizeof($$)); - $$.as.as = $2; - $$.as.type = $1; + $$.m.as.as = $2; + $$.m.as.type = $1; } | COMMUNITY STRING { bzero(&$$, sizeof($$)); - if (parsecommunity($2, &$$.community.as, - &$$.community.type) == -1) { + if (parsecommunity($2, &$$.m.community.as, + &$$.m.community.type) == -1) { free($2); YYERROR; } @@ -884,8 +907,8 @@ prefixlenop : unaryop number { yyerror("prefixlen must be < 128"); YYERROR; } - $$.prefixlen.op = $1; - $$.prefixlen.len_min = $2; + $$.op = $1; + $$.len_min = $2; } | number binaryop number { bzero(&$$, sizeof($$)); @@ -897,9 +920,9 @@ prefixlenop : unaryop number { yyerror("start prefixlen is bigger that end"); YYERROR; } - $$.prefixlen.op = $2; - $$.prefixlen.len_min = $1; - $$.prefixlen.len_max = $3; + $$.op = $2; + $$.len_min = $1; + $$.len_max = $3; } ; @@ -1682,36 +1705,54 @@ get_id(struct peer *newpeer) int expand_rule(struct filter_rule *rule, struct filter_peers_l *peer, - struct filter_match *match, struct filter_set *set) + struct filter_match_l *match, struct filter_set *set) { struct filter_rule *r; - struct filter_peers_l *p, *next; + struct filter_peers_l *p, *pnext; + struct filter_prefix_l *prefix, *prefix_next; p = peer; - do { - if ((r = calloc(1, sizeof(struct filter_rule))) == NULL) { - log_warn("expand_rule"); - return (-1); - } + prefix = match->prefix_l; + do { + if ((r = calloc(1, sizeof(struct filter_rule))) == + NULL) { + log_warn("expand_rule"); + return (-1); + } - memcpy(r, rule, sizeof(struct filter_rule)); - memcpy(&r->match, match, sizeof(struct filter_match)); - memcpy(&r->set, set, sizeof(struct filter_set)); + memcpy(r, rule, sizeof(struct filter_rule)); + memcpy(&r->match, match, sizeof(struct filter_match)); + memcpy(&r->set, set, sizeof(struct filter_set)); - if (p != NULL) - memcpy(&r->peer, &p->p, sizeof(struct filter_peers)); + if (p != NULL) + memcpy(&r->peer, &p->p, + sizeof(struct filter_peers)); - TAILQ_INSERT_TAIL(filter_l, r, entry); + if (prefix != NULL) + memcpy(&r->match.prefix, &prefix->p, + sizeof(r->match.prefix)); - if (p != NULL) { - next = p->next; - free(p); - p = next; - } else - p = NULL; + TAILQ_INSERT_TAIL(filter_l, r, entry); + + if (prefix != NULL) + prefix = prefix->next; + } while (prefix != NULL); + + if (p != NULL) + p = p->next; } while (p != NULL); + for (p = peer; p != NULL; p = pnext) { + pnext = p->next; + free(p); + } + + for (prefix = match->prefix_l; prefix != NULL; prefix = prefix_next) { + prefix_next = prefix->next; + free(prefix); + } + return (0); } |