Added IPv6 support for -I / -E.

* added another Python search path and try-catch ModuleNotFoundError again
 * run_tests.sh checks for OpenBSD netcat (required for -q)

Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
This commit is contained in:
Toni Uhlig
2021-04-10 23:43:19 +02:00
parent ba586e1ecf
commit 131cf5385b
8 changed files with 288 additions and 156 deletions

View File

@@ -349,12 +349,14 @@ def defaultArgumentParser():
return parser return parser
def validateAddress(args): def validateAddress(args):
tcp_addr_set = False
address = None address = None
if args.host is None: if args.host is None:
address_tcpip = (DEFAULT_HOST, DEFAULT_PORT) address_tcpip = (DEFAULT_HOST, DEFAULT_PORT)
else: else:
address_tcpip = (args.host, args.port) address_tcpip = (args.host, args.port)
tcp_addr_set = True
if args.unix is None: if args.unix is None:
address_unix = DEFAULT_UNIX address_unix = DEFAULT_UNIX
@@ -366,7 +368,7 @@ def validateAddress(args):
possible_sock_mode = os.stat(address_unix).st_mode possible_sock_mode = os.stat(address_unix).st_mode
except: except:
pass pass
if stat.S_ISSOCK(possible_sock_mode): if tcp_addr_set == False and stat.S_ISSOCK(possible_sock_mode):
address = address_unix address = address_unix
else: else:
address = address_tcpip address = address_tcpip

View File

@@ -3,6 +3,7 @@
import os import os
import sys 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') sys.path.append(os.path.dirname(sys.argv[0]) + '/../usr/share/nDPId')
try: try:
import nDPIsrvd import nDPIsrvd

View File

@@ -3,6 +3,7 @@
import os import os
import sys 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') sys.path.append(os.path.dirname(sys.argv[0]) + '/../usr/share/nDPId')
try: try:
import nDPIsrvd import nDPIsrvd

View File

@@ -3,6 +3,7 @@
import os import os
import sys 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') sys.path.append(os.path.dirname(sys.argv[0]) + '/../usr/share/nDPId')
try: try:
import nDPIsrvd import nDPIsrvd

View File

@@ -4,6 +4,7 @@ import base64
import os import os
import sys 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') sys.path.append(os.path.dirname(sys.argv[0]) + '/../usr/share/nDPId')
try: try:
import nDPIsrvd import nDPIsrvd

View File

@@ -3,6 +3,7 @@
import os import os
import sys 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') sys.path.append(os.path.dirname(sys.argv[0]) + '/../usr/share/nDPId')
try: try:
import nDPIsrvd import nDPIsrvd

416
nDPId.c
View File

@@ -26,8 +26,8 @@
#define UNIX_PATH_MAX 108 #define UNIX_PATH_MAX 108
#endif #endif
#if ((NDPI_MAJOR == 3 && NDPI_MINOR < 6) || NDPI_MAJOR < 3) && NDPI_API_VERSION < 4087 #if ((NDPI_MAJOR == 3 && NDPI_MINOR < 5) || NDPI_MAJOR < 3) && NDPI_API_VERSION < 4087
#error "nDPI >= 3.6.0 or API version >= 4087 required" #error "nDPI >= 3.5.0 or API version >= 4087 required"
#endif #endif
#if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) #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; } v4;
struct struct
{ {
uint64_t ip6[2]; union {
uint64_t ip[2];
uint32_t ip_u32[4];
};
} v6; } 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 struct nDPId_reader_thread reader_threads[nDPId_MAX_READER_THREADS] = {};
static int nDPId_main_thread_shutdown = 0; static int nDPId_main_thread_shutdown = 0;
static uint64_t global_flow_id = 1; static uint64_t global_flow_id = 1;
static int ip4_interface_avail = 0, ip6_interface_avail = 0;
#ifdef ENABLE_MEMORY_PROFILING #ifdef ENABLE_MEMORY_PROFILING
static uint64_t ndpi_memory_alloc_count = 0; static uint64_t ndpi_memory_alloc_count = 0;
@@ -265,9 +269,9 @@ static struct
{ {
/* opts */ /* opts */
char * pcap_file_or_interface; char * pcap_file_or_interface;
union nDPId_ip pcap_dev_ip; union nDPId_ip pcap_dev_ip4, pcap_dev_ip6;
union nDPId_ip pcap_dev_netmask; union nDPId_ip pcap_dev_netmask4, pcap_dev_netmask6;
union nDPId_ip pcap_dev_subnet; union nDPId_ip pcap_dev_subnet4, pcap_dev_subnet6;
uint8_t process_internal_initial_direction; uint8_t process_internal_initial_direction;
uint8_t process_external_initial_direction; uint8_t process_external_initial_direction;
char * bpf_str; 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, struct nDPId_flow_info * const flow,
enum flow_event event); enum flow_event event);
static void ip_netmask_to_subnet(union nDPId_ip * ip, static void ip_netmask_to_subnet(union nDPId_ip const * const ip,
union nDPId_ip * netmask, union nDPId_ip const * const netmask,
union nDPId_ip * subnet, union nDPId_ip * const subnet,
enum nDPId_l3_type type) enum nDPId_l3_type type)
{ {
switch (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; subnet->v4.ip = ip->v4.ip & netmask->v4.ip;
break; break;
case L3_IP6: case L3_IP6:
subnet->v6.ip6[0] = ip->v6.ip6[0] & netmask->v6.ip6[0]; subnet->v6.ip[0] = ip->v6.ip[0] & netmask->v6.ip[0];
subnet->v6.ip6[1] = ip->v6.ip6[1] & netmask->v6.ip6[1]; subnet->v6.ip[1] = ip->v6.ip[1] & netmask->v6.ip[1];
break; break;
} }
} }
static int is_ip_in_subnet(union nDPId_ip * cmp_ip, static int is_ip_in_subnet(union nDPId_ip const * const cmp_ip,
union nDPId_ip * netmask, union nDPId_ip const * const netmask,
union nDPId_ip * cmp_subnet, union nDPId_ip const * const cmp_subnet,
enum nDPId_l3_type type) enum nDPId_l3_type const type)
{ {
switch (type) switch (type)
{ {
case L3_IP: case L3_IP:
return (cmp_ip->v4.ip & netmask->v4.ip) == cmp_subnet->v4.ip; return (cmp_ip->v4.ip & netmask->v4.ip) == cmp_subnet->v4.ip;
case L3_IP6: case L3_IP6:
return (cmp_ip->v6.ip6[0] & netmask->v6.ip6[0]) == cmp_subnet->v6.ip6[0] && return (cmp_ip->v6.ip[0] & netmask->v6.ip[0]) == cmp_subnet->v6.ip[0] &&
(cmp_ip->v6.ip6[1] & netmask->v6.ip6[1]) == cmp_subnet->v6.ip6[1]; (cmp_ip->v6.ip[1] & netmask->v6.ip[1]) == cmp_subnet->v6.ip[1];
} }
return 0; 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 int get_ip6_address_and_netmask(char const * const ifa_name, size_t ifnamelen)
static void get_v6_ip_from_sockaddr(struct sockaddr_in6 * saddr, union nDPId_ip * dest)
{ {
dest->v6.ip6[0] = *(uint64_t *)&saddr->sin6_addr.s6_addr[0]; FILE * f;
dest->v6.ip6[0] = *(uint64_t *)&saddr->sin6_addr.s6_addr[7]; char addr6[INET6_ADDRSTRLEN], netmask6[INET6_ADDRSTRLEN], subnet6[INET6_ADDRSTRLEN], devname[21];
} struct sockaddr_in6 sap;
#endif 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;
}
/*
* 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) 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 * ifaddrs = NULL;
struct ifaddrs * ifa; struct ifaddrs * ifa;
int sock = -1;
if (getifaddrs(&ifaddrs) != 0 || ifaddrs == NULL) if (getifaddrs(&ifaddrs) != 0 || ifaddrs == NULL)
{ {
@@ -402,91 +554,45 @@ static int get_ip_netmask_from_pcap_dev(char const * const pcap_dev)
continue; continue;
} }
size_t ifnamelen = strlen(ifa->ifa_name); size_t ifnamelen = strnlen(ifa->ifa_name, IFNAMSIZ);
enum nDPId_l3_type type; if (strncmp(ifa->ifa_name, pcap_dev, IFNAMSIZ) == 0 && ifnamelen == strnlen(pcap_dev, IFNAMSIZ))
switch (ifa->ifa_addr->sa_family)
{ {
case AF_INET: found_dev = 1;
type = L3_IP; switch (ifa->ifa_addr->sa_family)
break; {
case AF_INET6: case AF_INET:
type = L3_IP6; if (ip4_interface_avail == 0 && get_ip4_address_and_netmask(ifa->ifa_name, ifnamelen) != 0)
break; {
default: retval = 1;
continue; }
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;
}
} }
}
if (strcmp(ifa->ifa_name, pcap_dev) == 0 && ifnamelen == strlen(pcap_dev)) if (found_dev != 0 &&
{ (nDPId_options.process_internal_initial_direction != 0 ||
if (type == L3_IP6) nDPId_options.process_external_initial_direction != 0) &&
{ ip4_interface_avail == 0 && ip6_interface_avail == 0)
syslog(LOG_DAEMON, "IPv6 network interfaces in combination with -I / -E is not supported for now"); {
continue; syslog(LOG_DAEMON | LOG_ERR,
} "Interface %s does not have any IPv4 / IPv6 address set, -I / -E won't work.",
pcap_dev);
sock = socket(ifa->ifa_addr->sa_family, SOCK_DGRAM, IPPROTO_IP); retval = 1;
struct ifreq ifr;
if (sock < 0)
{
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;
}
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); freeifaddrs(ifaddrs);
if (sock >= 0) return retval;
{
close(sock);
}
return 1;
} }
#ifdef ENABLE_MEMORY_PROFILING #ifdef ENABLE_MEMORY_PROFILING
@@ -756,10 +862,13 @@ static int setup_reader_threads(void)
errno = 0; errno = 0;
if (get_ip_netmask_from_pcap_dev(nDPId_options.pcap_file_or_interface) != 0) if (get_ip_netmask_from_pcap_dev(nDPId_options.pcap_file_or_interface) != 0)
{ {
syslog(LOG_DAEMON | LOG_ERR, if (errno != 0)
"Could not get netmask for pcap device %s: %s", {
nDPId_options.pcap_file_or_interface, syslog(LOG_DAEMON | LOG_ERR,
strerror(errno)); "Could not get netmask for pcap device %s: %s",
nDPId_options.pcap_file_or_interface,
strerror(errno));
}
return 1; 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) 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] && return A->src.v6.ip[0] == B->src.v6.ip[0] && A->src.v6.ip[1] == B->src.v6.ip[1] &&
A->dst.v6.ip6[0] == B->dst.v6.ip6[0] && A->dst.v6.ip6[1] == B->dst.v6.ip6[1]; A->dst.v6.ip[0] == B->dst.v6.ip[0] && A->dst.v6.ip[1] == B->dst.v6.ip[1];
} }
return 0; 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) 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]) || if ((A->src.v6.ip[0] < B->src.v6.ip[0] && A->src.v6.ip[1] < B->src.v6.ip[1]) ||
(A->dst.v6.ip6[0] < B->dst.v6.ip6[0] && A->dst.v6.ip6[1] < B->dst.v6.ip6[1])) (A->dst.v6.ip[0] < B->dst.v6.ip[0] && A->dst.v6.ip[1] < B->dst.v6.ip[1]))
{ {
return -1; return -1;
} }
if ((A->src.v6.ip6[0] > B->src.v6.ip6[0] && A->src.v6.ip6[1] > B->src.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.ip6[0] > B->dst.v6.ip6[0] && A->dst.v6.ip6[1] > B->dst.v6.ip6[1])) (A->dst.v6.ip[0] > B->dst.v6.ip[0] && A->dst.v6.ip[1] > B->dst.v6.ip[1]))
{ {
return 1; return 1;
} }
@@ -1047,11 +1156,11 @@ static void jsonize_l3_l4(struct nDPId_workflow * const workflow, struct nDPId_f
break; break;
case L3_IP6: case L3_IP6:
ndpi_serialize_string_string(serializer, "l3_proto", "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)); 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)); 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; return;
} }
flow_basic.src.v6.ip6[0] = ip6->ip6_src.u6_addr.u6_addr64[0]; flow_basic.src.v6.ip[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.src.v6.ip[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.ip[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.dst.v6.ip[1] = ip6->ip6_dst.u6_addr.u6_addr64[1];
uint64_t min_addr[2]; 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[0] = flow_basic.dst.v6.ip[0];
min_addr[1] = flow_basic.dst.v6.ip6[0]; min_addr[1] = flow_basic.dst.v6.ip[0];
} }
else else
{ {
min_addr[0] = flow_basic.src.v6.ip6[0]; min_addr[0] = flow_basic.src.v6.ip[0];
min_addr[1] = flow_basic.src.v6.ip6[0]; min_addr[1] = flow_basic.src.v6.ip[0];
} }
thread_index = min_addr[0] + min_addr[1] + ip6->ip6_hdr.ip6_un1_nxt; 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, (uint8_t *)&flow_basic.hashval,
sizeof(flow_basic.hashval)) != 0) 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.src.v6.ip[0] + flow_basic.src.v6.ip[1];
flow_basic.hashval += flow_basic.dst.v6.ip6[0] + flow_basic.dst.v6.ip6[1]; flow_basic.hashval += flow_basic.dst.v6.ip[0] + flow_basic.dst.v6.ip[1];
} }
break; break;
} }
@@ -2177,15 +2286,15 @@ static void ndpi_process_packet(uint8_t * const args,
if (tree_result == NULL) if (tree_result == NULL)
{ {
/* flow not found in btree: switch src <-> dst and try to find it again */ /* 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_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.ip6[0], flow_basic.dst.v6.ip6[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_src_port = flow_basic.src_port;
uint16_t orig_dst_port = flow_basic.dst_port; uint16_t orig_dst_port = flow_basic.dst_port;
flow_basic.src.v6.ip6[0] = orig_dst_ip[0]; flow_basic.src.v6.ip[0] = orig_dst_ip[0];
flow_basic.src.v6.ip6[1] = orig_dst_ip[1]; flow_basic.src.v6.ip[1] = orig_dst_ip[1];
flow_basic.dst.v6.ip6[0] = orig_src_ip[0]; flow_basic.dst.v6.ip[0] = orig_src_ip[0];
flow_basic.dst.v6.ip6[1] = orig_src_ip[1]; flow_basic.dst.v6.ip[1] = orig_src_ip[1];
flow_basic.src_port = orig_dst_port; flow_basic.src_port = orig_dst_port;
flow_basic.dst_port = orig_src_port; flow_basic.dst_port = orig_src_port;
@@ -2195,10 +2304,10 @@ static void ndpi_process_packet(uint8_t * const args,
direction_changed = 1; direction_changed = 1;
} }
flow_basic.src.v6.ip6[0] = orig_src_ip[0]; flow_basic.src.v6.ip[0] = orig_src_ip[0];
flow_basic.src.v6.ip6[1] = orig_src_ip[1]; flow_basic.src.v6.ip[1] = orig_src_ip[1];
flow_basic.dst.v6.ip6[0] = orig_dst_ip[0]; flow_basic.dst.v6.ip[0] = orig_dst_ip[0];
flow_basic.dst.v6.ip6[1] = orig_dst_ip[1]; flow_basic.dst.v6.ip[1] = orig_dst_ip[1];
flow_basic.src_port = orig_src_port; flow_basic.src_port = orig_src_port;
flow_basic.dst_port = orig_dst_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 */ /* 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 (nDPId_options.process_internal_initial_direction != 0 && flow_basic.tcp_is_midstream_flow == 0)
{ {
if (is_ip_in_subnet(&flow_basic.src, if (is_ip_in_subnet(&flow_basic.src, netmask, subnet, flow_basic.l3_type) == 0)
&nDPId_options.pcap_dev_netmask,
&nDPId_options.pcap_dev_subnet,
flow_basic.l3_type) == 0)
{ {
if (add_new_flow(workflow, &flow_basic, FT_SKIPPED, hashed_index) == NULL) 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) else if (nDPId_options.process_external_initial_direction != 0 && flow_basic.tcp_is_midstream_flow == 0)
{ {
if (is_ip_in_subnet(&flow_basic.src, if (is_ip_in_subnet(&flow_basic.src, netmask, subnet, flow_basic.l3_type) != 0)
&nDPId_options.pcap_dev_netmask,
&nDPId_options.pcap_dev_subnet,
flow_basic.l3_type) != 0)
{ {
if (add_new_flow(workflow, &flow_basic, FT_SKIPPED, hashed_index) == NULL) if (add_new_flow(workflow, &flow_basic, FT_SKIPPED, hashed_index) == NULL)
{ {

View File

@@ -5,12 +5,14 @@ set -e
LINE_SPACES=${LINE_SPACES:-48} LINE_SPACES=${LINE_SPACES:-48}
MYDIR="$(realpath "$(dirname ${0})")" MYDIR="$(realpath "$(dirname ${0})")"
nDPId_test_EXEC="${2:-"$(realpath "${MYDIR}/../nDPId-test")"}" 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 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-test-exec defaults to ${nDPId_test_EXEC}
path-to-nDPId-JSON-validator defaults to ${JSON_VALIDATOR}
EOF EOF
exit 2 exit 2
fi fi
@@ -21,23 +23,30 @@ LOCKFILE="$(realpath "${0}").lock"
touch "${LOCKFILE}" touch "${LOCKFILE}"
exec 42< "${LOCKFILE}" exec 42< "${LOCKFILE}"
flock -x -n 42 || { 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; exit 3;
} }
function sighandler() function sighandler()
{ {
printf '%s\n' ' Received shutdown SIGNAL, bye' >&2
rm -f "${LOCKFILE}" rm -f "${LOCKFILE}"
exit 4 exit 4
} }
trap sighandler SIGINT SIGTERM trap sighandler SIGINT SIGTERM
if [ ! -x "${nDPId_test_EXEC}" ]; then if [ ! -x "${nDPId_test_EXEC}" ]; then
cat <<EOF cat >&2 <<EOF
Required nDPId-test executable does not exist; ${nDPId_test_EXEC} Required nDPId-test executable does not exist; ${nDPId_test_EXEC}
EOF EOF
exit 5 exit 5
fi 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" nDPI_TEST_DIR="${nDPI_SOURCE_ROOT}/tests/pcap"
cat <<EOF cat <<EOF
@@ -117,7 +126,7 @@ for out_file in $(ls results/*.out); do
fi fi
cat "${out_file}" | nc -q 1 -l 127.0.0.1 9000 & cat "${out_file}" | nc -q 1 -l 127.0.0.1 9000 &
nc_pid=$! 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" --host 127.0.0.1 --port 9000 2>>"/tmp/nDPId-test-stderr/$(basename ${pcap_file}).out"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
printf ' %s\n' '[OK]' printf ' %s\n' '[OK]'