/* * Copyright (c) 2017 Linus Lüssing * * SPDX-License-Identifier: GPL-2.0+ * License-Filename: LICENSE */ #include #include #include #include #include "addr_store.h" #include "gluon-arp-limiter.h" #include "lookup3.h" static struct addr_list *addr_node_alloc(void *addr, struct addr_store *store) { struct addr_list *node; size_t addr_len = store->addr_len; node = malloc(sizeof(struct addr_list) + addr_len); if (!node) return NULL; memcpy(node->addr, addr, addr_len); node->next = NULL; node->tic = clock; return node; } static struct addr_list *addr_list_search(void *addr, size_t addr_len, struct addr_list *list) { struct addr_list *node = list; struct addr_list *ret = NULL; if (!node) goto out; do { // Found it! if (!memcmp(node->addr, addr, addr_len)) { ret = node; break; } node = node->next; } while (node); out: return ret; } static void addr_list_add(struct addr_list *node, struct addr_list **list) { node->next = *list; *list = node; } static struct addr_list **addr_store_get_bucket(void *addr, struct addr_store *store) { int len = store->addr_len / sizeof(uint32_t); int idx; uint32_t ret; ret = hashword(addr, len, 0); idx = ret % ADDR_STORE_NUM_BUCKETS; return &store->buckets[idx]; } int addr_store_add(void *addr, struct addr_store *store) { struct addr_list **bucket = addr_store_get_bucket(addr, store); struct addr_list *node = addr_list_search(addr, store->addr_len, *bucket); if (node) { node->tic = clock; return -EEXIST; } node = addr_node_alloc(addr, store); if (!node) { printf("Error: Out of memory\n"); return -ENOMEM; } addr_list_add(node, bucket); return 0; } int addr_store_init(size_t addr_len, void (*destructor)(struct addr_list *), char *(*ntoa)(void *), struct addr_store *store) { int i; store->addr_len = addr_len; store->destructor = destructor; store->ntoa = ntoa; for (i = 0; i < ADDR_STORE_NUM_BUCKETS; i++) store->buckets[i] = NULL; return 0; } static char *addr_ntoa(void *addr, struct addr_store *store) { return store->ntoa(addr); } static void addr_store_dump(struct addr_store *store) { int i; struct addr_list *node; for (i = 0; i < ADDR_STORE_NUM_BUCKETS; i++) { node = store->buckets[i]; if (node) printf("Bucket #%i:\n", i); while (node) { printf("\t%s\n", addr_ntoa(node->addr, store)); node = node->next; } } } void addr_store_cleanup(struct addr_store *store) { struct addr_list *node, *prev; int i; for (i = 0; i < ADDR_STORE_NUM_BUCKETS; i++) { node = store->buckets[i]; prev = NULL; while (node) { if (node->tic != clock) { store->destructor(node); if (prev) { prev->next = node->next; free(node); node = prev->next; } else { store->buckets[i] = node->next; free(node); node = store->buckets[i]; } } else { prev = node; node = node->next; } } } addr_store_dump(store); }