/** * Retrieve or create data structure via fragment identification. * * @param nat_proto4 Radix tree of fragments * @param nat_timeout Linked list in which to watch for timeout * @param ipv4_src Source IPv4 address * @param id Fragment identification * * @return Structure for fragments (either retrieved or created) * @return NULL when structure for fragments couldn't be created */ struct s_nat_fragments *nat_in_fragments(radixtree_t *nat_proto4, linkedlist_t *nat_timeout, struct s_ipv4_addr ipv4_src, unsigned short id) { struct s_nat_fragments *result; /* create structure to search in the tree */ struct s_radixtree_fragments4 radixsearch4; radixsearch4.addr = ipv4_src; radixsearch4.id = id; if ((result = radixtree_lookup(nat_proto4, radixtree_chunker, &radixsearch4, sizeof(radixsearch4))) != NULL) { return result; } else { /* when fragmentation is not found, add one */ if ((result = (struct s_nat_fragments *) malloc(sizeof(struct s_nat_fragments))) == NULL) { log_error("Lack of free memory"); return NULL; } result->id = id; result->connection = NULL; result->queue = NULL; radixtree_insert(nat_proto4, radixtree_chunker, &radixsearch4, sizeof(radixsearch4), result); linkedlist_append(nat_timeout, result); return result; } }
uint32_t string_pool_append(char *pool, uint32_t *n_pool, radixtree_t *r, const char *str) { uint32_t location = radixtree_find_exact (r, str); if (location == RADIXTREE_NONE) { size_t n = strlen(str); /* TODO: check if n_pool + n < max */ strncpy (&pool[*n_pool], str, n); location = *n_pool; *n_pool += n; radixtree_insert(r, str, location); } return location; }
/** * Lookup or create NAT connection for outgoing IPv6 packet. * * @param nat_proto6 IPv6 NAT table * @param nat_proto4 IPv4 NAT table * @param eth_src Source MAC address * @param ipv6_src Source IPv6 address * @param ipv6_dst Destination IPv6 address * @param port_src Source port * @param port_dst Destination port * @param create Whether or not to create new NAT entry * * @return NULL when it wasn't possible to create connection * @return pointer to connection structure otherwise */ struct s_nat *nat_out(radixtree_t *nat_proto6, radixtree_t *nat_proto4, struct s_mac_addr eth_src, struct s_ipv6_addr ipv6_src, struct s_ipv6_addr ipv6_dst, unsigned short port_src, unsigned short port_dst, unsigned char create) { struct s_nat *result, *connection; struct s_radixtree_nat4 radixsearch4; struct s_radixtree_nat6 radixsearch6; /* create structure to search in the tree */ radixsearch6.ipv6 = ipv6_src; ipv6_to_ipv4(&ipv6_dst, &radixsearch6.ipv4); radixsearch6.port_src = port_src; radixsearch6.port_dst = port_dst; if ((result = (struct s_nat *) radixtree_lookup(nat_proto6, radixtree_chunker, &radixsearch6, sizeof(radixsearch6))) == NULL) { if (create > 0) { /* if no connection is found, let's create one */ if ((connection = (struct s_nat *) malloc(sizeof(struct s_nat))) == NULL) { log_error("Lack of free memory"); return NULL; } connection->mac = eth_src; connection->ipv6 = ipv6_src; connection->ipv4 = radixsearch6.ipv4; connection->ipv6_port_src = port_src; connection->ipv4_port_dst = port_dst; connection->state = 1; connection->llnode = NULL; radixsearch4.addr = radixsearch6.ipv4; radixsearch4.port_src = port_dst; radixsearch4.zeros = 0x0; /* generate some outgoing port */ do { /* returns port from range 1024 - 65535 */ radixsearch4.port_dst = (rand() % 64511) + 1024; 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_chunker, &radixsearch6, sizeof(radixsearch6), connection); radixtree_insert(nat_proto4, radixtree_chunker, &radixsearch4, sizeof(radixsearch4), connection); return connection; } else { return NULL; } } else { /* when connection is found, return it */ return result; } }