ring_tx: handle EINTR from sendto
[netsniff-ng.git] / trie.c
blobf0eecd55014867631ac6d5926c00254861ae180c
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2011 Daniel Borkmann.
4 * Subject to the GPL, version 2.
5 */
7 #include <stdint.h>
8 #include <string.h>
9 #include <netinet/in.h>
11 #include "patricia.h"
12 #include "locking.h"
13 #include "trie.h"
14 #include "ipv4.h"
15 #include "ipv6.h"
17 static struct patricia_node *tree = NULL;
19 static struct rwlock tree_lock;
21 void trie_addr_lookup(char *buff, size_t len, int ipv4, int *fd,
22 struct sockaddr_storage *addr, size_t *alen)
24 void *data;
25 size_t dlen;
26 struct ipv4hdr *hdr4 = (void *) buff;
27 struct ipv6hdr *hdr6 = (void *) buff;
29 data = ipv4 ? (void *) &hdr4->h_daddr : (void *) &hdr6->daddr;
30 dlen = ipv4 ? sizeof(hdr4->h_daddr) : sizeof(hdr6->daddr);
32 if (unlikely((ipv4 && ((struct ipv4hdr *) buff)->h_version != 4) ||
33 (!ipv4 && ((struct ipv6hdr *) buff)->version != 6))) {
34 memset(addr, 0, sizeof(*addr));
35 (*alen) = 0;
36 (*fd) = -1;
37 return;
40 rwlock_rd_lock(&tree_lock);
41 (*fd) = ptree_search_data_exact(data, dlen, addr, alen, tree);
42 rwlock_unlock(&tree_lock);
45 int trie_addr_maybe_update(char *buff, size_t len, int ipv4, int fd,
46 struct sockaddr_storage *addr, size_t alen)
48 int ret;
49 void *data;
50 size_t dlen;
51 struct ipv4hdr *hdr4 = (void *) buff;
52 struct ipv6hdr *hdr6 = (void *) buff;
54 data = ipv4 ? (void *) &hdr4->h_saddr : (void *) &hdr6->saddr;
55 dlen = ipv4 ? sizeof(hdr4->h_saddr) : sizeof(hdr6->saddr);
57 if (unlikely((ipv4 && ((struct ipv4hdr *) buff)->h_version != 4) ||
58 (!ipv4 && ((struct ipv6hdr *) buff)->version != 6)))
59 return -1;
61 rwlock_wr_lock(&tree_lock);
62 ret = ptree_add_entry(data, dlen, fd, addr, alen, &tree);
63 rwlock_unlock(&tree_lock);
65 return ret;
68 void trie_addr_remove(int fd)
70 int found = 1;
71 struct patricia_node *n = NULL;
73 rwlock_wr_lock(&tree_lock);
75 while (found) {
76 ptree_get_key(fd, tree, &n);
77 if (n) {
78 ptree_del_entry(n->key, n->klen, &tree);
79 n = NULL;
80 } else
81 found = 0;
84 rwlock_unlock(&tree_lock);
87 void trie_addr_remove_addr(struct sockaddr_storage *addr, size_t alen)
89 int found = 1;
90 struct patricia_node *n = NULL;
92 rwlock_wr_lock(&tree_lock);
94 while (found) {
95 ptree_get_key_addr(addr, alen, tree, &n);
96 if (n) {
97 ptree_del_entry(n->key, n->klen, &tree);
98 n = NULL;
99 } else
100 found = 0;
103 rwlock_unlock(&tree_lock);
106 void trie_init(void)
108 rwlock_init(&tree_lock);
111 void trie_cleanup(void)
113 rwlock_wr_lock(&tree_lock);
114 ptree_free(tree);
115 rwlock_unlock(&tree_lock);
116 rwlock_destroy(&tree_lock);