diff options
-rw-r--r-- | dependencies/nDPIsrvd.py | 4 | ||||
-rwxr-xr-x | examples/py-flow-info/flow-info.py | 1 | ||||
-rwxr-xr-x | examples/py-flow-undetected-to-pcap/flow-undetected-to-pcap.py | 1 | ||||
-rwxr-xr-x | examples/py-json-stdout/json-stdout.py | 1 | ||||
-rwxr-xr-x | examples/py-risky-flow-to-pcap/risky-flow-to-pcap.py | 1 | ||||
-rwxr-xr-x | examples/py-schema-validation/py-schema-validation.py | 1 | ||||
-rw-r--r-- | nDPId.c | 410 | ||||
-rwxr-xr-x | test/run_tests.sh | 19 |
8 files changed, 285 insertions, 153 deletions
diff --git a/dependencies/nDPIsrvd.py b/dependencies/nDPIsrvd.py index d8cccc266..643a1a7e5 100644 --- a/dependencies/nDPIsrvd.py +++ b/dependencies/nDPIsrvd.py @@ -349,12 +349,14 @@ def defaultArgumentParser(): return parser def validateAddress(args): + tcp_addr_set = False address = None if args.host is None: address_tcpip = (DEFAULT_HOST, DEFAULT_PORT) else: address_tcpip = (args.host, args.port) + tcp_addr_set = True if args.unix is None: address_unix = DEFAULT_UNIX @@ -366,7 +368,7 @@ def validateAddress(args): possible_sock_mode = os.stat(address_unix).st_mode except: pass - if stat.S_ISSOCK(possible_sock_mode): + if tcp_addr_set == False and stat.S_ISSOCK(possible_sock_mode): address = address_unix else: address = address_tcpip diff --git a/examples/py-flow-info/flow-info.py b/examples/py-flow-info/flow-info.py index 6f90ec7fa..acb811f65 100755 --- a/examples/py-flow-info/flow-info.py +++ b/examples/py-flow-info/flow-info.py @@ -3,6 +3,7 @@ import os import sys +sys.path.append(os.path.dirname(sys.argv[0]) + '/../share/nDPId') sys.path.append(os.path.dirname(sys.argv[0]) + '/../usr/share/nDPId') try: import nDPIsrvd diff --git a/examples/py-flow-undetected-to-pcap/flow-undetected-to-pcap.py b/examples/py-flow-undetected-to-pcap/flow-undetected-to-pcap.py index e5636312f..fcefe847f 100755 --- a/examples/py-flow-undetected-to-pcap/flow-undetected-to-pcap.py +++ b/examples/py-flow-undetected-to-pcap/flow-undetected-to-pcap.py @@ -3,6 +3,7 @@ import os import sys +sys.path.append(os.path.dirname(sys.argv[0]) + '/../share/nDPId') sys.path.append(os.path.dirname(sys.argv[0]) + '/../usr/share/nDPId') try: import nDPIsrvd diff --git a/examples/py-json-stdout/json-stdout.py b/examples/py-json-stdout/json-stdout.py index 8200bf12b..9693ecef6 100755 --- a/examples/py-json-stdout/json-stdout.py +++ b/examples/py-json-stdout/json-stdout.py @@ -3,6 +3,7 @@ import os import sys +sys.path.append(os.path.dirname(sys.argv[0]) + '/../share/nDPId') sys.path.append(os.path.dirname(sys.argv[0]) + '/../usr/share/nDPId') try: import nDPIsrvd diff --git a/examples/py-risky-flow-to-pcap/risky-flow-to-pcap.py b/examples/py-risky-flow-to-pcap/risky-flow-to-pcap.py index 42004eebe..cdf4257c1 100755 --- a/examples/py-risky-flow-to-pcap/risky-flow-to-pcap.py +++ b/examples/py-risky-flow-to-pcap/risky-flow-to-pcap.py @@ -4,6 +4,7 @@ import base64 import os import sys +sys.path.append(os.path.dirname(sys.argv[0]) + '/../share/nDPId') sys.path.append(os.path.dirname(sys.argv[0]) + '/../usr/share/nDPId') try: import nDPIsrvd diff --git a/examples/py-schema-validation/py-schema-validation.py b/examples/py-schema-validation/py-schema-validation.py index e8fc390f1..defba96e9 100755 --- a/examples/py-schema-validation/py-schema-validation.py +++ b/examples/py-schema-validation/py-schema-validation.py @@ -3,6 +3,7 @@ import os import sys +sys.path.append(os.path.dirname(sys.argv[0]) + '/../share/nDPId') sys.path.append(os.path.dirname(sys.argv[0]) + '/../usr/share/nDPId') try: import nDPIsrvd @@ -26,8 +26,8 @@ #define UNIX_PATH_MAX 108 #endif -#if ((NDPI_MAJOR == 3 && NDPI_MINOR < 6) || NDPI_MAJOR < 3) && NDPI_API_VERSION < 4087 -#error "nDPI >= 3.6.0 or API version >= 4087 required" +#if ((NDPI_MAJOR == 3 && NDPI_MINOR < 5) || NDPI_MAJOR < 3) && NDPI_API_VERSION < 4087 +#error "nDPI >= 3.5.0 or API version >= 4087 required" #endif #if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) @@ -47,7 +47,10 @@ union nDPId_ip { } v4; struct { - uint64_t ip6[2]; + union { + uint64_t ip[2]; + uint32_t ip_u32[4]; + }; } v6; }; @@ -253,6 +256,7 @@ static char const * const daemon_event_name_table[DAEMON_EVENT_COUNT] = { static struct nDPId_reader_thread reader_threads[nDPId_MAX_READER_THREADS] = {}; static int nDPId_main_thread_shutdown = 0; static uint64_t global_flow_id = 1; +static int ip4_interface_avail = 0, ip6_interface_avail = 0; #ifdef ENABLE_MEMORY_PROFILING static uint64_t ndpi_memory_alloc_count = 0; @@ -265,9 +269,9 @@ static struct { /* opts */ char * pcap_file_or_interface; - union nDPId_ip pcap_dev_ip; - union nDPId_ip pcap_dev_netmask; - union nDPId_ip pcap_dev_subnet; + union nDPId_ip pcap_dev_ip4, pcap_dev_ip6; + union nDPId_ip pcap_dev_netmask4, pcap_dev_netmask6; + union nDPId_ip pcap_dev_subnet4, pcap_dev_subnet6; uint8_t process_internal_initial_direction; uint8_t process_external_initial_direction; char * bpf_str; @@ -333,9 +337,9 @@ static void jsonize_flow_event(struct nDPId_reader_thread * const reader_thread, struct nDPId_flow_info * const flow, enum flow_event event); -static void ip_netmask_to_subnet(union nDPId_ip * ip, - union nDPId_ip * netmask, - union nDPId_ip * subnet, +static void ip_netmask_to_subnet(union nDPId_ip const * const ip, + union nDPId_ip const * const netmask, + union nDPId_ip * const subnet, enum nDPId_l3_type type) { switch (type) @@ -344,51 +348,199 @@ static void ip_netmask_to_subnet(union nDPId_ip * ip, subnet->v4.ip = ip->v4.ip & netmask->v4.ip; break; case L3_IP6: - subnet->v6.ip6[0] = ip->v6.ip6[0] & netmask->v6.ip6[0]; - subnet->v6.ip6[1] = ip->v6.ip6[1] & netmask->v6.ip6[1]; + subnet->v6.ip[0] = ip->v6.ip[0] & netmask->v6.ip[0]; + subnet->v6.ip[1] = ip->v6.ip[1] & netmask->v6.ip[1]; break; } } -static int is_ip_in_subnet(union nDPId_ip * cmp_ip, - union nDPId_ip * netmask, - union nDPId_ip * cmp_subnet, - enum nDPId_l3_type type) +static int is_ip_in_subnet(union nDPId_ip const * const cmp_ip, + union nDPId_ip const * const netmask, + union nDPId_ip const * const cmp_subnet, + enum nDPId_l3_type const type) { switch (type) { case L3_IP: return (cmp_ip->v4.ip & netmask->v4.ip) == cmp_subnet->v4.ip; case L3_IP6: - return (cmp_ip->v6.ip6[0] & netmask->v6.ip6[0]) == cmp_subnet->v6.ip6[0] && - (cmp_ip->v6.ip6[1] & netmask->v6.ip6[1]) == cmp_subnet->v6.ip6[1]; + return (cmp_ip->v6.ip[0] & netmask->v6.ip[0]) == cmp_subnet->v6.ip[0] && + (cmp_ip->v6.ip[1] & netmask->v6.ip[1]) == cmp_subnet->v6.ip[1]; } return 0; } -static void get_v4_ip_from_sockaddr(struct sockaddr_in * saddr, union nDPId_ip * dest) +static void get_ip_from_sockaddr(struct sockaddr const * const saddr, union nDPId_ip * dest) { - dest->v4.ip = saddr->sin_addr.s_addr; + switch (saddr->sa_family) + { + case AF_INET: + dest->v4.ip = ((struct sockaddr_in *)saddr)->sin_addr.s_addr; + break; + case AF_INET6: + dest->v6.ip_u32[0] = ((struct sockaddr_in6 *)saddr)->sin6_addr.s6_addr32[0]; + dest->v6.ip_u32[1] = ((struct sockaddr_in6 *)saddr)->sin6_addr.s6_addr32[1]; + dest->v6.ip_u32[2] = ((struct sockaddr_in6 *)saddr)->sin6_addr.s6_addr32[2]; + dest->v6.ip_u32[3] = ((struct sockaddr_in6 *)saddr)->sin6_addr.s6_addr32[3]; + break; + } } -#if 0 -static void get_v6_ip_from_sockaddr(struct sockaddr_in6 * saddr, union nDPId_ip * dest) +static int get_ip6_address_and_netmask(char const * const ifa_name, size_t ifnamelen) { - dest->v6.ip6[0] = *(uint64_t *)&saddr->sin6_addr.s6_addr[0]; - dest->v6.ip6[0] = *(uint64_t *)&saddr->sin6_addr.s6_addr[7]; + FILE * f; + char addr6[INET6_ADDRSTRLEN], netmask6[INET6_ADDRSTRLEN], subnet6[INET6_ADDRSTRLEN], devname[21]; + struct sockaddr_in6 sap; + int plen, scope, dad_status, if_idx, retval = 0; + char addr6p[8][5]; + + f = fopen("/proc/net/if_inet6", "r"); + if (f == NULL) + { + return 1; + } + + while (fscanf(f, + "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n", + addr6p[0], + addr6p[1], + addr6p[2], + addr6p[3], + addr6p[4], + addr6p[5], + addr6p[6], + addr6p[7], + &if_idx, + &plen, + &scope, + &dad_status, + devname) != EOF) + { + if (strncmp(devname, ifa_name, ifnamelen) == 0) + { + sprintf(addr6, + "%s:%s:%s:%s:%s:%s:%s:%s", + addr6p[0], + addr6p[1], + addr6p[2], + addr6p[3], + addr6p[4], + addr6p[5], + addr6p[6], + addr6p[7]); + + memset(&sap, 0, sizeof(sap)); + if (inet_pton(AF_INET6, addr6, (struct sockaddr *)&sap.sin6_addr) != 1) + { + retval = 1; + goto error; + } + inet_ntop(AF_INET6, &sap.sin6_addr, addr6, sizeof(addr6)); + sap.sin6_family = AF_INET6; + get_ip_from_sockaddr((struct sockaddr *)&sap, &nDPId_options.pcap_dev_ip6); + + memset(&sap, 0, sizeof(sap)); + memset(&sap.sin6_addr.s6_addr, 0xFF, plen / 8); + if (plen < 128 && (plen % 32) != 0) + { + sap.sin6_addr.s6_addr32[plen / 32] = 0xFFFFFFFF << (32 - (plen % 32)); + } + inet_ntop(AF_INET6, &sap.sin6_addr, netmask6, sizeof(netmask6)); + sap.sin6_family = AF_INET6; + get_ip_from_sockaddr((struct sockaddr *)&sap, &nDPId_options.pcap_dev_netmask6); + + ip_netmask_to_subnet(&nDPId_options.pcap_dev_ip6, + &nDPId_options.pcap_dev_netmask6, + &nDPId_options.pcap_dev_subnet6, + L3_IP6); + inet_ntop(AF_INET6, &nDPId_options.pcap_dev_subnet6.v6, subnet6, sizeof(subnet6)); + + syslog(LOG_DAEMON, + "%s IPv6 address/prefix netmask subnet: %s/%u %s %s", + nDPId_options.pcap_file_or_interface, + addr6, + plen, + netmask6, + subnet6); + } + } + +error: + fclose(f); + + return retval; +} + +static int get_ip4_address_and_netmask(char const * const ifa_name, size_t ifnamelen) +{ + int retval = 0; + int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + struct ifreq ifr; + + if (sock < 0) + { + retval = 1; + goto error; + } + if (ifnamelen >= sizeof(ifr.ifr_name)) + { + retval = 1; + goto error; + } + + memset(&ifr, 0, sizeof(ifr)); + memcpy(ifr.ifr_name, ifa_name, ifnamelen); + ifr.ifr_name[ifnamelen] = '\0'; + ifr.ifr_netmask.sa_family = AF_INET; + if (ioctl(sock, SIOCGIFNETMASK, &ifr) == -1) + { + retval = 1; + goto error; + } + get_ip_from_sockaddr(&ifr.ifr_netmask, &nDPId_options.pcap_dev_netmask4); + + memset(&ifr, 0, sizeof(ifr)); + memcpy(ifr.ifr_name, ifa_name, ifnamelen); + ifr.ifr_name[ifnamelen] = '\0'; + ifr.ifr_addr.sa_family = AF_INET; + if (ioctl(sock, SIOCGIFADDR, &ifr) == -1) + { + retval = 1; + goto error; + } + get_ip_from_sockaddr(&ifr.ifr_netmask, &nDPId_options.pcap_dev_ip4); + + ip_netmask_to_subnet(&nDPId_options.pcap_dev_ip4, + &nDPId_options.pcap_dev_netmask4, + &nDPId_options.pcap_dev_subnet4, + L3_IP); + + { + char addr[INET_ADDRSTRLEN]; + char netm[INET_ADDRSTRLEN]; + char subn[INET_ADDRSTRLEN]; + void * saddr = &nDPId_options.pcap_dev_ip4.v4.ip; + void * snetm = &nDPId_options.pcap_dev_netmask4.v4.ip; + void * ssubn = &nDPId_options.pcap_dev_subnet4.v4.ip; + syslog(LOG_DAEMON, + "%s IPv4 address netmask subnet: %s %s %s", + nDPId_options.pcap_file_or_interface, + inet_ntop(AF_INET, saddr, addr, sizeof(addr)), + inet_ntop(AF_INET, snetm, netm, sizeof(netm)), + inet_ntop(AF_INET, ssubn, subn, sizeof(subn))); + } + +error: + close(sock); + return retval; } -#endif -/* - * Only IPv4 supported for now! - * IPv6 support planned via /proc/net/if_inet6 - */ static int get_ip_netmask_from_pcap_dev(char const * const pcap_dev) { + int retval = 0, found_dev = 0; struct ifaddrs * ifaddrs = NULL; struct ifaddrs * ifa; - int sock = -1; if (getifaddrs(&ifaddrs) != 0 || ifaddrs == NULL) { @@ -402,91 +554,45 @@ static int get_ip_netmask_from_pcap_dev(char const * const pcap_dev) continue; } - size_t ifnamelen = strlen(ifa->ifa_name); - enum nDPId_l3_type type; - - switch (ifa->ifa_addr->sa_family) - { - case AF_INET: - type = L3_IP; - break; - case AF_INET6: - type = L3_IP6; - break; - default: - continue; - } - - if (strcmp(ifa->ifa_name, pcap_dev) == 0 && ifnamelen == strlen(pcap_dev)) + size_t ifnamelen = strnlen(ifa->ifa_name, IFNAMSIZ); + if (strncmp(ifa->ifa_name, pcap_dev, IFNAMSIZ) == 0 && ifnamelen == strnlen(pcap_dev, IFNAMSIZ)) { - if (type == L3_IP6) - { - syslog(LOG_DAEMON, "IPv6 network interfaces in combination with -I / -E is not supported for now"); - continue; - } - - sock = socket(ifa->ifa_addr->sa_family, SOCK_DGRAM, IPPROTO_IP); - struct ifreq ifr; - - if (sock < 0) + found_dev = 1; + switch (ifa->ifa_addr->sa_family) { - break; - } - if (ifnamelen >= sizeof(ifr.ifr_name)) - { - break; - } - - memset(&ifr, 0, sizeof(ifr)); - memcpy(ifr.ifr_name, ifa->ifa_name, ifnamelen); - ifr.ifr_name[ifnamelen] = '\0'; - ifr.ifr_netmask.sa_family = ifa->ifa_addr->sa_family; - if (ioctl(sock, SIOCGIFNETMASK, &ifr) == -1) - { - break; - } - get_v4_ip_from_sockaddr((struct sockaddr_in *)&ifr.ifr_netmask, &nDPId_options.pcap_dev_netmask); - - memset(&ifr, 0, sizeof(ifr)); - memcpy(ifr.ifr_name, ifa->ifa_name, ifnamelen); - ifr.ifr_name[ifnamelen] = '\0'; - ifr.ifr_addr.sa_family = ifa->ifa_addr->sa_family; - if (ioctl(sock, SIOCGIFADDR, &ifr) == -1) - { - break; + case AF_INET: + if (ip4_interface_avail == 0 && get_ip4_address_and_netmask(ifa->ifa_name, ifnamelen) != 0) + { + retval = 1; + } + ip4_interface_avail = 1; + break; + case AF_INET6: + if (ip6_interface_avail == 0 && get_ip6_address_and_netmask(ifa->ifa_name, ifnamelen) != 0) + { + retval = 1; + } + ip6_interface_avail = 1; + break; + default: + break; } - get_v4_ip_from_sockaddr((struct sockaddr_in *)&ifr.ifr_netmask, &nDPId_options.pcap_dev_ip); - - ip_netmask_to_subnet(&nDPId_options.pcap_dev_ip, - &nDPId_options.pcap_dev_netmask, - &nDPId_options.pcap_dev_subnet, - type); - - char addr[INET_ADDRSTRLEN]; - char netm[INET_ADDRSTRLEN]; - char subn[INET_ADDRSTRLEN]; - void * saddr = &nDPId_options.pcap_dev_ip.v4.ip; - void * snetm = &nDPId_options.pcap_dev_netmask.v4.ip; - void * ssubn = &nDPId_options.pcap_dev_subnet.v4.ip; - syslog(LOG_DAEMON, - "%s address/netmask/subnet: %s/%s/%s", - nDPId_options.pcap_file_or_interface, - inet_ntop(ifa->ifa_addr->sa_family, saddr, addr, sizeof(addr)), - inet_ntop(ifa->ifa_addr->sa_family, snetm, netm, sizeof(netm)), - inet_ntop(ifa->ifa_addr->sa_family, ssubn, subn, sizeof(subn))); - - freeifaddrs(ifaddrs); - close(sock); - return 0; } } - freeifaddrs(ifaddrs); - if (sock >= 0) + if (found_dev != 0 && + (nDPId_options.process_internal_initial_direction != 0 || + nDPId_options.process_external_initial_direction != 0) && + ip4_interface_avail == 0 && ip6_interface_avail == 0) { - close(sock); + syslog(LOG_DAEMON | LOG_ERR, + "Interface %s does not have any IPv4 / IPv6 address set, -I / -E won't work.", + pcap_dev); + retval = 1; } - return 1; + + freeifaddrs(ifaddrs); + return retval; } #ifdef ENABLE_MEMORY_PROFILING @@ -756,10 +862,13 @@ static int setup_reader_threads(void) errno = 0; if (get_ip_netmask_from_pcap_dev(nDPId_options.pcap_file_or_interface) != 0) { - syslog(LOG_DAEMON | LOG_ERR, - "Could not get netmask for pcap device %s: %s", - nDPId_options.pcap_file_or_interface, - strerror(errno)); + if (errno != 0) + { + syslog(LOG_DAEMON | LOG_ERR, + "Could not get netmask for pcap device %s: %s", + nDPId_options.pcap_file_or_interface, + strerror(errno)); + } return 1; } } @@ -804,8 +913,8 @@ static int ip_tuples_equal(struct nDPId_flow_basic const * const A, struct nDPId } else if (A->l3_type == L3_IP6 && B->l3_type == L3_IP6) { - return A->src.v6.ip6[0] == B->src.v6.ip6[0] && A->src.v6.ip6[1] == B->src.v6.ip6[1] && - A->dst.v6.ip6[0] == B->dst.v6.ip6[0] && A->dst.v6.ip6[1] == B->dst.v6.ip6[1]; + return A->src.v6.ip[0] == B->src.v6.ip[0] && A->src.v6.ip[1] == B->src.v6.ip[1] && + A->dst.v6.ip[0] == B->dst.v6.ip[0] && A->dst.v6.ip[1] == B->dst.v6.ip[1]; } return 0; } @@ -832,13 +941,13 @@ static int ip_tuples_compare(struct nDPId_flow_basic const * const A, struct nDP } else if (A->l3_type == L3_IP6 && B->l3_type == L3_IP6) { - if ((A->src.v6.ip6[0] < B->src.v6.ip6[0] && A->src.v6.ip6[1] < B->src.v6.ip6[1]) || - (A->dst.v6.ip6[0] < B->dst.v6.ip6[0] && A->dst.v6.ip6[1] < B->dst.v6.ip6[1])) + if ((A->src.v6.ip[0] < B->src.v6.ip[0] && A->src.v6.ip[1] < B->src.v6.ip[1]) || + (A->dst.v6.ip[0] < B->dst.v6.ip[0] && A->dst.v6.ip[1] < B->dst.v6.ip[1])) { return -1; } - if ((A->src.v6.ip6[0] > B->src.v6.ip6[0] && A->src.v6.ip6[1] > B->src.v6.ip6[1]) || - (A->dst.v6.ip6[0] > B->dst.v6.ip6[0] && A->dst.v6.ip6[1] > B->dst.v6.ip6[1])) + if ((A->src.v6.ip[0] > B->src.v6.ip[0] && A->src.v6.ip[1] > B->src.v6.ip[1]) || + (A->dst.v6.ip[0] > B->dst.v6.ip[0] && A->dst.v6.ip[1] > B->dst.v6.ip[1])) { return 1; } @@ -1047,11 +1156,11 @@ static void jsonize_l3_l4(struct nDPId_workflow * const workflow, struct nDPId_f break; case L3_IP6: ndpi_serialize_string_string(serializer, "l3_proto", "ip6"); - if (inet_ntop(AF_INET6, &flow->flow_basic.src.v6.ip6[0], src_name, sizeof(src_name)) == NULL) + if (inet_ntop(AF_INET6, &flow->flow_basic.src.v6.ip[0], src_name, sizeof(src_name)) == NULL) { syslog(LOG_DAEMON | LOG_ERR, "Could not convert IPv6 source ip to string: %s", strerror(errno)); } - if (inet_ntop(AF_INET6, &flow->flow_basic.dst.v6.ip6[0], dst_name, sizeof(dst_name)) == NULL) + if (inet_ntop(AF_INET6, &flow->flow_basic.dst.v6.ip[0], dst_name, sizeof(dst_name)) == NULL) { syslog(LOG_DAEMON | LOG_ERR, "Could not convert IPv6 destination ip to string: %s", strerror(errno)); } @@ -2057,20 +2166,20 @@ static void ndpi_process_packet(uint8_t * const args, return; } - flow_basic.src.v6.ip6[0] = ip6->ip6_src.u6_addr.u6_addr64[0]; - flow_basic.src.v6.ip6[1] = ip6->ip6_src.u6_addr.u6_addr64[1]; - flow_basic.dst.v6.ip6[0] = ip6->ip6_dst.u6_addr.u6_addr64[0]; - flow_basic.dst.v6.ip6[1] = ip6->ip6_dst.u6_addr.u6_addr64[1]; + flow_basic.src.v6.ip[0] = ip6->ip6_src.u6_addr.u6_addr64[0]; + flow_basic.src.v6.ip[1] = ip6->ip6_src.u6_addr.u6_addr64[1]; + flow_basic.dst.v6.ip[0] = ip6->ip6_dst.u6_addr.u6_addr64[0]; + flow_basic.dst.v6.ip[1] = ip6->ip6_dst.u6_addr.u6_addr64[1]; uint64_t min_addr[2]; - if (flow_basic.src.v6.ip6[0] > flow_basic.dst.v6.ip6[0] && flow_basic.src.v6.ip6[1] > flow_basic.dst.v6.ip6[1]) + if (flow_basic.src.v6.ip[0] > flow_basic.dst.v6.ip[0] && flow_basic.src.v6.ip[1] > flow_basic.dst.v6.ip[1]) { - min_addr[0] = flow_basic.dst.v6.ip6[0]; - min_addr[1] = flow_basic.dst.v6.ip6[0]; + min_addr[0] = flow_basic.dst.v6.ip[0]; + min_addr[1] = flow_basic.dst.v6.ip[0]; } else { - min_addr[0] = flow_basic.src.v6.ip6[0]; - min_addr[1] = flow_basic.src.v6.ip6[0]; + min_addr[0] = flow_basic.src.v6.ip[0]; + min_addr[1] = flow_basic.src.v6.ip[0]; } thread_index = min_addr[0] + min_addr[1] + ip6->ip6_hdr.ip6_un1_nxt; } @@ -2165,8 +2274,8 @@ static void ndpi_process_packet(uint8_t * const args, (uint8_t *)&flow_basic.hashval, sizeof(flow_basic.hashval)) != 0) { - flow_basic.hashval = flow_basic.src.v6.ip6[0] + flow_basic.src.v6.ip6[1]; - flow_basic.hashval += flow_basic.dst.v6.ip6[0] + flow_basic.dst.v6.ip6[1]; + flow_basic.hashval = flow_basic.src.v6.ip[0] + flow_basic.src.v6.ip[1]; + flow_basic.hashval += flow_basic.dst.v6.ip[0] + flow_basic.dst.v6.ip[1]; } break; } @@ -2177,15 +2286,15 @@ static void ndpi_process_packet(uint8_t * const args, if (tree_result == NULL) { /* flow not found in btree: switch src <-> dst and try to find it again */ - uint64_t orig_src_ip[2] = {flow_basic.src.v6.ip6[0], flow_basic.src.v6.ip6[1]}; - uint64_t orig_dst_ip[2] = {flow_basic.dst.v6.ip6[0], flow_basic.dst.v6.ip6[1]}; + uint64_t orig_src_ip[2] = {flow_basic.src.v6.ip[0], flow_basic.src.v6.ip[1]}; + uint64_t orig_dst_ip[2] = {flow_basic.dst.v6.ip[0], flow_basic.dst.v6.ip[1]}; uint16_t orig_src_port = flow_basic.src_port; uint16_t orig_dst_port = flow_basic.dst_port; - flow_basic.src.v6.ip6[0] = orig_dst_ip[0]; - flow_basic.src.v6.ip6[1] = orig_dst_ip[1]; - flow_basic.dst.v6.ip6[0] = orig_src_ip[0]; - flow_basic.dst.v6.ip6[1] = orig_src_ip[1]; + flow_basic.src.v6.ip[0] = orig_dst_ip[0]; + flow_basic.src.v6.ip[1] = orig_dst_ip[1]; + flow_basic.dst.v6.ip[0] = orig_src_ip[0]; + flow_basic.dst.v6.ip[1] = orig_src_ip[1]; flow_basic.src_port = orig_dst_port; flow_basic.dst_port = orig_src_port; @@ -2195,10 +2304,10 @@ static void ndpi_process_packet(uint8_t * const args, direction_changed = 1; } - flow_basic.src.v6.ip6[0] = orig_src_ip[0]; - flow_basic.src.v6.ip6[1] = orig_src_ip[1]; - flow_basic.dst.v6.ip6[0] = orig_dst_ip[0]; - flow_basic.dst.v6.ip6[1] = orig_dst_ip[1]; + flow_basic.src.v6.ip[0] = orig_src_ip[0]; + flow_basic.src.v6.ip[1] = orig_src_ip[1]; + flow_basic.dst.v6.ip[0] = orig_dst_ip[0]; + flow_basic.dst.v6.ip[1] = orig_dst_ip[1]; flow_basic.src_port = orig_src_port; flow_basic.dst_port = orig_dst_port; } @@ -2207,12 +2316,22 @@ static void ndpi_process_packet(uint8_t * const args, { /* flow still not found, must be new or midstream */ + union nDPId_ip const * netmask; + union nDPId_ip const * subnet; + switch (flow_basic.l3_type) + { + case L3_IP: + netmask = &nDPId_options.pcap_dev_netmask4; + subnet = &nDPId_options.pcap_dev_subnet4; + break; + case L3_IP6: + netmask = &nDPId_options.pcap_dev_netmask6; + subnet = &nDPId_options.pcap_dev_subnet6; + break; + } if (nDPId_options.process_internal_initial_direction != 0 && flow_basic.tcp_is_midstream_flow == 0) { - if (is_ip_in_subnet(&flow_basic.src, - &nDPId_options.pcap_dev_netmask, - &nDPId_options.pcap_dev_subnet, - flow_basic.l3_type) == 0) + if (is_ip_in_subnet(&flow_basic.src, netmask, subnet, flow_basic.l3_type) == 0) { if (add_new_flow(workflow, &flow_basic, FT_SKIPPED, hashed_index) == NULL) { @@ -2236,10 +2355,7 @@ static void ndpi_process_packet(uint8_t * const args, } else if (nDPId_options.process_external_initial_direction != 0 && flow_basic.tcp_is_midstream_flow == 0) { - if (is_ip_in_subnet(&flow_basic.src, - &nDPId_options.pcap_dev_netmask, - &nDPId_options.pcap_dev_subnet, - flow_basic.l3_type) != 0) + if (is_ip_in_subnet(&flow_basic.src, netmask, subnet, flow_basic.l3_type) != 0) { if (add_new_flow(workflow, &flow_basic, FT_SKIPPED, hashed_index) == NULL) { diff --git a/test/run_tests.sh b/test/run_tests.sh index 4b2603eff..ef7a15243 100755 --- a/test/run_tests.sh +++ b/test/run_tests.sh @@ -5,12 +5,14 @@ set -e LINE_SPACES=${LINE_SPACES:-48} MYDIR="$(realpath "$(dirname ${0})")" nDPId_test_EXEC="${2:-"$(realpath "${MYDIR}/../nDPId-test")"}" +JSON_VALIDATOR="${3:-"$(realpath "${MYDIR}/../examples/py-schema-validation/py-schema-validation.py")"}" -if [ $# -ne 1 -a $# -ne 2 ]; then +if [ $# -ne 1 -a $# -ne 2 -a $# -ne 3 ]; then cat <<EOF -usage: ${0} [path-to-nDPI-source-root] [path-to-nDPId-test-exec] +usage: ${0} [path-to-nDPI-source-root] [path-to-nDPId-test-exec] [path-to-nDPId-JSON-validator] path-to-nDPId-test-exec defaults to ${nDPId_test_EXEC} + path-to-nDPId-JSON-validator defaults to ${JSON_VALIDATOR} EOF exit 2 fi @@ -21,23 +23,30 @@ LOCKFILE="$(realpath "${0}").lock" touch "${LOCKFILE}" exec 42< "${LOCKFILE}" flock -x -n 42 || { - printf '%s\n' "Could not aquire file lock for ${0}. Already running instance?"; + printf '%s\n' "Could not aquire file lock for ${0}. Already running instance?" >&2; exit 3; } function sighandler() { + printf '%s\n' ' Received shutdown SIGNAL, bye' >&2 rm -f "${LOCKFILE}" exit 4 } trap sighandler SIGINT SIGTERM if [ ! -x "${nDPId_test_EXEC}" ]; then -cat <<EOF +cat >&2 <<EOF Required nDPId-test executable does not exist; ${nDPId_test_EXEC} EOF exit 5 fi +nc -h |& head -n1 | grep -qoE '^OpenBSD netcat' || { + printf '%s\n' "OpenBSD netcat (nc) version required!" >&2; + printf '%s\n' "Your version: $(nc -h |& head -n1)" >&2; + exit 6; +} + nDPI_TEST_DIR="${nDPI_SOURCE_ROOT}/tests/pcap" cat <<EOF @@ -117,7 +126,7 @@ for out_file in $(ls results/*.out); do fi cat "${out_file}" | nc -q 1 -l 127.0.0.1 9000 & nc_pid=$! - ${MYDIR}/../examples/py-schema-validation/py-schema-validation.py \ + ${JSON_VALIDATOR} \ --host 127.0.0.1 --port 9000 2>>"/tmp/nDPId-test-stderr/$(basename ${pcap_file}).out" if [ $? -eq 0 ]; then printf ' %s\n' '[OK]' |