Hello,

Here is a patch to expand RIB names in rules. When playing with multi-RIBs, it
allows to simplify ruleset.

 Ex :
# cat /etc/bgpd.conf
[...]
peer_ribs = "{ m1, m2, m3 }"
deny rib m2 from any
allow rib $peer_ribs from any prefix { 2001:db8:1::/48, 2001:db8:2::/48 }

# bgpd -dnv
[...]
deny rib m2 from any 
allow rib m3 from any prefix 2001:db8:2::/48 
allow rib m3 from any prefix 2001:db8:1::/48 
allow rib m2 from any prefix 2001:db8:2::/48 
allow rib m2 from any prefix 2001:db8:1::/48 
allow rib m1 from any prefix 2001:db8:2::/48 
allow rib m1 from any prefix 2001:db8:1::/48 


Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
retrieving revision 1.293
diff -u -p -r1.293 parse.y
--- parse.y     5 Jan 2017 13:53:09 -0000       1.293
+++ parse.y     7 Jan 2017 12:34:08 -0000
@@ -91,6 +91,11 @@ static struct filter_rule    *curpeer_filte
 static struct filter_rule      *curgroup_filter[2];
 static u_int32_t                id;
 
+struct filter_rib_l {
+       struct filter_rib_l     *next;
+       char                     name[PEER_DESCR_LEN];
+};
+
 struct filter_peers_l {
        struct filter_peers_l   *next;
        struct filter_peers      p;
@@ -128,8 +133,9 @@ struct rde_rib      *find_rib(char *);
 int             get_id(struct peer *);
 int             merge_prefixspec(struct filter_prefix_l *,
                    struct filter_prefixlen *);
-int             expand_rule(struct filter_rule *, struct filter_peers_l *,
-                   struct filter_match_l *, struct filter_set_head *);
+int             expand_rule(struct filter_rule *, struct filter_rib_l *,
+                   struct filter_peers_l *, struct filter_match_l *,
+                   struct filter_set_head *);
 int             str2key(char *, char *, size_t);
 int             neighbor_consistent(struct peer *);
 int             merge_filterset(struct filter_set_head *, struct filter_set *);
@@ -153,6 +159,7 @@ typedef struct {
                char                    *string;
                struct bgpd_addr         addr;
                u_int8_t                 u8;
+               struct filter_rib_l     *filter_rib;
                struct filter_peers_l   *filter_peers;
                struct filter_match_l    filter_match;
                struct filter_prefix_l  *filter_prefix;
@@ -203,10 +210,11 @@ typedef struct {
 %type  <v.number>              asnumber as4number as4number_any optnumber
 %type  <v.number>              espah family restart origincode nettype
 %type  <v.number>              yesno inout restricted
-%type  <v.string>              string filter_rib
+%type  <v.string>              string
 %type  <v.addr>                address
 %type  <v.prefix>              prefix addrspec
 %type  <v.u8>                  action quick direction delete
+%type  <v.filter_rib>          filter_rib_h filter_rib_l filter_rib
 %type  <v.filter_peers>        filter_peer filter_peer_l filter_peer_h
 %type  <v.filter_match>        filter_match filter_elm filter_match_h
 %type  <v.filter_as>           filter_as filter_as_l filter_as_h
@@ -1458,9 +1466,10 @@ encspec          : /* nada */    {
                }
                ;
 
-filterrule     : action quick filter_rib direction filter_peer_h 
filter_match_h filter_set
+filterrule     : action quick filter_rib_h direction filter_peer_h 
filter_match_h filter_set
                {
                        struct filter_rule       r;
+                       struct filter_rib_l      *rb, *rbnext;
 
                        bzero(&r, sizeof(r));
                        r.action = $1;
@@ -1470,25 +1479,15 @@ filterrule      : action quick filter_rib dir
                                if (r.dir != DIR_IN) {
                                        yyerror("rib only allowed on \"from\" "
                                            "rules.");
-                                       free($3);
-                                       YYERROR;
-                               }
-                               if (!find_rib($3)) {
-                                       yyerror("rib \"%s\" does not exist.",
-                                           $3);
-                                       free($3);
-                                       YYERROR;
-                               }
-                               if (strlcpy(r.rib, $3, sizeof(r.rib)) >=
-                                   sizeof(r.rib)) {
-                                       yyerror("rib name \"%s\" too long: "
-                                           "max %zu", $3, sizeof(r.rib) - 1);
-                                       free($3);
+
+                                       for (rb = $3; rb != NULL; rb = rbnext) {
+                                               rbnext = rb->next;
+                                               free(rb);
+                                       }
                                        YYERROR;
                                }
-                               free($3);
                        }
-                       if (expand_rule(&r, $5, &$6, $7) == -1)
+                       if (expand_rule(&r, $3, $5, &$6, $7) == -1)
                                YYERROR;
                }
                ;
@@ -1506,8 +1505,38 @@ direction        : FROM          { $$ = DIR_IN; }
                | TO            { $$ = DIR_OUT; }
                ;
 
-filter_rib     : /* empty */   { $$ = NULL; }
-               | RIB STRING    { $$ = $2; }
+filter_rib_h   : /* empty */                   { $$ = NULL; }
+               | RIB filter_rib                { $$ = $2; }
+               | RIB '{' filter_rib_l '}'      { $$ = $3; }
+
+filter_rib_l   : filter_rib                    { $$ = $1; }
+               | filter_rib_l comma filter_rib {
+                       $3->next = $1;
+                       $$ = $3;
+               }
+               ;
+
+filter_rib     : STRING        {
+                       if (!find_rib($1)) {
+                               yyerror("rib \"%s\" does not exist.", $1);
+                               free($1);
+                               YYERROR;
+                       }
+                       if (($$ = calloc(1, sizeof(struct filter_rib_l))) ==
+                           NULL)
+                               fatal(NULL);
+                       $$->next = NULL;
+                       if (strlcpy($$->name, $1, sizeof($$->name)) >=
+                           sizeof($$->name)) {
+                               yyerror("rib name \"%s\" too long: "
+                                   "max %zu", $1, sizeof($$->name) - 1);
+                               free($1);
+                               free($$);
+                               YYERROR;
+                       }
+                       free($1);
+               }
+               ;
 
 filter_peer_h  : filter_peer
                | '{' filter_peer_l '}'         { $$ = $2; }
@@ -3439,58 +3468,76 @@ merge_prefixspec(struct filter_prefix_l 
 }
 
 int
-expand_rule(struct filter_rule *rule, struct filter_peers_l *peer,
-    struct filter_match_l *match, struct filter_set_head *set)
+expand_rule(struct filter_rule *rule, struct filter_rib_l *rib,
+    struct filter_peers_l *peer, struct filter_match_l *match,
+    struct filter_set_head *set)
 {
        struct filter_rule      *r;
+       struct filter_rib_l     *rb, *rbnext;
        struct filter_peers_l   *p, *pnext;
        struct filter_prefix_l  *prefix, *prefix_next;
        struct filter_as_l      *a, *anext;
        struct filter_set       *s;
 
-       p = peer;
+       rb = rib;
        do {
-               a = match->as_l;
+               p = peer;
                do {
-                       prefix = match->prefix_l;
+                       a = match->as_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));
-                               TAILQ_INIT(&r->set);
-                               copy_filterset(set, &r->set);
-
-                               if (p != NULL)
-                                       memcpy(&r->peer, &p->p,
-                                           sizeof(struct filter_peers));
-
-                               if (prefix != NULL)
-                                       memcpy(&r->match.prefix, &prefix->p,
-                                           sizeof(r->match.prefix));
+                               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));
+                                       TAILQ_INIT(&r->set);
+                                       copy_filterset(set, &r->set);
+
+                                       if (rb != NULL)
+                                               strlcpy(r->rib, rb->name,
+                                                    sizeof(r->rib));
+
+                                       if (p != NULL)
+                                               memcpy(&r->peer, &p->p,
+                                                   sizeof(struct 
filter_peers));
+
+                                       if (prefix != NULL)
+                                               memcpy(&r->match.prefix, 
&prefix->p,
+                                                   sizeof(r->match.prefix));
+
+                                       if (a != NULL)
+                                               memcpy(&r->match.as, &a->a,
+                                                   sizeof(struct filter_as));
+
+                                       TAILQ_INSERT_TAIL(filter_l, r, entry);
+
+                                       if (prefix != NULL)
+                                               prefix = prefix->next;
+                               } while (prefix != NULL);
 
                                if (a != NULL)
-                                       memcpy(&r->match.as, &a->a,
-                                           sizeof(struct filter_as));
-
-                               TAILQ_INSERT_TAIL(filter_l, r, entry);
+                                       a = a->next;
+                       } while (a != NULL);
 
-                               if (prefix != NULL)
-                                       prefix = prefix->next;
-                       } while (prefix != NULL);
-
-                       if (a != NULL)
-                               a = a->next;
-               } while (a != NULL);
-
-               if (p != NULL)
-                       p = p->next;
-       } while (p != NULL);
+                       if (p != NULL)
+                               p = p->next;
+               } while (p != NULL);
+
+               if (rb != NULL)
+                       rb = rb->next;
+       } while (rb != NULL);
+
+       for (rb = rib; rb != NULL; rb = rbnext) {
+               rbnext = rb->next;
+               free(rb);
+       }
 
        for (p = peer; p != NULL; p = pnext) {
                pnext = p->next;

Reply via email to