summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2020-12-29 15:30:35 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2020-12-29 15:30:35 +0000
commit68b30a4a74fac863ff7b169f5fe5e4fbd00b63d3 (patch)
tree5c51382c1807e6a3efdfbb3969b081d07a100127
parent52b095eff069b55cbb0cf52c477e8219e6a3feef (diff)
In preparation for RTR support change the representation of the roa-set
in the parent to a simple RB tree based on struct roa. With this overlapping ROAs (same prefix & source-as but different maxlen) are now merged in the RDE when the lookup trie is constructed. OK benno@
-rw-r--r--usr.sbin/bgpd/bgpd.c46
-rw-r--r--usr.sbin/bgpd/bgpd.h29
-rw-r--r--usr.sbin/bgpd/config.c38
-rw-r--r--usr.sbin/bgpd/parse.y69
-rw-r--r--usr.sbin/bgpd/printconf.c52
-rw-r--r--usr.sbin/bgpd/rde.c35
-rw-r--r--usr.sbin/bgpd/rde_trie.c36
7 files changed, 160 insertions, 145 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index b181811a62c..264202b65f8 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.230 2020/11/05 11:52:59 claudio Exp $ */
+/* $OpenBSD: bgpd.c,v 1.231 2020/12/29 15:30:34 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -502,6 +502,7 @@ send_config(struct bgpd_config *conf)
struct as_set *aset;
struct prefixset *ps;
struct prefixset_item *psi, *npsi;
+ struct roa *roa, *nroa;
reconfpending = 2; /* one per child */
@@ -567,7 +568,6 @@ send_config(struct bgpd_config *conf)
if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET_ITEM,
0, 0, -1, psi, sizeof(*psi)) == -1)
return (-1);
- set_free(psi->set);
free(psi);
}
free(ps);
@@ -579,23 +579,12 @@ send_config(struct bgpd_config *conf)
if (imsg_compose(ibuf_rde, IMSG_RECONF_ORIGIN_SET, 0, 0, -1,
ps->name, sizeof(ps->name)) == -1)
return (-1);
- RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) {
- struct roa_set *rs;
- size_t i, l, n;
- RB_REMOVE(prefixset_tree, &ps->psitems, psi);
- rs = 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_SET_ITEMS,
- 0, 0, -1, rs + i, l * sizeof(*rs)) == -1)
- return -1;
- }
- if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET_ITEM,
- 0, 0, -1, psi, sizeof(*psi)) == -1)
+ RB_FOREACH_SAFE(roa, roa_tree, &ps->roaitems, nroa) {
+ RB_REMOVE(roa_tree, &conf->roa, roa);
+ if (imsg_compose(ibuf_rde, IMSG_RECONF_ROA_ITEM, 0, 0,
+ -1, roa, sizeof(*roa)) == -1)
return (-1);
- set_free(psi->set);
- free(psi);
+ free(roa);
}
free(ps);
}
@@ -604,23 +593,12 @@ send_config(struct bgpd_config *conf)
if (imsg_compose(ibuf_rde, IMSG_RECONF_ROA_SET, 0, 0, -1,
NULL, 0) == -1)
return (-1);
- RB_FOREACH_SAFE(psi, prefixset_tree, &conf->roa, npsi) {
- struct roa_set *rs;
- size_t i, l, n;
- RB_REMOVE(prefixset_tree, &conf->roa, psi);
- rs = 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_SET_ITEMS,
- 0, 0, -1, rs + i, l * sizeof(*rs)) == -1)
- return -1;
- }
- if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIX_SET_ITEM,
- 0, 0, -1, psi, sizeof(*psi)) == -1)
+ RB_FOREACH_SAFE(roa, roa_tree, &conf->roa, nroa) {
+ RB_REMOVE(roa_tree, &conf->roa, roa);
+ if (imsg_compose(ibuf_rde, IMSG_RECONF_ROA_ITEM, 0, 0,
+ -1, roa, sizeof(*roa)) == -1)
return (-1);
- set_free(psi->set);
- free(psi);
+ free(roa);
}
}
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index e0d5f61b6d9..e84fedf11b8 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.406 2020/12/23 13:20:47 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.407 2020/12/29 15:30:34 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -264,6 +264,21 @@ struct rde_prefixset {
};
SIMPLEQ_HEAD(rde_prefixset_head, rde_prefixset);
+struct roa {
+ RB_ENTRY(roa) entry;
+ uint8_t aid;
+ uint8_t prefixlen;
+ uint8_t maxlen;
+ uint8_t pad;
+ uint32_t asnum;
+ union {
+ struct in_addr inet;
+ struct in6_addr inet6;
+ } prefix;
+};
+
+RB_HEAD(roa_tree, roa);
+
struct set_table;
struct as_set;
SIMPLEQ_HEAD(as_set_head, as_set);
@@ -280,7 +295,7 @@ struct bgpd_config {
struct mrt_head *mrt;
struct prefixset_head prefixsets;
struct prefixset_head originsets;
- struct prefixset_tree roa;
+ struct roa_tree roa;
struct rde_prefixset_head rde_prefixsets;
struct rde_prefixset_head rde_originsets;
struct rde_prefixset rde_roa;
@@ -492,7 +507,7 @@ enum imsg_type {
IMSG_RECONF_AS_SET_DONE,
IMSG_RECONF_ORIGIN_SET,
IMSG_RECONF_ROA_SET,
- IMSG_RECONF_ROA_SET_ITEMS,
+ IMSG_RECONF_ROA_ITEM,
IMSG_RECONF_DRAIN,
IMSG_RECONF_DONE,
IMSG_UPDATE,
@@ -1035,13 +1050,13 @@ struct roa_set {
struct prefixset_item {
struct filter_prefix p;
RB_ENTRY(prefixset_item) entry;
- struct set_table *set;
};
struct prefixset {
int sflags;
char name[SET_NAME_LEN];
struct prefixset_tree psitems;
+ struct roa_tree roaitems;
SIMPLEQ_ENTRY(prefixset) entry;
};
@@ -1181,12 +1196,13 @@ void free_config(struct bgpd_config *);
void free_prefixsets(struct prefixset_head *);
void free_rde_prefixsets(struct rde_prefixset_head *);
void free_prefixtree(struct prefixset_tree *);
+void free_roatree(struct roa_tree *);
void filterlist_free(struct filter_head *);
int host(const char *, struct bgpd_addr *, u_int8_t *);
u_int32_t get_bgpid(void);
void expand_networks(struct bgpd_config *);
-int prefixset_cmp(struct prefixset_item *, struct prefixset_item *);
RB_PROTOTYPE(prefixset_tree, prefixset_item, entry, prefixset_cmp);
+RB_PROTOTYPE(roa_tree, roa, entry, roa_cmp);
/* kroute.c */
int kr_init(int *);
@@ -1287,8 +1303,7 @@ int set_equal(const struct set_table *,
/* rde_trie.c */
int trie_add(struct trie_head *, struct bgpd_addr *, u_int8_t, u_int8_t,
u_int8_t);
-int trie_roa_add(struct trie_head *, struct bgpd_addr *, u_int8_t,
- struct set_table *);
+int trie_roa_add(struct trie_head *, struct roa *);
void trie_free(struct trie_head *);
int trie_match(struct trie_head *, struct bgpd_addr *, u_int8_t, int);
int trie_roa_check(struct trie_head *, struct bgpd_addr *, u_int8_t,
diff --git a/usr.sbin/bgpd/config.c b/usr.sbin/bgpd/config.c
index 5cd5a01e188..b5471e584e0 100644
--- a/usr.sbin/bgpd/config.c
+++ b/usr.sbin/bgpd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.96 2020/12/29 09:49:04 claudio Exp $ */
+/* $OpenBSD: config.c,v 1.97 2020/12/29 15:30:34 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -117,6 +117,7 @@ free_prefixsets(struct prefixset_head *psh)
while (!SIMPLEQ_EMPTY(psh)) {
ps = SIMPLEQ_FIRST(psh);
+ free_roatree(&ps->roaitems);
free_prefixtree(&ps->psitems);
SIMPLEQ_REMOVE_HEAD(psh, entry);
free(ps);
@@ -146,12 +147,22 @@ free_prefixtree(struct prefixset_tree *p)
RB_FOREACH_SAFE(psi, prefixset_tree, p, npsi) {
RB_REMOVE(prefixset_tree, p, psi);
- set_free(psi->set);
free(psi);
}
}
void
+free_roatree(struct roa_tree *r)
+{
+ struct roa *roa, *nroa;
+
+ RB_FOREACH_SAFE(roa, roa_tree, r, nroa) {
+ RB_REMOVE(roa_tree, r, roa);
+ free(roa);
+ }
+}
+
+void
free_config(struct bgpd_config *conf)
{
struct peer *p, *next;
@@ -166,7 +177,7 @@ free_config(struct bgpd_config *conf)
free_rde_prefixsets(&conf->rde_prefixsets);
free_rde_prefixsets(&conf->rde_originsets);
as_sets_free(&conf->as_sets);
- free_prefixtree(&conf->roa);
+ free_roatree(&conf->roa);
while ((la = TAILQ_FIRST(conf->listen_addrs)) != NULL) {
TAILQ_REMOVE(conf->listen_addrs, la, entry);
@@ -230,7 +241,7 @@ merge_config(struct bgpd_config *xconf, struct bgpd_config *conf)
mrt_mergeconfig(xconf->mrt, conf->mrt);
/* switch the roa, first remove the old one */
- free_prefixtree(&xconf->roa);
+ free_roatree(&xconf->roa);
/* then move the RB tree root */
RB_ROOT(&xconf->roa) = RB_ROOT(&conf->roa);
RB_ROOT(&conf->roa) = NULL;
@@ -528,7 +539,7 @@ expand_networks(struct bgpd_config *c)
}
}
-int
+static inline int
prefixset_cmp(struct prefixset_item *a, struct prefixset_item *b)
{
int i;
@@ -572,3 +583,20 @@ prefixset_cmp(struct prefixset_item *a, struct prefixset_item *b)
}
RB_GENERATE(prefixset_tree, prefixset_item, entry, prefixset_cmp);
+
+static inline int
+roa_cmp(struct roa *a, struct roa *b)
+{
+ size_t len = 4 + sizeof(a->asnum);
+
+ if (a->aid == b->aid) {
+ if (a->aid == AID_INET)
+ len += sizeof(a->prefix.inet);
+ else
+ len += sizeof(a->prefix.inet6);
+ }
+
+ return memcmp(&a->aid, &b->aid, len);
+}
+
+RB_GENERATE(roa_tree, roa, entry, roa_cmp);
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index 7085042d137..5b8e29b9357 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.410 2020/10/27 19:13:34 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.411 2020/12/29 15:30:34 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -94,7 +94,7 @@ static struct peer *curgroup;
static struct rde_rib *currib;
static struct l3vpn *curvpn;
static struct prefixset *curpset, *curoset;
-static struct prefixset_tree *curpsitree;
+static struct roa_tree *curroatree;
static struct filter_head *filter_l;
static struct filter_head *peerfilter_l;
static struct filter_head *groupfilter_l;
@@ -498,9 +498,9 @@ prefixset_item : prefix prefixlenop {
;
roa_set : ROASET '{' optnl {
- curpsitree = &conf->roa;
+ curroatree = &conf->roa;
} roa_set_l optnl '}' {
- curpsitree = NULL;
+ curroatree = NULL;
}
| ROASET '{' optnl '}' /* nothing */
;
@@ -510,12 +510,12 @@ origin_set : ORIGINSET STRING '{' optnl {
free($2);
YYERROR;
}
- curpsitree = &curoset->psitems;
+ curroatree = &curoset->roaitems;
free($2);
} roa_set_l optnl '}' {
SIMPLEQ_INSERT_TAIL(&conf->originsets, curoset, entry);
curoset = NULL;
- curpsitree = NULL;
+ curroatree = NULL;
}
| ORIGINSET STRING '{' optnl '}' {
if ((curoset = new_prefix_set($2, 1)) == NULL) {
@@ -525,7 +525,7 @@ origin_set : ORIGINSET STRING '{' optnl {
free($2);
SIMPLEQ_INSERT_TAIL(&conf->originsets, curoset, entry);
curoset = NULL;
- curpsitree = NULL;
+ curroatree = NULL;
}
;
@@ -537,6 +537,7 @@ roa_set_l : prefixset_item SOURCEAS as4number_any {
YYERROR;
}
add_roa_set($1, $3, $1->p.len_max);
+ free($1);
}
| roa_set_l comma prefixset_item SOURCEAS as4number_any {
if ($3->p.len_min != $3->p.len) {
@@ -546,6 +547,7 @@ roa_set_l : prefixset_item SOURCEAS as4number_any {
YYERROR;
}
add_roa_set($3, $5, $3->p.len_max);
+ free($3);
}
;
@@ -4502,7 +4504,7 @@ new_prefix_set(char *name, int is_roa)
struct prefixset *pset;
if (is_roa) {
- type = "roa-set";
+ type = "origin-set";
sets = &conf->originsets;
}
@@ -4520,38 +4522,35 @@ new_prefix_set(char *name, int is_roa)
return NULL;
}
RB_INIT(&pset->psitems);
+ RB_INIT(&pset->roaitems);
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, *rsp;
-
- /* no prefixlen option in this tree */
- npsi->p.op = OP_NONE;
- npsi->p.len_max = npsi->p.len_min = npsi->p.len;
- psi = RB_INSERT(prefixset_tree, curpsitree, npsi);
- if (psi == NULL)
- psi = npsi;
- else
- free(npsi);
-
- if (psi->set == NULL)
- if ((psi->set = set_new(1, sizeof(rs))) == NULL)
- fatal("set_new");
-
- /* merge sets with same key, longer maxlen wins */
- if ((rsp = set_match(psi->set, as)) != NULL) {
- if (rsp->maxlen < max)
- rsp->maxlen = max;
- } else {
- rs.as = as;
- rs.maxlen = max;
- if (set_add(psi->set, &rs, 1) != 0)
- fatal("as_set_new");
- /* prep data so that set_match works */
- set_prep(psi->set);
+ struct roa *roa, *r;
+
+ if ((roa = calloc(1, sizeof(*roa))) == NULL)
+ fatal("add_roa_set");
+
+ roa->aid = npsi->p.addr.aid;
+ roa->prefixlen = npsi->p.len;
+ roa->maxlen = max;
+ roa->asnum = as;
+ switch (roa->aid) {
+ case AID_INET:
+ roa->prefix.inet = npsi->p.addr.v4;
+ break;
+ case AID_INET6:
+ roa->prefix.inet6 = npsi->p.addr.v6;
+ break;
+ default:
+ fatalx("Bad address family for roa_set address");
}
+
+ r = RB_INSERT(roa_tree, curroatree, roa);
+ if (r != NULL)
+ /* just ignore duplicates */
+ free(roa);
}
diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c
index 2d047e453ce..80be6f619f1 100644
--- a/usr.sbin/bgpd/printconf.c
+++ b/usr.sbin/bgpd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.143 2020/11/05 11:51:13 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.144 2020/12/29 15:30:34 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -41,7 +41,7 @@ void print_network(struct network_config *, const char *);
void print_as_sets(struct as_set_head *);
void print_prefixsets(struct prefixset_head *);
void print_originsets(struct prefixset_head *);
-void print_roa(struct prefixset_tree *p);
+void print_roa(struct roa_tree *);
void print_peer(struct peer_config *, struct bgpd_config *,
const char *);
const char *print_auth_alg(u_int8_t);
@@ -535,46 +535,42 @@ void
print_originsets(struct prefixset_head *psh)
{
struct prefixset *ps;
- struct prefixset_item *psi;
- struct roa_set *rs;
- size_t i, n;
+ struct roa *roa;
+ struct bgpd_addr addr;
SIMPLEQ_FOREACH(ps, psh, entry) {
printf("origin-set \"%s\" {", ps->name);
- RB_FOREACH(psi, prefixset_tree, &ps->psitems) {
- rs = set_get(psi->set, &n);
- for (i = 0; i < n; i++) {
- printf("\n\t");
- print_prefix(&psi->p);
- if (psi->p.len != rs[i].maxlen)
- printf(" maxlen %u", rs[i].maxlen);
- printf(" source-as %u", rs[i].as);
- }
+ RB_FOREACH(roa, roa_tree, &ps->roaitems) {
+ printf("\n\t");
+ addr.aid = roa->aid;
+ addr.v6 = roa->prefix.inet6;
+ printf("%s/%u", log_addr(&addr), roa->prefixlen);
+ if (roa->prefixlen != roa->maxlen)
+ printf(" maxlen %u", roa->maxlen);
+ printf(" source-as %u", roa->asnum);
}
printf("\n}\n\n");
}
}
void
-print_roa(struct prefixset_tree *p)
+print_roa(struct roa_tree *r)
{
- struct prefixset_item *psi;
- struct roa_set *rs;
- size_t i, n;
+ struct roa *roa;
+ struct bgpd_addr addr;
- if (RB_EMPTY(p))
+ if (RB_EMPTY(r))
return;
printf("roa-set {");
- RB_FOREACH(psi, prefixset_tree, p) {
- rs = set_get(psi->set, &n);
- for (i = 0; i < n; i++) {
- printf("\n\t");
- print_prefix(&psi->p);
- if (psi->p.len != rs[i].maxlen)
- printf(" maxlen %u", rs[i].maxlen);
- printf(" source-as %u", rs[i].as);
- }
+ RB_FOREACH(roa, roa_tree, r) {
+ printf("\n\t");
+ addr.aid = roa->aid;
+ addr.v6 = roa->prefix.inet6;
+ printf("%s/%u", log_addr(&addr), roa->prefixlen);
+ if (roa->prefixlen != roa->maxlen)
+ printf(" maxlen %u", roa->maxlen);
+ printf(" source-as %u", roa->asnum);
}
printf("\n}\n\n");
}
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 0656c32204f..55d4961f086 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.507 2020/12/04 11:57:13 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.508 2020/12/29 15:30:34 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -614,10 +614,10 @@ 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 l3vpn *vpn;
struct imsg imsg;
struct mrt xmrt;
+ struct roa roa;
struct rde_rib rr;
struct filterstate state;
struct imsgbuf *i;
@@ -813,24 +813,18 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
entry);
}
last_prefixset = ps;
- last_set = NULL;
break;
case IMSG_RECONF_ROA_SET:
strlcpy(nconf->rde_roa.name, "RPKI ROA",
sizeof(nconf->rde_roa.name));
last_prefixset = &nconf->rde_roa;
- last_set = NULL;
break;
- case IMSG_RECONF_ROA_SET_ITEMS:
- nmemb = imsg.hdr.len - IMSG_HEADER_SIZE;
- nmemb /= sizeof(struct roa_set);
- if (last_set == NULL) {
- last_set = set_new(1, sizeof(struct roa_set));
- if (last_set == NULL)
- fatal(NULL);
- }
- if (set_add(last_set, imsg.data, nmemb) != 0)
- fatal(NULL);
+ case IMSG_RECONF_ROA_ITEM:
+ if (imsg.hdr.len - IMSG_HEADER_SIZE !=
+ sizeof(roa))
+ fatalx("IMSG_RECONF_PREFIX_SET_ITEM bad len");
+ memcpy(&roa, imsg.data, sizeof(roa));
+ rv = trie_roa_add(&last_prefixset->th, &roa);
break;
case IMSG_RECONF_PREFIX_SET_ITEM:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
@@ -839,16 +833,9 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
memcpy(&psi, imsg.data, sizeof(psi));
if (last_prefixset == NULL)
fatalx("King Bula has no prefixset");
- if (last_set) {
- set_prep(last_set);
- rv = trie_roa_add(&last_prefixset->th,
- &psi.p.addr, psi.p.len, last_set);
- last_set = NULL;
- } else {
- rv = trie_add(&last_prefixset->th,
- &psi.p.addr, psi.p.len,
- psi.p.len_min, psi.p.len_max);
- }
+ 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),
diff --git a/usr.sbin/bgpd/rde_trie.c b/usr.sbin/bgpd/rde_trie.c
index 13b92b139d7..15dc624508a 100644
--- a/usr.sbin/bgpd/rde_trie.c
+++ b/usr.sbin/bgpd/rde_trie.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_trie.c,v 1.10 2018/10/26 16:53:55 claudio Exp $ */
+/* $OpenBSD: rde_trie.c,v 1.11 2020/12/29 15:30:34 claudio Exp $ */
/*
* Copyright (c) 2018 Claudio Jeker <claudio@openbsd.org>
@@ -378,30 +378,30 @@ trie_add(struct trie_head *th, struct bgpd_addr *prefix, u_int8_t plen,
* is a match.
*/
int
-trie_roa_add(struct trie_head *th, struct bgpd_addr *prefix, u_int8_t plen,
- struct set_table *set)
+trie_roa_add(struct trie_head *th, struct roa *roa)
{
struct tentry_v4 *n4;
struct tentry_v6 *n6;
struct set_table **stp;
+ struct roa_set rs, *rsp;
/* ignore possible default route since it does not make sense */
- switch (prefix->aid) {
+ switch (roa->aid) {
case AID_INET:
- if (plen > 32)
+ if (roa->prefixlen > 32)
return -1;
- n4 = trie_add_v4(th, &prefix->v4, plen);
+ n4 = trie_add_v4(th, &roa->prefix.inet, roa->prefixlen);
if (n4 == NULL)
return -1;
stp = &n4->set;
break;
case AID_INET6:
- if (plen > 128)
+ if (roa->prefixlen > 128)
return -1;
- n6 = trie_add_v6(th, &prefix->v6, plen);
+ n6 = trie_add_v6(th, &roa->prefix.inet6, roa->prefixlen);
if (n6 == NULL)
return -1;
stp = &n6->set;
@@ -411,10 +411,22 @@ trie_roa_add(struct trie_head *th, struct bgpd_addr *prefix, u_int8_t plen,
return -1;
}
- /* set_table already set, error out */
- if (*stp != NULL)
- return -1;
- *stp = set;
+ if (*stp == NULL)
+ if ((*stp = set_new(1, sizeof(rs))) == NULL)
+ return -1;
+
+ /* merge sets with same key, longer maxlen wins */
+ if ((rsp = set_match(*stp, roa->asnum)) != NULL) {
+ if (rsp->maxlen < roa->maxlen)
+ rsp->maxlen = roa->maxlen;
+ } else {
+ rs.as = roa->asnum;
+ rs.maxlen = roa->maxlen;
+ if (set_add(*stp, &rs, 1) != 0)
+ return -1;
+ /* prep data so that set_match works */
+ set_prep(*stp);
+ }
return 0;
}