mirror of
https://code.semirocket.science/wrapsix
synced 2024-11-10 00:01:01 +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;
|
radixsearch6.port_dst = port_dst;
|
||||||
|
|
||||||
if ((result = (struct s_nat *) radixtree_lookup(nat_proto6,
|
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 no connection is found, let's create one */
|
||||||
if ((connection =
|
if ((connection =
|
||||||
(struct s_nat *) malloc(sizeof(struct s_nat))) == NULL) {
|
(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 */
|
/* returns port from range 1024 - 65535 */
|
||||||
radixsearch4.port_dst = (rand() % 64511) + 1024;
|
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);
|
} while (result != NULL);
|
||||||
|
|
||||||
connection->ipv4_port_src = radixsearch4.port_dst;
|
connection->ipv4_port_src = radixsearch4.port_dst;
|
||||||
|
|
||||||
/* save this connection to the NAT table (to *both* of them) */
|
/* save this connection to the NAT table (to *both* of them) */
|
||||||
radixtree_insert(nat_proto6, radixtree_ipv6_chunker, &radixsearch6, connection);
|
radixtree_insert(nat_proto6, radixtree_chunker, &radixsearch6, sizeof(radixsearch6), connection);
|
||||||
radixtree_insert(nat_proto4, radixtree_ipv4_chunker, &radixsearch4, connection);
|
radixtree_insert(nat_proto4, radixtree_chunker, &radixsearch4, sizeof(radixsearch4), connection);
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
} else {
|
} 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.port_dst = port_dst;
|
||||||
radixsearch4.zeros = 0x0;
|
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 */
|
/* when connection is not found, drop the packet */
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} 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,
|
void radixtree_insert(radixtree_t *root,
|
||||||
unsigned char *(chunker)(void *data, unsigned char *count),
|
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
|
||||||
void *search_data, void *data)
|
void *search_data, unsigned char size, void *data)
|
||||||
{
|
{
|
||||||
radixtree_t *tmp;
|
radixtree_t *tmp;
|
||||||
unsigned char i, chunk_count;
|
unsigned char i, chunk_count;
|
||||||
unsigned char *chunks;
|
unsigned char *chunks;
|
||||||
|
|
||||||
chunks = chunker(search_data, &chunk_count);
|
chunks = chunker(search_data, size, &chunk_count);
|
||||||
|
|
||||||
tmp = root;
|
tmp = root;
|
||||||
tmp->count++;
|
tmp->count++;
|
||||||
@ -86,71 +86,57 @@ void radixtree_insert(radixtree_t *root,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void radixtree_delete(radixtree_t *root,
|
void radixtree_delete(radixtree_t *root,
|
||||||
unsigned char *(chunker)(void *data, unsigned char *count),
|
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
|
||||||
void *data)
|
void *data, unsigned char size)
|
||||||
{
|
{
|
||||||
radixtree_t *tmp,
|
radixtree_t *tmp,
|
||||||
*next;
|
*next;
|
||||||
unsigned char i, chunk_count;
|
unsigned char i, chunk_count;
|
||||||
unsigned char *chunks;
|
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 = root;
|
||||||
tmp->count--;
|
flags &= 0xfffffffe; /* unflag root */
|
||||||
|
|
||||||
for (i = 0; i < chunk_count; i++) {
|
for (i = 0; i < chunk_count; i++) {
|
||||||
unsigned char id;
|
next = tmp->array[chunks[i]];
|
||||||
|
if (flags & (0x1 << (i + 1))) {
|
||||||
id = chunks[i];
|
tmp->array[chunks[i]] = NULL;
|
||||||
|
tmp->count--;
|
||||||
/* already deleted? may cause data inconsistency! */
|
|
||||||
if (tmp->array[id] == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (flags & (0x1 << i)) {
|
||||||
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) {
|
|
||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = next;
|
tmp = next;
|
||||||
tmp->count--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(chunks);
|
free(chunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *radixtree_lookup(radixtree_t *root,
|
void *radixtree_lookup(radixtree_t *root,
|
||||||
unsigned char *(chunker)(void *data, unsigned char *count),
|
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
|
||||||
void *data)
|
void *data, unsigned char size)
|
||||||
{
|
{
|
||||||
radixtree_t *tmp;
|
radixtree_t *tmp;
|
||||||
unsigned char i, chunk_count, id;
|
unsigned char i, chunk_count, id;
|
||||||
unsigned char *chunks;
|
unsigned char *chunks;
|
||||||
|
|
||||||
chunks = chunker(data, &chunk_count);
|
chunks = chunker(data, size, &chunk_count);
|
||||||
|
|
||||||
tmp = root;
|
tmp = root;
|
||||||
|
|
||||||
@ -177,14 +163,24 @@ void *radixtree_lookup(radixtree_t *root,
|
|||||||
/* we never get here ;c) */
|
/* 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;
|
short i;
|
||||||
unsigned char counter;
|
unsigned char counter;
|
||||||
unsigned char *chunks;
|
unsigned char *chunks;
|
||||||
unsigned char *cdata = (unsigned char *) data;
|
unsigned char *cdata = (unsigned char *) data;
|
||||||
|
|
||||||
counter = 192 / 6;
|
counter = size * 8 / 6;
|
||||||
memcpy(count, &counter, sizeof(unsigned char));
|
memcpy(count, &counter, sizeof(unsigned char));
|
||||||
|
|
||||||
if ((chunks = (unsigned char *) malloc(counter * sizeof(unsigned char))) == NULL) {
|
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
|
* 240 == 1111 0000 == 0xf0
|
||||||
* 252 == 1111 1100 == 0xfc
|
* 252 == 1111 1100 == 0xfc
|
||||||
*/
|
*/
|
||||||
for (i = 0, counter = 0; counter < *count; i++) {
|
/* processes 3 bytes at a time */
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0, counter = 0; counter < *count; i++) {
|
for (i = 0, counter = 0; counter < *count; i++) {
|
||||||
chunks[counter++] = cdata[i] & 0x3f;
|
chunks[counter++] = cdata[i] & 0x3f;
|
||||||
chunks[counter++] = ((cdata[i] & 0xc0) >> 6) | ((cdata[i + 1] & 0x0f) << 2);
|
chunks[counter++] = ((cdata[i] & 0xc0) >> 6) | ((cdata[i + 1] & 0x0f) << 2);
|
||||||
|
@ -30,15 +30,14 @@ typedef struct radixtree {
|
|||||||
radixtree_t *radixtree_create(void);
|
radixtree_t *radixtree_create(void);
|
||||||
void radixtree_destroy(radixtree_t *t, unsigned char depth);
|
void radixtree_destroy(radixtree_t *t, unsigned char depth);
|
||||||
void radixtree_insert(radixtree_t *root,
|
void radixtree_insert(radixtree_t *root,
|
||||||
unsigned char *(chunker)(void *data, unsigned char *count),
|
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
|
||||||
void *search_data, void *data);
|
void *search_data, unsigned char size, void *data);
|
||||||
void radixtree_delete(radixtree_t *root,
|
void radixtree_delete(radixtree_t *root,
|
||||||
unsigned char *(chunker)(void *data, unsigned char *count),
|
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
|
||||||
void *data);
|
void *data, unsigned char size);
|
||||||
void *radixtree_lookup(radixtree_t *root,
|
void *radixtree_lookup(radixtree_t *root,
|
||||||
unsigned char *(chunker)(void *data, unsigned char *count),
|
unsigned char *(chunker)(void *data, unsigned char size, unsigned char *count),
|
||||||
void *data);
|
void *data, unsigned char size);
|
||||||
unsigned char *radixtree_ipv6_chunker(void *data, unsigned char *count);
|
unsigned char *radixtree_chunker(void *data, unsigned char size, unsigned char *count);
|
||||||
unsigned char *radixtree_ipv4_chunker(void *data, unsigned char *count);
|
|
||||||
|
|
||||||
#endif /* RADIXTREE_H */
|
#endif /* RADIXTREE_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user