From: claudio Date: Fri, 14 Sep 2018 10:22:11 +0000 (+0000) Subject: Extend as_set to allow for different sized objects to be added. The only X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=78355a53f812fcf3835ff1333f1486f2887bb923;p=openbsd Extend as_set to allow for different sized objects to be added. The only requirement is that the first value of the struct is a 32bit ID which is used in the bsearch. This allows to add more than just as numbers to a set. as_set_match now returns a pointer to this data or NULL if not found. OK benno@ --- diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index c20c6d40fb7..b2565d01a30 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.339 2018/09/10 11:01:15 benno Exp $ */ +/* $OpenBSD: bgpd.h,v 1.340 2018/09/14 10:22:11 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -1171,10 +1171,11 @@ 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); -int as_set_add(struct as_set *, u_int32_t *, size_t); +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 *); -int as_set_match(const struct as_set *, u_int32_t); +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 *); diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index 2a4fcd5595e..4c4fec3ad1a 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.352 2018/09/13 11:18:18 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.353 2018/09/14 10:22:11 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer @@ -403,15 +403,19 @@ include : INCLUDE STRING { ; as_set : ASSET STRING '{' optnl { - if (new_as_set($2) != 0) + if (new_as_set($2) != 0) { + free($2); YYERROR; + } free($2); } as_set_l optnl '}' { done_as_set(); } | ASSET STRING '{' optnl '}' { - if (new_as_set($2) != 0) + if (new_as_set($2) != 0) { + free($2); YYERROR; + } free($2); } @@ -4179,7 +4183,7 @@ new_as_set(char *name) return -1; } - aset = as_set_new(name, 0); + aset = as_set_new(name, 0, sizeof(u_int32_t)); if (aset == NULL) fatal(NULL); as_sets_insert(conf->as_sets, aset); diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 266481dccf1..986e63cce8a 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.422 2018/09/09 15:02:26 benno Exp $ */ +/* $OpenBSD: rde.c,v 1.423 2018/09/14 10:22:11 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -908,7 +908,8 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf) 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_set_new(name, nmemb, + sizeof(u_int32_t)); break; case IMSG_RECONF_AS_SET_ITEMS: nmemb = imsg.hdr.len - IMSG_HEADER_SIZE; diff --git a/usr.sbin/bgpd/rde_sets.c b/usr.sbin/bgpd/rde_sets.c index 1dc50cf3fbc..ae62eabdc0c 100644 --- a/usr.sbin/bgpd/rde_sets.c +++ b/usr.sbin/bgpd/rde_sets.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_sets.c,v 1.3 2018/09/10 11:01:15 benno Exp $ */ +/* $OpenBSD: rde_sets.c,v 1.4 2018/09/14 10:22:11 claudio Exp $ */ /* * Copyright (c) 2018 Claudio Jeker @@ -29,9 +29,10 @@ struct as_set { char name[SET_NAME_LEN]; - u_int32_t *set; + void *set; SIMPLEQ_ENTRY(as_set) entry; size_t nmemb; + size_t size; size_t max; int dirty; }; @@ -54,12 +55,6 @@ as_sets_lookup(struct as_set_head *as_sets, const char *name) return NULL; } -static void -as_set_free(struct as_set *aset) -{ - free(aset->set); - free(aset); -} void as_sets_free(struct as_set_head *as_sets) @@ -92,7 +87,8 @@ as_sets_print(struct as_set_head *as_sets) printf("\n\t"); len = 8; } - len += printf("%u ", aset->set[i]); + len += printf("%u ", *(u_int32_t *) + ((u_int8_t *)aset->set + i * aset->size)); } printf("\n}\n\n"); } @@ -120,7 +116,8 @@ as_sets_send(struct imsgbuf *ibuf, struct as_set_head *as_sets) l = (aset->nmemb - i > 1024 ? 1024 : aset->nmemb - i); if (imsg_compose(ibuf, IMSG_RECONF_AS_SET_ITEMS, 0, 0, - -1, aset->set + i, l * sizeof(*aset->set)) == -1) + -1, (u_int8_t *)aset->set + i * aset->size, + l * aset->size) == -1) return -1; } @@ -144,7 +141,7 @@ as_sets_mark_dirty(struct as_set_head *old, struct as_set_head *new) } struct as_set * -as_set_new(const char *name, size_t nmemb) +as_set_new(const char *name, size_t nmemb, size_t size) { struct as_set *aset; size_t len; @@ -157,10 +154,11 @@ as_set_new(const char *name, size_t nmemb) assert(len < sizeof(aset->name)); if (nmemb == 0) - nmemb = 16; + nmemb = 4; + aset->size = size; aset->max = nmemb; - aset->set = calloc(nmemb, sizeof(*aset->set)); + aset->set = calloc(nmemb, aset->size); if (aset->set == NULL) { free(aset); return NULL; @@ -169,8 +167,17 @@ as_set_new(const char *name, size_t nmemb) return aset; } +void +as_set_free(struct as_set *aset) +{ + if (aset == NULL) + return; + free(aset->set); + free(aset); +} + int -as_set_add(struct as_set *aset, u_int32_t *elms, size_t nelms) +as_set_add(struct as_set *aset, void *elms, size_t nelms) { if (aset->max < nelms || aset->max - nelms < aset->nmemb) { u_int32_t *s; @@ -183,14 +190,15 @@ as_set_add(struct as_set *aset, u_int32_t *elms, size_t nelms) for (new_size = aset->max; new_size < aset->nmemb + nelms; ) new_size += (new_size < 4096 ? new_size : 4096); - s = reallocarray(aset->set, new_size, sizeof(*aset->set)); + s = reallocarray(aset->set, new_size, aset->size); if (s == NULL) return -1; aset->set = s; aset->max = new_size; } - memcpy(aset->set + aset->nmemb, elms, nelms * sizeof(*elms)); + memcpy((u_int8_t *)aset->set + aset->nmemb * aset->size, elms, + nelms * aset->size); aset->nmemb += nelms; return 0; @@ -212,16 +220,17 @@ as_set_cmp(const void *ap, const void *bp) void as_set_prep(struct as_set *aset) { - qsort(aset->set, aset->nmemb, sizeof(*aset->set), as_set_cmp); + if (aset == NULL) + return; + qsort(aset->set, aset->nmemb, aset->size, as_set_cmp); } -int +void * as_set_match(const struct as_set *a, u_int32_t asnum) { - if (bsearch(&asnum, a->set, a->nmemb, sizeof(asnum), as_set_cmp)) - return 1; - else - return 0; + if (a == NULL) + return NULL; + return bsearch(&asnum, a->set, a->nmemb, a->size, as_set_cmp); } int @@ -229,7 +238,7 @@ as_set_equal(const struct as_set *a, const struct as_set *b) { if (a->nmemb != b->nmemb) return 0; - if (memcmp(a->set, b->set, a->nmemb * sizeof(*a->set)) != 0) + if (memcmp(a->set, b->set, a->nmemb * a->size) != 0) return 0; return 1; } diff --git a/usr.sbin/bgpd/util.c b/usr.sbin/bgpd/util.c index e28e3c5d28a..882214dceda 100644 --- a/usr.sbin/bgpd/util.c +++ b/usr.sbin/bgpd/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.34 2018/09/07 05:43:33 claudio Exp $ */ +/* $OpenBSD: util.c,v 1.35 2018/09/14 10:22:11 claudio Exp $ */ /* * Copyright (c) 2006 Claudio Jeker @@ -320,7 +320,7 @@ as_compare(struct filter_as *f, u_int32_t as, u_int32_t neighas) 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)); + return (as_set_match(f->aset, as) != NULL); if (f->flags & AS_FLAG_NEIGHBORAS) match = neighas;