diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2020-12-29 15:30:35 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2020-12-29 15:30:35 +0000 |
commit | 68b30a4a74fac863ff7b169f5fe5e4fbd00b63d3 (patch) | |
tree | 5c51382c1807e6a3efdfbb3969b081d07a100127 /usr.sbin | |
parent | 52b095eff069b55cbb0cf52c477e8219e6a3feef (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@
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/bgpd/bgpd.c | 46 | ||||
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 29 | ||||
-rw-r--r-- | usr.sbin/bgpd/config.c | 38 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 69 | ||||
-rw-r--r-- | usr.sbin/bgpd/printconf.c | 52 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 35 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_trie.c | 36 |
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; } |