Add network prefix-set <name> syntax to announce networks in a prefix-set.
authorbenno <benno@openbsd.org>
Sun, 9 Sep 2018 11:00:51 +0000 (11:00 +0000)
committerbenno <benno@openbsd.org>
Sun, 9 Sep 2018 11:00:51 +0000 (11:00 +0000)
feature discussed with deraadt@ and job@, ok claudio@

usr.sbin/bgpd/bgpd.c
usr.sbin/bgpd/bgpd.conf.5
usr.sbin/bgpd/bgpd.h
usr.sbin/bgpd/config.c
usr.sbin/bgpd/kroute.c
usr.sbin/bgpd/parse.y
usr.sbin/bgpd/printconf.c

index 7f2b963..c061007 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bgpd.c,v 1.197 2018/09/07 10:59:16 claudio Exp $ */
+/*     $OpenBSD: bgpd.c,v 1.198 2018/09/09 11:00:51 benno Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -452,6 +452,7 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct peer **peer_l)
                reconfpending = 0;
                return (1);
        }
+       expand_networks(conf);
 
        cflags = conf->flags;
        prepare_listeners(conf);
index cbfe011..31a14bd 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: bgpd.conf.5,v 1.176 2018/09/08 15:54:41 jmc Exp $
+.\" $OpenBSD: bgpd.conf.5,v 1.177 2018/09/09 11:00:51 benno Exp $
 .\"
 .\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
 .\" Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -16,7 +16,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: September 8 2018 $
+.Dd $Mdocdate: September 9 2018 $
 .Dt BGPD.CONF 5
 .Os
 .Sh NAME
@@ -290,6 +290,10 @@ Log received and sent updates.
 .Ic network
 .Pq Ic inet Ns | Ns Ic inet6
 .Ic priority Ar number Op Ic set ...\&
+.It Xo
+.Ic network prefix-set
+.Ar name
+.Op Ic set ...\&
 .Xc
 Announce the specified network as belonging to our AS.
 If set to
@@ -308,6 +312,9 @@ If set to
 routes with the specified
 .Ar priority
 will be announced.
+If a prefix-set
+.Ar name
+is specified, all networks in the prefix-set will be announced.
 .Bd -literal -offset indent
 network 192.168.7.0/24
 .Ed
index 0f4d1d0..0ab67ba 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: bgpd.h,v 1.337 2018/09/08 15:25:27 benno Exp $ */
+/*     $OpenBSD: bgpd.h,v 1.338 2018/09/09 11:00:51 benno Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -354,12 +354,14 @@ enum network_type {
        NETWORK_RTLABEL,
        NETWORK_MRTCLONE,
        NETWORK_PRIORITY,
+       NETWORK_PREFIXSET,
 };
 
 struct network_config {
        struct bgpd_addr         prefix;
        struct filter_set_head   attrset;
        struct rde_aspath       *asp;
+       char                     psname[SET_NAME_LEN];
        u_int                    rtableid;
        u_int16_t                rtlabel;
        enum network_type        type;
@@ -1081,6 +1083,8 @@ void                       free_config(struct bgpd_config *);
 void   free_prefixsets(struct prefixset_head *);
 void   filterlist_free(struct filter_head *);
 int    host(const char *, struct bgpd_addr *, u_int8_t *);
+void   copy_filterset(struct filter_set_head *, struct filter_set_head *);
+void   expand_networks(struct bgpd_config *);
 
 /* kroute.c */
 int             kr_init(void);
index bf4752b..1c0984f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: config.c,v 1.72 2018/09/07 05:43:33 claudio Exp $ */
+/*     $OpenBSD: config.c,v 1.73 2018/09/09 11:00:51 benno Exp $ */
 
 /*
  * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -497,3 +497,52 @@ get_mpe_label(struct rdomain *r)
        r->label = shim.shim_label;
        return (0);
 }
+
+void
+copy_filterset(struct filter_set_head *source, struct filter_set_head *dest)
+{
+       struct filter_set       *s, *t;
+
+       if (source == NULL)
+               return;
+
+       TAILQ_FOREACH(s, source, entry) {
+               if ((t = malloc(sizeof(struct filter_set))) == NULL)
+                       fatal(NULL);
+               memcpy(t, s, sizeof(struct filter_set));
+               TAILQ_INSERT_TAIL(dest, t, entry);
+       }
+}
+
+void
+expand_networks(struct bgpd_config *c)
+{
+       struct network          *n, *m, *tmp;
+       struct network_head     *nw = &c->networks;
+       struct prefixset        *ps;
+       struct prefixset_item   *psi;
+
+       TAILQ_FOREACH_SAFE(n, nw, entry, tmp) {
+               if (n->net.type == NETWORK_PREFIXSET) {
+                       TAILQ_REMOVE(nw, n, entry);
+                       if ((ps = find_prefixset(n->net.psname, c->prefixsets))
+                           == NULL)
+                               fatal("%s: prefixset %s not found", __func__,
+                                   n->net.psname);
+                       SIMPLEQ_FOREACH(psi, &ps->psitems, entry) {
+                               if ((m = calloc(1, sizeof(struct network)))
+                                   == NULL)
+                                       fatal(NULL);
+                               memcpy(&m->net.prefix, &psi->p.addr,
+                                   sizeof(m->net.prefix));
+                               m->net.prefixlen = psi->p.len;
+                               TAILQ_INIT(&m->net.attrset);
+                               copy_filterset(&n->net.attrset,
+                                   &m->net.attrset);
+                               TAILQ_INSERT_TAIL(nw, m, entry);
+                       }
+                       filterset_free(&n->net.attrset);
+                       free(n);
+               }
+       }
+}
index 8902eef..99bda3c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kroute.c,v 1.222 2018/07/22 16:55:01 claudio Exp $ */
+/*     $OpenBSD: kroute.c,v 1.223 2018/09/09 11:00:51 benno Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -1131,6 +1131,11 @@ kr_net_match(struct ktable *kt, struct kroute *kr)
                        if (kr->priority == xn->net.priority)
                                return (xn);
                        break;
+               case NETWORK_PREFIXSET:
+                       /* must not happen */
+                       log_warnx("%s: found a NETWORK_PREFIXSET, "
+                           "please send a bug report", __func__);
+                       break;
                }
        }
        return (NULL);
@@ -1171,6 +1176,11 @@ kr_net_match6(struct ktable *kt, struct kroute6 *kr6)
                        if (kr6->priority == xn->net.priority)
                                return (xn);
                        break;
+               case NETWORK_PREFIXSET:
+                       /* must not happen */
+                       log_warnx("%s: found a NETWORK_PREFIXSET, "
+                           "please send a bug report", __func__);
+                       break;
                }
        }
        return (NULL);
@@ -1208,6 +1218,8 @@ kr_net_reload(u_int rtableid, struct network_head *nh)
                n->net.old = 1;
 
        while ((n = TAILQ_FIRST(nh)) != NULL) {
+               log_debug("%s: processing %s/%u", __func__,
+                   log_addr(&n->net.prefix), n->net.prefixlen);
                TAILQ_REMOVE(nh, n, entry);
                n->net.old = 0;
                n->net.rtableid = rtableid;
index 7a9abf3..508696a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parse.y,v 1.341 2018/09/08 15:25:27 benno Exp $ */
+/*     $OpenBSD: parse.y,v 1.342 2018/09/09 11:00:51 benno Exp $ */
 
 /*
  * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -149,8 +149,6 @@ int          expand_rule(struct filter_rule *, struct filter_rib_l *,
 int             str2key(char *, char *, size_t);
 int             neighbor_consistent(struct peer *);
 int             merge_filterset(struct filter_set_head *, struct filter_set *);
-void            copy_filterset(struct filter_set_head *,
-                   struct filter_set_head *);
 void            merge_filter_lists(struct filter_head *, struct filter_head *);
 struct filter_rule     *get_rule(enum action_types);
 
@@ -448,7 +446,8 @@ prefixset_item      : prefix prefixlenop                    {
                                fatal(NULL);
                        memcpy(&$$->p.addr, &$1.prefix, sizeof($$->p.addr));
                        $$->p.len = $1.len;
-
+                       if ($2.op != OP_NONE)
+                               curpset->sflags |= PREFIXSET_FLAG_OPS;
                        if (merge_prefixspec(&$$->p, &$2) == -1) {
                                free($$);
                                YYERROR;
@@ -785,19 +784,34 @@ network           : NETWORK prefix filter_set     {
                        TAILQ_INSERT_TAIL(netconf, n, entry);
                }
                | NETWORK PREFIXSET STRING filter_set   {
-                       if ((find_prefixset($3, conf->prefixsets)) == NULL) {
-                               yyerror("prefix-set %s not defined", $3);
+                       struct prefixset *ps;
+                       struct network  *n;
+                       if ((ps = find_prefixset($3, conf->prefixsets))
+                           == NULL) {
+                               yyerror("prefix-set %s not defined", ps->name);
                                free($3);
+                               filterset_free($4);
                                free($4);
                                YYERROR;
                        }
-                       /*
-                        * XXX not implemented
-                        */
-                       yyerror("network prefix-set not implemented.");
+                       if (ps->sflags & PREFIXSET_FLAG_OPS) {
+                               yyerror("prefix-set %s has prefixlen operators "
+                                   "and cannot be used in network statements.",
+                                   ps->name);
+                               free($3);
+                               filterset_free($4);
+                               free($4);
+                               YYERROR;
+                       }
+                       if ((n = calloc(1, sizeof(struct network))) == NULL)
+                               fatal("new_network");
+                       strlcpy(n->net.psname, ps->name, sizeof(n->net.psname));
+                       TAILQ_INIT(&n->net.attrset);
+                       TAILQ_CONCAT(&n->net.attrset, $4, entry);
+                       n->net.type = NETWORK_PREFIXSET;
+                       TAILQ_INSERT_TAIL(netconf, n, entry);
                        free($3);
                        free($4);
-                       YYERROR;
                }
                | NETWORK family RTLABEL STRING filter_set      {
                        struct network  *n;
@@ -2141,7 +2155,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 in with a "
+                                   "operators and cannot be used with an "
                                    "or-longer filter", ps->name);
                                free($2);
                                YYERROR;
@@ -4090,22 +4104,6 @@ merge_filterset(struct filter_set_head *sh, struct filter_set *s)
        return (0);
 }
 
-void
-copy_filterset(struct filter_set_head *source, struct filter_set_head *dest)
-{
-       struct filter_set       *s, *t;
-
-       if (source == NULL)
-               return;
-
-       TAILQ_FOREACH(s, source, entry) {
-               if ((t = malloc(sizeof(struct filter_set))) == NULL)
-                       fatal(NULL);
-               memcpy(t, s, sizeof(struct filter_set));
-               TAILQ_INSERT_TAIL(dest, t, entry);
-       }
-}
-
 void
 merge_filter_lists(struct filter_head *dst, struct filter_head *src)
 {
index 361ebed..3742213 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: printconf.c,v 1.114 2018/09/08 15:25:27 benno Exp $   */
+/*     $OpenBSD: printconf.c,v 1.115 2018/09/09 11:00:51 benno Exp $   */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -426,6 +426,9 @@ print_network(struct network_config *n, const char *c)
                printf("%snetwork %s priority %d", c,
                    print_af(n->prefix.aid), n->priority);
                break;
+       case NETWORK_PREFIXSET:
+               printf("%snetwork prefix-set %s", c, n->psname);
+               break;
        default:
                printf("%snetwork %s/%u", c, log_addr(&n->prefix),
                    n->prefixlen);
@@ -854,6 +857,9 @@ print_config(struct bgpd_config *conf, struct rib_names *rib_l,
 
        print_mainconf(conf);
        printf("\n");
+       print_prefixsets(conf->prefixsets);
+       print_as_sets(conf->as_sets);
+       printf("\n");
        TAILQ_FOREACH(n, net_l, entry)
                print_network(&n->net, "");
        printf("\n");
@@ -871,8 +877,6 @@ print_config(struct bgpd_config *conf, struct rib_names *rib_l,
                            "no" : "yes");
        }
        printf("\n");
-       print_prefixsets(conf->prefixsets);
-       print_as_sets(conf->as_sets);
        print_mrt(conf, 0, 0, "", "");
        printf("\n");
        print_groups(conf, peer_l);