1 #include "mcache.h"
2 #include "util.h"
3
4 #include <assert.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 // Delete dead_node and all following nodes from cache
cache_prune(struct mcache_node * dead_node,struct mcache_node ** cache)9 void cache_prune(struct mcache_node *dead_node, struct mcache_node **cache)
10 {
11 struct mcache_node *node;
12 struct mcache_node *next;
13
14 if (dead_node == *cache) {
15 *cache = NULL;
16 } else {
17 for (node = *cache; node && node->next != dead_node; node = node->next) {
18 }
19
20 /* Assert that dead_node was found in the cache */
21 assert(node->next == dead_node);
22 node->next = NULL;
23 }
24
25 /* Delete remaining list */
26 for (node = dead_node; node; node = next) {
27 next = node->next;
28 free(node);
29 }
30 }
31
32 // Delete only deda_node from the cache
cache_del(struct mcache_node * dead_node,struct mcache_node ** cache)33 void cache_del(struct mcache_node *dead_node, struct mcache_node **cache)
34 {
35 struct mcache_node *node;
36
37 if (dead_node == *cache) {
38 *cache = dead_node->next;
39 } else {
40 for (node = *cache; node && node->next != dead_node; node = node->next) {
41 }
42
43 assert(node->next == dead_node);
44 node->next = dead_node->next;
45 }
46
47 free(dead_node);
48 }
49
50 // Add new node to the cache
cache_add(uint8_t * l2_addr,uint8_t * ip_addr,uint8_t len,time_t tstamp,uint16_t vlan_tag,struct mcache_node ** cache)51 void cache_add(uint8_t *l2_addr, uint8_t *ip_addr, uint8_t len, time_t tstamp,
52 uint16_t vlan_tag, struct mcache_node **cache)
53 {
54 struct mcache_node *node;
55
56 node = (struct mcache_node *)calloc(sizeof(*node), 1);
57
58 if (!node) {
59 log_msg(LOG_ERR, "%s: unable to allocate memory for new cache node", __FUNCTION__);
60 return;
61 }
62
63 memcpy(node->l2_addr, l2_addr, sizeof(node->l2_addr));
64 memcpy(node->ip_addr, ip_addr, len);
65 node->tstamp = tstamp;
66 node->addr_len = len;
67 node->vlan_tag = vlan_tag;
68
69 node->next = *cache;
70 *cache = node;
71 }
72
cache_lookup(uint8_t * l2_addr,uint8_t * ip_addr,uint8_t len,time_t tstamp,uint16_t vlan_tag,struct mcache_node ** cache)73 struct mcache_node *cache_lookup(uint8_t *l2_addr, uint8_t *ip_addr, uint8_t len,
74 time_t tstamp, uint16_t vlan_tag, struct mcache_node **cache)
75 {
76 struct mcache_node *node;
77
78 for (node = *cache; node != NULL; node = node->next) {
79 /* New cache nodes are inserted at the begining of the list
80 * resulting cache list ordered by timestamp.
81 *
82 * If we find old cache node we can safely delete it and all
83 * following nodes.
84 */
85 if (cfg.ratelimit > 0 && tstamp > node->tstamp + cfg.ratelimit) {
86 cache_prune(node, cache);
87 return NULL;
88 }
89
90 if (vlan_tag != node->vlan_tag) {
91 continue;
92 }
93
94 if (len != node->addr_len) {
95 continue;
96 }
97
98 if (memcmp(ip_addr, node->ip_addr, len) != 0) {
99 continue;
100 }
101
102 if (memcmp(l2_addr, node->l2_addr, sizeof(node->l2_addr)) != 0) {
103 cache_del(node, cache);
104 return NULL;
105 }
106
107 return node;
108 }
109
110 return NULL;
111 }
112