-/* $OpenBSD: bgpd.c,v 1.199 2018/09/20 07:46:39 claudio Exp $ */
+/* $OpenBSD: bgpd.c,v 1.200 2018/09/20 11:45:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
struct listen_addr *la;
struct rde_rib *rr;
struct rdomain *rd;
+ struct as_set *aset;
struct prefixset *ps;
struct prefixset_item *psi, *npsi;
}
/* as-sets for filters in the RDE */
- if (as_sets_send(ibuf_rde, conf->as_sets) == -1)
- return (-1);
- as_sets_free(conf->as_sets);
- conf->as_sets = NULL;
+ while ((aset = SIMPLEQ_FIRST(conf->as_sets)) != NULL) {
+ struct ibuf *wbuf;
+ u_int32_t *as;
+ size_t i, l, n;
+
+ SIMPLEQ_REMOVE_HEAD(conf->as_sets, entry);
+
+ as = set_get(aset->set, &n);
+ if ((wbuf = imsg_create(ibuf_rde, IMSG_RECONF_AS_SET, 0, 0,
+ sizeof(n) + sizeof(aset->name))) == NULL)
+ return -1;
+ if (imsg_add(wbuf, &n, sizeof(n)) == -1 ||
+ imsg_add(wbuf, aset->name, sizeof(aset->name)) == -1)
+ return -1;
+ imsg_close(ibuf_rde, wbuf);
+
+ for (i = 0; i < n; i += l) {
+ l = (n - i > 1024 ? 1024 : n - i);
+ if (imsg_compose(ibuf_rde, IMSG_RECONF_AS_SET_ITEMS,
+ 0, 0, -1, as + i, l) == -1)
+ return -1;
+ }
+
+ if (imsg_compose(ibuf_rde, IMSG_RECONF_AS_SET_DONE, 0, 0, -1,
+ NULL, 0) == -1)
+ return -1;
+
+ set_free(aset->set);
+ free(aset);
+ }
/* filters for the RDE */
while ((r = TAILQ_FIRST(conf->filters)) != NULL) {
-/* $OpenBSD: bgpd.h,v 1.342 2018/09/20 07:46:39 claudio Exp $ */
+/* $OpenBSD: bgpd.h,v 1.343 2018/09/20 11:45:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
struct rde_prefixset_head;
struct rde_prefixset;
+struct set_table;
struct as_set;
SIMPLEQ_HEAD(as_set_head, as_set);
SIMPLEQ_ENTRY(prefixset) entry;
};
+struct as_set {
+ char name[SET_NAME_LEN];
+ SIMPLEQ_ENTRY(as_set) entry;
+ struct set_table *set;
+ int dirty;
+};
+
struct rdomain {
SIMPLEQ_ENTRY(rdomain) entry;
char descr[PEER_DESCR_LEN];
const char *filterset_name(enum action_types);
/* rde_sets.c */
-void as_sets_insert(struct as_set_head *, struct as_set *);
struct as_set *as_sets_lookup(struct as_set_head *, const char *);
+struct as_set *as_sets_new(struct as_set_head *, const char *, size_t,
+ size_t);
void as_sets_free(struct as_set_head *);
-void as_sets_print(struct as_set_head *);
-int as_sets_send(struct imsgbuf *, struct as_set_head *);
void as_sets_mark_dirty(struct as_set_head *, struct as_set_head *);
-
-struct as_set *as_set_new(const char *, size_t, size_t);
-void as_set_free(struct as_set *);
-int as_set_add(struct as_set *, void *, size_t);
-void as_set_prep(struct as_set *);
-void *as_set_match(const struct as_set *, u_int32_t);
-int as_set_equal(const struct as_set *, const struct as_set *);
-int as_set_dirty(const struct as_set *);
+int as_set_match(const struct as_set *, u_int32_t);
+
+struct set_table *set_new(size_t, size_t);
+void set_free(struct set_table *);
+int set_add(struct set_table *, void *, size_t);
+void *set_get(struct set_table *, size_t *);
+void set_prep(struct set_table *);
+void *set_match(const struct set_table *, u_int32_t);
+int set_equal(const struct set_table *,
+ const struct set_table *);
/* util.c */
const char *log_addr(const struct bgpd_addr *);
-/* $OpenBSD: parse.y,v 1.354 2018/09/20 07:46:39 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.355 2018/09/20 11:45:59 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
return (r);
}
-struct as_set *curaset;
+struct set_table *curset;
static int
new_as_set(char *name)
{
return -1;
}
- aset = as_set_new(name, 0, sizeof(u_int32_t));
+ aset = as_sets_new(conf->as_sets, name, 0, sizeof(u_int32_t));
if (aset == NULL)
fatal(NULL);
- as_sets_insert(conf->as_sets, aset);
- curaset = aset;
+ curset = aset->set;
return 0;
}
static void
add_as_set(u_int32_t as)
{
- if (curaset == NULL)
+ if (curset == NULL)
fatalx("%s: bad mojo jojo", __func__);
- if (as_set_add(curaset, &as, 1) != 0)
+ if (set_add(curset, &as, 1) != 0)
fatal(NULL);
}
static void
done_as_set(void)
{
- curaset = NULL;
+ curset = NULL;
}
static int
-/* $OpenBSD: printconf.c,v 1.120 2018/09/20 07:46:39 claudio Exp $ */
+/* $OpenBSD: printconf.c,v 1.121 2018/09/20 11:45:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
void print_rdomain(struct rdomain *);
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_peer(struct peer_config *, struct bgpd_config *,
const char *);
printf("\n");
}
+void
+print_as_sets(struct as_set_head *as_sets)
+{
+ struct as_set *aset;
+ u_int32_t *as;
+ size_t i, n;
+ int len;
+
+ SIMPLEQ_FOREACH(aset, as_sets, entry) {
+ printf("as-set \"%s\" {\n\t", aset->name);
+ as = set_get(aset->set, &n);
+ for (i = 0, len = 8; i < n; i++) {
+ if (len > 72) {
+ printf("\n\t");
+ len = 8;
+ }
+ len += printf("%u ", as[i]);
+ }
+ printf("\n}\n\n");
+ }
+}
+
void
print_prefixsets(struct prefixset_head *psh)
{
print_mainconf(conf);
print_prefixsets(conf->prefixsets);
- as_sets_print(conf->as_sets);
+ print_as_sets(conf->as_sets);
TAILQ_FOREACH(n, net_l, entry)
print_network(&n->net, "");
if (!SIMPLEQ_EMPTY(rdom_l))
-/* $OpenBSD: rde.c,v 1.424 2018/09/20 11:06:04 benno Exp $ */
+/* $OpenBSD: rde.c,v 1.425 2018/09/20 11:45:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
name = (char *)imsg.data + sizeof(nmemb);
if (as_sets_lookup(as_sets_tmp, name) != NULL)
fatalx("duplicate as-set %s", name);
- last_as_set = as_set_new(name, nmemb,
+ last_as_set = as_sets_new(as_sets_tmp, name, nmemb,
sizeof(u_int32_t));
break;
case IMSG_RECONF_AS_SET_ITEMS:
nmemb = imsg.hdr.len - IMSG_HEADER_SIZE;
nmemb /= sizeof(u_int32_t);
- if (as_set_add(last_as_set, imsg.data, nmemb) != 0)
+ if (set_add(last_as_set->set, imsg.data, nmemb) != 0)
fatal(NULL);
break;
case IMSG_RECONF_AS_SET_DONE:
- as_set_prep(last_as_set);
- as_sets_insert(as_sets_tmp, last_as_set);
+ set_prep(last_as_set->set);
last_as_set = NULL;
break;
case IMSG_RECONF_RDOMAIN:
-/* $OpenBSD: rde.h,v 1.192 2018/09/20 11:06:04 benno Exp $ */
+/* $OpenBSD: rde.h,v 1.193 2018/09/20 11:45:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
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 as_set *);
+ struct set_table *);
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,
-/* $OpenBSD: rde_filter.c,v 1.107 2018/09/20 11:06:04 benno Exp $ */
+/* $OpenBSD: rde_filter.c,v 1.108 2018/09/20 11:45:59 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
}
if ((fa->match.as.flags & AS_FLAG_AS_SET) &&
- as_set_dirty(fa->match.as.aset)) {
+ fa->match.as.aset->dirty) {
log_debug("%s: as-set %s has changed",
__func__, fa->match.as.name);
return (0);
-/* $OpenBSD: rde_sets.c,v 1.4 2018/09/14 10:22:11 claudio Exp $ */
+/* $OpenBSD: rde_sets.c,v 1.5 2018/09/20 11:45:59 claudio Exp $ */
/*
* Copyright (c) 2018 Claudio Jeker <claudio@openbsd.org>
#include "rde.h"
-struct as_set {
- char name[SET_NAME_LEN];
+struct set_table {
void *set;
- SIMPLEQ_ENTRY(as_set) entry;
size_t nmemb;
size_t size;
size_t max;
- int dirty;
};
-void
-as_sets_insert(struct as_set_head *as_sets, struct as_set *aset)
+struct as_set *
+as_sets_new(struct as_set_head *as_sets, const char *name, size_t nmemb,
+ size_t size)
{
+ struct as_set *aset;
+ size_t len;
+
+ aset = calloc(1, sizeof(*aset));
+ if (aset == NULL)
+ return NULL;
+
+ len = strlcpy(aset->name, name, sizeof(aset->name));
+ assert(len < sizeof(aset->name));
+
+ aset->set = set_new(nmemb, size);
+ if (aset->set == NULL) {
+ free(aset);
+ return NULL;
+ }
+
SIMPLEQ_INSERT_TAIL(as_sets, aset, entry);
+ return aset;
}
struct as_set *
while (!SIMPLEQ_EMPTY(as_sets)) {
aset = SIMPLEQ_FIRST(as_sets);
SIMPLEQ_REMOVE_HEAD(as_sets, entry);
- as_set_free(aset);
+ set_free(aset->set);
+ free(aset);
}
free(as_sets);
}
-void
-as_sets_print(struct as_set_head *as_sets)
-{
- struct as_set *aset;
- size_t i;
- int len;
-
- if (as_sets == NULL)
- return;
- SIMPLEQ_FOREACH(aset, as_sets, entry) {
- printf("as-set \"%s\" {\n\t", aset->name);
- for (i = 0, len = 8; i < aset->nmemb; i++) {
- if (len > 72) {
- printf("\n\t");
- len = 8;
- }
- len += printf("%u ", *(u_int32_t *)
- ((u_int8_t *)aset->set + i * aset->size));
- }
- printf("\n}\n\n");
- }
-}
-
-int
-as_sets_send(struct imsgbuf *ibuf, struct as_set_head *as_sets)
-{
- struct as_set *aset;
- struct ibuf *wbuf;
- size_t i, l;
-
- if (as_sets == NULL)
- return 0;
- SIMPLEQ_FOREACH(aset, as_sets, entry) {
- if ((wbuf = imsg_create(ibuf, IMSG_RECONF_AS_SET, 0, 0,
- sizeof(aset->nmemb) + sizeof(aset->name))) == NULL)
- return -1;
- if (imsg_add(wbuf, &aset->nmemb, sizeof(aset->nmemb)) == -1 ||
- imsg_add(wbuf, aset->name, sizeof(aset->name)) == -1)
- return -1;
- imsg_close(ibuf, wbuf);
-
- for (i = 0; i < aset->nmemb; i += l) {
- l = (aset->nmemb - i > 1024 ? 1024 : aset->nmemb - i);
-
- if (imsg_compose(ibuf, IMSG_RECONF_AS_SET_ITEMS, 0, 0,
- -1, (u_int8_t *)aset->set + i * aset->size,
- l * aset->size) == -1)
- return -1;
- }
-
- if (imsg_compose(ibuf, IMSG_RECONF_AS_SET_DONE, 0, 0, -1,
- NULL, 0) == -1)
- return -1;
- }
- return 0;
-}
-
void
as_sets_mark_dirty(struct as_set_head *old, struct as_set_head *new)
{
SIMPLEQ_FOREACH(n, new, entry) {
if (old == NULL || (o = as_sets_lookup(old, n->name)) == NULL ||
- !as_set_equal(n, o))
+ !set_equal(n->set, o->set))
n->dirty = 1;
}
}
-struct as_set *
-as_set_new(const char *name, size_t nmemb, size_t size)
+int
+as_set_match(const struct as_set *aset, u_int32_t asnum)
{
- struct as_set *aset;
- size_t len;
+ return set_match(aset->set, asnum) != NULL;
+}
- aset = calloc(1, sizeof(*aset));
- if (aset == NULL)
- return NULL;
+struct set_table *
+set_new(size_t nmemb, size_t size)
+{
+ struct set_table *set;
- len = strlcpy(aset->name, name, sizeof(aset->name));
- assert(len < sizeof(aset->name));
+ set = calloc(1, sizeof(*set));
+ if (set == NULL)
+ return NULL;
if (nmemb == 0)
nmemb = 4;
- aset->size = size;
- aset->max = nmemb;
- aset->set = calloc(nmemb, aset->size);
- if (aset->set == NULL) {
- free(aset);
+ set->size = size;
+ set->max = nmemb;
+ set->set = calloc(nmemb, set->size);
+ if (set->set == NULL) {
+ free(set);
return NULL;
}
- return aset;
+ return set;
}
void
-as_set_free(struct as_set *aset)
+set_free(struct set_table *set)
{
- if (aset == NULL)
+ if (set == NULL)
return;
- free(aset->set);
- free(aset);
+ free(set->set);
+ free(set);
}
int
-as_set_add(struct as_set *aset, void *elms, size_t nelms)
+set_add(struct set_table *set, void *elms, size_t nelms)
{
- if (aset->max < nelms || aset->max - nelms < aset->nmemb) {
+ if (set->max < nelms || set->max - nelms < set->nmemb) {
u_int32_t *s;
size_t new_size;
- if (aset->nmemb >= SIZE_T_MAX - 4096 - nelms) {
+ if (set->nmemb >= SIZE_T_MAX - 4096 - nelms) {
errno = ENOMEM;
return -1;
}
- for (new_size = aset->max; new_size < aset->nmemb + nelms; )
+ for (new_size = set->max; new_size < set->nmemb + nelms; )
new_size += (new_size < 4096 ? new_size : 4096);
- s = reallocarray(aset->set, new_size, aset->size);
+ s = reallocarray(set->set, new_size, set->size);
if (s == NULL)
return -1;
- aset->set = s;
- aset->max = new_size;
+ set->set = s;
+ set->max = new_size;
}
- memcpy((u_int8_t *)aset->set + aset->nmemb * aset->size, elms,
- nelms * aset->size);
- aset->nmemb += nelms;
+ memcpy((u_int8_t *)set->set + set->nmemb * set->size, elms,
+ nelms * set->size);
+ set->nmemb += nelms;
return 0;
}
+void *
+set_get(struct set_table *set, size_t *nelms)
+{
+ *nelms = set->nmemb;
+ return set->set;
+}
+
static int
-as_set_cmp(const void *ap, const void *bp)
+set_cmp(const void *ap, const void *bp)
{
const u_int32_t *a = ap;
const u_int32_t *b = bp;
}
void
-as_set_prep(struct as_set *aset)
+set_prep(struct set_table *set)
{
- if (aset == NULL)
+ if (set == NULL)
return;
- qsort(aset->set, aset->nmemb, aset->size, as_set_cmp);
+ qsort(set->set, set->nmemb, set->size, set_cmp);
}
void *
-as_set_match(const struct as_set *a, u_int32_t asnum)
+set_match(const struct set_table *a, u_int32_t asnum)
{
if (a == NULL)
return NULL;
- return bsearch(&asnum, a->set, a->nmemb, a->size, as_set_cmp);
+ return bsearch(&asnum, a->set, a->nmemb, a->size, set_cmp);
}
int
-as_set_equal(const struct as_set *a, const struct as_set *b)
+set_equal(const struct set_table *a, const struct set_table *b)
{
+ /* allow NULL pointers to be passed */
+ if (a == NULL && b == NULL)
+ return 1;
+ if (a == NULL || b == NULL)
+ return 0;
+
if (a->nmemb != b->nmemb)
return 0;
if (memcmp(a->set, b->set, a->nmemb * a->size) != 0)
return 0;
return 1;
}
-
-int
-as_set_dirty(const struct as_set *a)
-{
- return (a->dirty);
-}
-/* $OpenBSD: rde_trie.c,v 1.6 2018/09/18 15:14:07 claudio Exp $ */
+/* $OpenBSD: rde_trie.c,v 1.7 2018/09/20 11:45:59 claudio Exp $ */
/*
* Copyright (c) 2018 Claudio Jeker <claudio@openbsd.org>
*/
struct tentry_v4 {
struct tentry_v4 *trie[2];
- struct as_set *aset; /* for roa source-as set */
+ struct set_table *set; /* for roa source-as set */
struct in_addr addr;
struct in_addr plenmask;
u_int8_t plen;
struct tentry_v6 {
struct tentry_v6 *trie[2];
- struct as_set *aset; /* for roa source-as set */
+ struct set_table *set; /* for roa source-as set */
struct in6_addr addr;
struct in6_addr plenmask;
u_int8_t plen;
}
/*
- * Insert a ROA entry for prefix/plen. The prefix will insert an as_set with
+ * Insert a ROA entry for prefix/plen. The prefix will insert a set with
* source_as and the maxlen as data. This makes it possible to validate if a
* prefix is matching this ROA record. It is possible to insert prefixes with
* source_as = 0. These entries will never return ROA_VALID on check and can
*/
int
trie_roa_add(struct trie_head *th, struct bgpd_addr *prefix, u_int8_t plen,
- struct as_set *aset)
+ struct set_table *set)
{
struct tentry_v4 *n4;
struct tentry_v6 *n6;
- struct as_set **ap;
+ struct set_table **stp;
/* ignore possible default route since it does not make sense */
n4 = trie_add_v4(th, &prefix->v4, plen);
if (n4 == NULL)
return -1;
- ap = &n4->aset;
+ stp = &n4->set;
break;
case AID_INET6:
if (plen > 128)
n6 = trie_add_v6(th, &prefix->v6, plen);
if (n6 == NULL)
return -1;
- ap = &n6->aset;
+ stp = &n6->set;
break;
default:
/* anything else fails */
return -1;
}
- /* aset already set, error out */
- if (*ap != NULL)
+ /* set_table already set, error out */
+ if (*stp != NULL)
return -1;
- *ap = aset;
+ *stp = set;
return 0;
}
return;
trie_free_v4(n->trie[0]);
trie_free_v4(n->trie[1]);
- as_set_free(n->aset);
+ set_free(n->set);
free(n);
}
return;
trie_free_v6(n->trie[0]);
trie_free_v6(n->trie[1]);
- as_set_free(n->aset);
+ set_free(n->set);
free(n);
}
/* Treat AS 0 as NONE which can never be matched */
if (as != 0) {
- rs = as_set_match(n->aset, as);
+ rs = set_match(n->set, as);
if (rs && plen <= rs->maxlen)
return ROA_VALID;
}
/* Treat AS 0 as NONE which can never be matched */
if (as != 0) {
- if ((rs = as_set_match(n->aset, as)) != NULL)
+ if ((rs = set_match(n->set, as)) != NULL)
if (plen == n->plen || plen <= rs->maxlen)
return ROA_VALID;
}
a->plenmask.s_addr != b->plenmask.s_addr)
return 0;
+ if (set_equal(a->set, b->set) == 0)
+ return 0;
+
if (trie_equal_v4(a->trie[0], b->trie[0]) == 0 ||
trie_equal_v4(a->trie[1], b->trie[1]) == 0)
return 0;
memcmp(&a->plenmask, &b->plenmask, sizeof(a->plenmask)) != 0)
return 0;
+ if (set_equal(a->set, b->set) == 0)
+ return 0;
+
if (trie_equal_v6(a->trie[0], b->trie[0]) == 0 ||
trie_equal_v6(a->trie[1], b->trie[1]) == 0)
return 0;
-/* $OpenBSD: util.c,v 1.38 2018/09/20 11:06:04 benno Exp $ */
+/* $OpenBSD: util.c,v 1.39 2018/09/20 11:45:59 claudio Exp $ */
/*
* Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
if (f->flags & AS_FLAG_AS_SET_NAME) /* should not happen */
return (0);
if (f->flags & AS_FLAG_AS_SET)
- return (as_set_match(f->aset, as) != NULL);
+ return (as_set_match(f->aset, as));
if (f->flags & AS_FLAG_NEIGHBORAS)
match = neighas;