From 47feec7c0b23dc3531658f59f4c12ecdb69397d1 Mon Sep 17 00:00:00 2001 From: benno Date: Sun, 9 Sep 2018 11:00:51 +0000 Subject: [PATCH] Add network prefix-set syntax to announce networks in a prefix-set. feature discussed with deraadt@ and job@, ok claudio@ --- usr.sbin/bgpd/bgpd.c | 3 ++- usr.sbin/bgpd/bgpd.conf.5 | 11 ++++++-- usr.sbin/bgpd/bgpd.h | 6 ++++- usr.sbin/bgpd/config.c | 51 +++++++++++++++++++++++++++++++++++- usr.sbin/bgpd/kroute.c | 14 +++++++++- usr.sbin/bgpd/parse.y | 54 +++++++++++++++++++-------------------- usr.sbin/bgpd/printconf.c | 10 +++++--- 7 files changed, 112 insertions(+), 37 deletions(-) diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c index 7f2b963c7dd..c06100781c9 100644 --- a/usr.sbin/bgpd/bgpd.c +++ b/usr.sbin/bgpd/bgpd.c @@ -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 @@ -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); diff --git a/usr.sbin/bgpd/bgpd.conf.5 b/usr.sbin/bgpd/bgpd.conf.5 index cbfe0110868..31a14bd86c3 100644 --- a/usr.sbin/bgpd/bgpd.conf.5 +++ b/usr.sbin/bgpd/bgpd.conf.5 @@ -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 .\" Copyright (c) 2003, 2004 Henning Brauer @@ -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 diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index 0f4d1d088b4..0ab67baae63 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -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 @@ -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); diff --git a/usr.sbin/bgpd/config.c b/usr.sbin/bgpd/config.c index bf4752b7ba4..1c0984facaf 100644 --- a/usr.sbin/bgpd/config.c +++ b/usr.sbin/bgpd/config.c @@ -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 @@ -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); + } + } +} diff --git a/usr.sbin/bgpd/kroute.c b/usr.sbin/bgpd/kroute.c index 8902eef1fd4..99bda3c50a3 100644 --- a/usr.sbin/bgpd/kroute.c +++ b/usr.sbin/bgpd/kroute.c @@ -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 @@ -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; diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index 7a9abf303fb..508696a8910 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -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 @@ -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) { diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c index 361ebed7c28..37422139747 100644 --- a/usr.sbin/bgpd/printconf.c +++ b/usr.sbin/bgpd/printconf.c @@ -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 @@ -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); -- 2.20.1