Added internal/external packet processing modes.

* only IPv4 supported for now
 * refactored nDPId's internal IP address storage
 * use fresh ndpi_free_flow_data() to free nDPI's dynamic allocated data

Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
This commit is contained in:
Toni Uhlig
2021-01-06 19:01:27 +01:00
parent 613e60ca2a
commit f637802c0a

368
nDPId.c
View File

@@ -1,8 +1,10 @@
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <linux/if_ether.h>
#include <linux/un.h>
#include <net/if.h>
#include <netinet/in.h>
#include <ndpi_api.h>
#include <ndpi_main.h>
@@ -13,6 +15,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <syslog.h>
#include <unistd.h>
@@ -29,6 +32,17 @@ enum nDPId_l3_type
L3_IP6
};
union nDPId_ip {
struct
{
uint32_t ip;
} v4;
struct
{
uint64_t ip6[2];
} v6;
};
struct nDPId_flow_info
{
uint32_t flow_id;
@@ -39,18 +53,8 @@ struct nDPId_flow_info
enum nDPId_l3_type l3_type;
union {
struct
{
uint32_t src;
uint32_t dst;
} v4;
struct
{
uint64_t src[2];
uint64_t dst[2];
} v6;
} ip_tuple;
union nDPId_ip src;
union nDPId_ip dst;
uint16_t min_l4_data_len;
uint16_t max_l4_data_len;
@@ -229,6 +233,11 @@ int main_thread_shutdown = 0;
static uint32_t global_flow_id = 0;
static char * pcap_file_or_interface = NULL;
static union nDPId_ip pcap_dev_ip = {};
static union nDPId_ip pcap_dev_netmask = {};
static union nDPId_ip pcap_dev_subnet = {};
static uint8_t process_internal_initial_direction = 0;
static uint8_t process_external_initial_direction = 0;
static char * bpf_str = NULL;
static int log_to_stderr = 0;
static char pidfile[UNIX_PATH_MAX] = nDPId_PIDFILE;
@@ -274,6 +283,162 @@ 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,
enum nDPId_l3_type type)
{
switch (type)
{
case L3_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];
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)
{
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 0;
}
static void get_v4_ip_from_sockaddr(struct sockaddr_in * saddr, union nDPId_ip * dest)
{
dest->v4.ip = saddr->sin_addr.s_addr;
}
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];
dest->v6.ip6[0] = *(uint64_t *)&saddr->sin6_addr.s6_addr[7];
}
/*
* 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)
{
struct ifaddrs * ifaddrs = NULL;
struct ifaddrs * ifa;
if (getifaddrs(&ifaddrs) != 0 || ifaddrs == NULL)
{
return 1;
}
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == NULL || (ifa->ifa_flags & IFF_RUNNING) == 0)
{
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))
{
int const sock = socket(ifa->ifa_addr->sa_family, SOCK_DGRAM, IPPROTO_IP);
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;
}
if (ifa->ifa_addr->sa_family == AF_INET)
{
get_v4_ip_from_sockaddr((struct sockaddr_in *)&ifr.ifr_netmask, &pcap_dev_netmask);
}
else
{
get_v6_ip_from_sockaddr((struct sockaddr_in6 *)&ifr.ifr_netmask, &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;
}
if (ifa->ifa_addr->sa_family == AF_INET)
{
get_v4_ip_from_sockaddr((struct sockaddr_in *)&ifr.ifr_netmask, &pcap_dev_ip);
}
else
{
get_v6_ip_from_sockaddr((struct sockaddr_in6 *)&ifr.ifr_netmask, &pcap_dev_ip);
}
ip_netmask_to_subnet(&pcap_dev_ip, &pcap_dev_netmask, &pcap_dev_subnet, type);
char addr[INET6_ADDRSTRLEN];
char netm[INET6_ADDRSTRLEN];
char subn[INET6_ADDRSTRLEN];
void * saddr =
(ifa->ifa_addr->sa_family == AF_INET ? (void *)&pcap_dev_ip.v4.ip : (void *)&pcap_dev_ip.v6.ip6);
void * snetm = (ifa->ifa_addr->sa_family == AF_INET ? (void *)&pcap_dev_netmask.v4.ip
: (void *)&pcap_dev_netmask.v6.ip6);
void * ssubn = (ifa->ifa_addr->sa_family == AF_INET ? (void *)&pcap_dev_subnet.v4.ip
: (void *)&pcap_dev_subnet.v6.ip6);
syslog(LOG_DAEMON,
"%s address/netmask/subnet: %s/%s/%s",
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);
return 0;
}
}
freeifaddrs(ifaddrs);
return 1;
}
static struct nDPId_workflow * init_workflow(char const * const file_or_device)
{
int pcap_argument_is_file = 0;
@@ -312,16 +477,15 @@ static struct nDPId_workflow * init_workflow(char const * const file_or_device)
struct bpf_program fp;
if (pcap_compile(workflow->pcap_handle, &fp, bpf_str, 1, PCAP_NETMASK_UNKNOWN) != 0)
{
syslog(LOG_DAEMON | LOG_ERR,
"pcap_compile: %s", pcap_geterr(workflow->pcap_handle));
syslog(LOG_DAEMON | LOG_ERR, "pcap_compile: %s", pcap_geterr(workflow->pcap_handle));
free_workflow(&workflow);
return NULL;
}
if (pcap_setfilter(workflow->pcap_handle, &fp) != 0)
{
syslog(LOG_DAEMON | LOG_ERR,
"pcap_setfilter: %s", pcap_geterr(workflow->pcap_handle));
syslog(LOG_DAEMON | LOG_ERR, "pcap_setfilter: %s", pcap_geterr(workflow->pcap_handle));
free_workflow(&workflow);
pcap_freecode(&fp);
return NULL;
}
pcap_freecode(&fp);
@@ -371,6 +535,7 @@ static void ndpi_flow_info_freer(void * const node)
{
struct nDPId_flow_info * const flow = (struct nDPId_flow_info *)node;
ndpi_free_flow_data(&flow->ndpi_flow);
ndpi_free(flow);
}
@@ -440,6 +605,33 @@ static int setup_reader_threads(void)
syslog(LOG_DAEMON, "Capturing packets from default device: %s", pcap_file_or_interface);
}
errno = 0;
if (access(pcap_file_or_interface, R_OK) != 0 && errno == ENOENT)
{
errno = 0;
if (get_ip_netmask_from_pcap_dev(pcap_file_or_interface) != 0)
{
syslog(LOG_DAEMON | LOG_ERR,
"Could not get netmask for pcap device %s: %s",
pcap_file_or_interface,
strerror(errno));
return 1;
}
}
else
{
if (process_internal_initial_direction != 0)
{
syslog(LOG_DAEMON | LOG_ERR, "You are processing a PCAP file, `-I' ignored");
process_internal_initial_direction = 0;
}
if (process_external_initial_direction != 0)
{
syslog(LOG_DAEMON | LOG_ERR, "You are processing a PCAP file, `-E' ignored");
process_external_initial_direction = 0;
}
}
for (unsigned long long int i = 0; i < reader_thread_count; ++i)
{
reader_threads[i].workflow = init_workflow(pcap_file_or_interface);
@@ -463,12 +655,12 @@ static int ip_tuples_equal(struct nDPId_flow_info const * const A, struct nDPId_
}
if (A->l3_type == L3_IP && B->l3_type == L3_IP6)
{
return A->ip_tuple.v4.src == B->ip_tuple.v4.src && A->ip_tuple.v4.dst == B->ip_tuple.v4.dst;
return A->src.v4.ip == B->src.v4.ip && A->dst.v4.ip == B->dst.v4.ip;
}
else if (A->l3_type == L3_IP6 && B->l3_type == L3_IP6)
{
return A->ip_tuple.v6.src[0] == B->ip_tuple.v6.src[0] && A->ip_tuple.v6.src[1] == B->ip_tuple.v6.src[1] &&
A->ip_tuple.v6.dst[0] == B->ip_tuple.v6.dst[0] && A->ip_tuple.v6.dst[1] == B->ip_tuple.v6.dst[1];
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 0;
}
@@ -484,24 +676,24 @@ static int ip_tuples_compare(struct nDPId_flow_info const * const A, struct nDPI
}
if (A->l3_type == L3_IP && B->l3_type == L3_IP6)
{
if (A->ip_tuple.v4.src < B->ip_tuple.v4.src || A->ip_tuple.v4.dst < B->ip_tuple.v4.dst)
if (A->src.v4.ip < B->src.v4.ip || A->dst.v4.ip < B->dst.v4.ip)
{
return -1;
}
if (A->ip_tuple.v4.src > B->ip_tuple.v4.src || A->ip_tuple.v4.dst > B->ip_tuple.v4.dst)
if (A->src.v4.ip > B->src.v4.ip || A->dst.v4.ip > B->dst.v4.ip)
{
return 1;
}
}
else if (A->l3_type == L3_IP6 && B->l3_type == L3_IP6)
{
if ((A->ip_tuple.v6.src[0] < B->ip_tuple.v6.src[0] && A->ip_tuple.v6.src[1] < B->ip_tuple.v6.src[1]) ||
(A->ip_tuple.v6.dst[0] < B->ip_tuple.v6.dst[0] && A->ip_tuple.v6.dst[1] < B->ip_tuple.v6.dst[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]))
{
return -1;
}
if ((A->ip_tuple.v6.src[0] > B->ip_tuple.v6.src[0] && A->ip_tuple.v6.src[1] > B->ip_tuple.v6.src[1]) ||
(A->ip_tuple.v6.dst[0] > B->ip_tuple.v6.dst[0] && A->ip_tuple.v6.dst[1] > B->ip_tuple.v6.dst[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]))
{
return 1;
}
@@ -650,22 +842,22 @@ static void jsonize_l3_l4(struct nDPId_workflow * const workflow, struct nDPId_f
{
case L3_IP:
ndpi_serialize_string_string(serializer, "l3_proto", "ip4");
if (inet_ntop(AF_INET, &flow->ip_tuple.v4.src, src_name, sizeof(src_name)) == NULL)
if (inet_ntop(AF_INET, &flow->src.v4.ip, src_name, sizeof(src_name)) == NULL)
{
syslog(LOG_DAEMON | LOG_ERR, "Could not convert IPv4 source ip to string: %s", strerror(errno));
}
if (inet_ntop(AF_INET, &flow->ip_tuple.v4.dst, dst_name, sizeof(dst_name)) == NULL)
if (inet_ntop(AF_INET, &flow->dst.v4.ip, dst_name, sizeof(dst_name)) == NULL)
{
syslog(LOG_DAEMON | LOG_ERR, "Could not convert IPv4 destination ip to string: %s", strerror(errno));
}
break;
case L3_IP6:
ndpi_serialize_string_string(serializer, "l3_proto", "ip6");
if (inet_ntop(AF_INET6, &flow->ip_tuple.v6.src[0], src_name, sizeof(src_name)) == NULL)
if (inet_ntop(AF_INET6, &flow->src.v6.ip6[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->ip_tuple.v6.dst[0], dst_name, sizeof(dst_name)) == NULL)
if (inet_ntop(AF_INET6, &flow->dst.v6.ip6[0], dst_name, sizeof(dst_name)) == NULL)
{
syslog(LOG_DAEMON | LOG_ERR, "Could not convert IPv6 destination ip to string: %s", strerror(errno));
}
@@ -1057,8 +1249,10 @@ static void jsonize_flow_event(struct nDPId_reader_thread * const reader_thread,
case FLOW_EVENT_NOT_DETECTED:
case FLOW_EVENT_GUESSED:
if (ndpi_dpi2json(
workflow->ndpi_struct, &flow->ndpi_flow, flow->guessed_l7_protocol, &workflow->ndpi_serializer) != 0)
if (ndpi_dpi2json(workflow->ndpi_struct,
&flow->ndpi_flow,
flow->guessed_l7_protocol,
&workflow->ndpi_serializer) != 0)
{
syslog(LOG_DAEMON | LOG_ERR,
"[%8llu, %4u] ndpi_dpi2json failed for not-detected/guessed flow",
@@ -1370,7 +1564,7 @@ static int process_datalink_layer(struct nDPId_reader_thread * const reader_thre
ntohl(*((uint32_t *)&packet[eth_offset])));
return 1;
}
*ip_offset = 4 + eth_offset;
*ip_offset = sizeof(dlt_hdr) + eth_offset;
break;
}
case DLT_EN10MB:
@@ -1526,6 +1720,7 @@ static void ndpi_process_packet(uint8_t * const args,
}
flow.l3_type = L3_IP;
if (ndpi_detection_get_l4(
(uint8_t *)ip, ip_size, &l4_ptr, &l4_len, &flow.l4_protocol, NDPI_DETECTION_ONLY_IPV4) != 0)
{
@@ -1535,9 +1730,9 @@ static void ndpi_process_packet(uint8_t * const args,
return;
}
flow.ip_tuple.v4.src = ip->saddr;
flow.ip_tuple.v4.dst = ip->daddr;
uint32_t min_addr = (flow.ip_tuple.v4.src > flow.ip_tuple.v4.dst ? flow.ip_tuple.v4.dst : flow.ip_tuple.v4.src);
flow.src.v4.ip = ip->saddr;
flow.dst.v4.ip = ip->daddr;
uint32_t min_addr = (flow.src.v4.ip > flow.dst.v4.ip ? flow.dst.v4.ip : flow.src.v4.ip);
thread_index = min_addr + ip->protocol;
}
else if (ip6 != NULL)
@@ -1565,20 +1760,20 @@ static void ndpi_process_packet(uint8_t * const args,
return;
}
flow.ip_tuple.v6.src[0] = ip6->ip6_src.u6_addr.u6_addr64[0];
flow.ip_tuple.v6.src[1] = ip6->ip6_src.u6_addr.u6_addr64[1];
flow.ip_tuple.v6.dst[0] = ip6->ip6_dst.u6_addr.u6_addr64[0];
flow.ip_tuple.v6.dst[1] = ip6->ip6_dst.u6_addr.u6_addr64[1];
flow.src.v6.ip6[0] = ip6->ip6_src.u6_addr.u6_addr64[0];
flow.src.v6.ip6[1] = ip6->ip6_src.u6_addr.u6_addr64[1];
flow.dst.v6.ip6[0] = ip6->ip6_dst.u6_addr.u6_addr64[0];
flow.dst.v6.ip6[1] = ip6->ip6_dst.u6_addr.u6_addr64[1];
uint64_t min_addr[2];
if (flow.ip_tuple.v6.src[0] > flow.ip_tuple.v6.dst[0] && flow.ip_tuple.v6.src[1] > flow.ip_tuple.v6.dst[1])
if (flow.src.v6.ip6[0] > flow.dst.v6.ip6[0] && flow.src.v6.ip6[1] > flow.dst.v6.ip6[1])
{
min_addr[0] = flow.ip_tuple.v6.dst[0];
min_addr[1] = flow.ip_tuple.v6.dst[0];
min_addr[0] = flow.dst.v6.ip6[0];
min_addr[1] = flow.dst.v6.ip6[0];
}
else
{
min_addr[0] = flow.ip_tuple.v6.src[0];
min_addr[1] = flow.ip_tuple.v6.src[0];
min_addr[0] = flow.src.v6.ip6[0];
min_addr[1] = flow.src.v6.ip6[0];
}
thread_index = min_addr[0] + min_addr[1] + ip6->ip6_hdr.ip6_un1_nxt;
}
@@ -1648,8 +1843,8 @@ static void ndpi_process_packet(uint8_t * const args,
{
case L3_IP:
if (ndpi_flowv4_flow_hash(flow.l4_protocol,
flow.ip_tuple.v4.src,
flow.ip_tuple.v4.dst,
flow.src.v4.ip,
flow.dst.v4.ip,
flow.src_port,
flow.dst_port,
0,
@@ -1657,7 +1852,7 @@ static void ndpi_process_packet(uint8_t * const args,
(uint8_t *)&flow.hashval,
sizeof(flow.hashval)) != 0)
{
flow.hashval = flow.ip_tuple.v4.src + flow.ip_tuple.v4.dst; // fallback
flow.hashval = flow.src.v4.ip + flow.dst.v4.ip; // fallback
}
break;
case L3_IP6:
@@ -1671,8 +1866,8 @@ static void ndpi_process_packet(uint8_t * const args,
(uint8_t *)&flow.hashval,
sizeof(flow.hashval)) != 0)
{
flow.hashval = flow.ip_tuple.v6.src[0] + flow.ip_tuple.v6.src[1];
flow.hashval += flow.ip_tuple.v6.dst[0] + flow.ip_tuple.v6.dst[1];
flow.hashval = flow.src.v6.ip6[0] + flow.src.v6.ip6[1];
flow.hashval += flow.dst.v6.ip6[0] + flow.dst.v6.ip6[1];
}
break;
}
@@ -1683,15 +1878,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.ip_tuple.v6.src[0], flow.ip_tuple.v6.src[1]};
uint64_t orig_dst_ip[2] = {flow.ip_tuple.v6.dst[0], flow.ip_tuple.v6.dst[1]};
uint64_t orig_src_ip[2] = {flow.src.v6.ip6[0], flow.src.v6.ip6[1]};
uint64_t orig_dst_ip[2] = {flow.dst.v6.ip6[0], flow.dst.v6.ip6[1]};
uint16_t orig_src_port = flow.src_port;
uint16_t orig_dst_port = flow.dst_port;
flow.ip_tuple.v6.src[0] = orig_dst_ip[0];
flow.ip_tuple.v6.src[1] = orig_dst_ip[1];
flow.ip_tuple.v6.dst[0] = orig_src_ip[0];
flow.ip_tuple.v6.dst[1] = orig_src_ip[1];
flow.src.v6.ip6[0] = orig_dst_ip[0];
flow.src.v6.ip6[1] = orig_dst_ip[1];
flow.dst.v6.ip6[0] = orig_src_ip[0];
flow.dst.v6.ip6[1] = orig_src_ip[1];
flow.src_port = orig_dst_port;
flow.dst_port = orig_src_port;
@@ -1701,10 +1896,10 @@ static void ndpi_process_packet(uint8_t * const args,
direction_changed = 1;
}
flow.ip_tuple.v6.src[0] = orig_src_ip[0];
flow.ip_tuple.v6.src[1] = orig_src_ip[1];
flow.ip_tuple.v6.dst[0] = orig_dst_ip[0];
flow.ip_tuple.v6.dst[1] = orig_dst_ip[1];
flow.src.v6.ip6[0] = orig_src_ip[0];
flow.src.v6.ip6[1] = orig_src_ip[1];
flow.dst.v6.ip6[0] = orig_dst_ip[0];
flow.dst.v6.ip6[1] = orig_dst_ip[1];
flow.src_port = orig_src_port;
flow.dst_port = orig_dst_port;
}
@@ -1712,6 +1907,22 @@ static void ndpi_process_packet(uint8_t * const args,
if (tree_result == NULL)
{
/* flow still not found, must be new */
if (process_internal_initial_direction != 0)
{
if (is_ip_in_subnet(&flow.src, &pcap_dev_netmask, &pcap_dev_subnet, flow.l3_type) == 0)
{
return;
}
}
else if (process_external_initial_direction != 0)
{
if (is_ip_in_subnet(&flow.src, &pcap_dev_netmask, &pcap_dev_subnet, flow.l3_type) != 0)
{
return;
}
}
if (workflow->cur_active_flows == workflow->max_active_flows)
{
jsonize_packet_event(reader_thread, header, packet, type, ip_offset, NULL, PACKET_EVENT_PAYLOAD);
@@ -1746,12 +1957,16 @@ static void ndpi_process_packet(uint8_t * const args,
flow_to_process->flow_id = global_flow_id++;
#endif
memset(&flow_to_process->ndpi_flow, 0, (SIZEOF_FLOW_STRUCT > sizeof(struct ndpi_flow_struct) ?
SIZEOF_FLOW_STRUCT : sizeof(struct ndpi_flow_struct)));
memset(&flow_to_process->ndpi_src, 0, (SIZEOF_ID_STRUCT > sizeof(struct ndpi_id_struct) ?
SIZEOF_ID_STRUCT : sizeof(struct ndpi_id_struct)));
memset(&flow_to_process->ndpi_dst, 0, (SIZEOF_ID_STRUCT > sizeof(struct ndpi_id_struct) ?
SIZEOF_ID_STRUCT : sizeof(struct ndpi_id_struct)));
memset(&flow_to_process->ndpi_flow,
0,
(SIZEOF_FLOW_STRUCT > sizeof(struct ndpi_flow_struct) ? SIZEOF_FLOW_STRUCT
: sizeof(struct ndpi_flow_struct)));
memset(&flow_to_process->ndpi_src,
0,
(SIZEOF_ID_STRUCT > sizeof(struct ndpi_id_struct) ? SIZEOF_ID_STRUCT : sizeof(struct ndpi_id_struct)));
memset(&flow_to_process->ndpi_dst,
0,
(SIZEOF_ID_STRUCT > sizeof(struct ndpi_id_struct) ? SIZEOF_ID_STRUCT : sizeof(struct ndpi_id_struct)));
if (ndpi_tsearch(flow_to_process, &workflow->ndpi_flows_active[hashed_index], ndpi_workflow_node_cmp) == NULL)
{
@@ -2130,7 +2345,7 @@ static void sighandler(int signum)
static void print_subopt_usage(void)
{
enum nDPId_subopts index = 0;
int index = MAX_FLOWS_PER_THREAD;
char * const * token = &subopt_token[0];
fprintf(stderr, "\tsubopts:\n");
@@ -2183,13 +2398,17 @@ static int parse_options(int argc, char ** argv)
static char const usage[] =
"Usage: %s "
"[-i pcap-file/interface] [-P bpf-filter]"
"[-i pcap-file/interface] [-I] [-E] [-P bpf-filter]"
"[-l] [-c path-to-unix-sock] "
"[-d] [-p pidfile] "
"[-u user] [-g group] "
"[-a instance-alias] "
"[-o subopt=value]\n\n"
"\t-i\tInterface or file from where to read packets from.\n"
"\t-I\tProcess only packets where the source address of the first packet\n"
"\t \tis part of the interface subnet. (Internal mode)\n"
"\t-E\tProcess only packets where the source address of the first packet\n"
"\t \tis *NOT* part of the interface subnet. (External mode)\n"
"\t-P\tSet an optional berkeley packet filter.\n"
"\t-l\tLog all messages to stderr as well.\n"
"\t-c\tPath to the Collector UNIX socket which acts as the JSON sink.\n"
@@ -2200,13 +2419,19 @@ static int parse_options(int argc, char ** argv)
"\t-a\tSet an optional name of this daemon instance which will be part of every JSON message.\n"
"\t-o\t(Carefully) Tune some daemon options. See subopts below.\n\n";
while ((opt = getopt(argc, argv, "hi:P:lc:dp:u:g:a:o:")) != -1)
while ((opt = getopt(argc, argv, "hi:IEP:lc:dp:u:g:a:o:")) != -1)
{
switch (opt)
{
case 'i':
pcap_file_or_interface = strdup(optarg);
break;
case 'I':
process_internal_initial_direction = 1;
break;
case 'E':
process_external_initial_direction = 1;
break;
case 'P':
bpf_str = strdup(optarg);
break;
@@ -2376,6 +2601,13 @@ static int validate_options(char const * const arg0)
max_idle_time);
retval = 1;
}
if (process_internal_initial_direction != 0 && process_external_initial_direction != 0)
{
fprintf(stderr,
"%s: Internal and External packet processing does not make sense as this is the default.\n",
arg0);
retval = 1;
}
return retval;
}