aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.seed11
-rw-r--r--example/Makefile.dpdk.in27
-rw-r--r--example/Makefile.in5
-rw-r--r--example/README.DPDK31
-rw-r--r--example/ndpiReader.c106
-rw-r--r--example/ndpi_util.c78
-rw-r--r--example/ndpi_util.h18
-rw-r--r--packages/openwrt/Makefile59
-rw-r--r--src/lib/ndpi_content_match.c.inc1
-rw-r--r--src/lib/ndpi_main.c19
-rw-r--r--src/lib/protocols/ssl.c34
-rw-r--r--src/lib/protocols/stun.c16
-rw-r--r--tests/result/KakaoTalk_chat.pcap.out2
-rw-r--r--tests/result/whatsapp_login_call.pcap.out30
-rw-r--r--tests/result/whatsapp_voice_and_message.pcap.out19
15 files changed, 380 insertions, 76 deletions
diff --git a/configure.seed b/configure.seed
index f3b267904..11220f885 100644
--- a/configure.seed
+++ b/configure.seed
@@ -40,6 +40,14 @@ AC_CHECK_HEADERS([netinet/in.h stdint.h stdlib.h string.h unistd.h])
PCAP_HOME=$HOME/PF_RING/userland
+DPDK_TARGET=
+if test -d $HOME/DPDK; then :
+ echo "Enabling DPDK support in ndpiReader"
+ DPDK_TARGET=dpdk
+else
+ echo "DPDK support disabled (missing $HOME/DPDK)"
+fi
+
if test -d $PCAP_HOME; then :
echo -n ""
else
@@ -138,7 +146,7 @@ AC_ARG_ENABLE([debug-messages],
AC_CHECK_LIB(pthread, pthread_setaffinity_np, AC_DEFINE_UNQUOTED(HAVE_PTHREAD_SETAFFINITY_NP, 1, [libc has pthread_setaffinity_np]))
-AC_CONFIG_FILES([Makefile example/Makefile tests/Makefile libndpi.pc src/include/ndpi_define.h src/lib/Makefile])
+AC_CONFIG_FILES([Makefile example/Makefile example/Makefile.dpdk tests/Makefile libndpi.pc src/include/ndpi_define.h src/lib/Makefile])
AC_CONFIG_HEADERS(src/include/ndpi_config.h)
AC_SUBST(GIT_RELEASE)
AC_SUBST(NDPI_MAJOR)
@@ -152,6 +160,7 @@ AC_SUBST(PCAP_LIB)
AC_SUBST(DL_LIB)
AC_SUBST(HS_LIB)
AC_SUBST(HS_INC)
+AC_SUBST(DPDK_TARGET)
AC_SUBST(HAVE_PTHREAD_SETAFFINITY_NP)
AC_OUTPUT
diff --git a/example/Makefile.dpdk.in b/example/Makefile.dpdk.in
new file mode 100644
index 000000000..8519d7d0e
--- /dev/null
+++ b/example/Makefile.dpdk.in
@@ -0,0 +1,27 @@
+#
+# Run 'make -f Makefile.dpdk' to compile the DPDK examples
+#
+# See http://core.dpdk.org/doc/quick-start/ for DPDK installation and setup
+#
+ifeq ($(RTE_SDK),)
+#$(error "Please define RTE_SDK environment variable")
+RTE_SDK = $(HOME)/DPDK
+RTE_TARGET = build
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+APP = ndpiReader
+LIBNDPI = $(PWD)/../src/lib/libndpi.a
+
+SRCS-y := ndpi_util.c ndpiReader.c
+
+CFLAGS += -g
+CFLAGS += -Wno-strict-prototypes -Wno-missing-prototypes -Wno-missing-declarations -Wno-unused-parameter -I $(PWD)/../src/include @CFLAGS@ -DUSE_DPDK
+LDLIBS = $(LIBNDPI) -lpthread @LDFLAGS@
+
+include $(RTE_SDK)/mk/rte.extapp.mk
+
diff --git a/example/Makefile.in b/example/Makefile.in
index 8c18f94dc..a5ca6acce 100644
--- a/example/Makefile.in
+++ b/example/Makefile.in
@@ -5,7 +5,7 @@ LDFLAGS=$(LIBNDPI) -lpcap -lpthread @LDFLAGS@
OBJS=ndpiReader.o ndpi_util.o
PREFIX?=/usr/local
-all: ndpiReader
+all: ndpiReader @DPDK_TARGET@
ndpiReader: $(OBJS) $(LIBNDPI)
$(CXX) $(CFLAGS) $(OBJS) -o $@ $(LDFLAGS)
@@ -16,6 +16,9 @@ ndpiReader: $(OBJS) $(LIBNDPI)
install:
cp ndpiReader $(DESTDIR)$(PREFIX)/bin
+dpdk:
+ make -f Makefile.dpdk
+
clean:
/bin/rm -f *.o ndpiReader
diff --git a/example/README.DPDK b/example/README.DPDK
new file mode 100644
index 000000000..472597c3f
--- /dev/null
+++ b/example/README.DPDK
@@ -0,0 +1,31 @@
+Prerequisites
+-------------
+
+You need to install and compile DPDK in your HOME directory as explained in
+See http://core.dpdk.org/doc/quick-start/ for DPDK installation and setup
+
+Once DPDK is built make sure to create a symbolic link
+
+$ cd
+$ ln -s dpdk-18.08 DPDK
+
+so the build process will use the DPDK directory letting you have multiple
+DPDK versions available on your system
+
+
+Build
+-----
+Everything will happen automagically but if you want to do it by hand
+do: make -f Makefile.dpdk
+
+
+Run Application
+---------------
+Supposing to capture packets from device eno1 you can start the
+application as follows:
+
+sudo ./build/ndpiReader -c 1 --vdev=net_pcap0,iface=eno1 -- -v 1
+
+NOTE:
+- ndpiReader without DPDK support sits in this directory
+- ndpiReader with DPDK support can be found inside the ./build directory
diff --git a/example/ndpiReader.c b/example/ndpiReader.c
index faa453ee2..89f5714a8 100644
--- a/example/ndpiReader.c
+++ b/example/ndpiReader.c
@@ -204,7 +204,9 @@ typedef struct ndpi_id {
// used memory counters
u_int32_t current_ndpi_memory = 0, max_ndpi_memory = 0;
-
+#ifdef USE_DPDK
+static int dpdk_port_id = 0, dpdk_run_capture = 1;
+#endif
void test_lib(); /* Forward */
@@ -227,7 +229,11 @@ static void setupDetection(u_int16_t thread_id, pcap_t * pcap_handle);
static void help(u_int long_help) {
printf("Welcome to nDPI %s\n\n", ndpi_revision());
- printf("ndpiReader -i <file|device> [-f <filter>][-s <duration>][-m <duration>]\n"
+ printf("ndpiReader "
+#ifndef USE_DPDK
+ "-i <file|device> "
+#endif
+ "[-f <filter>][-s <duration>][-m <duration>]\n"
" [-p <protos>][-l <loops> [-q][-d][-h][-t][-v <level>]\n"
" [-n <threads>][-w <file>][-c <file>][-j <file>][-x <file>]\n\n"
"Usage:\n"
@@ -457,7 +463,18 @@ static void parseOptions(int argc, char **argv) {
if(trace) fprintf(trace, " #### %s #### \n", __FUNCTION__);
#endif
- while ((opt = getopt_long(argc, argv, "c:df:g:i:hp:l:s:tv:V:n:j:rp:w:q0123:456:7:89:m:b:x:", longopts, &option_idx)) != EOF) {
+#ifdef USE_DPDK
+ {
+ int ret = rte_eal_init(argc, argv);
+
+ if(ret < 0)
+ rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
+
+ argc -= ret, argv += ret;
+ }
+#endif
+
+ while((opt = getopt_long(argc, argv, "c:df:g:i:hp:l:s:tv:V:n:j:rp:w:q0123:456:7:89:m:b:x:", longopts, &option_idx)) != EOF) {
#ifdef DEBUG_TRACE
if(trace) fprintf(trace, " #### -%c [%s] #### \n", opt, optarg ? optarg : "");
#endif
@@ -603,7 +620,7 @@ static void parseOptions(int argc, char **argv) {
case '9':
extcap_packet_filter = ndpi_get_proto_by_name(ndpi_info_mod, optarg);
- if (extcap_packet_filter == NDPI_PROTOCOL_UNKNOWN) extcap_packet_filter = atoi(optarg);
+ if(extcap_packet_filter == NDPI_PROTOCOL_UNKNOWN) extcap_packet_filter = atoi(optarg);
break;
case 257:
@@ -616,6 +633,7 @@ static void parseOptions(int argc, char **argv) {
}
}
+#ifndef USE_DPDK
if(!bpf_filter_flag) {
if(do_capture) {
quiet_mode = 1;
@@ -630,7 +648,7 @@ static void parseOptions(int argc, char **argv) {
if(strchr(_pcap_file[0], ',')) { /* multiple ingress interfaces */
num_threads = 0; /* setting number of threads = number of interfaces */
__pcap_file = strtok(_pcap_file[0], ",");
- while (__pcap_file != NULL && num_threads < MAX_NUM_READER_THREADS) {
+ while(__pcap_file != NULL && num_threads < MAX_NUM_READER_THREADS) {
_pcap_file[num_threads++] = __pcap_file;
__pcap_file = strtok(NULL, ",");
}
@@ -647,13 +665,14 @@ static void parseOptions(int argc, char **argv) {
if(num_cores > 1 && bind_mask != NULL) {
char *core_id = strtok(bind_mask, ":");
thread_id = 0;
- while (core_id != NULL && thread_id < num_threads) {
+ while(core_id != NULL && thread_id < num_threads) {
core_affinity[thread_id++] = atoi(core_id) % num_cores;
core_id = strtok(NULL, ":");
}
}
#endif
}
+#endif
#ifdef DEBUG_TRACE
if(trace) fclose(trace);
@@ -719,7 +738,7 @@ char* intoaV4(u_int32_t addr, char* buf, u_int16_t bufLen) {
}
*--cp = '.';
addr >>= 8;
- } while (--n > 0);
+ } while(--n > 0);
/* Convert the string to lowercase */
retStr = (char*)(cp+1);
@@ -769,7 +788,7 @@ static void printFlow(u_int16_t id, struct ndpi_flow_info *flow, u_int16_t threa
ndpi_get_proto_name(ndpi_thread_info[thread_id].workflow->ndpi_struct, flow->detected_protocol.app_protocol));
if(flow->detected_protocol.category != 0)
- fprintf(out, "[cat: %s/%u]",
+ fprintf(out, "[cat: %s/%u]",
ndpi_category_get_name(ndpi_thread_info[thread_id].workflow->ndpi_struct,
flow->detected_protocol.category),
(unsigned int)flow->detected_protocol.category);
@@ -924,7 +943,7 @@ static void node_proto_guess_walker(const void *node, ndpi_VISIT which, int dept
}
process_ndpi_collected_info(ndpi_thread_info[thread_id].workflow, flow);
-
+
ndpi_thread_info[thread_id].workflow->stats.protocol_counter[flow->detected_protocol.app_protocol] += flow->src2dst_packets + flow->dst2src_packets;
ndpi_thread_info[thread_id].workflow->stats.protocol_counter_bytes[flow->detected_protocol.app_protocol] += flow->src2dst_bytes + flow->dst2src_bytes;
ndpi_thread_info[thread_id].workflow->stats.protocol_flows[flow->detected_protocol.app_protocol]++;
@@ -985,7 +1004,7 @@ int updateIpTree(u_int32_t key, u_int8_t version,
if(rootp == (addr_node **)0)
return 0;
- while (*rootp != (addr_node *)0) {
+ while(*rootp != (addr_node *)0) {
/* Knuth's T1: */
if((version == (*rootp)->version) && (key == (*rootp)->addr)) {
/* T2: */
@@ -1015,7 +1034,7 @@ int updateIpTree(u_int32_t key, u_int8_t version,
/* *********************************************** */
void freeIpTree(addr_node *root) {
- if (root == NULL)
+ if(root == NULL)
return;
freeIpTree(root->left);
@@ -1210,9 +1229,9 @@ static void deleteReceivers(struct receiver *receivers) {
/* *********************************************** */
/* implementation of: https://jeroen.massar.ch/presentations/files/FloCon2010-TopK.pdf
*
- * if (table1.size < max1 || acceptable){
+ * if(table1.size < max1 || acceptable){
* create new element and add to the table1
- * if (table1.size > max2) {
+ * if(table1.size > max2) {
* cut table1 back to max1
* merge table 1 to table2
* if(table2.size > max1)
@@ -2266,9 +2285,13 @@ free_stats:
* @brief Force a pcap_dispatch() or pcap_loop() call to return
*/
static void breakPcapLoop(u_int16_t thread_id) {
+#ifdef USE_DPDK
+ dpdk_run_capture = 0;
+#else
if(ndpi_thread_info[thread_id].workflow->pcap_handle != NULL) {
pcap_breakloop(ndpi_thread_info[thread_id].workflow->pcap_handle);
}
+#endif
}
/**
@@ -2335,15 +2358,26 @@ static void configurePcapHandle(pcap_t * pcap_handle) {
* @brief Open a pcap file or a specified device - Always returns a valid pcap_t
*/
static pcap_t * openPcapFileOrDevice(u_int16_t thread_id, const u_char * pcap_file) {
-
u_int snaplen = 1536;
int promisc = 1;
char pcap_error_buffer[PCAP_ERRBUF_SIZE];
pcap_t * pcap_handle = NULL;
/* trying to open a live interface */
- if((pcap_handle = pcap_open_live((char*)pcap_file, snaplen, promisc,
- 500, pcap_error_buffer)) == NULL) {
+#ifdef USE_DPDK
+ struct rte_mempool *mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS,
+ MBUF_CACHE_SIZE, 0,
+ RTE_MBUF_DEFAULT_BUF_SIZE,
+ rte_socket_id());
+
+ if(mbuf_pool == NULL)
+ rte_exit(EXIT_FAILURE, "Cannot create mbuf pool: are hugepages ok?\n");
+
+ if(dpdk_port_init(dpdk_port_id, mbuf_pool) != 0)
+ rte_exit(EXIT_FAILURE, "DPDK: Cannot init port %u: please see README.dpdk\n", dpdk_port_id);
+#else
+ if((pcap_handle = pcap_open_live((char*)pcap_file, snaplen,
+ promisc, 500, pcap_error_buffer)) == NULL) {
capture_for = capture_until = 0;
live_capture = 0;
@@ -2370,11 +2404,17 @@ static pcap_t * openPcapFileOrDevice(u_int16_t thread_id, const u_char * pcap_fi
} else {
live_capture = 1;
- if((!json_flag) && (!quiet_mode))
+ if((!json_flag) && (!quiet_mode)) {
+#ifdef USE_DPDK
+ printf("Capturing from DPDK (port 0)...\n");
+#else
printf("Capturing live traffic from device %s...\n", pcap_file);
+#endif
+ }
}
configurePcapHandle(pcap_handle);
+#endif /* !DPDK */
if(capture_for > 0) {
if((!json_flag) && (!quiet_mode))
@@ -2520,13 +2560,13 @@ static void runPcapLoop(u_int16_t thread_id) {
* @brief Process a running thread
*/
void * processing_thread(void *_thread_id) {
-
long thread_id = (long) _thread_id;
char pcap_error_buffer[PCAP_ERRBUF_SIZE];
#if defined(linux) && defined(HAVE_PTHREAD_SETAFFINITY_NP)
if(core_affinity[thread_id] >= 0) {
cpu_set_t cpuset;
+
CPU_ZERO(&cpuset);
CPU_SET(core_affinity[thread_id], &cpuset);
@@ -2539,6 +2579,33 @@ void * processing_thread(void *_thread_id) {
#endif
if((!json_flag) && (!quiet_mode)) printf("Running thread %ld...\n", thread_id);
+#ifdef USE_DPDK
+ while(dpdk_run_capture) {
+ struct rte_mbuf *bufs[BURST_SIZE];
+ u_int16_t num = rte_eth_rx_burst(dpdk_port_id, 0, bufs, BURST_SIZE);
+ u_int i;
+
+ if(num == 0) {
+ usleep(1);
+ continue;
+ }
+
+ for(i = 0; i < PREFETCH_OFFSET && i < num; i++)
+ rte_prefetch0(rte_pktmbuf_mtod(bufs[i], void *));
+
+ for(i = 0; i < num; i++) {
+ char *data = rte_pktmbuf_mtod(bufs[i], char *);
+ int len = rte_pktmbuf_pkt_len(bufs[i]);
+ struct pcap_pkthdr h;
+
+ h.len = h.caplen = len;
+ gettimeofday(&h.ts, NULL);
+
+ pcap_process_packet((u_char*)&thread_id, &h, (const u_char *)data);
+ rte_pktmbuf_free(bufs[i]);
+ }
+ }
+#else
pcap_loop:
runPcapLoop(thread_id);
@@ -2551,6 +2618,7 @@ pcap_loop:
goto pcap_loop;
}
}
+#endif
return NULL;
}
@@ -3239,7 +3307,7 @@ int orginal_main(int argc, char **argv) {
automataUnitTest();
ndpi_info_mod = ndpi_init_detection_module();
- if (ndpi_info_mod == NULL) return -1;
+ if(ndpi_info_mod == NULL) return -1;
memset(ndpi_thread_info, 0, sizeof(ndpi_thread_info));
diff --git a/example/ndpi_util.c b/example/ndpi_util.c
index 977a246ec..1a0d45914 100644
--- a/example/ndpi_util.c
+++ b/example/ndpi_util.c
@@ -219,7 +219,7 @@ void ndpi_flow_info_freer(void *node) {
/* ***************************************************** */
void ndpi_workflow_free(struct ndpi_workflow * workflow) {
- int i;
+ u_int i;
for(i=0; i<workflow->prefs.num_roots; i++)
ndpi_tdestroy(workflow->ndpi_flows_root[i], ndpi_flow_info_freer);
@@ -232,8 +232,8 @@ void ndpi_workflow_free(struct ndpi_workflow * workflow) {
/* ***************************************************** */
int ndpi_workflow_node_cmp(const void *a, const void *b) {
- struct ndpi_flow_info *fa = (struct ndpi_flow_info*)a;
- struct ndpi_flow_info *fb = (struct ndpi_flow_info*)b;
+ const struct ndpi_flow_info *fa = (const struct ndpi_flow_info*)a;
+ const struct ndpi_flow_info *fb = (const struct ndpi_flow_info*)b;
if(fa->hashval < fb->hashval) return(-1); else if(fa->hashval > fb->hashval) return(1);
@@ -307,7 +307,7 @@ static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow
u_int32_t idx, l4_offset, hashval;
struct ndpi_flow_info flow;
void *ret;
- u_int8_t *l3, *l4;
+ const u_int8_t *l3, *l4;
/*
Note: to keep things simple (ndpiReader is just a demo app)
@@ -322,10 +322,10 @@ static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow
return NULL;
l4_offset = iph->ihl * 4;
- l3 = (u_int8_t*)iph;
+ l3 = (const u_int8_t*)iph;
} else {
l4_offset = sizeof(struct ndpi_ipv6hdr);
- l3 = (u_int8_t*)iph6;
+ l3 = (const u_int8_t*)iph6;
}
if(l4_packet_len < 64)
@@ -345,7 +345,7 @@ static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow
workflow->stats.max_packet_len = l4_packet_len;
*proto = iph->protocol;
- l4 = ((u_int8_t *) l3 + l4_offset);
+ l4 = ((const u_int8_t *) l3 + l4_offset);
if(iph->protocol == IPPROTO_TCP && l4_packet_len >= 20) {
u_int tcp_len;
@@ -355,7 +355,7 @@ static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow
*tcph = (struct ndpi_tcphdr *)l4;
*sport = ntohs((*tcph)->source), *dport = ntohs((*tcph)->dest);
tcp_len = ndpi_min(4*(*tcph)->doff, l4_packet_len);
- *payload = &l4[tcp_len];
+ *payload = (u_int8_t*)&l4[tcp_len];
*payload_len = ndpi_max(0, l4_packet_len-4*(*tcph)->doff);
} else if(iph->protocol == IPPROTO_UDP && l4_packet_len >= 8) {
// udp
@@ -363,8 +363,8 @@ static struct ndpi_flow_info *get_ndpi_flow_info(struct ndpi_workflow * workflow
workflow->stats.udp_count++;
*udph = (struct ndpi_udphdr *)l4;
*sport = ntohs((*udph)->source), *dport = ntohs((*udph)->dest);
- *payload = &l4[sizeof(struct ndpi_udphdr)];
- *payload_len = ndpi_max(0, l4_packet_len-sizeof(struct ndpi_udphdr));
+ *payload = (u_int8_t*)&l4[sizeof(struct ndpi_udphdr)];
+ *payload_len = (l4_packet_len > sizeof(struct ndpi_udphdr)) ? l4_packet_len-sizeof(struct ndpi_udphdr) : 0;
} else {
// non tcp/udp protocols
*sport = *dport = 0;
@@ -507,7 +507,7 @@ static struct ndpi_flow_info *get_ndpi_flow_info6(struct ndpi_workflow * workflo
iph.protocol = iph6->ip6_hdr.ip6_un1_nxt;
if(iph.protocol == IPPROTO_DSTOPTS /* IPv6 destination option */) {
- u_int8_t *options = (u_int8_t*)iph6 + sizeof(const struct ndpi_ipv6hdr);
+ const u_int8_t *options = (const u_int8_t*)iph6 + sizeof(const struct ndpi_ipv6hdr);
iph.protocol = options[0];
}
@@ -530,7 +530,7 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl
/* BITTORRENT */
if(flow->detected_protocol.app_protocol == NDPI_PROTOCOL_BITTORRENT) {
- int i, j, n = 0;
+ u_int i, j, n = 0;
for(i=0, j = 0; j < sizeof(flow->bittorent_hash)-1; i++) {
sprintf(&flow->bittorent_hash[j], "%02x",
@@ -751,8 +751,14 @@ struct ndpi_proto ndpi_workflow_process_packet (struct ndpi_workflow * workflow,
workflow->last_time = time;
/*** check Data Link type ***/
- const int datalink_type = pcap_datalink(workflow->pcap_handle);
+ int datalink_type;
+#ifdef USE_DPDK
+ datalink_type = DLT_EN10MB;
+#else
+ datalink_type = (int)pcap_datalink(workflow->pcap_handle);
+#endif
+
datalink_check:
switch(datalink_type) {
case DLT_NULL:
@@ -1076,3 +1082,49 @@ u_int32_t ethernet_crc32(const void* data, size_t n_bytes) {
__crc32(data, n_bytes, &crc);
return crc;
}
+
+/* *********************************************** */
+
+#ifdef USE_DPDK
+
+static const struct rte_eth_conf port_conf_default = {
+ .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN }
+};
+
+/* ************************************ */
+
+int dpdk_port_init(int port, struct rte_mempool *mbuf_pool) {
+ struct rte_eth_conf port_conf = port_conf_default;
+ const u_int16_t rx_rings = 1, tx_rings = 1;
+ int retval;
+ u_int16_t q;
+
+ /* 1 RX queue */
+ retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
+
+ if(retval != 0)
+ return retval;
+
+ for (q = 0; q < rx_rings; q++) {
+ retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE, rte_eth_dev_socket_id(port), NULL, mbuf_pool);
+ if(retval < 0)
+ return retval;
+ }
+
+ for (q = 0; q < tx_rings; q++) {
+ retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE, rte_eth_dev_socket_id(port), NULL);
+ if(retval < 0)
+ return retval;
+ }
+
+ retval = rte_eth_dev_start(port);
+
+ if(retval < 0)
+ return retval;
+
+ rte_eth_promiscuous_enable(port);
+
+ return 0;
+}
+
+#endif
diff --git a/example/ndpi_util.h b/example/ndpi_util.h
index d1d461490..eb9ab8e65 100644
--- a/example/ndpi_util.h
+++ b/example/ndpi_util.h
@@ -31,6 +31,24 @@
#include <pcap.h>
+#ifdef USE_DPDK
+#include <rte_eal.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_cycles.h>
+#include <rte_lcore.h>
+#include <rte_mbuf.h>
+
+#define RX_RING_SIZE 128
+#define TX_RING_SIZE 512
+#define NUM_MBUFS 8191
+#define MBUF_CACHE_SIZE 250
+#define BURST_SIZE 32
+#define PREFETCH_OFFSET 3
+
+extern int dpdk_port_init(int port, struct rte_mempool *mbuf_pool);
+#endif
+
#define MAX_NUM_READER_THREADS 16
#define IDLE_SCAN_PERIOD 10 /* msec (use TICK_RESOLUTION = 1000) */
#define MAX_IDLE_TIME 30000
diff --git a/packages/openwrt/Makefile b/packages/openwrt/Makefile
new file mode 100644
index 000000000..4b8429b59
--- /dev/null
+++ b/packages/openwrt/Makefile
@@ -0,0 +1,59 @@
+#
+# Copyright (C) 2018 - ntop.org
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=libndpi
+PKG_VERSION:=1333.ab2f3ce
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://github.com/ntop/nDPI.git
+PKG_SOURCE_VERSION:=ab2f3cefc89017d73e67faa4eb4011e7e3f2044d
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_PROTO:=git
+
+PKG_MAINTAINER:=Emanuele Faranda <faranda@ntop.org>
+PKG_LICENSE:=GPL3
+PKG_BUILD_DEPENDS:=+libpcap
+PKG_BUILD_PARALLEL:=1
+
+# autogen fix
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libndpi
+ SECTION:=network
+ CATEGORY:=Network
+ #DEPENDS:=+libc +libjson-c +libpthread
+ TITLE:=nDPI Deep Packet Inspection Library
+ URL:=https://www.ntop.org
+endef
+
+define Package/libndpi/description
+ Open and Extensible GPLv3 Deep Packet Inspection Library
+endef
+
+CONFIGURE_ARGS += \
+ --with-pic \
+ --disable-json-c \
+
+define Build/Prepare
+ $(call Build/Prepare/Default)
+endef
+
+define Build/Configure
+ ( cd $(PKG_BUILD_DIR); ./autogen.sh )
+ $(call Build/Configure/Default)
+endef
+
+define Build/InstallDev
+ $(INSTALL_DIR) $(STAGING_DIR)/usr/local/include/libndpi
+ $(CP) $(PKG_BUILD_DIR)/src/include/* $(STAGING_DIR)/usr/local/include/libndpi
+ $(INSTALL_DIR) $(STAGING_DIR)/usr/local/lib
+ $(CP) $(PKG_BUILD_DIR)/src/lib/libndpi.* $(STAGING_DIR)/usr/local/lib
+endef
+
+$(eval $(call BuildPackage,libndpi))
diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc
index e39fc3939..71e236d37 100644
--- a/src/lib/ndpi_content_match.c.inc
+++ b/src/lib/ndpi_content_match.c.inc
@@ -706,6 +706,7 @@ static ndpi_network host_protocol_list[] = {
{ 0x287F816D /* 40.126.129.109 */, 32, NDPI_PROTOCOL_SKYPE },
{ 0x4237DF00 /* 65.55.223.0 */, 26, NDPI_PROTOCOL_SKYPE },
{ 0x17600000 /* 23.96.0.0 */, 13, NDPI_PROTOCOL_SKYPE },
+ { 0x34724A05 /* 52.114.74.5 */, 32, NDPI_PROTOCOL_SKYPE },
/*
Blizzard Entertainment, Inc
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index 6f3d03a48..8e9bb53fc 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -3971,6 +3971,12 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st
if((guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN)
|| (guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN)) {
+
+ if((guessed_protocol_id == 0)
+ && (flow->protos.stun_ssl.stun.num_binding_requests > 0)
+ && (flow->protos.stun_ssl.stun.num_processed_pkts > 0))
+ guessed_protocol_id = NDPI_PROTOCOL_STUN;
+
ndpi_int_change_protocol(ndpi_struct, flow,
guessed_host_protocol_id,
guessed_protocol_id);
@@ -3988,16 +3994,25 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st
&& (flow->guessed_protocol_id == NDPI_PROTOCOL_STUN)) {
check_stun_export:
if(flow->protos.stun_ssl.stun.num_processed_pkts > 0) {
- if(flow->protos.stun_ssl.stun.num_processed_pkts >= NDPI_MIN_NUM_STUN_DETECTION) {
+ if(/* (flow->protos.stun_ssl.stun.num_processed_pkts >= NDPI_MIN_NUM_STUN_DETECTION) */
+ flow->protos.stun_ssl.stun.is_skype) {
u_int16_t proto = (flow->protos.stun_ssl.stun.num_binding_requests < 4) ? NDPI_PROTOCOL_SKYPE_CALL_IN : NDPI_PROTOCOL_SKYPE_CALL_OUT;
ndpi_set_detected_protocol(ndpi_struct, flow, proto, NDPI_PROTOCOL_SKYPE);
} else
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_STUN, flow->guessed_host_protocol_id);
+ ndpi_set_detected_protocol(ndpi_struct, flow, flow->guessed_host_protocol_id, NDPI_PROTOCOL_STUN);
}
}
ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0];
+
+ if(ret.master_protocol == NDPI_PROTOCOL_STUN) {
+ if(ret.app_protocol == NDPI_PROTOCOL_FACEBOOK)
+ ret.app_protocol = NDPI_PROTOCOL_MESSENGER;
+ else if(ret.app_protocol == NDPI_PROTOCOL_GOOGLE)
+ ret.app_protocol = NDPI_PROTOCOL_HANGOUT;
+ }
+
ndpi_fill_protocol_category(ndpi_struct, flow, &ret);
return(ret);
diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c
index d7f7a9687..25d535a57 100644
--- a/src/lib/protocols/ssl.c
+++ b/src/lib/protocols/ssl.c
@@ -249,7 +249,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
offset++;
compression_len = packet->payload[offset];
offset++;
-
+
#ifdef CERTIFICATE_DEBUG
printf("SSL [compression_len: %u]\n", compression_len);
#endif
@@ -260,7 +260,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
if(offset < total_len) {
extensions_len = ntohs(*((u_int16_t*)&packet->payload[offset]));
offset += 2;
-
+
#ifdef CERTIFICATE_DEBUG
printf("SSL [extensions_len: %u]\n", extensions_len);
#endif
@@ -282,7 +282,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
#ifdef CERTIFICATE_DEBUG
printf("SSL [extension_id: %u][extension_len: %u]\n", extension_id, extension_len);
#endif
-
+
if(extension_id == 0) {
#if 1
u_int16_t len;
@@ -316,7 +316,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
snprintf(flow->protos.stun_ssl.ssl.client_certificate,
sizeof(flow->protos.stun_ssl.ssl.client_certificate), "%s", buffer);
}
-
+
/* We're happy now */
return(2 /* Client Certificate */);
}
@@ -342,7 +342,7 @@ int sslTryAndRetrieveServerCertificate(struct ndpi_detection_module_struct *ndpi
if((packet->payload_packet_len > 9) && (packet->payload[0] == 0x16)) {
char certificate[64];
int rc;
-
+
certificate[0] = '\0';
rc = getSSLcertificate(ndpi_struct, flow, certificate, sizeof(certificate));
packet->ssl_certificate_num_checks++;
@@ -400,7 +400,7 @@ int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_s
strlen(certificate),
&ret_match,
NDPI_PROTOCOL_SSL);
-
+
if(subproto != NDPI_PROTOCOL_UNKNOWN) {
/* If we've detected the subprotocol from client certificate but haven't had a chance
* to see the server certificate yet, set up extra packet processing to wait
@@ -408,7 +408,7 @@ int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_s
if(((flow->l4.tcp.ssl_seen_client_cert == 1) && (flow->protos.stun_ssl.ssl.client_certificate[0] != '\0')) && ((flow->l4.tcp.ssl_seen_server_cert != 1) && (flow->protos.stun_ssl.ssl.server_certificate[0] == '\0'))) {
sslInitExtraPacketProcessing(0, flow);
}
-
+
ndpi_set_detected_protocol(ndpi_struct, flow, subproto,
ndpi_ssl_refine_master_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SSL));
return(rc); /* Fix courtesy of Gianluca Costa <g.costa@xplico.org> */
@@ -523,13 +523,10 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct
struct ndpi_packet_struct *packet = &flow->packet;
if((packet->payload_packet_len >= 5)
- && (packet->payload[0] == 0x16)
+ && ((packet->payload[0] == 0x16) || packet->payload[0] == 0x17)
&& (packet->payload[1] == 0x03)
- && ((packet->payload[2] == 0x00)
- || (packet->payload[2] == 0x01)
- || (packet->payload[2] == 0x02)
- || (packet->payload[2] == 0x03)
- )) {
+ && ((packet->payload[2] == 0x00) || (packet->payload[2] == 0x01) ||
+ (packet->payload[2] == 0x02) || (packet->payload[2] == 0x03))) {
u_int32_t temp;
NDPI_LOG_DBG2(ndpi_struct, "search sslv3\n");
// SSLv3 Record
@@ -691,6 +688,17 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc
flow->l4.tcp.ssl_stage = 1 + packet->packet_direction;
return;
}
+
+ // Application Data pkt
+ if(packet->payload[0] == 0x17 && packet->payload[1] == 0x03
+ && (packet->payload[2] == 0x00 || packet->payload[2] == 0x01 ||
+ packet->payload[2] == 0x02 || packet->payload[2] == 0x03)) {
+ if(packet->payload_packet_len - ntohs(get_u_int16_t(packet->payload, 3)) == 5) {
+ NDPI_LOG_DBG2(ndpi_struct, "TLS len match\n");
+ flow->l4.tcp.ssl_stage = 1 + packet->packet_direction;
+ return;
+ }
+ }
}
if(packet->payload_packet_len > 40 &&
diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c
index ad6a585f9..cb1322e5e 100644
--- a/src/lib/protocols/stun.c
+++ b/src/lib/protocols/stun.c
@@ -106,7 +106,7 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
case 0x4002:
/* These are the only messages apparently whatsapp voice can use */
break;
-
+
case 0x8054: /* Candidate Identifier */
if((len == 4)
&& ((offset+7) < payload_length)
@@ -119,6 +119,20 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
}
break;
+ case 0x8055: /* MS Service Quality (skype?) */
+ break;
+
+ /* Proprietary fields found on skype calls */
+ case 0x24DF:
+ case 0x3802:
+ case 0x8036:
+ case 0x8095:
+ case 0x0800:
+ /* printf("====>>>> %04X\n", attribute); */
+ flow->protos.stun_ssl.stun.is_skype = 1;
+ return(NDPI_IS_STUN);
+ break;
+
case 0x8070: /* Implementation Version */
if((len == 4)
&& ((offset+7) < payload_length)
diff --git a/tests/result/KakaoTalk_chat.pcap.out b/tests/result/KakaoTalk_chat.pcap.out
index 2648cce2a..eedfab56a 100644
--- a/tests/result/KakaoTalk_chat.pcap.out
+++ b/tests/result/KakaoTalk_chat.pcap.out
@@ -40,7 +40,7 @@ KakaoTalk 55 9990 15
30 UDP 10.24.82.188:24596 <-> 10.188.1.1:53 [proto: 5.119/DNS.Facebook][cat: SocialNetwork/6][1 pkts/78 bytes <-> 1 pkts/118 bytes][Host: api.facebook.com]
31 UDP 10.24.82.188:38448 <-> 10.188.1.1:53 [proto: 5.193/DNS.KakaoTalk][cat: VoIP/10][1 pkts/76 bytes <-> 1 pkts/114 bytes][Host: auth.kakao.com]
32 UDP 10.24.82.188:58810 <-> 10.188.1.1:53 [proto: 5.193/DNS.KakaoTalk][cat: VoIP/10][1 pkts/76 bytes <-> 1 pkts/114 bytes][Host: item.kakao.com]
- 33 TCP 10.24.82.188:58927 -> 54.255.253.199:5223 [proto: 178/Amazon][cat: Web/5][2 pkts/181 bytes -> 0 pkts/0 bytes]
+ 33 TCP 10.24.82.188:58927 -> 54.255.253.199:5223 [proto: 64.178/SSL_No_Cert.Amazon][cat: Web/5][2 pkts/181 bytes -> 0 pkts/0 bytes]
34 UDP 10.24.82.188:43077 <-> 10.188.1.1:53 [proto: 5.193/DNS.KakaoTalk][cat: VoIP/10][1 pkts/81 bytes <-> 1 pkts/97 bytes][Host: dn-l.talk.kakao.com]
35 TCP 10.24.82.188:34686 -> 173.194.72.188:5228 [proto: 126/Google][cat: Web/5][1 pkts/164 bytes -> 0 pkts/0 bytes]
36 ICMP 10.24.82.188:0 -> 10.188.191.1:0 [proto: 81/ICMP][cat: Network/14][1 pkts/147 bytes -> 0 pkts/0 bytes]
diff --git a/tests/result/whatsapp_login_call.pcap.out b/tests/result/whatsapp_login_call.pcap.out
index 0fa82a7df..666b3d70a 100644
--- a/tests/result/whatsapp_login_call.pcap.out
+++ b/tests/result/whatsapp_login_call.pcap.out
@@ -2,13 +2,13 @@ Unknown 27 2322 2
HTTP 11 726 3
MDNS 8 952 4
DHCP 10 3420 1
-STUN 70 9464 14
ICMP 10 700 1
SSL 8 589 2
Dropbox 4 2176 1
Apple 105 22176 19
WhatsApp 182 25154 2
Spotify 3 258 1
+Messenger 70 9464 14
WhatsAppVoice 706 91156 4
AppleStore 85 28087 2
ApplePush 22 5926 1
@@ -26,20 +26,20 @@ ApplePush 22 5926 1
11 UDP 192.168.2.1:17500 -> 192.168.2.255:17500 [proto: 121/Dropbox][cat: Cloud/13][4 pkts/2176 bytes -> 0 pkts/0 bytes]
12 TCP 192.168.2.4:49199 <-> 17.172.100.70:993 [proto: 51.140/IMAPS.Apple][cat: Web/5][9 pkts/1130 bytes <-> 8 pkts/868 bytes]
13 ICMP 192.168.2.4:0 -> 91.253.176.65:0 [proto: 81/ICMP][cat: Network/14][10 pkts/700 bytes -> 0 pkts/0 bytes]
- 14 UDP 192.168.2.4:51518 <-> 31.13.64.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 15 UDP 192.168.2.4:51518 <-> 31.13.70.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 16 UDP 192.168.2.4:51518 <-> 31.13.73.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 17 UDP 192.168.2.4:51518 <-> 31.13.79.192:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 18 UDP 192.168.2.4:51518 <-> 31.13.85.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 19 UDP 192.168.2.4:51518 <-> 31.13.91.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 20 UDP 192.168.2.4:51518 <-> 31.13.100.14:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 21 UDP 192.168.2.4:52794 <-> 31.13.73.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 22 UDP 192.168.2.4:52794 <-> 31.13.74.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 23 UDP 192.168.2.4:52794 <-> 31.13.79.192:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 24 UDP 192.168.2.4:52794 <-> 31.13.90.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 25 UDP 192.168.2.4:52794 <-> 31.13.93.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 26 UDP 192.168.2.4:52794 <-> 173.252.114.1:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 27 UDP 192.168.2.4:52794 <-> 179.60.192.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 14 UDP 192.168.2.4:51518 <-> 31.13.64.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 15 UDP 192.168.2.4:51518 <-> 31.13.70.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 16 UDP 192.168.2.4:51518 <-> 31.13.73.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 17 UDP 192.168.2.4:51518 <-> 31.13.79.192:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 18 UDP 192.168.2.4:51518 <-> 31.13.85.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 19 UDP 192.168.2.4:51518 <-> 31.13.91.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 20 UDP 192.168.2.4:51518 <-> 31.13.100.14:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 21 UDP 192.168.2.4:52794 <-> 31.13.73.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 22 UDP 192.168.2.4:52794 <-> 31.13.74.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 23 UDP 192.168.2.4:52794 <-> 31.13.79.192:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 24 UDP 192.168.2.4:52794 <-> 31.13.90.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 25 UDP 192.168.2.4:52794 <-> 31.13.93.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 26 UDP 192.168.2.4:52794 <-> 173.252.114.1:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 27 UDP 192.168.2.4:52794 <-> 179.60.192.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
28 TCP 192.168.2.4:49172 <-> 23.50.148.228:443 [proto: 91/SSL][cat: Web/5][3 pkts/174 bytes <-> 2 pkts/217 bytes]
29 TCP 192.168.2.4:49192 <-> 93.186.135.8:80 [proto: 7/HTTP][cat: Web/5][3 pkts/198 bytes <-> 2 pkts/132 bytes]
30 UDP 192.168.2.4:51897 <-> 192.168.2.1:53 [proto: 5.140/DNS.Apple][cat: Web/5][1 pkts/79 bytes <-> 1 pkts/251 bytes][Host: query.ess.apple.com]
diff --git a/tests/result/whatsapp_voice_and_message.pcap.out b/tests/result/whatsapp_voice_and_message.pcap.out
index e14163cbd..a8bd6e497 100644
--- a/tests/result/whatsapp_voice_and_message.pcap.out
+++ b/tests/result/whatsapp_voice_and_message.pcap.out
@@ -1,17 +1,16 @@
-SkypeCallIn 9 1184 1
-STUN 35 4732 7
WhatsApp 217 22139 5
+Messenger 44 5916 8
1 TCP 10.8.0.1:42241 <-> 173.192.222.189:5222 [proto: 142/WhatsApp][cat: Chat/9][30 pkts/2539 bytes <-> 32 pkts/3070 bytes]
2 TCP 10.8.0.1:35480 <-> 184.173.179.46:443 [proto: 142/WhatsApp][cat: Chat/9][24 pkts/3029 bytes <-> 22 pkts/1961 bytes]
3 TCP 10.8.0.1:44819 <-> 158.85.58.42:5222 [proto: 142/WhatsApp][cat: Chat/9][15 pkts/2690 bytes <-> 15 pkts/2019 bytes]
4 TCP 10.8.0.1:49721 <-> 158.85.58.109:5222 [proto: 142/WhatsApp][cat: Chat/9][26 pkts/2311 bytes <-> 26 pkts/2300 bytes]
5 TCP 10.8.0.1:51570 <-> 158.85.5.199:443 [proto: 142/WhatsApp][cat: Chat/9][14 pkts/1123 bytes <-> 13 pkts/1097 bytes]
- 6 UDP 10.8.0.1:53620 <-> 31.13.73.48:3478 [proto: 125.49/Skype.SkypeCallIn][cat: VoIP/10][5 pkts/840 bytes <-> 4 pkts/344 bytes]
- 7 UDP 10.8.0.1:53620 <-> 31.13.64.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 8 UDP 10.8.0.1:53620 <-> 31.13.74.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 9 UDP 10.8.0.1:53620 <-> 31.13.79.192:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 10 UDP 10.8.0.1:53620 <-> 31.13.84.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 11 UDP 10.8.0.1:53620 <-> 31.13.93.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 12 UDP 10.8.0.1:53620 <-> 173.252.121.1:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
- 13 UDP 10.8.0.1:53620 <-> 179.60.192.48:3478 [proto: 119.78/Facebook.STUN][cat: Network/14][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 6 UDP 10.8.0.1:53620 <-> 31.13.73.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][5 pkts/840 bytes <-> 4 pkts/344 bytes]
+ 7 UDP 10.8.0.1:53620 <-> 31.13.64.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 8 UDP 10.8.0.1:53620 <-> 31.13.74.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 9 UDP 10.8.0.1:53620 <-> 31.13.79.192:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 10 UDP 10.8.0.1:53620 <-> 31.13.84.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 11 UDP 10.8.0.1:53620 <-> 31.13.93.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 12 UDP 10.8.0.1:53620 <-> 173.252.121.1:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]
+ 13 UDP 10.8.0.1:53620 <-> 179.60.192.48:3478 [proto: 78.157/STUN.Messenger][cat: Chat/9][3 pkts/504 bytes <-> 2 pkts/172 bytes]