1 #include "rtr/db/db_table.h"
2
3 #include <sys/types.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
4 #include <sys/socket.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
5
6 #include "log.h"
7 #include "data_structure/uthash_nonfatal.h"
8
9 struct hashable_roa {
10 struct vrp data;
11 UT_hash_handle hh;
12 };
13
14 struct hashable_key {
15 struct router_key data;
16 UT_hash_handle hh;
17 };
18
19 struct db_table {
20 struct hashable_roa *roas;
21 struct hashable_key *router_keys;
22 };
23
24 struct db_table *
db_table_create(void)25 db_table_create(void)
26 {
27 struct db_table *table;
28
29 table = malloc(sizeof(struct db_table));
30 if (table == NULL)
31 return NULL;
32
33 table->roas = NULL;
34 table->router_keys = NULL;
35 return table;
36 }
37
38 void
db_table_destroy(struct db_table * table)39 db_table_destroy(struct db_table *table)
40 {
41 struct hashable_roa *node;
42 struct hashable_roa *tmp;
43 struct hashable_key *node_key;
44 struct hashable_key *tmp_key;
45
46 HASH_ITER(hh, table->roas, node, tmp) {
47 HASH_DEL(table->roas, node);
48 free(node);
49 }
50
51 HASH_ITER(hh, table->router_keys, node_key, tmp_key) {
52 HASH_DEL(table->router_keys, node_key);
53 free(node_key);
54 }
55
56 free(table);
57 }
58
59 int
db_table_foreach_roa(struct db_table * table,vrp_foreach_cb cb,void * arg)60 db_table_foreach_roa(struct db_table *table, vrp_foreach_cb cb, void *arg)
61 {
62 struct hashable_roa *node, *tmp;
63 int error;
64
65 HASH_ITER(hh, table->roas, node, tmp) {
66 error = cb(&node->data, arg);
67 if (error)
68 return error;
69 }
70
71 return 0;
72 }
73
74 int
db_table_foreach_router_key(struct db_table * table,router_key_foreach_cb cb,void * arg)75 db_table_foreach_router_key(struct db_table *table, router_key_foreach_cb cb,
76 void *arg)
77 {
78 struct hashable_key *node, *tmp;
79 int error;
80
81 HASH_ITER(hh, table->router_keys, node, tmp) {
82 error = cb(&node->data, arg);
83 if (error)
84 return error;
85 }
86
87 return 0;
88 }
89
90 static struct hashable_roa *
create_roa(uint32_t asn,uint8_t max_length)91 create_roa(uint32_t asn, uint8_t max_length)
92 {
93 struct hashable_roa *roa;
94
95 roa = malloc(sizeof(struct hashable_roa));
96 if (roa == NULL)
97 return NULL;
98 /* Needed by uthash */
99 memset(roa, 0, sizeof(struct hashable_roa));
100
101 roa->data.asn = asn;
102 roa->data.max_prefix_length = max_length;
103
104 return roa;
105 }
106
107 static int
add_roa(struct db_table * table,struct hashable_roa * new)108 add_roa(struct db_table *table, struct hashable_roa *new)
109 {
110 struct hashable_roa *old;
111
112 errno = 0;
113 HASH_REPLACE(hh, table->roas, data, sizeof(new->data), new, old);
114 if (errno)
115 return -pr_val_errno(errno, "ROA couldn't be added to hash table");
116 if (old != NULL)
117 free(old);
118
119 return 0;
120 }
121
122 static int
add_router_key(struct db_table * table,struct hashable_key * new)123 add_router_key(struct db_table *table, struct hashable_key *new)
124 {
125 struct hashable_key *old;
126
127 errno = 0;
128 HASH_REPLACE(hh, table->router_keys, data, sizeof(new->data), new, old);
129 if (errno)
130 return -pr_val_errno(errno, "Router Key couldn't be added to hash table");
131 if (old != NULL)
132 free(old);
133
134 return 0;
135 }
136
137 unsigned int
db_table_roa_count(struct db_table * table)138 db_table_roa_count(struct db_table *table)
139 {
140 return HASH_COUNT(table->roas);
141 }
142
143 unsigned int
db_table_router_key_count(struct db_table * table)144 db_table_router_key_count(struct db_table *table)
145 {
146 return HASH_COUNT(table->router_keys);
147 }
148
149 void
db_table_remove_roa(struct db_table * table,struct vrp const * del)150 db_table_remove_roa(struct db_table *table, struct vrp const *del)
151 {
152 struct hashable_roa *ptr;
153
154 HASH_FIND(hh, table->roas, del, sizeof(*del), ptr);
155 if (ptr != NULL) {
156 HASH_DELETE(hh, table->roas, ptr);
157 free(ptr);
158 }
159 }
160
161 void
db_table_remove_router_key(struct db_table * table,struct router_key const * del)162 db_table_remove_router_key(struct db_table *table,
163 struct router_key const *del)
164 {
165 struct hashable_key *ptr;
166
167 HASH_FIND(hh, table->router_keys, del, sizeof(*del), ptr);
168 if (ptr != NULL) {
169 HASH_DELETE(hh, table->router_keys, ptr);
170 free(ptr);
171 }
172 }
173
174 int
rtrhandler_handle_roa_v4(struct db_table * table,uint32_t asn,struct ipv4_prefix const * prefix4,uint8_t max_length)175 rtrhandler_handle_roa_v4(struct db_table *table, uint32_t asn,
176 struct ipv4_prefix const *prefix4, uint8_t max_length)
177 {
178 struct hashable_roa *roa;
179 int error;
180
181 roa = create_roa(asn, max_length);
182 if (roa == NULL)
183 return pr_enomem();
184 roa->data.prefix.v4 = prefix4->addr;
185 roa->data.prefix_length = prefix4->len;
186 roa->data.addr_fam = AF_INET;
187
188 error = add_roa(table, roa);
189 if (error)
190 free(roa);
191 return error;
192 }
193
194 int
rtrhandler_handle_roa_v6(struct db_table * table,uint32_t asn,struct ipv6_prefix const * prefix6,uint8_t max_length)195 rtrhandler_handle_roa_v6(struct db_table *table, uint32_t asn,
196 struct ipv6_prefix const *prefix6, uint8_t max_length)
197 {
198 struct hashable_roa *roa;
199 int error;
200
201 roa = create_roa(asn, max_length);
202 if (roa == NULL)
203 return pr_enomem();
204 roa->data.prefix.v6 = prefix6->addr;
205 roa->data.prefix_length = prefix6->len;
206 roa->data.addr_fam = AF_INET6;
207
208 error = add_roa(table, roa);
209 if (error)
210 free(roa);
211 return error;
212 }
213
214 int
rtrhandler_handle_router_key(struct db_table * table,unsigned char const * ski,uint32_t as,unsigned char const * spk)215 rtrhandler_handle_router_key(struct db_table *table,
216 unsigned char const *ski, uint32_t as, unsigned char const *spk)
217 {
218 struct hashable_key *key;
219 int error;
220
221 key = malloc(sizeof(struct hashable_key));
222 if (key == NULL)
223 return pr_enomem();
224 /* Needed by uthash */
225 memset(key, 0, sizeof(struct hashable_key));
226
227 router_key_init(&key->data, ski, as, spk);
228
229 error = add_router_key(table, key);
230 if (error)
231 free(key);
232
233 return error;
234 }
235
236 /*
237 * Copies `@roas1 - roas2` into @deltas.
238 *
239 * (Places the ROAs that exist in @roas1 but not in @roas2 in @deltas.)
240 */
241 static int
add_roa_deltas(struct hashable_roa * roas1,struct hashable_roa * roas2,struct deltas * deltas,int op)242 add_roa_deltas(struct hashable_roa *roas1, struct hashable_roa *roas2,
243 struct deltas *deltas, int op)
244 {
245 struct hashable_roa *n1; /* A node from @roas1 */
246 struct hashable_roa *n2; /* A node from @roas2 */
247 int error;
248
249 for (n1 = roas1; n1 != NULL; n1 = n1->hh.next) {
250 HASH_FIND(hh, roas2, &n1->data, sizeof(n1->data), n2);
251 if (n2 == NULL) {
252 error = deltas_add_roa(deltas, &n1->data, op);
253 if (error)
254 return error;
255 }
256 }
257
258 return 0;
259 }
260
261 static int
add_router_key_delta(struct deltas * deltas,struct hashable_key * key,int op)262 add_router_key_delta(struct deltas *deltas, struct hashable_key *key, int op)
263 {
264 return deltas_add_router_key(deltas, &key->data, op);
265 }
266
267 /*
268 * Copies `@keys1 - keys2` into @deltas.
269 *
270 * (Places the Router Keys that exist in @keys1 but not in @key2 in @deltas.)
271 */
272 static int
add_router_key_deltas(struct hashable_key * keys1,struct hashable_key * keys2,struct deltas * deltas,int op)273 add_router_key_deltas(struct hashable_key *keys1, struct hashable_key *keys2,
274 struct deltas *deltas, int op)
275 {
276 struct hashable_key *n1; /* A node from @keys1 */
277 struct hashable_key *n2; /* A node from @keys2 */
278 int error;
279
280 for (n1 = keys1; n1 != NULL; n1 = n1->hh.next) {
281 HASH_FIND(hh, keys2, &n1->data, sizeof(n1->data), n2);
282 if (n2 == NULL) {
283 error = add_router_key_delta(deltas, n1, op);
284 if (error)
285 return error;
286 }
287 }
288
289 return 0;
290 }
291
292 int
compute_deltas(struct db_table * old,struct db_table * new,struct deltas ** result)293 compute_deltas(struct db_table *old, struct db_table *new,
294 struct deltas **result)
295 {
296 struct deltas *deltas;
297 int error;
298
299 error = deltas_create(&deltas);
300 if (error)
301 return error;
302
303 error = add_roa_deltas(new->roas, old->roas, deltas, FLAG_ANNOUNCEMENT);
304 if (error)
305 goto fail;
306 error = add_roa_deltas(old->roas, new->roas, deltas, FLAG_WITHDRAWAL);
307 if (error)
308 goto fail;
309 error = add_router_key_deltas(new->router_keys, old->router_keys,
310 deltas, FLAG_ANNOUNCEMENT);
311 if (error)
312 goto fail;
313 error = add_router_key_deltas(old->router_keys, new->router_keys,
314 deltas, FLAG_WITHDRAWAL);
315 if (error)
316 goto fail;
317
318 *result = deltas;
319 return 0;
320
321 fail:
322 deltas_refput(deltas);
323 return error;
324 }
325