summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2018-09-21 04:55:28 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2018-09-21 04:55:28 +0000
commitc9201bc0b69a2be92aca7d8c39195bc0d246b8fb (patch)
treed5373796284c98f0577f087e8925e6172affbcdf /usr.sbin/bgpd
parent9b75b4aa744ae84a3ac99f7756a21a9b2abaf4ce (diff)
Implement code to parse, print and reload roa-set tables.
This is sharing a lot of code with prefixset which makes all a bit easier. A roa-set is defined like this: roa-set "test2" { 1.2.3.0/24 source-as 1, 1.2.8.0/22 maxlen 24 source-as 3 } No support for acting on this data yet. Put it in deraadt@, OK benno@, input and OK denis@
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r--usr.sbin/bgpd/bgpd.c30
-rw-r--r--usr.sbin/bgpd/bgpd.h7
-rw-r--r--usr.sbin/bgpd/config.c12
-rw-r--r--usr.sbin/bgpd/parse.y112
-rw-r--r--usr.sbin/bgpd/printconf.c33
-rw-r--r--usr.sbin/bgpd/rde.c51
6 files changed, 216 insertions, 29 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index d422fe98467..108f636b48d 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.200 2018/09/20 11:45:59 claudio Exp $ */
+/* $OpenBSD: bgpd.c,v 1.201 2018/09/21 04:55:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -516,6 +516,34 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct peer **peer_l)
if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIXSETITEM, 0,
0, -1, psi, sizeof(*psi)) == -1)
return (-1);
+ set_free(psi->set);
+ free(psi);
+ }
+ free(ps);
+ }
+
+ /* roasets for filters in the RDE */
+ while ((ps = SIMPLEQ_FIRST(conf->roasets)) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(conf->roasets, entry);
+ if (imsg_compose(ibuf_rde, IMSG_RECONF_ROA_SET, 0, 0, -1,
+ ps->name, sizeof(ps->name)) == -1)
+ return (-1);
+ RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) {
+ u_int32_t *as;
+ size_t i, l, n;
+ RB_REMOVE(prefixset_tree, &ps->psitems, psi);
+ as = set_get(psi->set, &n);
+ for (i = 0; i < n; i += l) {
+ l = (n - i > 1024 ? 1024 : n - i);
+ if (imsg_compose(ibuf_rde,
+ IMSG_RECONF_ROA_AS_SET_ITEMS,
+ 0, 0, -1, as + i, l) == -1)
+ return -1;
+ }
+ if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIXSETITEM, 0,
+ 0, -1, psi, sizeof(*psi)) == -1)
+ return (-1);
+ set_free(psi->set);
free(psi);
}
free(ps);
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index 509589bb66b..3f7e61ffcd7 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.343 2018/09/20 11:45:59 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.344 2018/09/21 04:55:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -229,7 +229,9 @@ struct bgpd_config {
struct listen_addrs *listen_addrs;
struct mrt_head *mrt;
struct prefixset_head *prefixsets;
+ struct prefixset_head *roasets;
struct rde_prefixset_head *rde_prefixsets;
+ struct rde_prefixset_head *rde_roasets;
struct as_set_head *as_sets;
char *csock;
char *rcsock;
@@ -431,6 +433,8 @@ enum imsg_type {
IMSG_RECONF_AS_SET,
IMSG_RECONF_AS_SET_ITEMS,
IMSG_RECONF_AS_SET_DONE,
+ IMSG_RECONF_ROA_SET,
+ IMSG_RECONF_ROA_AS_SET_ITEMS,
IMSG_RECONF_DONE,
IMSG_UPDATE,
IMSG_UPDATE_ERR,
@@ -961,6 +965,7 @@ struct roa_set {
struct prefixset_item {
struct filter_prefix p;
RB_ENTRY(prefixset_item) entry;
+ struct set_table *set;
};
RB_HEAD(prefixset_tree, prefixset_item);
diff --git a/usr.sbin/bgpd/config.c b/usr.sbin/bgpd/config.c
index b34d7aaec5e..60c2d86d08f 100644
--- a/usr.sbin/bgpd/config.c
+++ b/usr.sbin/bgpd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.74 2018/09/20 07:46:39 claudio Exp $ */
+/* $OpenBSD: config.c,v 1.75 2018/09/21 04:55:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -67,6 +67,8 @@ new_config(void)
if ((conf->prefixsets = calloc(1, sizeof(struct prefixset_head)))
== NULL)
fatal(NULL);
+ if ((conf->roasets = calloc(1, sizeof(struct prefixset_head))) == NULL)
+ fatal(NULL);
if ((conf->as_sets = calloc(1, sizeof(struct as_set_head))) == NULL)
fatal(NULL);
if ((conf->filters = calloc(1, sizeof(struct filter_head))) == NULL)
@@ -81,6 +83,7 @@ new_config(void)
TAILQ_INIT(&conf->networks);
SIMPLEQ_INIT(&conf->rdomains);
SIMPLEQ_INIT(conf->prefixsets);
+ SIMPLEQ_INIT(conf->roasets);
SIMPLEQ_INIT(conf->as_sets);
TAILQ_INIT(conf->filters);
@@ -129,6 +132,7 @@ free_prefixsets(struct prefixset_head *psh)
ps = SIMPLEQ_FIRST(psh);
RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) {
RB_REMOVE(prefixset_tree, &ps->psitems, psi);
+ set_free(psi->set);
free(psi);
}
SIMPLEQ_REMOVE_HEAD(psh, entry);
@@ -147,6 +151,7 @@ free_config(struct bgpd_config *conf)
free_networks(&conf->networks);
filterlist_free(conf->filters);
free_prefixsets(conf->prefixsets);
+ free_prefixsets(conf->roasets);
as_sets_free(conf->as_sets);
while ((la = TAILQ_FIRST(conf->listen_addrs)) != NULL) {
@@ -225,6 +230,11 @@ merge_config(struct bgpd_config *xconf, struct bgpd_config *conf,
xconf->prefixsets = conf->prefixsets;
conf->prefixsets = NULL;
+ /* switch the roasets, first remove the old ones */
+ free_prefixsets(xconf->roasets);
+ xconf->roasets = conf->roasets;
+ conf->roasets = NULL;
+
/* switch the as_sets, first remove the old ones */
as_sets_free(xconf->as_sets);
xconf->as_sets = conf->as_sets;
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index 91b1e4796c6..931fa057468 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.355 2018/09/20 11:45:59 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.356 2018/09/21 04:55:27 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -93,6 +93,7 @@ static struct peer *curpeer;
static struct peer *curgroup;
static struct rdomain *currdom;
static struct prefixset *curpset;
+static struct prefixset *curroaset;
static struct filter_head *filter_l;
static struct filter_head *peerfilter_l;
static struct filter_head *groupfilter_l;
@@ -162,7 +163,8 @@ int parseextcommunity(struct filter_extcommunity *, char *,
static int new_as_set(char *);
static void add_as_set(u_int32_t);
static void done_as_set(void);
-static int new_prefix_set(char *);
+static struct prefixset *new_prefix_set(char *, int);
+static void add_roa_set(struct prefixset_item *, u_int32_t, u_int8_t);
typedef struct {
union {
@@ -211,7 +213,7 @@ typedef struct {
%token FROM TO ANY
%token CONNECTED STATIC
%token COMMUNITY EXTCOMMUNITY LARGECOMMUNITY DELETE
-%token PREFIX PREFIXLEN PREFIXSET
+%token PREFIX PREFIXLEN PREFIXSET ROASET
%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
@@ -250,6 +252,7 @@ grammar : /* empty */
| grammar include '\n'
| grammar as_set '\n'
| grammar prefixset '\n'
+ | grammar roa_set '\n'
| grammar conf_main '\n'
| grammar rdomain '\n'
| grammar neighbor '\n'
@@ -423,7 +426,7 @@ as_set_l : as4number_any { add_as_set($1); }
| as_set_l comma as4number_any { add_as_set($3); }
prefixset : PREFIXSET STRING '{' optnl {
- if (new_prefix_set($2) != 0) {
+ if ((curpset = new_prefix_set($2, 0)) == NULL) {
free($2);
YYERROR;
}
@@ -433,7 +436,7 @@ prefixset : PREFIXSET STRING '{' optnl {
curpset = NULL;
}
| PREFIXSET STRING '{' optnl '}' {
- if (new_prefix_set($2) != 0) {
+ if ((curpset = new_prefix_set($2, 0)) == NULL) {
free($2);
YYERROR;
}
@@ -487,6 +490,47 @@ prefixset_item : prefix prefixlenop {
}
;
+roa_set : ROASET STRING '{' optnl {
+ if ((curroaset = new_prefix_set($2, 1)) == NULL) {
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ } roa_set_l optnl '}' {
+ SIMPLEQ_INSERT_TAIL(conf->roasets, curroaset, entry);
+ curroaset = NULL;
+ }
+ | ROASET STRING '{' optnl '}' {
+ if ((curroaset = new_prefix_set($2, 1)) == NULL) {
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ SIMPLEQ_INSERT_TAIL(conf->roasets, curroaset, entry);
+ curroaset = NULL;
+ }
+ ;
+
+roa_set_l : prefixset_item SOURCEAS as4number_any {
+ if ($1->p.len_min != $1->p.len) {
+ yyerror("unsupported prefixlen operation in "
+ "roa-set");
+ free($1);
+ YYERROR;
+ }
+ add_roa_set($1, $3, $1->p.len_max);
+ }
+ | roa_set_l comma prefixset_item SOURCEAS as4number_any {
+ if ($3->p.len_min != $3->p.len) {
+ yyerror("unsupported prefixlen operation in "
+ "roa-set");
+ free($3);
+ YYERROR;
+ }
+ add_roa_set($3, $5, $3->p.len_max);
+ }
+ ;
+
conf_main : AS as4number {
conf->as = $2;
if ($2 > USHRT_MAX)
@@ -2768,6 +2812,7 @@ lookup(char *s)
{ "restart", RESTART},
{ "restricted", RESTRICTED},
{ "rib", RIB},
+ { "roa-set", ROASET },
{ "route-collector", ROUTECOLL},
{ "route-reflector", REFLECTOR},
{ "router-id", ROUTERID},
@@ -4230,21 +4275,52 @@ done_as_set(void)
curset = NULL;
}
-static int
-new_prefix_set(char *name)
+static struct prefixset *
+new_prefix_set(char *name, int is_roa)
{
- if (find_prefixset(name, conf->prefixsets) != NULL) {
- yyerror("prefix-set \"%s\" already exists", name);
- return -1;
+ const char *type = "prefix-set";
+ struct prefixset_head *sets = conf->prefixsets;
+ struct prefixset *pset;
+
+ if (is_roa) {
+ type = "roa-set";
+ sets = conf->roasets;
+ }
+
+ if (find_prefixset(name, sets) != NULL) {
+ yyerror("%s \"%s\" already exists", type, name);
+ return NULL;
}
- if ((curpset = calloc(1, sizeof(*curpset))) == NULL)
+ if ((pset = calloc(1, sizeof(*pset))) == NULL)
fatal("prefixset");
- if (strlcpy(curpset->name, name, sizeof(curpset->name)) >=
- sizeof(curpset->name)) {
- yyerror("prefix-set \"%s\" too long: max %zu",
- name, sizeof(curpset->name) - 1);
- return -1;
+ if (strlcpy(pset->name, name, sizeof(pset->name)) >=
+ sizeof(pset->name)) {
+ yyerror("%s \"%s\" too long: max %zu", type,
+ name, sizeof(pset->name) - 1);
+ free(pset);
+ return NULL;
}
- RB_INIT(&curpset->psitems);
- return 0;
+ RB_INIT(&pset->psitems);
+ return pset;
+}
+
+static void
+add_roa_set(struct prefixset_item *npsi, u_int32_t as, u_int8_t max)
+{
+ struct prefixset_item *psi;
+ struct roa_set rs;
+
+ /* no prefixlen option on this tree */
+ npsi->p.len_max = npsi->p.len_min = npsi->p.len;
+ psi = RB_INSERT(prefixset_tree, &curroaset->psitems, npsi);
+ if (psi == NULL)
+ psi = npsi;
+
+ if (psi->set == NULL)
+ if ((psi->set = set_new(1, sizeof(rs))) == NULL)
+ fatal("set_new");
+ rs.as = as;
+ rs.maxlen = max;
+ if (set_add(psi->set, &rs, 1) != 0)
+ fatal("as_set_new");
}
diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c
index d4648c1b4a7..451a50bf686 100644
--- a/usr.sbin/bgpd/printconf.c
+++ b/usr.sbin/bgpd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.121 2018/09/20 11:45:59 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.122 2018/09/21 04:55:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -42,6 +42,7 @@ const char *print_af(u_int8_t);
void print_network(struct network_config *, const char *);
void print_as_sets(struct as_set_head *);
void print_prefixsets(struct prefixset_head *);
+void print_roasets(struct prefixset_head *);
void print_peer(struct peer_config *, struct bgpd_config *,
const char *);
const char *print_auth_alg(u_int8_t);
@@ -486,6 +487,35 @@ print_prefixsets(struct prefixset_head *psh)
}
void
+print_roasets(struct prefixset_head *psh)
+{
+ struct prefixset *ps;
+ struct prefixset_item *psi;
+ struct roa_set *rs;
+ size_t i, n;
+
+ SIMPLEQ_FOREACH(ps, psh, entry) {
+ int count = 0;
+ printf("roa-set \"%s\" {", ps->name);
+ RB_FOREACH(psi, prefixset_tree, &ps->psitems) {
+ rs = set_get(psi->set, &n);
+ for (i = 0; i < n; i++) {
+ if (count++ % 2 == 0)
+ printf("\n\t");
+ else
+ printf(", ");
+
+ print_prefix(&psi->p);
+ if (psi->p.len != rs[i].maxlen)
+ printf(" maxlen %u", rs[i].maxlen);
+ printf(" source-as %u", rs[i].as);
+ }
+ }
+ printf("\n}\n\n");
+ }
+}
+
+void
print_peer(struct peer_config *p, struct bgpd_config *conf, const char *c)
{
char *method;
@@ -891,6 +921,7 @@ print_config(struct bgpd_config *conf, struct rib_names *rib_l,
print_mainconf(conf);
print_prefixsets(conf->prefixsets);
print_as_sets(conf->as_sets);
+ print_roasets(conf->roasets);
TAILQ_FOREACH(n, net_l, entry)
print_network(&n->net, "");
if (!SIMPLEQ_EMPTY(rdom_l))
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 39ccae7a0d2..23081362d3f 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.425 2018/09/20 11:45:59 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.426 2018/09/21 04:55:27 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -131,6 +131,7 @@ time_t reloadtime;
struct rde_peer_head peerlist;
struct rde_peer *peerself;
struct rde_prefixset_head *prefixsets_tmp, *prefixsets_old;
+struct rde_prefixset_head *roasets_tmp, *roasets_old;
struct as_set_head *as_sets_tmp, *as_sets_old;
struct filter_head *out_rules, *out_rules_tmp;
struct rdomain_head *rdomains_l, *newdomains;
@@ -689,6 +690,7 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
{
static struct rde_prefixset *last_prefixset;
static struct as_set *last_as_set;
+ static struct set_table *last_set;
static struct rdomain *rd;
struct imsg imsg;
struct mrt xmrt;
@@ -702,7 +704,7 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
struct prefixset_item psi;
char *name;
size_t nmemb;
- int n, fd;
+ int n, fd, rv;
u_int16_t rid;
while (ibuf) {
@@ -774,6 +776,11 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
if (prefixsets_tmp == NULL)
fatal(NULL);
SIMPLEQ_INIT(prefixsets_tmp);
+ roasets_tmp = calloc(1,
+ sizeof(struct rde_prefixset_head));
+ if (roasets_tmp == NULL)
+ fatal(NULL);
+ SIMPLEQ_INIT(roasets_tmp);
as_sets_tmp = calloc(1,
sizeof(struct as_set_head));
if (as_sets_tmp == NULL)
@@ -877,6 +884,7 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
TAILQ_INSERT_TAIL(out_rules_tmp, r, entry);
break;
case IMSG_RECONF_PREFIXSET:
+ case IMSG_RECONF_ROA_SET:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
sizeof(ps->name))
fatalx("IMSG_RECONF_PREFIXSET bad len");
@@ -884,9 +892,22 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
if (ps == NULL)
fatal(NULL);
memcpy(ps->name, imsg.data, sizeof(ps->name));
- SIMPLEQ_INSERT_TAIL(prefixsets_tmp, ps, entry);
+ if (imsg.hdr.type == IMSG_RECONF_ROA_SET) {
+ SIMPLEQ_INSERT_TAIL(roasets_tmp, ps, entry);
+ ps->roa = 1;
+ last_set = set_new(1, sizeof(struct roa_set));
+ if (last_set == NULL)
+ fatal(NULL);
+ } else
+ SIMPLEQ_INSERT_TAIL(prefixsets_tmp, ps, entry);
last_prefixset = ps;
break;
+ case IMSG_RECONF_ROA_AS_SET_ITEMS:
+ nmemb = imsg.hdr.len - IMSG_HEADER_SIZE;
+ nmemb /= sizeof(struct roa_set);
+ if (set_add(last_set, imsg.data, nmemb) != 0)
+ fatal(NULL);
+ break;
case IMSG_RECONF_PREFIXSETITEM:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
sizeof(psi))
@@ -894,11 +915,19 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
memcpy(&psi, imsg.data, sizeof(psi));
if (last_prefixset == NULL)
fatalx("King Bula has no prefixset");
- if (trie_add(&last_prefixset->th, &psi.p.addr,
- psi.p.len, psi.p.len_min, psi.p.len_max) == -1)
- log_warnx("trie_add(%s) %s/%u, %u-%u) failed",
+ if (last_prefixset->roa) {
+ set_prep(last_set);
+ rv = trie_roa_add(&last_prefixset->th,
+ &psi.p.addr, psi.p.len, last_set);
+ } else {
+ rv = trie_add(&last_prefixset->th,
+ &psi.p.addr, psi.p.len,
+ psi.p.len_min, psi.p.len_max);
+ }
+ if (rv == -1)
+ log_warnx("trie_add(%s) %s/%u) failed",
last_prefixset->name, log_addr(&psi.p.addr),
- psi.p.len, psi.p.len_min, psi.p.len_max);
+ psi.p.len);
break;
case IMSG_RECONF_AS_SET:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
@@ -2795,6 +2824,7 @@ rde_reload_done(void)
}
prefixsets_old = conf->rde_prefixsets;
+ roasets_old = conf->rde_roasets;
as_sets_old = conf->as_sets;
memcpy(conf, nconf, sizeof(struct bgpd_config));
@@ -2802,6 +2832,7 @@ rde_reload_done(void)
conf->csock = NULL;
conf->rcsock = NULL;
conf->prefixsets = NULL;
+ conf->roasets = NULL;
free(nconf);
nconf = NULL;
@@ -2826,11 +2857,15 @@ rde_reload_done(void)
/* XXX WHERE IS THE SYNC ??? */
rde_mark_prefixsets_dirty(prefixsets_old, prefixsets_tmp);
+ rde_mark_prefixsets_dirty(roasets_old, roasets_tmp);
as_sets_mark_dirty(as_sets_old, as_sets_tmp);
/* swap the prefixsets */
conf->rde_prefixsets = prefixsets_tmp;
prefixsets_tmp = NULL;
+ /* the roa-sets */
+ conf->rde_roasets = roasets_tmp;
+ roasets_tmp = NULL;
/* and the as_sets */
conf->as_sets = as_sets_tmp;
as_sets_tmp = NULL;
@@ -3022,6 +3057,8 @@ rde_softreconfig_done(void)
rde_free_prefixsets(prefixsets_old);
prefixsets_old = NULL;
+ rde_free_prefixsets(roasets_old);
+ roasets_old = NULL;
as_sets_free(as_sets_old);
as_sets_old = NULL;