1 /* $OpenBSD: rde_sets.c,v 1.13 2024/09/10 09:38:45 claudio Exp $ */
2
3 /*
4 * Copyright (c) 2018 Claudio Jeker <claudio@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 #include <sys/types.h>
19 #include <sys/queue.h>
20
21 #include <assert.h>
22 #include <errno.h>
23 #include <limits.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "rde.h"
29
30 struct set_table {
31 void *set;
32 size_t nmemb;
33 size_t size;
34 size_t max;
35 };
36
37 struct as_set *
as_sets_new(struct as_set_head * as_sets,const char * name,size_t nmemb,size_t size)38 as_sets_new(struct as_set_head *as_sets, const char *name, size_t nmemb,
39 size_t size)
40 {
41 struct as_set *aset;
42 size_t len;
43
44 aset = calloc(1, sizeof(*aset));
45 if (aset == NULL)
46 return NULL;
47
48 len = strlcpy(aset->name, name, sizeof(aset->name));
49 assert(len < sizeof(aset->name));
50
51 aset->set = set_new(nmemb, size);
52 if (aset->set == NULL) {
53 free(aset);
54 return NULL;
55 }
56
57 SIMPLEQ_INSERT_TAIL(as_sets, aset, entry);
58 return aset;
59 }
60
61 struct as_set *
as_sets_lookup(struct as_set_head * as_sets,const char * name)62 as_sets_lookup(struct as_set_head *as_sets, const char *name)
63 {
64 struct as_set *aset;
65
66 SIMPLEQ_FOREACH(aset, as_sets, entry) {
67 if (strcmp(aset->name, name) == 0)
68 return aset;
69 }
70 return NULL;
71 }
72
73
74 void
as_sets_free(struct as_set_head * as_sets)75 as_sets_free(struct as_set_head *as_sets)
76 {
77 struct as_set *aset;
78
79 if (as_sets == NULL)
80 return;
81 while (!SIMPLEQ_EMPTY(as_sets)) {
82 aset = SIMPLEQ_FIRST(as_sets);
83 SIMPLEQ_REMOVE_HEAD(as_sets, entry);
84 set_free(aset->set);
85 free(aset);
86 }
87 }
88
89 void
as_sets_mark_dirty(struct as_set_head * old,struct as_set_head * new)90 as_sets_mark_dirty(struct as_set_head *old, struct as_set_head *new)
91 {
92 struct as_set *n, *o;
93
94 SIMPLEQ_FOREACH(n, new, entry) {
95 if (old == NULL || (o = as_sets_lookup(old, n->name)) == NULL ||
96 !set_equal(n->set, o->set)) {
97 n->dirty = 1;
98 n->lastchange = getmonotime();
99 } else
100 n->lastchange = o->lastchange;
101 }
102 }
103
104 int
as_set_match(const struct as_set * aset,uint32_t asnum)105 as_set_match(const struct as_set *aset, uint32_t asnum)
106 {
107 return set_match(aset->set, asnum) != NULL;
108 }
109
110 struct set_table *
set_new(size_t nmemb,size_t size)111 set_new(size_t nmemb, size_t size)
112 {
113 struct set_table *set;
114
115 set = calloc(1, sizeof(*set));
116 if (set == NULL)
117 return NULL;
118
119 if (nmemb == 0)
120 nmemb = 4;
121
122 set->size = size;
123 set->max = nmemb;
124 set->set = calloc(nmemb, set->size);
125 if (set->set == NULL) {
126 free(set);
127 return NULL;
128 }
129
130 rdemem.aset_cnt++;
131 rdemem.aset_size += sizeof(*set);
132 rdemem.aset_size += set->size * set->max;
133 return set;
134 }
135
136 void
set_free(struct set_table * set)137 set_free(struct set_table *set)
138 {
139 if (set == NULL)
140 return;
141 rdemem.aset_cnt--;
142 rdemem.aset_size -= sizeof(*set);
143 rdemem.aset_size -= set->size * set->max;
144 rdemem.aset_nmemb -= set->nmemb;
145 free(set->set);
146 free(set);
147 }
148
149 int
set_add(struct set_table * set,void * elms,size_t nelms)150 set_add(struct set_table *set, void *elms, size_t nelms)
151 {
152 if (nelms == 0) /* nothing todo */
153 return 0;
154
155 if (set->max < nelms || set->max - nelms < set->nmemb) {
156 uint32_t *s;
157 size_t new_size;
158
159 if (set->nmemb >= SIZE_MAX - 4096 - nelms) {
160 errno = ENOMEM;
161 return -1;
162 }
163 for (new_size = set->max; new_size < set->nmemb + nelms; )
164 new_size += (new_size < 4096 ? new_size : 4096);
165
166 s = reallocarray(set->set, new_size, set->size);
167 if (s == NULL)
168 return -1;
169 rdemem.aset_size += set->size * (new_size - set->max);
170 set->set = s;
171 set->max = new_size;
172 }
173
174 memcpy((uint8_t *)set->set + set->nmemb * set->size, elms,
175 nelms * set->size);
176 set->nmemb += nelms;
177 rdemem.aset_nmemb += nelms;
178
179 return 0;
180 }
181
182 void *
set_get(struct set_table * set,size_t * nelms)183 set_get(struct set_table *set, size_t *nelms)
184 {
185 *nelms = set->nmemb;
186 return set->set;
187 }
188
189 static int
set_cmp(const void * ap,const void * bp)190 set_cmp(const void *ap, const void *bp)
191 {
192 const uint32_t *a = ap;
193 const uint32_t *b = bp;
194
195 if (*a > *b)
196 return 1;
197 else if (*a < *b)
198 return -1;
199 return 0;
200 }
201
202 void
set_prep(struct set_table * set)203 set_prep(struct set_table *set)
204 {
205 if (set == NULL)
206 return;
207 qsort(set->set, set->nmemb, set->size, set_cmp);
208 }
209
210 void *
set_match(const struct set_table * a,uint32_t asnum)211 set_match(const struct set_table *a, uint32_t asnum)
212 {
213 if (a == NULL)
214 return NULL;
215 return bsearch(&asnum, a->set, a->nmemb, a->size, set_cmp);
216 }
217
218 int
set_equal(const struct set_table * a,const struct set_table * b)219 set_equal(const struct set_table *a, const struct set_table *b)
220 {
221 /* allow NULL pointers to be passed */
222 if (a == NULL && b == NULL)
223 return 1;
224 if (a == NULL || b == NULL)
225 return 0;
226
227 if (a->nmemb != b->nmemb)
228 return 0;
229 if (memcmp(a->set, b->set, a->nmemb * a->size) != 0)
230 return 0;
231 return 1;
232 }
233
234 size_t
set_nmemb(const struct set_table * set)235 set_nmemb(const struct set_table *set)
236 {
237 return set->nmemb;
238 }
239