diff options
author | Alfredo Cardigliano <cardigliano@ntop.org> | 2021-02-23 10:01:56 +0100 |
---|---|---|
committer | Alfredo Cardigliano <cardigliano@ntop.org> | 2021-02-23 10:01:56 +0100 |
commit | f8e83f7e35ae76473d55359c250eed76c3cb6077 (patch) | |
tree | 6f4b1a14d1564e17ba25ac13e78dc6d98a04733e /src | |
parent | b757cf606b2e94f8e928f8abc2a6295d83352f12 (diff) |
Add support for MAC to Patricia tree. Expose full API to applications. Add utility functions.
Diffstat (limited to 'src')
-rw-r--r-- | src/include/ndpi_api.h.in | 21 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 31 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 126 | ||||
-rw-r--r-- | src/lib/third_party/include/ndpi_patricia.h | 69 | ||||
-rw-r--r-- | src/lib/third_party/src/ndpi_patricia.c | 197 |
5 files changed, 268 insertions, 176 deletions
diff --git a/src/include/ndpi_api.h.in b/src/include/ndpi_api.h.in index 33a795ea0..8446c9ca6 100644 --- a/src/include/ndpi_api.h.in +++ b/src/include/ndpi_api.h.in @@ -962,7 +962,26 @@ extern "C" { const char* ndpi_http_method2str(ndpi_http_method m); ndpi_http_method ndpi_http_str2method(const char* method, u_int16_t method_len); - /* ptree (trie) API */ + /* Utility functions to fill prefix (used by the patricia tree) */ + int ndpi_fill_prefix_v4(ndpi_prefix_t *p, const struct in_addr *a, int b, int mb); + int ndpi_fill_prefix_v6(ndpi_prefix_t *prefix, const struct in6_addr *addr, int bits, int maxbits); + int ndpi_fill_prefix_mac(ndpi_prefix_t *prefix, u_int8_t *mac, int bits, int maxbits); + + /* Patricia tree API (radix tree supporting IPv4/IPv6/MAC) */ + ndpi_patricia_tree_t *ndpi_patricia_new(u_int16_t maxbits); + ndpi_patricia_tree_t *ndpi_patricia_clone (const ndpi_patricia_tree_t * const from); + void ndpi_patricia_destroy(ndpi_patricia_tree_t *patricia, ndpi_void_fn_t func); + + ndpi_patricia_node_t *ndpi_patricia_search_exact(ndpi_patricia_tree_t *patricia, ndpi_prefix_t *prefix); + ndpi_patricia_node_t *ndpi_patricia_search_best(ndpi_patricia_tree_t *patricia, ndpi_prefix_t *prefix); + ndpi_patricia_node_t *ndpi_patricia_lookup(ndpi_patricia_tree_t *patricia, ndpi_prefix_t *prefix); + size_t ndpi_patricia_walk_inorder(ndpi_patricia_node_t *node, ndpi_void_fn2_t func); + void ndpi_patricia_remove(ndpi_patricia_tree_t *patricia, ndpi_patricia_node_t *node); + + void ndpi_patricia_set_node_u64(ndpi_patricia_node_t *node, u_int64_t value); + u_int64_t ndpi_patricia_get_node_u64(ndpi_patricia_node_t *node); + + /* ptree (trie) API - a wrapper on top of Patricia that seamlessly handle IPv4 and IPv6 */ ndpi_ptree_t* ndpi_ptree_create(void); int ndpi_ptree_insert(ndpi_ptree_t *tree, const ndpi_ip_addr_t *addr, u_int8_t bits, u_int64_t user_data); int ndpi_ptree_match_addr(ndpi_ptree_t *tree, const ndpi_ip_addr_t *addr, u_int64_t *user_data); diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index dd6e83e2b..d2579c0eb 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1574,6 +1574,37 @@ struct ndpi_jitter_struct { /* **************************************** */ +#ifndef WIN32 +#define NDPI_PATRICIA_IPV6 +#else +#undef NDPI_PATRICIA_IPV6 +#endif + +#ifndef AF_MAC +#define AF_MAC 99 +#endif + +typedef struct _ndpi_prefix_t { + u_int16_t family; /* AF_INET | AF_INET6 */ + u_int16_t bitlen; /* same as mask? */ + int ref_count; /* reference count */ + union { + struct in_addr sin; +#ifdef NDPI_PATRICIA_IPV6 + struct in6_addr sin6; +#endif /* IPV6 */ + u_int8_t mac[6]; + } add; +} ndpi_prefix_t; + +typedef void (*ndpi_void_fn_t)(void *data); +typedef void (*ndpi_void_fn2_t)(ndpi_prefix_t *prefix, void *data); + +typedef struct _ndpi_patricia_node_t ndpi_patricia_node_t; +typedef struct _ndpi_patricia_tree_t ndpi_patricia_tree_t; + +/* **************************************** */ + typedef struct ndpi_ptree ndpi_ptree_t; /* **************************************** */ diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index 8a27184e3..b866ed537 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -166,8 +166,8 @@ char *ndpi_strdup(const char *s) { /* Opaque structure defined here */ struct ndpi_ptree { - patricia_tree_t *v4; - patricia_tree_t *v6; + ndpi_patricia_tree_t *v4; + ndpi_patricia_tree_t *v6; }; /* *********************************************************************************** */ @@ -1660,11 +1660,11 @@ static int ac_match_handler(AC_MATCH_t *m, AC_TEXT_t *txt, AC_REP_t *match) { /* ******************************************************************** */ -static int fill_prefix_v4(prefix_t *p, const struct in_addr *a, int b, int mb) { +int ndpi_fill_prefix_v4(ndpi_prefix_t *p, const struct in_addr *a, int b, int mb) { if(b < 0 || b > mb) return(-1); - memset(p, 0, sizeof(prefix_t)); + memset(p, 0, sizeof(ndpi_prefix_t)); memcpy(&p->add.sin, a, (mb + 7) / 8); p->family = AF_INET; p->bitlen = b; @@ -1675,8 +1675,8 @@ static int fill_prefix_v4(prefix_t *p, const struct in_addr *a, int b, int mb) { /* ******************************************* */ -static int fill_prefix_v6(prefix_t *prefix, const struct in6_addr *addr, int bits, int maxbits) { -#ifdef PATRICIA_IPV6 +int ndpi_fill_prefix_v6(ndpi_prefix_t *prefix, const struct in6_addr *addr, int bits, int maxbits) { +#ifdef NDPI_PATRICIA_IPV6 if(bits < 0 || bits > maxbits) return -1; @@ -1691,6 +1691,30 @@ static int fill_prefix_v6(prefix_t *prefix, const struct in6_addr *addr, int bit /* ******************************************* */ +int ndpi_fill_prefix_mac(ndpi_prefix_t *prefix, u_int8_t *mac, int bits, int maxbits) { + if(bits < 0 || bits > maxbits) + return -1; + + memcpy(prefix->add.mac, mac, 6); + prefix->family = AF_MAC, prefix->bitlen = bits, prefix->ref_count = 0; + + return 0; +} + +/* ******************************************* */ + +void ndpi_patricia_set_node_u64(ndpi_patricia_node_t *node, u_int64_t value) { + node->value.u.uv64 = value; +} + +/* ******************************************* */ + +u_int64_t ndpi_patricia_get_node_u64(ndpi_patricia_node_t *node) { + return(node->value.u.uv64); +} + +/* ******************************************* */ + u_int8_t ndpi_is_public_ipv4(u_int32_t a /* host byte order */) { if( ((a & 0xFF000000) == 0x0A000000 /* 10.0.0.0/8 */) || ((a & 0xFFF00000) == 0xAC100000 /* 172.16.0.0/12 */) @@ -1707,8 +1731,8 @@ u_int8_t ndpi_is_public_ipv4(u_int32_t a /* host byte order */) { u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_str, struct in_addr *pin /* network byte order */) { - prefix_t prefix; - patricia_node_t *node; + ndpi_prefix_t prefix; + ndpi_patricia_node_t *node; if(ndpi_str->ndpi_num_custom_protocols == 0) { /* @@ -1724,7 +1748,7 @@ u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_str } /* Make sure all in network byte order otherwise compares wont work */ - fill_prefix_v4(&prefix, pin, 32, ((patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); + ndpi_fill_prefix_v4(&prefix, pin, 32, ((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); node = ndpi_patricia_search_best(ndpi_str->protocols_ptree, &prefix); return(node ? node->value.u.uv32.user_value : NDPI_PROTOCOL_UNKNOWN); @@ -1735,11 +1759,11 @@ u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_str u_int16_t ndpi_network_port_ptree_match(struct ndpi_detection_module_struct *ndpi_str, struct in_addr *pin /* network byte order */, u_int16_t port /* network byte order */) { - prefix_t prefix; - patricia_node_t *node; + ndpi_prefix_t prefix; + ndpi_patricia_node_t *node; /* Make sure all in network byte order otherwise compares wont work */ - fill_prefix_v4(&prefix, pin, 32, ((patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); + ndpi_fill_prefix_v4(&prefix, pin, 32, ((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); node = ndpi_patricia_search_best(ndpi_str->protocols_ptree, &prefix); if(node) { @@ -1776,11 +1800,11 @@ u_int8_t ndpi_is_tor_flow(struct ndpi_detection_module_struct *ndpi_str, struct /* ******************************************* */ -static patricia_node_t* add_to_ptree(patricia_tree_t *tree, int family, void *addr, int bits) { - prefix_t prefix; - patricia_node_t *node; +static ndpi_patricia_node_t* add_to_ptree(ndpi_patricia_tree_t *tree, int family, void *addr, int bits) { + ndpi_prefix_t prefix; + ndpi_patricia_node_t *node; - fill_prefix_v4(&prefix, (struct in_addr *) addr, bits, tree->maxbits); + ndpi_fill_prefix_v4(&prefix, (struct in_addr *) addr, bits, tree->maxbits); node = ndpi_patricia_lookup(tree, &prefix); if(node) memset(&node->value, 0, sizeof(node->value)); @@ -1825,7 +1849,7 @@ int ndpi_load_ipv4_ptree(struct ndpi_detection_module_struct *ndpi_str, if(addr) { struct in_addr pin; - patricia_node_t *node; + ndpi_patricia_node_t *node; cidr = strtok_r(NULL, "\n", &saveptr); @@ -1850,7 +1874,7 @@ static void ndpi_init_ptree_ipv4(struct ndpi_detection_module_struct *ndpi_str, for(i = 0; host_list[i].network != 0x0; i++) { struct in_addr pin; - patricia_node_t *node; + ndpi_patricia_node_t *node; if(skip_tor_hosts && (host_list[i].value == NDPI_PROTOCOL_TOR)) continue; @@ -1866,7 +1890,7 @@ static void ndpi_init_ptree_ipv4(struct ndpi_detection_module_struct *ndpi_str, static int ndpi_add_host_ip_subprotocol(struct ndpi_detection_module_struct *ndpi_str, char *value, u_int16_t protocol_id) { - patricia_node_t *node; + ndpi_patricia_node_t *node; struct in_addr pin; int bits = 32; char *ptr = strrchr(value, '/'); @@ -2111,7 +2135,7 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs } #endif - if((ndpi_str->protocols_ptree = ndpi_New_Patricia(32 /* IPv4 */)) != NULL) + if((ndpi_str->protocols_ptree = ndpi_patricia_new(32 /* IPv4 */)) != NULL) ndpi_init_ptree_ipv4(ndpi_str, ndpi_str->protocols_ptree, host_protocol_list, prefs & ndpi_dont_load_tor_hosts); NDPI_BITMASK_RESET(ndpi_str->detection_bitmask); @@ -2154,8 +2178,8 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs ndpi_str->custom_categories.hostnames.ac_automa = ac_automata_init(ac_match_handler); ndpi_str->custom_categories.hostnames_shadow.ac_automa = ac_automata_init(ac_match_handler); - ndpi_str->custom_categories.ipAddresses = ndpi_New_Patricia(32 /* IPv4 */); - ndpi_str->custom_categories.ipAddresses_shadow = ndpi_New_Patricia(32 /* IPv4 */); + ndpi_str->custom_categories.ipAddresses = ndpi_patricia_new(32 /* IPv4 */); + ndpi_str->custom_categories.ipAddresses_shadow = ndpi_patricia_new(32 /* IPv4 */); if((ndpi_str->custom_categories.ipAddresses == NULL) || (ndpi_str->custom_categories.ipAddresses_shadow == NULL)) { NDPI_LOG_ERR(ndpi_str, "[NDPI] Error allocating Patricia trees\n"); @@ -2389,11 +2413,11 @@ int ndpi_get_custom_category_match(struct ndpi_detection_module_struct *ndpi_str if(inet_pton(AF_INET, ipbuf, &pin) == 1) { /* Search IP */ - prefix_t prefix; - patricia_node_t *node; + ndpi_prefix_t prefix; + ndpi_patricia_node_t *node; /* Make sure all in network byte order otherwise compares wont work */ - fill_prefix_v4(&prefix, &pin, 32, ((patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); + ndpi_fill_prefix_v4(&prefix, &pin, 32, ((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); node = ndpi_patricia_search_best(ndpi_str->custom_categories.ipAddresses, &prefix); if(node) { @@ -2440,7 +2464,7 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) { ndpi_lru_free_cache(ndpi_str->msteams_cache); if(ndpi_str->protocols_ptree) - ndpi_Destroy_Patricia((patricia_tree_t *) ndpi_str->protocols_ptree, free_ptree_data); + ndpi_patricia_destroy((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree, free_ptree_data); if(ndpi_str->udpRoot != NULL) ndpi_tdestroy(ndpi_str->udpRoot, ndpi_free); @@ -2478,10 +2502,10 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) { 1 /* free patterns strings memory */); if(ndpi_str->custom_categories.ipAddresses != NULL) - ndpi_Destroy_Patricia((patricia_tree_t *) ndpi_str->custom_categories.ipAddresses, free_ptree_data); + ndpi_patricia_destroy((ndpi_patricia_tree_t *) ndpi_str->custom_categories.ipAddresses, free_ptree_data); if(ndpi_str->custom_categories.ipAddresses_shadow != NULL) - ndpi_Destroy_Patricia((patricia_tree_t *) ndpi_str->custom_categories.ipAddresses_shadow, free_ptree_data); + ndpi_patricia_destroy((ndpi_patricia_tree_t *) ndpi_str->custom_categories.ipAddresses_shadow, free_ptree_data); #ifdef CUSTOM_NDPI_PROTOCOLS #include "../../../nDPI-custom/ndpi_exit_detection_module.c" @@ -4618,7 +4642,7 @@ uint8_t ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, int ndpi_load_ip_category(struct ndpi_detection_module_struct *ndpi_str, const char *ip_address_and_mask, ndpi_protocol_category_t category) { - patricia_node_t *node; + ndpi_patricia_node_t *node; struct in_addr pin; int bits = 32; char *ptr; @@ -4734,10 +4758,10 @@ uint8_t ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, ndpi_str->custom_categories.hostnames_shadow.ac_automa = ac_automata_init(ac_match_handler); if(ndpi_str->custom_categories.ipAddresses != NULL) - ndpi_Destroy_Patricia((patricia_tree_t *) ndpi_str->custom_categories.ipAddresses, free_ptree_data); + ndpi_patricia_destroy((ndpi_patricia_tree_t *) ndpi_str->custom_categories.ipAddresses, free_ptree_data); ndpi_str->custom_categories.ipAddresses = ndpi_str->custom_categories.ipAddresses_shadow; - ndpi_str->custom_categories.ipAddresses_shadow = ndpi_New_Patricia(32 /* IPv4 */); + ndpi_str->custom_categories.ipAddresses_shadow = ndpi_patricia_new(32 /* IPv4 */); ndpi_str->custom_categories.categories_loaded = 1; @@ -4749,22 +4773,22 @@ uint8_t ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, int ndpi_fill_ip_protocol_category(struct ndpi_detection_module_struct *ndpi_str, u_int32_t saddr, u_int32_t daddr, ndpi_protocol *ret) { if(ndpi_str->custom_categories.categories_loaded) { - prefix_t prefix; - patricia_node_t *node; + ndpi_prefix_t prefix; + ndpi_patricia_node_t *node; if(saddr == 0) node = NULL; else { /* Make sure all in network byte order otherwise compares wont work */ - fill_prefix_v4(&prefix, (struct in_addr *) &saddr, 32, - ((patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); + ndpi_fill_prefix_v4(&prefix, (struct in_addr *) &saddr, 32, + ((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); node = ndpi_patricia_search_best(ndpi_str->custom_categories.ipAddresses, &prefix); } if(!node) { if(daddr != 0) { - fill_prefix_v4(&prefix, (struct in_addr *) &daddr, 32, - ((patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); + ndpi_fill_prefix_v4(&prefix, (struct in_addr *) &daddr, 32, + ((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); node = ndpi_patricia_search_best(ndpi_str->custom_categories.ipAddresses, &prefix); } } @@ -6950,8 +6974,8 @@ uint8_t ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, ndpi_ptree_t *tree = (ndpi_ptree_t *) ndpi_malloc(sizeof(ndpi_ptree_t)); if(tree) { - tree->v4 = ndpi_New_Patricia(32); - tree->v6 = ndpi_New_Patricia(128); + tree->v4 = ndpi_patricia_new(32); + tree->v6 = ndpi_patricia_new(128); if((!tree->v4) || (!tree->v6)) { ndpi_ptree_destroy(tree); @@ -6967,9 +6991,9 @@ uint8_t ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, void ndpi_ptree_destroy(ndpi_ptree_t *tree) { if(tree) { if(tree->v4) - ndpi_Destroy_Patricia(tree->v4, free_ptree_data); + ndpi_patricia_destroy(tree->v4, free_ptree_data); if(tree->v6) - ndpi_Destroy_Patricia(tree->v6, free_ptree_data); + ndpi_patricia_destroy(tree->v6, free_ptree_data); ndpi_free(tree); } @@ -6980,17 +7004,17 @@ uint8_t ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, int ndpi_ptree_insert(ndpi_ptree_t *tree, const ndpi_ip_addr_t *addr, u_int8_t bits, u_int64_t user_data) { u_int8_t is_v6 = ndpi_is_ipv6(addr); - patricia_tree_t *ptree = is_v6 ? tree->v6 : tree->v4; - prefix_t prefix; - patricia_node_t *node; + ndpi_patricia_tree_t *ptree = is_v6 ? tree->v6 : tree->v4; + ndpi_prefix_t prefix; + ndpi_patricia_node_t *node; if(bits > ptree->maxbits) return(-1); if(is_v6) - fill_prefix_v6(&prefix, (const struct in6_addr *) &addr->ipv6, bits, ptree->maxbits); + ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *) &addr->ipv6, bits, ptree->maxbits); else - fill_prefix_v4(&prefix, (const struct in_addr *) &addr->ipv4, bits, ptree->maxbits); + ndpi_fill_prefix_v4(&prefix, (const struct in_addr *) &addr->ipv4, bits, ptree->maxbits); /* Verify that the node does not already exist */ node = ndpi_patricia_search_best(ptree, &prefix); @@ -7014,15 +7038,15 @@ uint8_t ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, int ndpi_ptree_match_addr(ndpi_ptree_t *tree, const ndpi_ip_addr_t *addr, u_int64_t *user_data) { u_int8_t is_v6 = ndpi_is_ipv6(addr); - patricia_tree_t *ptree = is_v6 ? tree->v6 : tree->v4; - prefix_t prefix; - patricia_node_t *node; + ndpi_patricia_tree_t *ptree = is_v6 ? tree->v6 : tree->v4; + ndpi_prefix_t prefix; + ndpi_patricia_node_t *node; int bits = ptree->maxbits; if(is_v6) - fill_prefix_v6(&prefix, (const struct in6_addr *) &addr->ipv6, bits, ptree->maxbits); + ndpi_fill_prefix_v6(&prefix, (const struct in6_addr *) &addr->ipv6, bits, ptree->maxbits); else - fill_prefix_v4(&prefix, (const struct in_addr *) &addr->ipv4, bits, ptree->maxbits); + ndpi_fill_prefix_v4(&prefix, (const struct in_addr *) &addr->ipv4, bits, ptree->maxbits); node = ndpi_patricia_search_best(ptree, &prefix); diff --git a/src/lib/third_party/include/ndpi_patricia.h b/src/lib/third_party/include/ndpi_patricia.h index 4e9bbe483..a8478986e 100644 --- a/src/lib/third_party/include/ndpi_patricia.h +++ b/src/lib/third_party/include/ndpi_patricia.h @@ -41,15 +41,11 @@ #ifndef _NDPI_PATRICIA_H #define _NDPI_PATRICIA_H -#ifndef WIN32 -#define PATRICIA_IPV6 HAVE_IPV6 -#else -#undef PATRICIA_IPV6 -#endif +#include "ndpi_api.h" /* typedef unsigned int u_int; */ /* { from defs.h */ -#define prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin) +#define ndpi_prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin) #define MAXLINE 1024 @@ -80,25 +76,13 @@ /* { from mrt.h */ -typedef struct the_prefix4_t { +typedef struct _prefix4_t { u_int16_t family; /* AF_INET | AF_INET6 */ u_int16_t bitlen; /* same as mask? */ int ref_count; /* reference count */ struct in_addr sin; } prefix4_t; -typedef struct the_prefix_t { - u_int16_t family; /* AF_INET | AF_INET6 */ - u_int16_t bitlen; /* same as mask? */ - int ref_count; /* reference count */ - union { - struct in_addr sin; -#ifdef PATRICIA_IPV6 - struct in6_addr sin6; -#endif /* IPV6 */ - } add; -} prefix_t; - /* } */ /* pointer to usr data (ex. route flap info) */ @@ -115,35 +99,20 @@ union patricia_node_value_t { } u; }; -typedef struct _patricia_node_t { +typedef struct _ndpi_patricia_node_t { u_int16_t bit; /* flag if this node used */ - prefix_t *prefix; /* who we are in patricia tree */ - struct _patricia_node_t *l, *r; /* left and right children */ - struct _patricia_node_t *parent;/* may be used */ + ndpi_prefix_t *prefix; /* who we are in patricia tree */ + struct _ndpi_patricia_node_t *l, *r; /* left and right children */ + struct _ndpi_patricia_node_t *parent;/* may be used */ void *data; /* pointer to data */ union patricia_node_value_t value; -} patricia_node_t; +} ndpi_patricia_node_t; -typedef struct _patricia_tree_t { - patricia_node_t *head; +typedef struct _ndpi_patricia_tree_t { + ndpi_patricia_node_t *head; u_int16_t maxbits; /* for IP, 32 bit addresses */ int num_active_node; /* for debug purpose */ -} patricia_tree_t; - -typedef void (*void_fn_t)(void *data); -typedef void (*void_fn2_t)(prefix_t *prefix, void *data); - -/* renamed to ndpi_Patricia to avoid name conflicts */ -patricia_node_t *ndpi_patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix); -patricia_node_t *ndpi_patricia_search_best (patricia_tree_t *patricia, prefix_t *prefix); -patricia_node_t * ndpi_patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, - int inclusive); -patricia_node_t *ndpi_patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix); -void ndpi_patricia_remove (patricia_tree_t *patricia, patricia_node_t *node); -patricia_tree_t *ndpi_New_Patricia (u_int16_t maxbits); -void ndpi_Clear_Patricia (patricia_tree_t *patricia, void_fn_t func); -void ndpi_Destroy_Patricia (patricia_tree_t *patricia, void_fn_t func); -void ndpi_patricia_process (patricia_tree_t *patricia, void_fn2_t func); +} ndpi_patricia_tree_t; #ifdef WIN32 #define PATRICIA_MAXBITS 128 @@ -158,17 +127,17 @@ void ndpi_patricia_process (patricia_tree_t *patricia, void_fn2_t func); #define PATRICIA_WALK(Xhead, Xnode) \ do { \ - patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \ - patricia_node_t **Xsp = Xstack; \ - patricia_node_t *Xrn = (Xhead); \ + ndpi_patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \ + ndpi_patricia_node_t **Xsp = Xstack; \ + ndpi_patricia_node_t *Xrn = (Xhead); \ while ((Xnode = Xrn)) { \ if (Xnode->prefix) #define PATRICIA_WALK_ALL(Xhead, Xnode) \ do { \ - patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \ - patricia_node_t **Xsp = Xstack; \ - patricia_node_t *Xrn = (Xhead); \ + ndpi_patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \ + ndpi_patricia_node_t **Xsp = Xstack; \ + ndpi_patricia_node_t *Xrn = (Xhead); \ while ((Xnode = Xrn)) { \ if (1) @@ -176,7 +145,7 @@ void ndpi_patricia_process (patricia_tree_t *patricia, void_fn2_t func); if (Xsp != Xstack) { \ Xrn = *(--Xsp); \ } else { \ - Xrn = (patricia_node_t *) 0; \ + Xrn = (ndpi_patricia_node_t *) 0; \ } \ continue; } @@ -191,7 +160,7 @@ void ndpi_patricia_process (patricia_tree_t *patricia, void_fn2_t func); } else if (Xsp != Xstack) { \ Xrn = *(--Xsp); \ } else { \ - Xrn = (patricia_node_t *) 0; \ + Xrn = (ndpi_patricia_node_t *) 0; \ } \ } \ } while (0) diff --git a/src/lib/third_party/src/ndpi_patricia.c b/src/lib/third_party/src/ndpi_patricia.c index 139c17676..c0da14da3 100644 --- a/src/lib/third_party/src/ndpi_patricia.c +++ b/src/lib/third_party/src/ndpi_patricia.c @@ -54,7 +54,6 @@ #include <arpa/inet.h> /* BSD, Linux, Solaris: for inet_addr */ #endif #include "ndpi_patricia.h" -#include "ndpi_api.h" static void ndpi_DeleteEntry(void *a) { ndpi_free(a); @@ -65,11 +64,19 @@ static void ndpi_DeleteEntry(void *a) { /* ndpi_prefix_tochar * convert prefix information to bytes */ -static u_char* ndpi_prefix_tochar (prefix_t * prefix) +static u_char* ndpi_prefix_tochar (ndpi_prefix_t * prefix) { + unsigned short family; + if(prefix == NULL) return (NULL); + family = prefix->family; + + if(family == AF_INET) return ((u_char *) & prefix->add.sin); + else if(family == AF_INET6) return ((u_char *) & prefix->add.sin6); + else /* if(family == AF_MAC) */ return ((u_char *) & prefix->add.mac); + return ((u_char *) & prefix->add.sin); } @@ -115,10 +122,10 @@ static int ndpi_my_inet_pton (int af, const char *src, void *dst) } memcpy (dst, xp, sizeof(struct in_addr)); return (1); -#if defined(PATRICIA_IPV6) +#if defined(NDPI_PATRICIA_IPV6) } else if(af == AF_INET6) { return (inet_pton (af, src, dst)); -#endif /* PATRICIA_IPV6 */ +#endif /* NDPI_PATRICIA_IPV6 */ } else { #ifndef NT errno = EAFNOSUPPORT; @@ -135,7 +142,7 @@ static int ndpi_my_inet_pton (int af, const char *src, void *dst) * convert prefix information to ascii string with length * thread safe and (almost) re-entrant implementation */ -static char * ndpi_prefix_toa2x (prefix_t *prefix, char *buff, int with_len) +static char * ndpi_prefix_toa2x (ndpi_prefix_t *prefix, char *buff, int with_len) { if(prefix == NULL) return ((char*)"(Null)"); @@ -165,7 +172,7 @@ static char * ndpi_prefix_toa2x (prefix_t *prefix, char *buff, int with_len) if(prefix->family == AF_INET) { u_char *a; assert (prefix->bitlen <= sizeof(struct in_addr) * 8); - a = prefix_touchar (prefix); + a = ndpi_prefix_touchar (prefix); if(with_len) { sprintf (buff, "%d.%d.%d.%d/%d", a[0], a[1], a[2], a[3], prefix->bitlen); @@ -175,7 +182,7 @@ static char * ndpi_prefix_toa2x (prefix_t *prefix, char *buff, int with_len) } return (buff); } -#if defined(PATRICIA_IPV6) +#if defined(NDPI_PATRICIA_IPV6) else if(prefix->family == AF_INET6) { char *r; r = (char *) inet_ntop (AF_INET6, &prefix->add.sin6, buff, 48 /* a guess value */ ); @@ -185,7 +192,7 @@ static char * ndpi_prefix_toa2x (prefix_t *prefix, char *buff, int with_len) } return (buff); } -#endif /* PATRICIA_IPV6 */ +#endif /* NDPI_PATRICIA_IPV6 */ else return (NULL); } @@ -193,43 +200,43 @@ static char * ndpi_prefix_toa2x (prefix_t *prefix, char *buff, int with_len) /* ndpi_prefix_toa2 * convert prefix information to ascii string */ -static char * ndpi_prefix_toa2 (prefix_t *prefix, char *buff) +static char * ndpi_prefix_toa2 (ndpi_prefix_t *prefix, char *buff) { return (ndpi_prefix_toa2x (prefix, buff, 0)); } /* ndpi_prefix_toa */ -static char * ndpi_prefix_toa (prefix_t * prefix) +static char * ndpi_prefix_toa (ndpi_prefix_t * prefix) { return (ndpi_prefix_toa2 (prefix, (char *) NULL)); } #endif -static prefix_t * ndpi_New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix) +static ndpi_prefix_t * ndpi_New_Prefix2 (int family, void *dest, int bitlen, ndpi_prefix_t *prefix) { int dynamic_allocated = 0; int default_bitlen = sizeof(struct in_addr) * 8; -#if defined(PATRICIA_IPV6) +#if defined(NDPI_PATRICIA_IPV6) if(family == AF_INET6) { default_bitlen = sizeof(struct in6_addr) * 8; if(prefix == NULL) { - prefix = (prefix_t*)ndpi_calloc(1, sizeof (prefix_t)); + prefix = (ndpi_prefix_t*)ndpi_calloc(1, sizeof (ndpi_prefix_t)); dynamic_allocated++; } memcpy (&prefix->add.sin6, dest, sizeof(struct in6_addr)); } else -#endif /* PATRICIA_IPV6 */ +#endif /* NDPI_PATRICIA_IPV6 */ if(family == AF_INET) { if(prefix == NULL) { #ifndef NT - prefix = (prefix_t*)ndpi_calloc(1, sizeof (prefix4_t)); + prefix = (ndpi_prefix_t*)ndpi_calloc(1, sizeof (prefix4_t)); #else //for some reason, compiler is getting //prefix4_t size incorrect on NT - prefix = ndpi_calloc(1, sizeof (prefix_t)); + prefix = ndpi_calloc(1, sizeof (ndpi_prefix_t)); #endif /* NT */ dynamic_allocated++; @@ -251,14 +258,14 @@ static prefix_t * ndpi_New_Prefix2 (int family, void *dest, int bitlen, prefix_t } #if 0 -static prefix_t * ndpi_New_Prefix (int family, void *dest, int bitlen) +static ndpi_prefix_t * ndpi_New_Prefix (int family, void *dest, int bitlen) { return (ndpi_New_Prefix2 (family, dest, bitlen, NULL)); } #endif -static prefix_t * -ndpi_Ref_Prefix (prefix_t * prefix) +static ndpi_prefix_t * +ndpi_Ref_Prefix (ndpi_prefix_t * prefix) { if(prefix == NULL) return (NULL); @@ -272,7 +279,7 @@ ndpi_Ref_Prefix (prefix_t * prefix) } static void -ndpi_Deref_Prefix (prefix_t * prefix) +ndpi_Deref_Prefix (ndpi_prefix_t * prefix) { if(prefix == NULL) return; @@ -293,10 +300,10 @@ static int num_active_patricia = 0; /* these routines support continuous mask only */ -patricia_tree_t * -ndpi_New_Patricia (u_int16_t maxbits) +ndpi_patricia_tree_t * +ndpi_patricia_new (u_int16_t maxbits) { - patricia_tree_t *patricia = (patricia_tree_t*)ndpi_calloc(1, sizeof *patricia); + ndpi_patricia_tree_t *patricia = (ndpi_patricia_tree_t*)ndpi_calloc(1, sizeof *patricia); patricia->maxbits = maxbits; patricia->head = NULL; @@ -312,18 +319,18 @@ ndpi_New_Patricia (u_int16_t maxbits) * before deleting the node */ void -ndpi_Clear_Patricia (patricia_tree_t *patricia, void_fn_t func) +ndpi_Clear_Patricia (ndpi_patricia_tree_t *patricia, ndpi_void_fn_t func) { assert (patricia); if(patricia->head) { - patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; - patricia_node_t **Xsp = Xstack; - patricia_node_t *Xrn = patricia->head; + ndpi_patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; + ndpi_patricia_node_t **Xsp = Xstack; + ndpi_patricia_node_t *Xrn = patricia->head; while (Xrn) { - patricia_node_t *l = Xrn->l; - patricia_node_t *r = Xrn->r; + ndpi_patricia_node_t *l = Xrn->l; + ndpi_patricia_node_t *r = Xrn->r; if(Xrn->prefix) { ndpi_Deref_Prefix (Xrn->prefix); @@ -354,9 +361,8 @@ ndpi_Clear_Patricia (patricia_tree_t *patricia, void_fn_t func) /* ndpi_DeleteEntry (patricia); */ } - void -ndpi_Destroy_Patricia (patricia_tree_t *patricia, void_fn_t func) +ndpi_patricia_destroy (ndpi_patricia_tree_t *patricia, ndpi_void_fn_t func) { ndpi_Clear_Patricia (patricia, func); ndpi_DeleteEntry (patricia); @@ -368,9 +374,9 @@ ndpi_Destroy_Patricia (patricia_tree_t *patricia, void_fn_t func) * if func is supplied, it will be called as func(node->prefix, node->data) */ void -ndpi_patricia_process (patricia_tree_t *patricia, void_fn2_t func) +ndpi_patricia_process (ndpi_patricia_tree_t *patricia, ndpi_void_fn2_t func) { - patricia_node_t *node; + ndpi_patricia_node_t *node; assert (func); PATRICIA_WALK (patricia->head, node) { @@ -378,8 +384,51 @@ ndpi_patricia_process (patricia_tree_t *patricia, void_fn2_t func) } PATRICIA_WALK_END; } +static size_t +ndpi_patricia_clone_walk(ndpi_patricia_node_t *node, ndpi_patricia_tree_t *dst) +{ + ndpi_patricia_node_t *cloned_node; + size_t n = 0; + + if(node->l) { + n += ndpi_patricia_clone_walk(node->l, dst); + } + + if(node->prefix) { + cloned_node = ndpi_patricia_lookup(dst, node->prefix); + + if(cloned_node) { + /* Note: this is not cloning clone referenced void * data / user_data */ + memcpy(&cloned_node->value, &node->value, sizeof(cloned_node->value)); + } + + n++; + } + + if(node->r) { + n += ndpi_patricia_clone_walk(node->r, dst); + } + + return n; +} + +ndpi_patricia_tree_t * +ndpi_patricia_clone (const ndpi_patricia_tree_t * const from) +{ + if(!from) return (NULL); + + ndpi_patricia_tree_t *patricia = ndpi_patricia_new(from->maxbits); + + if(!patricia) return (NULL); + + if(from->head) + ndpi_patricia_clone_walk(from->head, patricia); + + return (patricia); +} + size_t -ndpi_patricia_walk_inorder(patricia_node_t *node, void_fn2_t func) +ndpi_patricia_walk_inorder(ndpi_patricia_node_t *node, ndpi_void_fn2_t func) { size_t n = 0; assert(func); @@ -401,10 +450,10 @@ ndpi_patricia_walk_inorder(patricia_node_t *node, void_fn2_t func) } -patricia_node_t * -ndpi_patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) +ndpi_patricia_node_t * +ndpi_patricia_search_exact (ndpi_patricia_tree_t *patricia, ndpi_prefix_t *prefix) { - patricia_node_t *node; + ndpi_patricia_node_t *node; u_char *addr; u_int16_t bitlen; @@ -416,7 +465,7 @@ ndpi_patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) return (NULL); node = patricia->head; - addr = prefix_touchar (prefix); + addr = ndpi_prefix_touchar (prefix); bitlen = prefix->bitlen; while (node->bit < bitlen) { @@ -474,11 +523,11 @@ ndpi_patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix) /* if inclusive != 0, "best" may be the given prefix itself */ -patricia_node_t * -ndpi_patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusive) +ndpi_patricia_node_t * +ndpi_patricia_search_best2 (ndpi_patricia_tree_t *patricia, ndpi_prefix_t *prefix, int inclusive) { - patricia_node_t *node; - patricia_node_t *stack[PATRICIA_MAXBITS + 1]; + ndpi_patricia_node_t *node; + ndpi_patricia_node_t *stack[PATRICIA_MAXBITS + 1]; u_char *addr; u_int16_t bitlen; int cnt = 0; @@ -491,7 +540,7 @@ ndpi_patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inc return (NULL); node = patricia->head; - addr = prefix_touchar (prefix); + addr = ndpi_prefix_touchar (prefix); bitlen = prefix->bitlen; while (node->bit < bitlen) { @@ -571,17 +620,17 @@ ndpi_patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inc } -patricia_node_t * -ndpi_patricia_search_best (patricia_tree_t *patricia, prefix_t *prefix) +ndpi_patricia_node_t * +ndpi_patricia_search_best (ndpi_patricia_tree_t *patricia, ndpi_prefix_t *prefix) { return (ndpi_patricia_search_best2 (patricia, prefix, 1)); } -patricia_node_t * -ndpi_patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) +ndpi_patricia_node_t * +ndpi_patricia_lookup (ndpi_patricia_tree_t *patricia, ndpi_prefix_t *prefix) { - patricia_node_t *node, *new_node, *parent, *glue; + ndpi_patricia_node_t *node, *new_node, *parent, *glue; u_char *addr, *test_addr; u_int16_t bitlen, check_bit, differ_bit; int i, j; @@ -596,7 +645,7 @@ ndpi_patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) assert (prefix->bitlen <= patricia->maxbits); if(patricia->head == NULL) { - node = (patricia_node_t*)ndpi_calloc(1, sizeof *node); + node = (ndpi_patricia_node_t*)ndpi_calloc(1, sizeof *node); node->bit = prefix->bitlen; node->prefix = ndpi_Ref_Prefix (prefix); node->parent = NULL; @@ -611,7 +660,7 @@ ndpi_patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) return (node); } - addr = prefix_touchar (prefix); + addr = ndpi_prefix_touchar (prefix); bitlen = prefix->bitlen; node = patricia->head; @@ -651,7 +700,7 @@ ndpi_patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) ndpi_prefix_toa (node->prefix), node->prefix->bitlen); #endif /* PATRICIA_DEBUG */ - test_addr = prefix_touchar (node->prefix); + test_addr = ndpi_prefix_touchar (node->prefix); /* find the first bit different */ check_bit = (node->bit < bitlen)? node->bit: bitlen; differ_bit = 0; @@ -709,7 +758,7 @@ ndpi_patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) return (node); } - new_node = (patricia_node_t*)ndpi_calloc(1, sizeof *new_node); + new_node = (ndpi_patricia_node_t*)ndpi_calloc(1, sizeof *new_node); if(!new_node) return NULL; new_node->bit = prefix->bitlen; new_node->prefix = ndpi_Ref_Prefix (prefix); @@ -762,7 +811,7 @@ ndpi_patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) #endif /* PATRICIA_DEBUG */ } else { - glue = (patricia_node_t*)ndpi_calloc(1, sizeof *glue); + glue = (ndpi_patricia_node_t*)ndpi_calloc(1, sizeof *glue); if(!glue) return(NULL); glue->bit = differ_bit; @@ -802,9 +851,9 @@ ndpi_patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix) void -ndpi_patricia_remove (patricia_tree_t *patricia, patricia_node_t *node) +ndpi_patricia_remove (ndpi_patricia_tree_t *patricia, ndpi_patricia_node_t *node) { - patricia_node_t *parent, *child; + ndpi_patricia_node_t *parent, *child; assert (patricia); assert (node); @@ -910,15 +959,15 @@ ndpi_patricia_remove (patricia_tree_t *patricia, patricia_node_t *node) #if 0 /* ndpi_ascii2prefix */ -static prefix_t * ndpi_ascii2prefix (int family, char *string) +static ndpi_prefix_t * ndpi_ascii2prefix (int family, char *string) { long bitlen; long maxbitlen = 0; char *cp; struct in_addr sin; -#if defined(PATRICIA_IPV6) +#if defined(NDPI_PATRICIA_IPV6) struct in6_addr sin6; -#endif /* PATRICIA_IPV6 */ +#endif /* NDPI_PATRICIA_IPV6 */ char save[MAXLINE]; if(string == NULL) @@ -927,19 +976,19 @@ static prefix_t * ndpi_ascii2prefix (int family, char *string) /* easy way to handle both families */ if(family == 0) { family = AF_INET; -#if defined(PATRICIA_IPV6) +#if defined(NDPI_PATRICIA_IPV6) if(strchr (string, ':')) family = AF_INET6; -#endif /* PATRICIA_IPV6 */ +#endif /* NDPI_PATRICIA_IPV6 */ } if(family == AF_INET) { maxbitlen = sizeof(struct in_addr) * 8; } -#if defined(PATRICIA_IPV6) +#if defined(NDPI_PATRICIA_IPV6) else if(family == AF_INET6) { maxbitlen = sizeof(struct in6_addr) * 8; } -#endif /* PATRICIA_IPV6 */ +#endif /* NDPI_PATRICIA_IPV6 */ if((cp = strchr (string, '/')) != NULL) { bitlen = atol (cp + 1); @@ -961,7 +1010,7 @@ static prefix_t * ndpi_ascii2prefix (int family, char *string) return (ndpi_New_Prefix (AF_INET, &sin, bitlen)); } -#if defined(PATRICIA_IPV6) +#if defined(NDPI_PATRICIA_IPV6) else if(family == AF_INET6) { // Get rid of this with next IPv6 upgrade #if defined(NT) && !defined(HAVE_INET_NTOP) @@ -973,16 +1022,16 @@ static prefix_t * ndpi_ascii2prefix (int family, char *string) #endif /* NT */ return (ndpi_New_Prefix (AF_INET6, &sin6, bitlen)); } -#endif /* PATRICIA_IPV6 */ +#endif /* NDPI_PATRICIA_IPV6 */ else return (NULL); } -patricia_node_t * -ndpi_make_and_lookup (patricia_tree_t *tree, char *string) +ndpi_patricia_node_t * +ndpi_make_and_lookup (ndpi_patricia_tree_t *tree, char *string) { - prefix_t *prefix; - patricia_node_t *node; + ndpi_prefix_t *prefix; + ndpi_patricia_node_t *node; prefix = ndpi_ascii2prefix (AF_INET, string); printf ("make_and_lookup: %s/%d\n", ndpi_prefix_toa (prefix), prefix->bitlen); @@ -991,11 +1040,11 @@ ndpi_make_and_lookup (patricia_tree_t *tree, char *string) return (node); } -patricia_node_t * -ndpi_try_search_exact (patricia_tree_t *tree, char *string) +ndpi_patricia_node_t * +ndpi_try_search_exact (ndpi_patricia_tree_t *tree, char *string) { - prefix_t *prefix; - patricia_node_t *node; + ndpi_prefix_t *prefix; + ndpi_patricia_node_t *node; prefix = ndpi_ascii2prefix (AF_INET, string); printf ("try_search_exact: %s/%d\n", ndpi_prefix_toa (prefix), prefix->bitlen); @@ -1011,9 +1060,9 @@ ndpi_try_search_exact (patricia_tree_t *tree, char *string) } void -ndpi_lookup_then_remove (patricia_tree_t *tree, char *string) +ndpi_lookup_then_remove (ndpi_patricia_tree_t *tree, char *string) { - patricia_node_t *node; + ndpi_patricia_node_t *node; if((node = try_search_exact (tree, string))) patricia_remove (tree, node); |