1
0
mirror of https://code.semirocket.science/wrapsix synced 2024-09-19 23:11:04 +03:00

A lot of changes and fixes in NAT and radix tree

Included MAC address into the NAT data structure
New chunking algorithms
Fixed memory leaks in RT code
(and more)
This commit is contained in:
Michal Zima 2012-03-24 08:26:13 +01:00
parent 214c42728b
commit d7a570b857
4 changed files with 118 additions and 58 deletions

View File

@ -20,7 +20,11 @@
#include <stdlib.h> /* malloc */
#include <time.h> /* time */
#include "ipv4.h"
#include "ipv6.h"
#include "nat.h"
#include "radixtree.h"
#include "wrapper.h"
struct s_radixtree_nat6 {
struct s_ipv6_addr ipv6;
@ -39,7 +43,7 @@ struct s_radixtree_nat4 {
radixtree_t *nat6_tcp, *nat6_udp, *nat6_icmp,
*nat4_tcp, *nat4_udp, *nat4_icmp;
void nat_init()
void nat_init(void)
{
nat6_tcp = radixtree_create();
nat6_udp = radixtree_create();
@ -50,33 +54,36 @@ void nat_init()
nat4_icmp = radixtree_create();
}
void nat_quit()
void nat_quit(void)
{
/* 128 + 16 + 32 + 16 = 198 / 6 = 33 */
radixtree_destroy(&nat6_tcp, 33);
radixtree_destroy(&nat6_udp, 33);
radixtree_destroy(&nat6_icmp, 33);
/* 128 + 16 + 32 + 16 = 192 / 6 = 32 */
radixtree_destroy(nat6_tcp, 32);
radixtree_destroy(nat6_udp, 32);
radixtree_destroy(nat6_icmp, 32);
/* 32 + 16 + 16 + 8 = 72 / 6 = 12 */
radixtree_destroy(&nat4_tcp, 12);
radixtree_destroy(&nat4_udp, 12);
radixtree_destroy(&nat4_icmp, 12);
radixtree_destroy(nat4_tcp, 12);
radixtree_destroy(nat4_udp, 12);
radixtree_destroy(nat4_icmp, 12);
}
struct s_nat *nat_out(radixtree_t *nat_proto6, radixtree_t *nat_proto4,
struct s_ipv6_addr ipv6_src, struct s_ipv6_addr ipv6_dst,
unsigned short port_src, unsigned short port_dst)
{
radixtree_t *result, *connection;
struct s_nat *result, *connection;
struct s_radixtree_nat4 radixsearch4;
struct s_radixtree_nat6 radixsearch6;
/* create structure to search in the tree */
struct s_radixtree_nat6 radixsearch6;
radixsearch6.ipv6 = ipv6_src;
radixsearch6.ipv4 = ipv6_to_ipv4(&ipv6_dst);
ipv6_to_ipv4(&ipv6_dst, &radixsearch6.ipv4);
radixsearch6.port_src = port_src;
radixsearch6.port_dst = port_dst;
if ((result = radixtree_lookup(nat_proto6, radixtree_outgoing_chunker, &radixsearch6)) == NULL) {
if ((result = (struct s_nat *) radixtree_lookup(nat_proto6, radixtree_ipv6_chunker, &radixsearch6)) == NULL) {
/* if no connection is found, let's create one */
if ((connection = (struct s_nat *) malloc(sizeof(struct s_nat))) == NULL) {
fprintf(stderr, "[Error] Lack of free memory\n");
return NULL;
@ -86,48 +93,50 @@ struct s_nat *nat_out(radixtree_t *nat_proto6, radixtree_t *nat_proto4,
connection->ipv4 = radixsearch6.ipv4;
connection->ipv6_port_src = port_src;
connection->ipv4_port_dst = port_dst;
result->last_packet = time(NULL);
connection->last_packet = time(NULL);
/* generate some outgoing port */
do {
/* return port from range 1024 - 65535 */
connection->ipv4_port_src = (rand() % 64511) + 1024;
result = radixtree_lookup(nat_proto6, radixtree_outgoing_chunker, &radixsearch6);
result = radixtree_lookup(nat_proto6, radixtree_ipv6_chunker, &radixsearch6);
} while (result != NULL);
/* save this connection to the NAT table (to *both* of them) */
struct s_radixtree_nat4 radixsearch4;
radixsearch4.addr = radixsearch6.ipv4;
radixsearch4.port_src = port_dst;
radixsearch4.port_dst = connection->ipv4_port_src;
radixsearch4.zeros = 0x0;
radixtree_insert(nat_proto6, radixtree_outgoing_chunker, &radixsearch6, connection);
radixtree_insert(nat_proto4, radixtree_incoming_chunker, &radixsearch4, connection);
radixtree_insert(nat_proto6, radixtree_ipv6_chunker, &radixsearch6, connection);
radixtree_insert(nat_proto4, radixtree_ipv4_chunker, &radixsearch4, connection);
return connection;
} else {
/* when connection is found, refresh it and return */
result->last_packet = time(NULL);
return result;
}
}
struct s_nat *nat_in(radixtree_t *nat_proto, struct s_ipv4_addr ipv4_src,
struct s_nat *nat_in(radixtree_t *nat_proto4, struct s_ipv4_addr ipv4_src,
unsigned short port_src, unsigned short port_dst)
{
radixtree_t *result;
struct s_nat *result;
/* create structure to search in the tree */
struct s_radixtree_nat4 radixsearch;
radixsearch.addr = ipv4_src;
radixsearch.port_src = port_src;
radixsearch.port_dst = port_dst;
radixsearch.zeros = 0x0;
struct s_radixtree_nat4 radixsearch4;
radixsearch4.addr = ipv4_src;
radixsearch4.port_src = port_src;
radixsearch4.port_dst = port_dst;
radixsearch4.zeros = 0x0;
if ((result = radixtree_lookup(nat_proto, radixtree_outgoing_chunker, &radixsearch)) == NULL) {
if ((result = (struct s_nat *) radixtree_lookup(nat_proto4, radixtree_ipv4_chunker, &radixsearch4)) == NULL) {
/* when connection is not found, drop the packet */
return NULL;
} else {
/* when connection is found, refresh it and return */
result->last_packet = time(NULL);
return result;
}

View File

@ -1,6 +1,6 @@
/*
* WrapSix
* Copyright (C) 2008-2010 Michal Zima <xhire@mujmalysvet.cz>
* Copyright (C) 2008-2011 Michal Zima <xhire@mujmalysvet.cz>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@ -21,11 +21,13 @@
#include <time.h> /* time_t */
#include "ethernet.h" /* s_mac_addr */
#include "ipv4.h" /* s_ipv4_addr */
#include "ipv6.h" /* s_ipv6_addr */
#include "radixtree.h" /* radixtree_t */
struct s_nat {
struct s_mac_addr mac;
struct s_ipv6_addr ipv6;
struct s_ipv4_addr ipv4;
unsigned short ipv6_port_src;
@ -37,13 +39,13 @@ struct s_nat {
extern radixtree_t *nat6_tcp, *nat6_udp, *nat6_icmp,
*nat4_tcp, *nat4_udp, *nat4_icmp;
void nat_init();
void nat_quit();
void nat_init(void);
void nat_quit(void);
struct s_nat *nat_out(radixtree_t *nat_proto6, radixtree_t *nat_proto4,
struct s_ipv6_addr ipv6_src, struct s_ipv6_addr ipv6_dst,
unsigned short port_src, unsigned short port_dst);
struct s_nat *nat_in(radixtree_t *nat_proto, struct s_ipv4_addr ipv4_src,
struct s_nat *nat_in(radixtree_t *nat_proto4, struct s_ipv4_addr ipv4_src,
unsigned short port_src, unsigned short port_dst);
#endif /* NAT_H */

View File

@ -1,6 +1,6 @@
/*
* WrapSix
* Copyright (C) 2008-2010 Michal Zima <xhire@mujmalysvet.cz>
* Copyright (C) 2008-2012 Michal Zima <xhire@mujmalysvet.cz>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@ -16,7 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
radixtree_t *radixtree_create()
#include <stdio.h> /* fprintf */
#include <stdlib.h> /* free, malloc */
#include <string.h> /* memcpy */
#include "radixtree.h"
radixtree_t *radixtree_create(void)
{
radixtree_t *radixtree;
@ -61,7 +67,7 @@ void radixtree_insert(radixtree_t *root,
for (i = 0; i < chunk_count; i++) {
unsigned char id;
id = chunk[i];
id = chunks[i];
if (i == chunk_count - 1) {
tmp->array[id] = data;
@ -75,6 +81,8 @@ void radixtree_insert(radixtree_t *root,
tmp = tmp->array[id];
tmp->count++;
}
free(chunks);
}
void radixtree_delete(radixtree_t *root,
@ -94,7 +102,7 @@ void radixtree_delete(radixtree_t *root,
for (i = 0; i < chunk_count; i++) {
unsigned char id;
id = chunk[i];
id = chunks[i];
/* already deleted? may cause data inconsistency! */
if (tmp->array[id] == NULL) {
@ -130,68 +138,104 @@ void radixtree_delete(radixtree_t *root,
tmp = next;
tmp->count--;
}
free(chunks);
}
radixtree_t *radixtree_lookup(radixtree_t *root,
unsigned char *(chunker)(void *data, unsigned char *count),
void *data)
void *radixtree_lookup(radixtree_t *root,
unsigned char *(chunker)(void *data, unsigned char *count),
void *data)
{
radixtree_t *tmp;
unsigned char i, chunk_count;
unsigned char i, chunk_count, id;
unsigned char *chunks;
chunks = chunker(data, &chunk_count);
tmp = root;
for (i = 0; i < chunk_count; i++) {
unsigned char id;
id = chunk[i];
for (i = 0;; i++) {
id = chunks[i];
/* leave the for cycle before tmp gets overwritten,
* if the final result was found */
if (i == chunk_count - 1) {
free(chunks);
return tmp->array[id];
}
/* leave if there is no result */
if (tmp->array[id] == NULL) {
free(chunks);
return NULL;
}
/* go deeper */
tmp = tmp->array[id];
}
/* we never get here ;c) */
}
unsigned char *radixtree_outgoing_chunker(void *data, unsigned char *count)
unsigned char *radixtree_ipv6_chunker(void *data, unsigned char *count)
{
short i;
unsigned char counter;
unsigned char *chunks;
unsigned char *cdata = (unsigned char *) data;
counter = 198 / 6;
counter = 192 / 6;
memcpy(count, &counter, sizeof(unsigned char));
unsigned char chunks[counter];
if ((chunks = (unsigned char *) malloc(counter * sizeof(unsigned char))) == NULL) {
fprintf(stderr, "[Error] Lack of free memory\n");
return NULL;
}
/* 128 + 16 + 32 + 16 - 6 = 192 */
for (i = 192, counter = 0; i >= 0; i -= 6, counter++) {
chunks[counter] = (*data >> i) & 63; /* 63 == 0011 1111 */
/*
* 3 == 0000 0011 == 0x03
* 15 == 0000 1111 == 0x0f
* 48 == 0011 0000 == 0x30
* 60 == 0011 1100 == 0x3c
* 63 == 0011 1111 == 0x3f
* 192 == 1100 0000 == 0xc0
* 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_incoming_chunker(void *data, unsigned char *count)
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));
unsigned char chunks[counter];
if ((chunks = (unsigned char *) malloc(counter * sizeof(unsigned char))) == NULL) {
fprintf(stderr, "[Error] Lack of free memory\n");
return NULL;
}
/* 32 + 16 + 16 + 8 - 6 = 66 */
for (i = 66, counter = 0; i >= 0; i -= 6, counter++) {
chunks[counter] = (*data >> i) & 63; /* 63 == 0011 1111 */
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;

View File

@ -1,6 +1,6 @@
/*
* WrapSix
* Copyright (C) 2008-2010 Michal Zima <xhire@mujmalysvet.cz>
* Copyright (C) 2008-2011 Michal Zima <xhire@mujmalysvet.cz>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@ -16,6 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef RADIXTREE_H
#define RADIXTREE_H
#define CHUNK_SIZE 6
#define ARRAY_SIZE 64 /* 2 ^ CHUNK_SIZE */
@ -24,7 +27,7 @@ typedef struct radixtree {
unsigned int count;
} radixtree_t;
radixtree_t *radixtree_create();
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),
@ -32,8 +35,10 @@ void radixtree_insert(radixtree_t *root,
void radixtree_delete(radixtree_t *root,
unsigned char *(chunker)(void *data, unsigned char *count),
void *data);
radixtree_t *radixtree_lookup(radixtree_t *root,
void *radixtree_lookup(radixtree_t *root,
unsigned char *(chunker)(void *data, unsigned char *count),
void *data);
unsigned char *radixtree_outgoing_chunker(void *data, unsigned char *count);
unsigned char *radixtree_incoming_chunker(void *data, unsigned char *count);
unsigned char *radixtree_ipv6_chunker(void *data, unsigned char *count);
unsigned char *radixtree_ipv4_chunker(void *data, unsigned char *count);
#endif /* RADIXTREE_H */