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@
-/* $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>
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);
-/* $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>
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;
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,
struct prefixset_item {
struct filter_prefix p;
RB_ENTRY(prefixset_item) entry;
+ struct set_table *set;
};
RB_HEAD(prefixset_tree, prefixset_item);
-/* $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>
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)
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);
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);
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) {
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;
-/* $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>
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;
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 {
%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
| grammar include '\n'
| grammar as_set '\n'
| grammar prefixset '\n'
+ | grammar roa_set '\n'
| grammar conf_main '\n'
| grammar rdomain '\n'
| grammar neighbor '\n'
| 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;
}
curpset = NULL;
}
| PREFIXSET STRING '{' optnl '}' {
- if (new_prefix_set($2) != 0) {
+ if ((curpset = new_prefix_set($2, 0)) == NULL) {
free($2);
YYERROR;
}
}
;
+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)
{ "restart", RESTART},
{ "restricted", RESTRICTED},
{ "rib", RIB},
+ { "roa-set", ROASET },
{ "route-collector", ROUTECOLL},
{ "route-reflector", REFLECTOR},
{ "router-id", ROUTERID},
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");
}
-/* $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>
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);
}
}
+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)
{
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))
-/* $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>
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;
{
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;
struct prefixset_item psi;
char *name;
size_t nmemb;
- int n, fd;
+ int n, fd, rv;
u_int16_t rid;
while (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)
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");
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))
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 !=
}
prefixsets_old = conf->rde_prefixsets;
+ roasets_old = conf->rde_roasets;
as_sets_old = conf->as_sets;
memcpy(conf, nconf, sizeof(struct bgpd_config));
conf->csock = NULL;
conf->rcsock = NULL;
conf->prefixsets = NULL;
+ conf->roasets = NULL;
free(nconf);
nconf = NULL;
/* 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;
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;