Extend as_set to allow for different sized objects to be added. The only
authorclaudio <claudio@openbsd.org>
Fri, 14 Sep 2018 10:22:11 +0000 (10:22 +0000)
committerclaudio <claudio@openbsd.org>
Fri, 14 Sep 2018 10:22:11 +0000 (10:22 +0000)
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@

usr.sbin/bgpd/bgpd.h
usr.sbin/bgpd/parse.y
usr.sbin/bgpd/rde.c
usr.sbin/bgpd/rde_sets.c
usr.sbin/bgpd/util.c

index c20c6d4..b2565d0 100644 (file)
@@ -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 <henning@openbsd.org>
@@ -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 *);
 
index 2a4fcd5..4c4fec3 100644 (file)
@@ -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 <henning@openbsd.org>
@@ -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);
index 266481d..986e63c 100644 (file)
@@ -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 <henning@openbsd.org>
@@ -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;
index 1dc50cf..ae62eab 100644 (file)
@@ -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 <claudio@openbsd.org>
 
 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;
 }
index e28e3c5..882214d 100644 (file)
@@ -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 <claudio@openbsd.org>
@@ -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;