addr_store.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Copyright (c) 2017 Linus Lüssing <linus.luessing@c0d3.blue>
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. * License-Filename: LICENSE
  6. */
  7. #include <errno.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "addr_store.h"
  12. #include "gluon-arp-limiter.h"
  13. #include "lookup3.h"
  14. static struct addr_list *addr_node_alloc(void *addr,
  15. struct addr_store *store)
  16. {
  17. struct addr_list *node;
  18. size_t addr_len = store->addr_len;
  19. node = malloc(sizeof(struct addr_list) + addr_len);
  20. if (!node)
  21. return NULL;
  22. memcpy(node->addr, addr, addr_len);
  23. node->next = NULL;
  24. node->tic = clock;
  25. return node;
  26. }
  27. static struct addr_list *addr_list_search(void *addr,
  28. size_t addr_len,
  29. struct addr_list *list)
  30. {
  31. struct addr_list *node = list;
  32. struct addr_list *ret = NULL;
  33. if (!node)
  34. goto out;
  35. do {
  36. // Found it!
  37. if (!memcmp(node->addr, addr, addr_len)) {
  38. ret = node;
  39. break;
  40. }
  41. node = node->next;
  42. } while (node);
  43. out:
  44. return ret;
  45. }
  46. static void addr_list_add(struct addr_list *node, struct addr_list **list)
  47. {
  48. node->next = *list;
  49. *list = node;
  50. }
  51. static struct addr_list **addr_store_get_bucket(void *addr,
  52. struct addr_store *store)
  53. {
  54. int len = store->addr_len / sizeof(uint32_t);
  55. int idx;
  56. uint32_t ret;
  57. ret = hashword(addr, len, 0);
  58. idx = ret % ADDR_STORE_NUM_BUCKETS;
  59. return &store->buckets[idx];
  60. }
  61. int addr_store_add(void *addr, struct addr_store *store)
  62. {
  63. struct addr_list **bucket = addr_store_get_bucket(addr, store);
  64. struct addr_list *node = addr_list_search(addr, store->addr_len,
  65. *bucket);
  66. if (node) {
  67. node->tic = clock;
  68. return -EEXIST;
  69. }
  70. node = addr_node_alloc(addr, store);
  71. if (!node) {
  72. printf("Error: Out of memory\n");
  73. return -ENOMEM;
  74. }
  75. addr_list_add(node, bucket);
  76. return 0;
  77. }
  78. int addr_store_init(size_t addr_len,
  79. void (*destructor)(struct addr_list *),
  80. char *(*ntoa)(void *),
  81. struct addr_store *store)
  82. {
  83. int i;
  84. store->addr_len = addr_len;
  85. store->destructor = destructor;
  86. store->ntoa = ntoa;
  87. for (i = 0; i < ADDR_STORE_NUM_BUCKETS; i++)
  88. store->buckets[i] = NULL;
  89. return 0;
  90. }
  91. static char *addr_ntoa(void *addr, struct addr_store *store)
  92. {
  93. return store->ntoa(addr);
  94. }
  95. static void addr_store_dump(struct addr_store *store)
  96. {
  97. int i;
  98. struct addr_list *node;
  99. for (i = 0; i < ADDR_STORE_NUM_BUCKETS; i++) {
  100. node = store->buckets[i];
  101. if (node)
  102. printf("Bucket #%i:\n", i);
  103. while (node) {
  104. printf("\t%s\n", addr_ntoa(node->addr, store));
  105. node = node->next;
  106. }
  107. }
  108. }
  109. void addr_store_cleanup(struct addr_store *store)
  110. {
  111. struct addr_list *node, *prev;
  112. int i;
  113. for (i = 0; i < ADDR_STORE_NUM_BUCKETS; i++) {
  114. node = store->buckets[i];
  115. prev = NULL;
  116. while (node) {
  117. if (node->tic != clock) {
  118. store->destructor(node);
  119. if (prev) {
  120. prev->next = node->next;
  121. free(node);
  122. node = prev->next;
  123. } else {
  124. store->buckets[i] = node->next;
  125. free(node);
  126. node = store->buckets[i];
  127. }
  128. } else {
  129. prev = node;
  130. node = node->next;
  131. }
  132. }
  133. }
  134. addr_store_dump(store);
  135. }