summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bgpd/bgpd.c33
-rw-r--r--usr.sbin/bgpd/bgpd.h21
-rw-r--r--usr.sbin/bgpd/config.c45
-rw-r--r--usr.sbin/bgpd/parse.y127
-rw-r--r--usr.sbin/bgpd/printconf.c31
-rw-r--r--usr.sbin/bgpd/rde.c7
-rw-r--r--usr.sbin/bgpd/rtr.c160
7 files changed, 399 insertions, 25 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index 8632d76ebec..c8778841bbb 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.254 2022/08/17 15:15:25 claudio Exp $ */
+/* $OpenBSD: bgpd.c,v 1.255 2022/11/18 10:17:23 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -27,6 +27,7 @@
#include <poll.h>
#include <pwd.h>
#include <signal.h>
+#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -594,7 +595,8 @@ send_config(struct bgpd_config *conf)
struct as_set *aset;
struct prefixset *ps;
struct prefixset_item *psi, *npsi;
- struct roa *roa, *nroa;
+ struct roa *roa;
+ struct aspa_set *aspa;
struct rtr_config *rtr;
reconfpending = 3; /* one per child */
@@ -676,24 +678,37 @@ 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(roa, roa_tree, &ps->roaitems, nroa) {
- RB_REMOVE(roa_tree, &ps->roaitems, roa);
+ RB_FOREACH(roa, roa_tree, &ps->roaitems) {
if (imsg_compose(ibuf_rde, IMSG_RECONF_ROA_ITEM, 0, 0,
-1, roa, sizeof(*roa)) == -1)
return (-1);
- free(roa);
}
+ free_roatree(&ps->roaitems);
free(ps);
}
- /* roa table and rtr config are sent to the RTR engine */
- RB_FOREACH_SAFE(roa, roa_tree, &conf->roa, nroa) {
- RB_REMOVE(roa_tree, &conf->roa, roa);
+ /* roa table, aspa table and rtr config are sent to the RTR engine */
+ RB_FOREACH(roa, roa_tree, &conf->roa) {
if (imsg_compose(ibuf_rtr, IMSG_RECONF_ROA_ITEM, 0, 0,
-1, roa, sizeof(*roa)) == -1)
return (-1);
- free(roa);
}
+ free_roatree(&conf->roa);
+ RB_FOREACH(aspa, aspa_tree, &conf->aspa) {
+ if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA, 0, 0,
+ -1, aspa, offsetof(struct aspa_set, tas)) == -1)
+ return (-1);
+ if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA_TAS, 0, 0,
+ -1, aspa->tas, sizeof(*aspa->tas) * aspa->num) == -1)
+ return (-1);
+ if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA_TAS_AID,
+ 0, 0, -1, aspa->tas_aid, aspa->num) == -1)
+ return (-1);
+ if (imsg_compose(ibuf_rtr, IMSG_RECONF_ASPA_DONE, 0, 0, -1,
+ NULL, 0) == -1)
+ return -1;
+ }
+ free_aspatree(&conf->aspa);
SIMPLEQ_FOREACH(rtr, &conf->rtrs, entry) {
if (imsg_compose(ibuf_rtr, IMSG_RECONF_RTR_CONFIG, rtr->id,
0, -1, rtr->descr, sizeof(rtr->descr)) == -1)
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index 70d47382f69..75a8cc9e440 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.454 2022/09/23 15:50:41 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.455 2022/11/18 10:17:23 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -263,6 +263,7 @@ struct roa {
};
RB_HEAD(roa_tree, roa);
+RB_HEAD(aspa_tree, aspa_set);
struct set_table;
struct as_set;
@@ -284,6 +285,7 @@ struct bgpd_config {
struct prefixset_head prefixsets;
struct prefixset_head originsets;
struct roa_tree roa;
+ struct aspa_tree aspa;
struct rde_prefixset_head rde_prefixsets;
struct rde_prefixset_head rde_originsets;
struct as_set_head as_sets;
@@ -582,6 +584,10 @@ enum imsg_type {
IMSG_RECONF_ORIGIN_SET,
IMSG_RECONF_ROA_SET,
IMSG_RECONF_ROA_ITEM,
+ IMSG_RECONF_ASPA,
+ IMSG_RECONF_ASPA_TAS,
+ IMSG_RECONF_ASPA_TAS_AID,
+ IMSG_RECONF_ASPA_DONE,
IMSG_RECONF_RTR_CONFIG,
IMSG_RECONF_DRAIN,
IMSG_RECONF_DONE,
@@ -1149,6 +1155,15 @@ struct as_set {
int dirty;
};
+struct aspa_set {
+ time_t expires;
+ uint32_t as;
+ uint32_t num;
+ uint32_t *tas;
+ uint8_t *tas_aid;
+ RB_ENTRY(aspa_set) entry;
+};
+
struct l3vpn {
SIMPLEQ_ENTRY(l3vpn) entry;
char descr[PEER_DESCR_LEN];
@@ -1270,14 +1285,16 @@ 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 free_aspa(struct aspa_set *);
+void free_aspatree(struct aspa_tree *);
void free_rtrs(struct rtr_config_head *);
void filterlist_free(struct filter_head *);
int host(const char *, struct bgpd_addr *, uint8_t *);
uint32_t get_bgpid(void);
void expand_networks(struct bgpd_config *, struct network_head *);
RB_PROTOTYPE(prefixset_tree, prefixset_item, entry, prefixset_cmp);
-int roa_cmp(struct roa *, struct roa *);
RB_PROTOTYPE(roa_tree, roa, entry, roa_cmp);
+RB_PROTOTYPE(aspa_tree, aspa_set, entry, aspa_cmp);
/* kroute.c */
int kr_init(int *, uint8_t);
diff --git a/usr.sbin/bgpd/config.c b/usr.sbin/bgpd/config.c
index d6f2163b750..28c0e83a2f3 100644
--- a/usr.sbin/bgpd/config.c
+++ b/usr.sbin/bgpd/config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: config.c,v 1.104 2022/08/17 15:15:25 claudio Exp $ */
+/* $OpenBSD: config.c,v 1.105 2022/11/18 10:17:23 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -59,6 +59,7 @@ new_config(void)
SIMPLEQ_INIT(&conf->rde_prefixsets);
SIMPLEQ_INIT(&conf->rde_originsets);
RB_INIT(&conf->roa);
+ RB_INIT(&conf->aspa);
SIMPLEQ_INIT(&conf->as_sets);
SIMPLEQ_INIT(&conf->rtrs);
@@ -171,6 +172,27 @@ free_roatree(struct roa_tree *r)
}
void
+free_aspa(struct aspa_set *aspa)
+{
+ if (aspa == NULL)
+ return;
+ free(aspa->tas);
+ free(aspa->tas_aid);
+ free(aspa);
+}
+
+void
+free_aspatree(struct aspa_tree *a)
+{
+ struct aspa_set *aspa, *naspa;
+
+ RB_FOREACH_SAFE(aspa, aspa_tree, a, naspa) {
+ RB_REMOVE(aspa_tree, a, aspa);
+ free_aspa(aspa);
+ }
+}
+
+void
free_rtrs(struct rtr_config_head *rh)
{
struct rtr_config *r;
@@ -198,6 +220,7 @@ free_config(struct bgpd_config *conf)
free_rde_prefixsets(&conf->rde_originsets);
as_sets_free(&conf->as_sets);
free_roatree(&conf->roa);
+ free_aspatree(&conf->aspa);
free_rtrs(&conf->rtrs);
while ((la = TAILQ_FIRST(conf->listen_addrs)) != NULL) {
@@ -267,6 +290,12 @@ merge_config(struct bgpd_config *xconf, struct bgpd_config *conf)
RB_ROOT(&xconf->roa) = RB_ROOT(&conf->roa);
RB_ROOT(&conf->roa) = NULL;
+ /* switch the aspa, first remove the old one */
+ free_aspatree(&xconf->aspa);
+ /* then move the RB tree root */
+ RB_ROOT(&xconf->aspa) = RB_ROOT(&conf->aspa);
+ RB_ROOT(&conf->aspa) = NULL;
+
/* switch the rtr_configs, first remove the old ones */
free_rtrs(&xconf->rtrs);
SIMPLEQ_CONCAT(&xconf->rtrs, &conf->rtrs);
@@ -582,7 +611,7 @@ prefixset_cmp(struct prefixset_item *a, struct prefixset_item *b)
RB_GENERATE(prefixset_tree, prefixset_item, entry, prefixset_cmp);
-int
+static inline int
roa_cmp(struct roa *a, struct roa *b)
{
int i;
@@ -627,3 +656,15 @@ roa_cmp(struct roa *a, struct roa *b)
}
RB_GENERATE(roa_tree, roa, entry, roa_cmp);
+
+static inline int
+aspa_cmp(struct aspa_set *a, struct aspa_set *b)
+{
+ if (a->as < b->as)
+ return (-1);
+ if (a->as > b->as)
+ return (1);
+ return (0);
+}
+
+RB_GENERATE(aspa_tree, aspa_set, entry, aspa_cmp);
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index ce44288b993..a52ebdfaf72 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.436 2022/09/21 21:12:04 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.437 2022/11/18 10:17:23 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -140,6 +140,13 @@ struct filter_match_l {
struct filter_prefixset *prefixset;
} fmopts;
+struct aspa_tas_l {
+ struct aspa_tas_l *next;
+ uint32_t as;
+ uint32_t num;
+ uint8_t aid;
+};
+
struct peer *alloc_peer(void);
struct peer *new_peer(void);
struct peer *new_group(void);
@@ -171,6 +178,7 @@ static void add_roa_set(struct prefixset_item *, uint32_t, uint8_t,
time_t);
static struct rtr_config *get_rtr(struct bgpd_addr *);
static int insert_rtr(struct rtr_config *);
+static int merge_aspa_set(uint32_t, struct aspa_tas_l *, time_t);
typedef struct {
union {
@@ -186,6 +194,7 @@ typedef struct {
struct filter_as_l *filter_as;
struct filter_set *filter_set;
struct filter_set_head *filter_set_head;
+ struct aspa_tas_l *aspa_elm;
struct {
struct bgpd_addr prefix;
uint8_t len;
@@ -222,8 +231,8 @@ typedef struct {
%token COMMUNITY EXTCOMMUNITY LARGECOMMUNITY DELETE
%token MAXCOMMUNITIES MAXEXTCOMMUNITIES MAXLARGECOMMUNITIES
%token PREFIX PREFIXLEN PREFIXSET
-%token ROASET ORIGINSET OVS EXPIRES
-%token ASSET SOURCEAS TRANSITAS PEERAS MAXASLEN MAXASSEQ
+%token ASPASET ROASET ORIGINSET OVS EXPIRES
+%token ASSET SOURCEAS TRANSITAS PEERAS PROVIDERAS CUSTOMERAS MAXASLEN MAXASSEQ
%token SET LOCALPREF MED METRIC NEXTHOP REJECT BLACKHOLE NOMODIFY SELF
%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ORIGIN PRIORITY
%token ERROR INCLUDE
@@ -254,6 +263,7 @@ typedef struct {
%type <v.filter_prefix> filter_prefix_m
%type <v.u8> unaryop equalityop binaryop filter_as_type
%type <v.encspec> encspec
+%type <v.aspa_elm> aspa_tas aspa_tas_l
%%
grammar : /* empty */
@@ -263,6 +273,7 @@ grammar : /* empty */
| grammar as_set '\n'
| grammar prefixset '\n'
| grammar roa_set '\n'
+ | grammar aspa_set '\n'
| grammar origin_set '\n'
| grammar rtr '\n'
| grammar rib '\n'
@@ -520,10 +531,8 @@ prefixset_item : prefix prefixlenop {
roa_set : ROASET '{' optnl {
curroatree = &conf->roa;
- noexpires = 0;
} roa_set_l optnl '}' {
curroatree = NULL;
- noexpires = 1;
}
| ROASET '{' optnl '}' /* nothing */
;
@@ -540,6 +549,7 @@ origin_set : ORIGINSET STRING '{' optnl {
SIMPLEQ_INSERT_TAIL(&conf->originsets, curoset, entry);
curoset = NULL;
curroatree = NULL;
+ noexpires = 0;
}
| ORIGINSET STRING '{' optnl '}' {
if ((curoset = new_prefix_set($2, 1)) == NULL) {
@@ -586,6 +596,55 @@ roa_set_l : prefixset_item SOURCEAS as4number_any expires {
}
;
+aspa_set : ASPASET '{' optnl aspa_set_l optnl '}'
+ | ASPASET '{' optnl '}'
+ ;
+
+aspa_set_l : aspa_elm
+ | aspa_set_l comma aspa_elm
+ ;
+
+aspa_elm : CUSTOMERAS as4number expires PROVIDERAS '{' optnl
+ aspa_tas_l optnl '}' {
+ int rv;
+ struct aspa_tas_l *a, *n;
+
+ rv = merge_aspa_set($2, $7, $3);
+
+ for (a = $7; a != NULL; a = n) {
+ n = a->next;
+ free(a);
+ }
+
+ if (rv == -1)
+ YYERROR;
+ }
+ ;
+
+aspa_tas_l : aspa_tas { $$ = $1; }
+ | aspa_tas_l comma aspa_tas {
+ $3->next = $1;
+ $3->num = $1->num + 1;
+ $$ = $3;
+ }
+ ;
+
+aspa_tas : as4number_any {
+ if (($$ = calloc(1, sizeof(*$$))) == NULL)
+ fatal(NULL);
+ $$->as = $1;
+ $$->aid = AID_UNSPEC;
+ $$->num = 1;
+ }
+ | as4number_any ALLOW family {
+ if (($$ = calloc(1, sizeof(*$$))) == NULL)
+ fatal(NULL);
+ $$->as = $1;
+ $$->aid = $3;
+ $$->num = 1;
+ }
+ ;
+
rtr : RTR address {
currtr = get_rtr(&$2);
currtr->remote_port = RTR_PORT;
@@ -609,6 +668,7 @@ rtr : RTR address {
rtropt_l : rtropt
| rtropt_l optnl rtropt
+ ;
rtropt : DESCR STRING {
if (strlcpy(currtr->descr, $2,
@@ -3090,12 +3150,14 @@ lookup(char *s)
{ "as-4byte", AS4BYTE },
{ "as-override", ASOVERRIDE},
{ "as-set", ASSET },
+ { "aspa-set", ASPASET},
{ "blackhole", BLACKHOLE},
{ "capabilities", CAPABILITIES},
{ "community", COMMUNITY},
{ "compare", COMPARE},
{ "connect-retry", CONNECTRETRY},
{ "connected", CONNECTED},
+ { "customer-as", CUSTOMERAS},
{ "default-route", DEFAULTROUTE},
{ "delete", DELETE},
{ "demote", DEMOTE},
@@ -3173,6 +3235,7 @@ lookup(char *s)
{ "prepend-neighbor", PREPEND_PEER},
{ "prepend-self", PREPEND_SELF},
{ "priority", PRIORITY},
+ { "provider-as", PROVIDERAS},
{ "qualify", QUALIFY},
{ "quick", QUICK},
{ "rd", RD},
@@ -4999,3 +5062,57 @@ insert_rtr(struct rtr_config *new)
return 0;
}
+
+static int
+merge_aspa_set(uint32_t as, struct aspa_tas_l *tas, time_t expires)
+{
+ struct aspa_set *aspa, needle = { .as = as };
+ uint32_t i, num, *newtas;
+ uint8_t *newtasaid = NULL;
+
+ aspa = RB_FIND(aspa_tree, &conf->aspa, &needle);
+ if (aspa == NULL) {
+ if ((aspa = calloc(1, sizeof(*aspa))) == NULL) {
+ yyerror("out of memory");
+ return -1;
+ }
+ aspa->as = as;
+ aspa->expires = expires;
+ RB_INSERT(aspa_tree, &conf->aspa, aspa);
+ }
+
+ if (UINT32_MAX - aspa->num <= tas->num) {
+ yyerror("aspa_set overflow");
+ return -1;
+ }
+ num = aspa->num + tas->num;
+ newtas = recallocarray(aspa->tas, aspa->num, num, sizeof(uint32_t));
+ if (newtas == NULL) {
+ yyerror("out of memory");
+ return -1;
+ }
+ newtasaid = recallocarray(aspa->tas_aid, aspa->num, num, 1);
+ if (newtasaid == NULL) {
+ free(newtas);
+ yyerror("out of memory");
+ return -1;
+ }
+
+ /* fill starting at the end since the tas list is reversed */
+ if (num > 0) {
+ for (i = num - 1; tas; tas = tas->next, i--) {
+ newtas[i] = tas->as;
+ if (tas->aid != AID_UNSPEC)
+ newtasaid[i] = tas->aid;
+ }
+ }
+
+ aspa->num = num;
+ aspa->tas = newtas;
+ aspa->tas_aid = newtasaid;
+ /* take the longest expiry time, same logic as for ROA entries */
+ if (aspa->expires != 0 && expires != 0 && expires > aspa->expires)
+ aspa->expires = expires;
+
+ return 0;
+}
diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c
index 605ed0009a7..461a3c46d08 100644
--- a/usr.sbin/bgpd/printconf.c
+++ b/usr.sbin/bgpd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.159 2022/09/21 21:12:04 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.160 2022/11/18 10:17:23 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -42,6 +42,7 @@ void print_as_sets(struct as_set_head *);
void print_prefixsets(struct prefixset_head *);
void print_originsets(struct prefixset_head *);
void print_roa(struct roa_tree *);
+void print_aspa(struct aspa_tree *);
void print_rtrs(struct rtr_config_head *);
void print_peer(struct peer_config *, struct bgpd_config *,
const char *);
@@ -591,6 +592,33 @@ print_roa(struct roa_tree *r)
}
void
+print_aspa(struct aspa_tree *a)
+{
+ struct aspa_set *aspa;
+ uint32_t i;
+
+ if (RB_EMPTY(a))
+ return;
+
+ printf("aspa-set {");
+ RB_FOREACH(aspa, aspa_tree, a) {
+ printf("\n\t");
+ printf("customer-as %s", log_as(aspa->as));
+ if (aspa->expires != 0)
+ printf(" expires %lld", (long long)aspa->expires);
+ printf(" provider-as { ");
+ for (i = 0; i < aspa->num; i++) {
+ printf("%s ", log_as(aspa->tas[i]));
+ if (aspa->tas_aid != NULL &&
+ aspa->tas_aid[i] != AID_UNSPEC)
+ printf("allow %s ", print_af(aspa->tas_aid[i]));
+ }
+ printf("}");
+ }
+ printf("\n}\n\n");
+}
+
+void
print_rtrs(struct rtr_config_head *rh)
{
struct rtr_config *r;
@@ -1096,6 +1124,7 @@ print_config(struct bgpd_config *conf, struct rib_names *rib_l)
print_mainconf(conf);
print_rtrs(&conf->rtrs);
print_roa(&conf->roa);
+ print_aspa(&conf->aspa);
print_as_sets(&conf->as_sets);
print_prefixsets(&conf->prefixsets);
print_originsets(&conf->originsets);
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 1d9730b9111..b6fd6d3f58e 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.579 2022/11/07 22:48:35 mbuhl Exp $ */
+/* $OpenBSD: rde.c,v 1.580 2022/11/18 10:17:23 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -323,6 +323,11 @@ rde_main(int debug, int verbose)
close(ibuf_se_ctl->fd);
free(ibuf_se_ctl);
}
+ if (ibuf_rtr) {
+ msgbuf_clear(&ibuf_rtr->w);
+ close(ibuf_rtr->fd);
+ free(ibuf_rtr);
+ }
msgbuf_clear(&ibuf_main->w);
close(ibuf_main->fd);
free(ibuf_main);
diff --git a/usr.sbin/bgpd/rtr.c b/usr.sbin/bgpd/rtr.c
index 0960f24c16a..cd3756f88f4 100644
--- a/usr.sbin/bgpd/rtr.c
+++ b/usr.sbin/bgpd/rtr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtr.c,v 1.8 2022/10/18 09:30:29 job Exp $ */
+/* $OpenBSD: rtr.c,v 1.9 2022/11/18 10:17:23 claudio Exp $ */
/*
* Copyright (c) 2020 Claudio Jeker <claudio@openbsd.org>
@@ -20,6 +20,7 @@
#include <poll.h>
#include <pwd.h>
#include <signal.h>
+#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -80,6 +81,24 @@ rtr_expire_roas(time_t now)
return recalc;
}
+static unsigned int
+rtr_expire_aspa(time_t now)
+{
+ struct aspa_set *aspa, *na;
+ unsigned int recalc = 0;
+
+ RB_FOREACH_SAFE(aspa, aspa_tree, &conf->aspa, na) {
+ if (aspa->expires != 0 && aspa->expires <= now) {
+ recalc++;
+ RB_REMOVE(aspa_tree, &conf->aspa, aspa);
+ free_aspa(aspa);
+ }
+ }
+ if (recalc != 0)
+ log_info("%u aspa-set entries expired", recalc);
+ return recalc;
+}
+
void
roa_insert(struct roa_tree *rt, struct roa *in)
{
@@ -193,6 +212,8 @@ rtr_main(int debug, int verbose)
EXPIRE_TIMEOUT);
if (rtr_expire_roas(time(NULL)) != 0)
rtr_recalc();
+ if (rtr_expire_aspa(time(NULL)) != 0)
+ rtr_recalc();
}
}
@@ -218,10 +239,11 @@ rtr_main(int debug, int verbose)
static void
rtr_dispatch_imsg_parent(struct imsgbuf *ibuf)
{
- struct imsg imsg;
- struct roa *roa;
- struct rtr_session *rs;
- int n, fd;
+ static struct aspa_set *aspa;
+ struct imsg imsg;
+ struct roa *roa;
+ struct rtr_session *rs;
+ int n, fd;
while (ibuf) {
if ((n = imsg_get(ibuf, &imsg)) == -1)
@@ -274,6 +296,48 @@ rtr_dispatch_imsg_parent(struct imsgbuf *ibuf)
fatalx("IMSG_RECONF_ROA_ITEM bad len");
roa_insert(&nconf->roa, imsg.data);
break;
+ case IMSG_RECONF_ASPA:
+ if (imsg.hdr.len - IMSG_HEADER_SIZE !=
+ offsetof(struct aspa_set, tas))
+ fatalx("IMSG_RECONF_ASPA bad len");
+ if (aspa != NULL)
+ fatalx("unexpected IMSG_RECONF_ASPA");
+ if ((aspa = calloc(1, sizeof(*aspa))) == NULL)
+ fatal("aspa alloc");
+ memcpy(aspa, imsg.data, offsetof(struct aspa_set, tas));
+ break;
+ case IMSG_RECONF_ASPA_TAS:
+ if (aspa == NULL)
+ fatalx("unexpected IMSG_RECONF_ASPA_TAS");
+ if (imsg.hdr.len - IMSG_HEADER_SIZE !=
+ aspa->num * sizeof(*aspa->tas))
+ fatalx("IMSG_RECONF_ASPA_TAS bad len");
+ aspa->tas = reallocarray(NULL, aspa->num,
+ sizeof(*aspa->tas));
+ if (aspa->tas == NULL)
+ fatal("aspa tas alloc");
+ memcpy(aspa->tas, imsg.data,
+ aspa->num * sizeof(*aspa->tas));
+ break;
+ case IMSG_RECONF_ASPA_TAS_AID:
+ if (aspa == NULL)
+ fatalx("unexpected IMSG_RECONF_ASPA_TAS_ID");
+ if (imsg.hdr.len - IMSG_HEADER_SIZE != aspa->num)
+ fatalx("IMSG_RECONF_ASPA_TAS_AID bad len");
+ aspa->tas_aid = malloc(aspa->num);
+ if (aspa->tas_aid == NULL)
+ fatal("aspa tas aid alloc");
+ memcpy(aspa->tas_aid, imsg.data, aspa->num);
+ break;
+ case IMSG_RECONF_ASPA_DONE:
+ if (aspa == NULL)
+ fatalx("unexpected IMSG_RECONF_ASPA_DONE");
+ if (RB_INSERT(aspa_tree, &nconf->aspa, aspa) != NULL) {
+ log_warnx("duplicate ASPA set received");
+ free_aspa(aspa);
+ }
+ aspa = NULL;
+ break;
case IMSG_RECONF_RTR_CONFIG:
if (imsg.hdr.len - IMSG_HEADER_SIZE != PEER_DESCR_LEN)
fatalx("IMSG_RECONF_RTR_CONFIG bad len");
@@ -296,9 +360,15 @@ rtr_dispatch_imsg_parent(struct imsgbuf *ibuf)
/* then move the RB tree root */
RB_ROOT(&conf->roa) = RB_ROOT(&nconf->roa);
RB_ROOT(&nconf->roa) = NULL;
+ /* switch the aspa tree, first remove the old one */
+ free_aspatree(&conf->aspa);
+ /* then move the RB tree root */
+ RB_ROOT(&conf->aspa) = RB_ROOT(&nconf->aspa);
+ RB_ROOT(&nconf->aspa) = NULL;
/* finally merge the rtr session */
rtr_config_merge();
rtr_expire_roas(time(NULL));
+ rtr_expire_aspa(time(NULL));
rtr_recalc();
log_info("RTR engine reconfigured");
imsg_compose(ibuf_main, IMSG_RECONF_DONE, 0, 0,
@@ -348,6 +418,77 @@ rtr_imsg_compose(int type, uint32_t id, pid_t pid, void *data, size_t datalen)
}
/*
+ * Add an asnum to the aspa_set. The aspa_set is sorted by asnum.
+ * The aid is altered into a bitmask to simplify the merge of entries
+ * that just use a different aid.
+ */
+static void
+aspa_set_entry(struct aspa_set *aspa, uint32_t asnum, uint8_t aid)
+{
+ uint32_t i, num, *newtas;
+ uint8_t *newtasaid;
+
+ switch (aid) {
+ case AID_INET:
+ aid = 0x1;
+ break;
+ case AID_INET6:
+ aid = 0x2;
+ break;
+ case AID_UNSPEC:
+ aid = 0x3;
+ break;
+ default:
+ fatalx("aspa_set bad AID");
+ }
+
+ for (i = 0; i < aspa->num; i++) {
+ if (asnum < aspa->tas[i] || aspa->tas[i] == 0)
+ break;
+ if (asnum == aspa->tas[i]) {
+ aspa->tas_aid[i] |= aid;
+ return;
+ }
+ }
+
+ num = aspa->num + 1;
+ newtas = recallocarray(aspa->tas, aspa->num, num, sizeof(uint32_t));
+ newtasaid = recallocarray(aspa->tas_aid, aspa->num, num, 1);
+ if (newtas == NULL || newtasaid == NULL)
+ fatal("aspa_set merge");
+
+ if (i < aspa->num) {
+ memmove(newtas + i + 1, newtas + i,
+ (aspa->num - i) * sizeof(uint32_t));
+ memmove(newtasaid + i + 1, newtasaid + i, (aspa->num - i));
+ }
+ newtas[i] = asnum;
+ newtasaid[i] = aid;
+
+ aspa->num = num;
+ aspa->tas = newtas;
+ aspa->tas_aid = newtasaid;
+}
+
+static void
+rtr_aspa_merge_set(struct aspa_tree *a, struct aspa_set *mergeset)
+{
+ struct aspa_set *aspa, needle = { .as = mergeset->as };
+ uint32_t i;
+
+ aspa = RB_FIND(aspa_tree, a, &needle);
+ if (aspa == NULL) {
+ if ((aspa = calloc(1, sizeof(*aspa))) == NULL)
+ fatal("aspa insert");
+ aspa->as = mergeset->as;
+ RB_INSERT(aspa_tree, a, aspa);
+ }
+
+ for (i = 0; i < mergeset->num; i++)
+ aspa_set_entry(aspa, mergeset->tas[i], mergeset->tas_aid[i]);
+}
+
+/*
* Merge all RPKI ROA trees into one as one big union.
* Simply try to add all roa entries into a new RB tree.
* This could be made a fair bit faster but for now this is good enough.
@@ -356,9 +497,12 @@ void
rtr_recalc(void)
{
struct roa_tree rt;
+ struct aspa_tree at;
struct roa *roa, *nr;
+ struct aspa_set *aspa;
RB_INIT(&rt);
+ RB_INIT(&at);
RB_FOREACH(roa, roa_tree, &conf->roa)
roa_insert(&rt, roa);
@@ -371,5 +515,11 @@ rtr_recalc(void)
roa, sizeof(*roa));
free(roa);
}
+
+ RB_FOREACH(aspa, aspa_tree, &conf->aspa)
+ rtr_aspa_merge_set(&at, aspa);
+
+ free_aspatree(&at);
+
imsg_compose(ibuf_rde, IMSG_RECONF_DONE, 0, 0, -1, NULL, 0);
}