mirror of
https://code.semirocket.science/wrapsix
synced 2024-12-22 12:30:18 +02:00
Revised radix tree
Dropped chunker duplication and created one universal Rewritten function for deleting entries from the tree (limiting the tree to 32 levels)
This commit is contained in:
parent
d7e506abed
commit
9ac06588a8
10
src/nat.c
10
src/nat.c
@ -85,7 +85,7 @@ struct s_nat *nat_out(radixtree_t *nat_proto6, radixtree_t *nat_proto4,
|
||||
radixsearch6.port_dst = port_dst;
|
||||
|
||||
if ((result = (struct s_nat *) radixtree_lookup(nat_proto6,
|
||||
radixtree_ipv6_chunker, &radixsearch6)) == NULL) {
|
||||
radixtree_chunker, &radixsearch6, sizeof(radixsearch6))) == NULL) {
|
||||
/* if no connection is found, let's create one */
|
||||
if ((connection =
|
||||
(struct s_nat *) malloc(sizeof(struct s_nat))) == NULL) {
|
||||
@ -109,14 +109,14 @@ struct s_nat *nat_out(radixtree_t *nat_proto6, radixtree_t *nat_proto4,
|
||||
/* returns port from range 1024 - 65535 */
|
||||
radixsearch4.port_dst = (rand() % 64511) + 1024;
|
||||
|
||||
result = radixtree_lookup(nat_proto4, radixtree_ipv4_chunker, &radixsearch4);
|
||||
result = radixtree_lookup(nat_proto4, radixtree_chunker, &radixsearch4, sizeof(radixsearch4));
|
||||
} while (result != NULL);
|
||||
|
||||
connection->ipv4_port_src = radixsearch4.port_dst;
|
||||
|
||||
/* save this connection to the NAT table (to *both* of them) */
|
||||
radixtree_insert(nat_proto6, radixtree_ipv6_chunker, &radixsearch6, connection);
|
||||
radixtree_insert(nat_proto4, radixtree_ipv4_chunker, &radixsearch4, connection);
|
||||
radixtree_insert(nat_proto6, radixtree_chunker, &radixsearch6, sizeof(radixsearch6), connection);
|
||||
radixtree_insert(nat_proto4, radixtree_chunker, &radixsearch4, sizeof(radixsearch4), connection);
|
||||
|
||||
return connection;
|
||||
} else {
|
||||
@ -138,7 +138,7 @@ struct s_nat *nat_in(radixtree_t *nat_proto4, struct s_ipv4_addr ipv4_src,
|
||||
radixsearch4.port_dst = port_dst;
|
||||
radixsearch4.zeros = 0x0;
|
||||
|
||||
if ((result = (struct s_nat *) radixtree_lookup(nat_proto4, radixtree_ipv4_chunker, &radixsearch4)) == NULL) {
|
||||
if ((result = (struct s_nat *) radixtree_lookup(nat_proto4, radixtree_chunker, &radixsearch4, sizeof(radixsearch4))) == NULL) {
|
||||
/* when connection is not found, drop the packet */
|
||||
return NULL;
|
||||
} else {
|
||||
|
114
src/radixtree.c
114
src/radixtree.c
@ -52,14 +52,14 @@ void radixtree_destroy(radixtree_t *t, unsigned char depth)
|
||||
}
|
||||
|
||||
void radixtree_insert(radixtree_t *root,
|
||||
unsigned char *(chunker)(void *data, unsigned char *count),
|
||||
void *search_data, void *data)
|
||||
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
|
||||
void *search_data, unsigned char size, void *data)
|
||||
{
|
||||
radixtree_t *tmp;
|
||||
unsigned char i, chunk_count;
|
||||
unsigned char *chunks;
|
||||
|
||||
chunks = chunker(search_data, &chunk_count);
|
||||
chunks = chunker(search_data, size, &chunk_count);
|
||||
|
||||
tmp = root;
|
||||
tmp->count++;
|
||||
@ -86,71 +86,57 @@ void radixtree_insert(radixtree_t *root,
|
||||
}
|
||||
|
||||
void radixtree_delete(radixtree_t *root,
|
||||
unsigned char *(chunker)(void *data, unsigned char *count),
|
||||
void *data)
|
||||
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
|
||||
void *data, unsigned char size)
|
||||
{
|
||||
radixtree_t *tmp,
|
||||
*next;
|
||||
unsigned char i, chunk_count;
|
||||
unsigned char *chunks;
|
||||
unsigned int flags = 0;
|
||||
|
||||
chunks = chunker(data, &chunk_count);
|
||||
chunks = chunker(data, size, &chunk_count);
|
||||
|
||||
for (i = 0, tmp = root; i < chunk_count && tmp != NULL; i++, tmp = tmp->array[chunks[i]]) {
|
||||
flags = tmp->count == 1 ? flags | (0x1 << i) : 0;
|
||||
|
||||
if (i + 1 == chunk_count) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if was at leaf, decrement counter */
|
||||
if (i + 1 == chunk_count) {
|
||||
tmp->count--;
|
||||
}
|
||||
|
||||
tmp = root;
|
||||
tmp->count--;
|
||||
flags &= 0xfffffffe; /* unflag root */
|
||||
|
||||
for (i = 0; i < chunk_count; i++) {
|
||||
unsigned char id;
|
||||
|
||||
id = chunks[i];
|
||||
|
||||
/* already deleted? may cause data inconsistency! */
|
||||
if (tmp->array[id] == NULL) {
|
||||
return;
|
||||
next = tmp->array[chunks[i]];
|
||||
if (flags & (0x1 << (i + 1))) {
|
||||
tmp->array[chunks[i]] = NULL;
|
||||
tmp->count--;
|
||||
}
|
||||
|
||||
if (i == chunk_count - 1) {
|
||||
if (tmp->count == 0) {
|
||||
free(tmp);
|
||||
} else {
|
||||
tmp->array[id] = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* now you *have to* call free on data too
|
||||
* but probably not here...
|
||||
**/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
next = tmp->array[id];
|
||||
|
||||
/* if it is the last entry in this tree branch */
|
||||
if (next->count == 1) {
|
||||
tmp->array[id] = NULL;
|
||||
}
|
||||
|
||||
if (i != 0 && tmp->count == 0) {
|
||||
if (flags & (0x1 << i)) {
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
tmp = next;
|
||||
tmp->count--;
|
||||
}
|
||||
|
||||
free(chunks);
|
||||
}
|
||||
|
||||
void *radixtree_lookup(radixtree_t *root,
|
||||
unsigned char *(chunker)(void *data, unsigned char *count),
|
||||
void *data)
|
||||
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
|
||||
void *data, unsigned char size)
|
||||
{
|
||||
radixtree_t *tmp;
|
||||
unsigned char i, chunk_count, id;
|
||||
unsigned char *chunks;
|
||||
|
||||
chunks = chunker(data, &chunk_count);
|
||||
chunks = chunker(data, size, &chunk_count);
|
||||
|
||||
tmp = root;
|
||||
|
||||
@ -177,14 +163,24 @@ void *radixtree_lookup(radixtree_t *root,
|
||||
/* we never get here ;c) */
|
||||
}
|
||||
|
||||
unsigned char *radixtree_ipv6_chunker(void *data, unsigned char *count)
|
||||
/**
|
||||
* Universal chunker.
|
||||
*
|
||||
* @param data Data to chunk
|
||||
* @param size Size of the data; must be divisible by 3
|
||||
* @param count Variable into which is put information about number of
|
||||
* chunks produced
|
||||
*
|
||||
* @return Array of chunks
|
||||
*/
|
||||
unsigned char *radixtree_chunker(void *data, unsigned char size, unsigned char *count)
|
||||
{
|
||||
short i;
|
||||
unsigned char counter;
|
||||
unsigned char *chunks;
|
||||
unsigned char *cdata = (unsigned char *) data;
|
||||
|
||||
counter = 192 / 6;
|
||||
counter = size * 8 / 6;
|
||||
memcpy(count, &counter, sizeof(unsigned char));
|
||||
|
||||
if ((chunks = (unsigned char *) malloc(counter * sizeof(unsigned char))) == NULL) {
|
||||
@ -202,33 +198,7 @@ unsigned char *radixtree_ipv6_chunker(void *data, unsigned char *count)
|
||||
* 240 == 1111 0000 == 0xf0
|
||||
* 252 == 1111 1100 == 0xfc
|
||||
*/
|
||||
for (i = 0, counter = 0; counter < *count; i++) {
|
||||
chunks[counter++] = cdata[i] & 0x3f;
|
||||
chunks[counter++] = ((cdata[i] & 0xc0) >> 6) | ((cdata[i + 1] & 0x0f) << 2);
|
||||
i++;
|
||||
chunks[counter++] = ((cdata[i] & 0xf0) >> 4) | ((cdata[i + 1] & 0x03) << 4);
|
||||
i++;
|
||||
chunks[counter++] = ((cdata[i] & 0xfc) >> 2);
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
unsigned char *radixtree_ipv4_chunker(void *data, unsigned char *count)
|
||||
{
|
||||
short i;
|
||||
unsigned char counter;
|
||||
unsigned char *chunks;
|
||||
unsigned char *cdata = (unsigned char *) data;
|
||||
|
||||
counter = 72 / 6;
|
||||
memcpy(count, &counter, sizeof(unsigned char));
|
||||
|
||||
if ((chunks = (unsigned char *) malloc(counter * sizeof(unsigned char))) == NULL) {
|
||||
fprintf(stderr, "[Error] Lack of free memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* processes 3 bytes at a time */
|
||||
for (i = 0, counter = 0; counter < *count; i++) {
|
||||
chunks[counter++] = cdata[i] & 0x3f;
|
||||
chunks[counter++] = ((cdata[i] & 0xc0) >> 6) | ((cdata[i + 1] & 0x0f) << 2);
|
||||
|
@ -30,15 +30,14 @@ typedef struct radixtree {
|
||||
radixtree_t *radixtree_create(void);
|
||||
void radixtree_destroy(radixtree_t *t, unsigned char depth);
|
||||
void radixtree_insert(radixtree_t *root,
|
||||
unsigned char *(chunker)(void *data, unsigned char *count),
|
||||
void *search_data, void *data);
|
||||
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
|
||||
void *search_data, unsigned char size, void *data);
|
||||
void radixtree_delete(radixtree_t *root,
|
||||
unsigned char *(chunker)(void *data, unsigned char *count),
|
||||
void *data);
|
||||
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
|
||||
void *data, unsigned char size);
|
||||
void *radixtree_lookup(radixtree_t *root,
|
||||
unsigned char *(chunker)(void *data, unsigned char *count),
|
||||
void *data);
|
||||
unsigned char *radixtree_ipv6_chunker(void *data, unsigned char *count);
|
||||
unsigned char *radixtree_ipv4_chunker(void *data, unsigned char *count);
|
||||
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
|
||||
void *data, unsigned char size);
|
||||
unsigned char *radixtree_chunker(void *data, unsigned char size, unsigned char *count);
|
||||
|
||||
#endif /* RADIXTREE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user