aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md22
-rw-r--r--configure.ac2
-rw-r--r--example/ndpiReader.c260
-rw-r--r--libndpi.sym5
-rw-r--r--src/include/linux_compat.h88
-rw-r--r--src/include/ndpi_main.h7
-rw-r--r--src/include/ndpi_protocol_ids.h4
-rw-r--r--src/include/ndpi_protocols.h4
-rw-r--r--src/include/ndpi_typedefs.h8
-rw-r--r--src/lib/Makefile.am2
-rw-r--r--src/lib/ndpi_content_match.c.inc8
-rw-r--r--src/lib/ndpi_main.c92
-rw-r--r--src/lib/protocols/dcerpc.c19
-rw-r--r--src/lib/protocols/hep.c68
-rw-r--r--src/lib/protocols/kakaotalk_voice.c2
-rw-r--r--src/lib/protocols/mail_smtp.c8
-rw-r--r--src/lib/protocols/skype.c4
-rw-r--r--src/lib/protocols/steam.c1
-rw-r--r--src/lib/protocols/tcp_udp.c4
-rw-r--r--src/lib/protocols/ubntac2.c63
-rw-r--r--tests/pcap/webex.pcapbin0 -> 890207 bytes
-rw-r--r--tests/result/NTPv3.pcap.out4
-rw-r--r--tests/result/README.txt5
-rw-r--r--tests/result/webex.pcap.out68
24 files changed, 603 insertions, 145 deletions
diff --git a/README.md b/README.md
index 6209069e2..4061e3231 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,13 @@
-# What is nDPI ?
+![ntop][ntopng_logo] ![ntop][ntop_logo]
+# nDPI
+
+[![Build Status](https://travis-ci.org/ntop/nDPI.png?branch=master)](https://travis-ci.org/ntop/nDPI)
+
+## What is nDPI ?
nDPI is an open source LGPLv3 library for deep-packet inspection. Based on OpenDPI it includes ntop extensions. We have tried to push them into the OpenDPI source tree but nobody answered emails so we have decided to create our own source tree
-# How To Compile nDPI
+### How To Compile nDPI
In order to compile this library do
@@ -14,7 +19,7 @@ Please note that the pre-requisites for compilation include:
- GNU tools (autogen, automake, autoconf, libtool)
- GNU C compiler (gcc)
-# How To Add A New Protocol Dissector
+### How To Add A New Protocol Dissector
The entire procedure of adding new protocols in detail:
@@ -30,13 +35,18 @@ The entire procedure of adding new protocols in detail:
10. ./configure
11. make
-# Creating A Source File Tar Ball
+### Creating A Source File Tar Ball
If you want to distribute a source tar file of nDPI do:
- make dist
-# Acknowledgements
+### Acknowledgements
+
+Many thanks to <A HREF=http://www.radcom.com>Radcom</A> Ltd for supporting the development of nDPI.
+
+
+[ntopng_logo]: https://camo.githubusercontent.com/0f789abcef232035c05e0d2e82afa3cc3be46485/687474703a2f2f7777772e6e746f702e6f72672f77702d636f6e74656e742f75706c6f6164732f323031312f30382f6e746f706e672d69636f6e2d313530783135302e706e67
-Many thanks to <A HREF=http://www.radcom.com>Radcom</A> Ltd for supporting the development of nDPI. \ No newline at end of file
+[ntop_logo]: https://camo.githubusercontent.com/58e2a1ecfff62d8ecc9d74633bd1013f26e06cba/687474703a2f2f7777772e6e746f702e6f72672f77702d636f6e74656e742f75706c6f6164732f323031352f30352f6e746f702e706e67
diff --git a/configure.ac b/configure.ac
index 403c57417..d2dfc4357 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,7 +46,7 @@ fi
if test -f $PCAP_HOME/libpcap/libpcap.a; then :
echo "Using libpcap from $PCAP_HOME"
PCAP_INC="-I $PCAP_HOME/libpcap"
- PCAP_LIB="$PCAP_HOME/libpcap/libpcap.a $PCAP_HOME/lib/libpfring.a $LIBNUMA"
+ PCAP_LIB="$PCAP_HOME/libpcap/libpcap.a $PCAP_HOME/lib/libpfring.a $LIBNUMA `$PCAP_HOME/lib/pfring_config --libs`"
AC_CHECK_LIB([rt], [clock_gettime], [PCAP_LIB="$PCAP_LIB -lrt"])
AC_CHECK_LIB([nl], [nl_handle_alloc], [PCAP_LIB="$PCAP_LIB -lnl"])
diff --git a/example/ndpiReader.c b/example/ndpiReader.c
index 73166761f..71bb1f352 100644
--- a/example/ndpiReader.c
+++ b/example/ndpiReader.c
@@ -54,6 +54,35 @@
#include <sys/socket.h>
#define MAX_NUM_READER_THREADS 16
+#define IDLE_SCAN_PERIOD 10 /* msec (use detection_tick_resolution = 1000) */
+#define MAX_IDLE_TIME 30000
+#define IDLE_SCAN_BUDGET 1024
+#define NUM_ROOTS 512
+#define GTP_U_V1_PORT 2152
+#define TZSP_PORT 37008
+#define MAX_NDPI_FLOWS 200000000
+
+#ifndef ETH_P_IP
+#define ETH_P_IP 0x0800 /* IPv4 */
+#endif
+
+#ifndef ETH_P_IPv6
+#define ETH_P_IPV6 0x86dd /* IPv6 */
+#endif
+
+#define VLAN 0x8100
+#define MPLS 0x8847
+#define PPPoE 0x8864
+
+/* mask for FCF */
+#define WIFI_DATA 0x2 /* 0000 0010 */
+#define FCF_TYPE(fc) (((fc) >> 2) & 0x3) /* 0000 0011 = 0x3 */
+#define FCF_SUBTYPE(fc) (((fc) >> 4) & 0xF) /* 0000 1111 = 0xF */
+#define FCF_TO_DS(fc) ((fc) & 0x0100)
+#define FCF_FROM_DS(fc) ((fc) & 0x0200)
+
+/* mask for Bad FCF presence */
+#define BAD_FCS 0x50 /* 0101 0000 */
/**
* @brief Set main components necessary to the detection
@@ -100,12 +129,6 @@ static u_int32_t detection_tick_resolution = 1000;
static time_t capture_for = 0;
static time_t capture_until = 0;
-#define IDLE_SCAN_PERIOD 10 /* msec (use detection_tick_resolution = 1000) */
-#define MAX_IDLE_TIME 30000
-#define IDLE_SCAN_BUDGET 1024
-
-#define NUM_ROOTS 512
-
static u_int32_t num_flows;
struct thread_stats {
@@ -143,8 +166,6 @@ struct reader_thread {
static struct reader_thread ndpi_thread_info[MAX_NUM_READER_THREADS];
-#define GTP_U_V1_PORT 2152
-#define MAX_NDPI_FLOWS 200000000
/**
* @brief ID tracking
*/
@@ -155,10 +176,6 @@ typedef struct ndpi_id {
static u_int32_t size_id_struct = 0; // ID tracking structure size
-#ifndef ETH_P_IP
-#define ETH_P_IP 0x0800
-#endif
-
// flow tracking
typedef struct ndpi_flow {
u_int32_t lower_ip;
@@ -207,7 +224,7 @@ static void help(u_int long_help) {
#endif
" -d | Disable protocol guess and use only DPI\n"
" -q | Quiet mode\n"
- " -t | Dissect GTP tunnels\n"
+ " -t | Dissect GTP/TZSP tunnels\n"
" -r | Print nDPI version and git revision\n"
" -w <path> | Write test output on the specified file. This is useful for\n"
" | testing purposes in order to compare results across runs\n"
@@ -478,17 +495,17 @@ static void printFlow(u_int16_t thread_id, struct ndpi_flow *flow) {
if(!json_flag) {
#if 0
fprintf(out, "\t%s [VLAN: %u] %s:%u <-> %s:%u\n",
- ipProto2Name(flow->protocol), flow->vlan_id,
- flow->lower_name, ntohs(flow->lower_port),
- flow->upper_name, ntohs(flow->upper_port));
+ ipProto2Name(flow->protocol), flow->vlan_id,
+ flow->lower_name, ntohs(flow->lower_port),
+ flow->upper_name, ntohs(flow->upper_port));
#else
fprintf(out, "\t%u", ++num_flows);
fprintf(out, "\t%s %s:%u <-> %s:%u ",
- ipProto2Name(flow->protocol),
- flow->lower_name, ntohs(flow->lower_port),
- flow->upper_name, ntohs(flow->upper_port));
+ ipProto2Name(flow->protocol),
+ flow->lower_name, ntohs(flow->lower_port),
+ flow->upper_name, ntohs(flow->upper_port));
if(flow->vlan_id > 0) fprintf(out, "[VLAN: %u]", flow->vlan_id);
@@ -505,7 +522,7 @@ static void printFlow(u_int16_t thread_id, struct ndpi_flow *flow) {
ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, flow->detected_protocol.protocol));
fprintf(out, "[%u pkts/%llu bytes]",
- flow->packets, (long long unsigned int)flow->bytes);
+ flow->packets, (long long unsigned int)flow->bytes);
if(flow->host_server_name[0] != '\0') fprintf(out, "[Host: %s]", flow->host_server_name);
if(flow->ssl.client_certificate[0] != '\0') fprintf(out, "[SSL client: %s]", flow->ssl.client_certificate);
@@ -1525,66 +1542,150 @@ static void openPcapFileOrDevice(u_int16_t thread_id) {
/* ***************************************************** */
-static void pcap_packet_callback(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
+static void pcap_packet_callback(u_char *args,
+ const struct pcap_pkthdr *header,
+ const u_char *packet) {
+
+ /*
+ * Declare pointers to packet headers
+ */
+ /** --- Ethernet header --- **/
const struct ndpi_ethhdr *ethernet;
+
+ /** --- ieee802.11 --- **/
+ /* Radio Tap header */
+ const struct ndpi_radiotap_header *radiotap;
+ /* LLC header */
+ const struct ndpi_llc_header_proto *llc;
+ /* Data frame */
+ const struct ndpi_wifi_data_frame *wifi_data;
+
+ /** --- IP header --- **/
struct ndpi_iphdr *iph;
+ /** --- IPv6 header --- **/
struct ndpi_ip6_hdr *iph6;
+
+ /* lengths and offsets */
+ u_int16_t eth_offset = 0;
+ u_int16_t radio_len;
+ u_int16_t fc;
+ int wifi_data_len;
+ int llc_len;
+ u_int16_t llc_ether_type;
+ u_int32_t fcs;
+
u_int64_t time;
u_int16_t type, ip_offset, ip_len;
u_int16_t frag_off = 0, vlan_id = 0;
u_int8_t proto = 0, vlan_packet = 0;
+ u_int32_t label;
+
u_int16_t thread_id = *((u_int16_t*)args);
- // printf("[ndpiReader] pcap_packet_callback : [%u.%u.%u.%u.%u -> %u.%u.%u.%u.%u]\n", ethernet->h_dest[1],ethernet->h_dest[2],ethernet->h_dest[3],ethernet->h_dest[4],ethernet->h_dest[5],ethernet->h_source[1],ethernet->h_source[2],ethernet->h_source[3],ethernet->h_source[4],ethernet->h_source[5]);
+ int malformed_pkts = 0;
+
+ /* Increment raw packet counter */
ndpi_thread_info[thread_id].stats.raw_packet_count++;
if((capture_until != 0) && (header->ts.tv_sec >= capture_until)) {
if(ndpi_thread_info[thread_id]._pcap_handle != NULL)
pcap_breakloop(ndpi_thread_info[thread_id]._pcap_handle);
-
return;
}
+ /* Check if capture is live or not */
if (!live_capture) {
if (!pcap_start.tv_sec) pcap_start.tv_sec = header->ts.tv_sec, pcap_start.tv_usec = header->ts.tv_usec;
pcap_end.tv_sec = header->ts.tv_sec, pcap_end.tv_usec = header->ts.tv_usec;
}
+ /* setting time */
time = ((uint64_t) header->ts.tv_sec) * detection_tick_resolution +
header->ts.tv_usec / (1000000 / detection_tick_resolution);
- if(ndpi_thread_info[thread_id].last_time > time) { /* safety check */
- // printf("\nWARNING: timestamp bug in the pcap file (ts delta: %llu, repairing)\n", ndpi_thread_info[thread_id].last_time - time);
+ /* safety check */
+ if(ndpi_thread_info[thread_id].last_time > time) {
+ /* printf("\nWARNING: timestamp bug in the pcap file (ts delta: %llu, repairing)\n", ndpi_thread_info[thread_id].last_time - time); */
time = ndpi_thread_info[thread_id].last_time;
}
+ /* update last time value */
ndpi_thread_info[thread_id].last_time = time;
- if(ndpi_thread_info[thread_id]._pcap_datalink_type == DLT_NULL) {
- if(ntohl(*((u_int32_t*)packet)) == 2)
- type = ETH_P_IP;
- else
- type = 0x86DD; /* IPv6 */
-
- ip_offset = 4;
- } else if(ndpi_thread_info[thread_id]._pcap_datalink_type == DLT_EN10MB) {
- ethernet = (struct ndpi_ethhdr *) packet;
- ip_offset = sizeof(struct ndpi_ethhdr);
- type = ntohs(ethernet->h_proto);
- } else if(ndpi_thread_info[thread_id]._pcap_datalink_type == 113 /* Linux Cooked Capture */) {
- type = (packet[14] << 8) + packet[15];
- ip_offset = 16;
- } else
- return;
+ /*** check Data Link type ***/
+ int datalink_type = ndpi_thread_info[thread_id]._pcap_datalink_type;
+
+ datalink_check:
+ switch(datalink_type) {
+ case DLT_NULL :
+ if(ntohl(*((u_int32_t*)&packet[eth_offset])) == 2)
+ type = ETH_P_IP;
+ else
+ type = ETH_P_IPV6;
+
+ ip_offset = 4 + eth_offset;
+
+ case DLT_EN10MB :
+ ethernet = (struct ndpi_ethhdr *) &packet[eth_offset];
+ ip_offset = sizeof(struct ndpi_ethhdr) + eth_offset;
+ type = ntohs(ethernet->h_proto);
+ break;
+
+ /* Linux Cooked Capture - 113 */
+ case DLT_LINUX_SLL :
+ type = (packet[eth_offset+14] << 8) + packet[eth_offset+15];
+ ip_offset = 16 + eth_offset;
+ break;
+
+ /* Radiotap link-layer - 127 */
+ case DLT_IEEE802_11_RADIO :
+ radiotap = (struct ndpi_radiotap_header *) &packet[eth_offset];
+ radio_len = radiotap->len;
+
+ /* Check Bad FCS presence */
+ if((radiotap->flags & BAD_FCS) == BAD_FCS) {
+ malformed_pkts += 1;
+ ndpi_thread_info[thread_id].stats.total_discarded_bytes += header->len;
+ return;
+ }
+
+ fcs = header->len - 4;
+
+ /* Calculate 802.11 header length (variable) */
+ wifi_data = (struct ndpi_wifi_data_frame*)( packet + eth_offset + radio_len);
+ fc = wifi_data->fc;
+
+ /* check wifi data presence */
+ if(FCF_TYPE(fc) == WIFI_DATA) {
+ if((FCF_TO_DS(fc) && FCF_FROM_DS(fc) == 0x0) ||
+ (FCF_TO_DS(fc) == 0x0 && FCF_FROM_DS(fc)))
+ wifi_data_len = 26; /* + 4 byte fcs */
+
+ /* TODO: check QoS Control for aggregated MSDU */
+ } else /* no data frames */
+ break;
+
+ /* Check ether_type from LLC */
+ llc = (struct ndpi_llc_header_proto*)(packet + eth_offset + wifi_data_len + radio_len);
+ llc_ether_type = ntohs(llc->ether_IP_type);
+
+ /* Set IP header offset */
+ ip_offset = wifi_data_len + radio_len + sizeof(struct ndpi_llc_header_proto) + eth_offset;
+ break;
+
+ default:
+ return;
+ }
while(1) {
- if(type == 0x8100 /* VLAN */) {
+ if(type == VLAN) {
vlan_id = ((packet[ip_offset] << 8) + packet[ip_offset+1]) & 0xFFF;
type = (packet[ip_offset+2] << 8) + packet[ip_offset+3];
ip_offset += 4;
vlan_packet = 1;
- } else if(type == 0x8847 /* MPLS */) {
- u_int32_t label = ntohl(*((u_int32_t*)&packet[ip_offset]));
-
+ break;
+ }
+ else if(type == MPLS) {
+ label = ntohl(*((u_int32_t*)&packet[ip_offset]));
ndpi_thread_info[thread_id].stats.mpls_count++;
type = 0x800, ip_offset += 4;
@@ -1592,19 +1693,24 @@ static void pcap_packet_callback(u_char *args, const struct pcap_pkthdr *header,
ip_offset += 4;
label = ntohl(*((u_int32_t*)&packet[ip_offset]));
}
- } else if(type == 0x8864 /* PPPoE */) {
+ break;
+ }
+ else if(type == PPPoE) {
ndpi_thread_info[thread_id].stats.pppoe_count++;
type = 0x0800;
ip_offset += 8;
- } else
break;
- }
+ }
+ else
+ break;
+ } /* while(1) */
ndpi_thread_info[thread_id].stats.vlan_count += vlan_packet;
+ /* Check and set IP header size and total packet length */
iph = (struct ndpi_iphdr *) &packet[ip_offset];
- // just work on Ethernet packets that contain IP
+ /* just work on Ethernet packets that contain IP */
if(type == ETH_P_IP && header->caplen >= ip_offset) {
frag_off = ntohs(iph->frag_off);
@@ -1619,14 +1725,16 @@ static void pcap_packet_callback(u_char *args, const struct pcap_pkthdr *header,
}
}
+ /* Check IP version */
if(iph->version == 4) {
ip_len = ((u_short)iph->ihl * 4);
iph6 = NULL;
if((frag_off & 0x3FFF) != 0) {
- static u_int8_t ipv4_frags_warning_used = 0;
+ static u_int8_t ipv4_frags_warning_used = 0;
ndpi_thread_info[thread_id].stats.fragmented_count++;
+
if(ipv4_frags_warning_used == 0) {
if((!json_flag) && (!quiet_mode)) printf("\n\nWARNING: IPv4 fragments are not handled by this demo (nDPI supports them)\n");
ipv4_frags_warning_used = 1;
@@ -1641,22 +1749,21 @@ static void pcap_packet_callback(u_char *args, const struct pcap_pkthdr *header,
ip_len = sizeof(struct ndpi_ip6_hdr);
if(proto == 0x3C /* IPv6 destination option */) {
- u_int8_t *options = (u_int8_t*)&packet[ip_offset+ip_len];
+ u_int8_t *options = (u_int8_t*)&packet[ip_offset+ip_len];
proto = options[0];
ip_len += 8 * (options[1] + 1);
}
-
iph = NULL;
} else {
static u_int8_t ipv4_warning_used = 0;
v4_warning:
if(ipv4_warning_used == 0) {
- if((!json_flag) && (!quiet_mode)) printf("\n\nWARNING: only IPv4/IPv6 packets are supported in this demo (nDPI supports both IPv4 and IPv6), all other packets will be discarded\n\n");
+ if((!json_flag) && (!quiet_mode))
+ printf("\n\nWARNING: only IPv4/IPv6 packets are supported in this demo (nDPI supports both IPv4 and IPv6), all other packets will be discarded\n\n");
ipv4_warning_used = 1;
}
-
ndpi_thread_info[thread_id].stats.total_discarded_bytes += header->len;
return;
}
@@ -1671,9 +1778,10 @@ static void pcap_packet_callback(u_char *args, const struct pcap_pkthdr *header,
u_int8_t flags = packet[offset];
u_int8_t message_type = packet[offset+1];
- if((((flags & 0xE0) >> 5) == 1 /* GTPv1 */) && (message_type == 0xFF /* T-PDU */)) {
- ip_offset = ip_offset+ip_len+sizeof(struct ndpi_udphdr)+8 /* GTPv1 header len */;
+ if((((flags & 0xE0) >> 5) == 1 /* GTPv1 */) &&
+ (message_type == 0xFF /* T-PDU */)) {
+ ip_offset = ip_offset+ip_len+sizeof(struct ndpi_udphdr)+8; /* GTPv1 header len */
if(flags & 0x04) ip_offset += 1; /* next_ext_header is present */
if(flags & 0x02) ip_offset += 4; /* sequence_number is present (it also includes next_ext_header and pdu_number) */
if(flags & 0x01) ip_offset += 1; /* pdu_number is present */
@@ -1685,10 +1793,48 @@ static void pcap_packet_callback(u_char *args, const struct pcap_pkthdr *header,
goto v4_warning;
}
}
+ } else if((sport == TZSP_PORT) || (dport == TZSP_PORT)) {
+ /* https://en.wikipedia.org/wiki/TZSP */
+ u_int offset = ip_offset+ip_len+sizeof(struct ndpi_udphdr);
+ u_int8_t version = packet[offset];
+ u_int8_t type = packet[offset+1];
+ u_int16_t encapsulates = ntohs(*((u_int16_t*)&packet[offset+2]));
+
+ if((version == 1) && (type == 0) && (encapsulates == 1)) {
+ u_int8_t stop = 0;
+
+ offset += 4;
+
+ while((!stop) && (offset < header->caplen)) {
+ u_int8_t tag_type = packet[offset];
+ u_int8_t tag_len;
+
+ switch(tag_type) {
+ case 0: /* PADDING Tag */
+ tag_len = 1;
+ break;
+ case 1: /* END Tag */
+ tag_len = 1, stop = 1;
+ break;
+ default:
+ tag_len = packet[offset+1];
+ break;
+ }
+
+ offset += tag_len;
+
+ if(offset >= header->caplen)
+ return; /* Invalid packet */
+ else {
+ eth_offset = offset;
+ goto datalink_check;
+ }
+ }
+ }
}
}
- // process the packet
+ /* process the packet */
packet_processing(thread_id, time, vlan_id, iph, iph6,
ip_offset, header->len - ip_offset, header->len);
}
diff --git a/libndpi.sym b/libndpi.sym
index 906e61bfa..43d98f630 100644
--- a/libndpi.sym
+++ b/libndpi.sym
@@ -29,3 +29,8 @@ ndpi_get_proto_by_id
ndpi_get_protocol_id_master_proto
ndpi_guess_protocol_id
ndpi_protocol2name
+ndpi_get_lower_proto
+ndpi_is_proto
+ndpi_malloc
+ndpi_calloc
+ndpi_set_detected_protocol
diff --git a/src/include/linux_compat.h b/src/include/linux_compat.h
index 1410cda67..0497b31d0 100644
--- a/src/include/linux_compat.h
+++ b/src/include/linux_compat.h
@@ -43,21 +43,90 @@
#endif
#pragma pack(push, 1) /* push current alignment to stack */
-#pragma pack(1) /* set alignment to 1 byte boundary */
+#pragma pack(1) /* set alignment to 1 byte boundary */
-#pragma pack(pop) /* restore original alignment from stack */
+#pragma pack(pop) /* restore original alignment from stack */
-struct ndpi_ethhdr {
+
+/* ++++++++++++++++++++++++++++++++++++++++++++++++++ */
+/* +++++++++++ Ethernet data structures +++++++++++++ */
+/* ++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+struct ndpi_ethhdr
+{
u_char h_dest[6]; /* destination eth addr */
u_char h_source[6]; /* source ether addr */
u_int16_t h_proto; /* packet type ID field */
};
-struct ndpi_80211q {
- u_int16_t vlanId;
- u_int16_t protoType;
-};
+/* ++++++++++++++++++++++++++++++++++++++++++++++++++ */
+/* +++++++++++ ieee802.11 data structures +++++++++++ */
+/* ++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+/******* RADIO TAP *******/
+/* radiotap header */
+struct ndpi_radiotap_header
+{
+ u_int8_t version; /* set to 0 */
+ u_int8_t pad;
+ u_int16_t len;
+ u_int32_t present;
+ u_int64_t MAC_timestamp;
+ u_int8_t flags;
+
+} __attribute__((__packed__));
+
+/* Beacon frame */
+struct ndpi_beacon
+{
+ /* header -- 24 byte */
+ u_int16_t fc;
+ u_int16_t duration;
+ u_char rcv_addr[6];
+ u_char trsm_addr[6];
+ u_char bssid[6];
+ u_int16_t seq_ctrl;
+ /* body (variable) */
+ u_int64_t timestamp; /* 802.11 Timestamp value at frame send */
+ u_int16_t beacon_interval; /* Interval at which beacons are send */
+ u_int16_t capability;
+ /** List of information elements **/
+ /* union ndpi_80211_info info_element[0]; */
+} __attribute__((packed));
+
+
+/* Wifi data frame - TODO: specify when addr1 addr2 addr3 is rcv, trams or bssid*/
+struct ndpi_wifi_data_frame
+{
+ u_int16_t fc;
+ u_int16_t duration;
+ u_char addr1[6];
+ u_char addr2[6];
+ u_char addr3[6];
+ u_int16_t seq_ctrl;
+} __attribute__((packed));
+
+/* Logical-Link Control header */
+struct ndpi_llc_header_proto
+{
+ u_int8_t dsap;
+ u_int8_t ssap;
+ u_int8_t ctl;
+ /* u_int8_t pad1; */
+ u_int16_t org;
+ u_int8_t org2;
+ /* u_int8_t pad2; */
+ u_int16_t ether_IP_type;
+} __attribute__((packed));
+
+
+/* ++++++++++++++++++++++++++++++++++++++++++++++++++ */
+/* ++++++++++++++ IP data structures ++++++++++++++++ */
+/* ++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+
+/* IP header */
struct ndpi_iphdr {
#if defined(__LITTLE_ENDIAN__)
u_int8_t ihl:4, version:4;
@@ -166,6 +235,11 @@ struct ndpi_ip6_hdr {
struct ndpi_in6_addr ip6_dst;
};
+/* ++++++++++++++++++++++++++++++++++++++++++++++++++ */
+/* ++++++++ Transport Layer data structures +++++++++ */
+/* ++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+
struct ndpi_tcphdr {
u_int16_t source;
u_int16_t dest;
diff --git a/src/include/ndpi_main.h b/src/include/ndpi_main.h
index adec3edf1..1acc5e14f 100644
--- a/src/include/ndpi_main.h
+++ b/src/include/ndpi_main.h
@@ -143,13 +143,6 @@ extern int ndpi_get_protocol_id_master_proto(struct ndpi_detection_module_struct
u_int16_t** tcp_master_proto,
u_int16_t** udp_master_proto);
-extern u_int8_t ndpi_net_match(u_int32_t ip_to_check,
- u_int32_t net,
- u_int32_t num_bits);
-
-extern u_int8_t ndpi_ips_match(u_int32_t src, u_int32_t dst,
- u_int32_t net, u_int32_t num_bits);
-
#ifdef NDPI_ENABLE_DEBUG_MESSAGES
void ndpi_debug_get_last_log_function_line(struct ndpi_detection_module_struct *ndpi_struct,
const char **file, const char **func, u_int32_t * line);
diff --git a/src/include/ndpi_protocol_ids.h b/src/include/ndpi_protocol_ids.h
index cfb5897ba..8a94db2ce 100644
--- a/src/include/ndpi_protocol_ids.h
+++ b/src/include/ndpi_protocol_ids.h
@@ -201,6 +201,8 @@
#define NDPI_PROTOCOL_WHATSAPP_VOICE 189
#define NDPI_PROTOCOL_STARCRAFT 213 /* Matteo Bracci <matteobracci1@gmail.com> */
#define NDPI_PROTOCOL_TEREDO 214
+#define NDPI_PROTOCOL_HEP 216 /* Sipcapture.org QXIP BV */
+#define NDPI_PROTOCOL_UBNTAC2 217 /* Ubiquity UBNT AirControl 2 - Thomas Fjellstrom <thomas+ndpi@fjellstrom.ca> */
#define NDPI_CONTENT_AVI 39
#define NDPI_CONTENT_FLASH 40
@@ -263,7 +265,7 @@
#define NDPI_SERVICE_HOTSPOT_SHIELD 215
/* UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE */
-#define NDPI_LAST_IMPLEMENTED_PROTOCOL NDPI_SERVICE_HOTSPOT_SHIELD
+#define NDPI_LAST_IMPLEMENTED_PROTOCOL NDPI_PROTOCOL_UBNTAC2
#define NDPI_MAX_SUPPORTED_PROTOCOLS (NDPI_LAST_IMPLEMENTED_PROTOCOL + 1)
#define NDPI_MAX_NUM_CUSTOM_PROTOCOLS (NDPI_NUM_BITS-NDPI_LAST_IMPLEMENTED_PROTOCOL)
diff --git a/src/include/ndpi_protocols.h b/src/include/ndpi_protocols.h
index 6171f00bc..963aac6f2 100644
--- a/src/include/ndpi_protocols.h
+++ b/src/include/ndpi_protocols.h
@@ -72,6 +72,7 @@ void ndpi_search_oscar(struct ndpi_detection_module_struct *ndpi_struct, struct
void ndpi_search_jabber_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
void ndpi_search_irc_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
void ndpi_search_sip(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_hep(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
void ndpi_search_direct_download_link_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
void ndpi_search_mail_pop_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
@@ -195,6 +196,7 @@ void ndpi_search_eaq(struct ndpi_detection_module_struct *ndpi_struct, struct nd
void ndpi_search_kakaotalk_voice(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
void ndpi_search_mpegts(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
void ndpi_search_starcraft(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_ubntac2(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
/* --- INIT FUNCTIONS --- */
@@ -288,6 +290,7 @@ void init_rtsp_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int
void init_sflow_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask);
void init_shoutcast_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask);
void init_sip_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask);
+void init_hep_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask);
void init_skinny_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask);
void init_skype_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask);
void init_smb_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask);
@@ -332,5 +335,6 @@ void init_yahoo_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_in
void init_zattoo_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask);
void init_zmq_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask);
void init_stracraft_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask);
+void init_ubntac2_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask);
#endif /* __NDPI_PROTOCOLS_INCLUDE_FILE__ */
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index 8ea4650a6..7f82d0a28 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -672,12 +672,10 @@ typedef struct ndpi_flow_struct {
u_int16_t protocol_stack_info;
/* init parameter, internal used to set up timestamp,... */
- u_int16_t guessed_protocol_id;
+ u_int16_t guessed_protocol_id, guessed_host_proto_id;
- u_int8_t protocol_id_already_guessed:1;
- u_int8_t init_finished:1;
- u_int8_t setup_packet_direction:1;
- u_int8_t packet_direction:1; /* if ndpi_struct->direction_detect_disable == 1 */
+ u_int8_t protocol_id_already_guessed:1, host_already_guessed:1, init_finished:1, setup_packet_direction:1, packet_direction:1;
+ /* if ndpi_struct->direction_detect_disable == 1 */
/* tcp sequence number connection tracking */
u_int32_t next_tcp_seq_nr[2];
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 4e8b1f6c4..ee395f5cd 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -52,6 +52,7 @@ libndpi_la_SOURCES = ndpi_content_match.c.inc \
protocols/guildwars.c \
protocols/h323.c \
protocols/halflife2_and_mods.c \
+ protocols/hep.c \
protocols/http_activesync.c \
protocols/http.c \
protocols/iax.c \
@@ -139,6 +140,7 @@ libndpi_la_SOURCES = ndpi_content_match.c.inc \
protocols/tvants.c \
protocols/tvuplayer.c \
protocols/twitter.c \
+ protocols/ubntac2.c \
protocols/usenet.c \
protocols/veohtv.c \
protocols/viber.c \
diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc
index 5e0210d71..c2d219e5f 100644
--- a/src/lib/ndpi_content_match.c.inc
+++ b/src/lib/ndpi_content_match.c.inc
@@ -7320,10 +7320,13 @@ ndpi_protocol_match host_match[] = {
{ ".cnn.c", "CNN", NDPI_SERVICE_CNN, NDPI_PROTOCOL_FUN },
{ ".cnn.net", "CNN", NDPI_SERVICE_CNN, NDPI_PROTOCOL_FUN },
{ ".dropbox.com", "DropBox", NDPI_SERVICE_DROPBOX, NDPI_PROTOCOL_SAFE },
+ { ".ebay.", "eBay", NDPI_SERVICE_EBAY, NDPI_PROTOCOL_ACCEPTABLE },
{ ".ebay.com", "eBay", NDPI_SERVICE_EBAY, NDPI_PROTOCOL_ACCEPTABLE },
{ ".ebaystatic.com", "eBay", NDPI_SERVICE_EBAY, NDPI_PROTOCOL_ACCEPTABLE },
{ ".ebaydesc.com", "eBay", NDPI_SERVICE_EBAY, NDPI_PROTOCOL_ACCEPTABLE },
{ ".ebayrtm.com", "eBay", NDPI_SERVICE_EBAY, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".ebaystratus.com", "eBay", NDPI_SERVICE_EBAY, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".ebayimg.com", "eBay", NDPI_SERVICE_EBAY, NDPI_PROTOCOL_ACCEPTABLE },
{ ".facebook.com", "Facebook", NDPI_SERVICE_FACEBOOK, NDPI_PROTOCOL_FUN },
{ ".fbcdn.net", "Facebook", NDPI_SERVICE_FACEBOOK, NDPI_PROTOCOL_FUN },
{ "fbcdn-", "Facebook", NDPI_SERVICE_FACEBOOK, NDPI_PROTOCOL_FUN }, /* fbcdn-video-a-akamaihd.net */
@@ -7349,7 +7352,7 @@ ndpi_protocol_match host_match[] = {
{ "nflxext.com", "NetFlix", NDPI_SERVICE_NETFLIX, NDPI_PROTOCOL_FUN },
{ "nflximg.com", "NetFlix", NDPI_SERVICE_NETFLIX, NDPI_PROTOCOL_FUN },
{ "nflximg.net", "NetFlix", NDPI_SERVICE_NETFLIX, NDPI_PROTOCOL_FUN },
-
+ { "nflxvideo.net", "NetFlix", NDPI_SERVICE_NETFLIX, NDPI_PROTOCOL_FUN },
{ ".skype.", "Skype", NDPI_SERVICE_SKYPE, NDPI_PROTOCOL_ACCEPTABLE },
{ ".skypeassets.", "Skype", NDPI_SERVICE_SKYPE, NDPI_PROTOCOL_ACCEPTABLE },
{ ".skypedata.", "Skype", NDPI_SERVICE_SKYPE, NDPI_PROTOCOL_ACCEPTABLE },
@@ -7365,7 +7368,7 @@ ndpi_protocol_match host_match[] = {
{ "wikimediafoundation.", "Wikipedia", NDPI_SERVICE_WIKIPEDIA, NDPI_PROTOCOL_ACCEPTABLE },
{ ".whatsapp.net", "WhatsApp", NDPI_SERVICE_WHATSAPP, NDPI_PROTOCOL_ACCEPTABLE },
{ ".yahoo.", "Yahoo", NDPI_SERVICE_YAHOO, NDPI_PROTOCOL_ACCEPTABLE },
- { "yimg.com", "Yahoo", NDPI_SERVICE_YAHOO, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".yimg.com", "Yahoo", NDPI_SERVICE_YAHOO, NDPI_PROTOCOL_ACCEPTABLE },
{ "yahooapis.", "Yahoo", NDPI_SERVICE_YAHOO, NDPI_PROTOCOL_ACCEPTABLE },
{ "youtube.", "YouTube", NDPI_SERVICE_YOUTUBE, NDPI_PROTOCOL_FUN },
{ ".googlevideo.com", "YouTube", NDPI_SERVICE_YOUTUBE, NDPI_PROTOCOL_FUN },
@@ -7417,6 +7420,7 @@ ndpi_protocol_match host_match[] = {
{ "worldofwarcraft.com", "WorldOfWarcraft", NDPI_PROTOCOL_WORLDOFWARCRAFT, NDPI_PROTOCOL_FUN },
{ ".anchorfree.", "HotspotShield", NDPI_SERVICE_HOTSPOT_SHIELD, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS },
{ "hotspotshield.com", "HotspotShield", NDPI_SERVICE_HOTSPOT_SHIELD, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS },
+ { ".webex.com", "Webex", NDPI_PROTOCOL_WEBEX, NDPI_PROTOCOL_ACCEPTABLE },
{ NULL, 0 }
};
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index 5fb0b6cd8..5fe7e61af 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -833,6 +833,11 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
no_master, "IPP",
ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_HEP,
+ no_master,
+ no_master, "HEP",
+ ndpi_build_default_ports(ports_a, 9064, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 9063, 0, 0, 0, 0) /* UDP */);
ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_HTTP,
no_master,
no_master, "HTTP",
@@ -1622,7 +1627,12 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
no_master, "Starcraft",
ndpi_build_default_ports(ports_a, 1119, 0, 0, 0, 0), /* TCP */
ndpi_build_default_ports(ports_b, 1119, 0, 0, 0, 0)); /* UDP */
-
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_UBNTAC2,
+ no_master,
+ no_master, "UBNTAC2",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */
+ ndpi_build_default_ports(ports_b, 10001, 0, 0, 0, 0)); /* UDP */
+
/* calling function for host and content matched protocols */
init_string_based_protocols(ndpi_mod);
@@ -1666,20 +1676,20 @@ static int fill_prefix_v4(prefix_t *p, struct in_addr *a, int b, int mb) {
/* ******************************************* */
-u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, struct in_addr *pin) {
+u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, struct in_addr *pin /* network byte order */) {
prefix_t prefix;
patricia_node_t *node;
- pin->s_addr = ntohl(pin->s_addr); /* Make sure all in network byte order otherwise compares wont work */
+ /* Make sure all in network byte order otherwise compares wont work */
fill_prefix_v4(&prefix, pin, 32, ((patricia_tree_t*)ndpi_struct->protocols_ptree)->maxbits);
node = ndpi_patricia_search_best(ndpi_struct->protocols_ptree, &prefix);
-
+
return(node ? node->value.user_value : NDPI_PROTOCOL_UNKNOWN);
}
/* ******************************************* */
-u_int16_t ndpi_host_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t host) {
+u_int16_t ndpi_host_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t host /* network byte order */) {
struct in_addr pin;
pin.s_addr = host;
@@ -1700,11 +1710,9 @@ u_int8_t ndpi_is_tor_flow(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_packet_struct *packet = &flow->packet;
if(packet->tcp != NULL) {
- if(flow->packet.iph) {
- struct in_addr saddr = { packet->iph->saddr };
- struct in_addr daddr = { packet->iph->daddr };
- if(tor_ptree_match(ndpi_struct, &saddr)
- || tor_ptree_match(ndpi_struct, &daddr)) {
+ if(packet->iph) {
+ if(tor_ptree_match(ndpi_struct, (struct in_addr *)&packet->iph->saddr)
+ || tor_ptree_match(ndpi_struct, (struct in_addr *)&packet->iph->daddr)) {
return(1);
}
}
@@ -1736,7 +1744,7 @@ static void ndpi_init_ptree_ipv4(struct ndpi_detection_module_struct *ndpi_str,
struct in_addr pin;
patricia_node_t *node;
- pin.s_addr = ntohl(host_list[i].network);
+ pin.s_addr = htonl(host_list[i].network);
if((node = add_to_ptree(ptree, AF_INET, &pin, host_list[i].cidr /* bits */)) != NULL)
node->value.user_value = host_list[i].value;
}
@@ -1745,19 +1753,18 @@ static void ndpi_init_ptree_ipv4(struct ndpi_detection_module_struct *ndpi_str,
/* ******************************************* */
static int ndpi_add_host_ip_subprotocol(struct ndpi_detection_module_struct *ndpi_struct,
- char *value, int protocol_id) {
-
- patricia_node_t *node;
- struct in_addr pin;
+ char *value, int protocol_id) {
- inet_pton(AF_INET, value, &pin);
- pin.s_addr = ntohl(pin.s_addr);
-
- if((node = add_to_ptree(ndpi_struct->protocols_ptree, AF_INET, &pin, 32)) != NULL) {
- node->value.user_value = protocol_id;
- }
+ patricia_node_t *node;
+ struct in_addr pin;
+
+ inet_pton(AF_INET, value, &pin);
+
+ if((node = add_to_ptree(ndpi_struct->protocols_ptree, AF_INET, &pin, 32)) != NULL) {
+ node->value.user_value = protocol_id;
+ }
- return(0);
+ return(0);
}
#endif
@@ -1891,13 +1898,16 @@ u_int16_t ndpi_guess_protocol_id(struct ndpi_detection_module_struct *ndpi_struc
ndpi_default_ports_tree_node_t node;
if(sport && dport) {
- node.default_port = sport;
+ int low = ndpi_min(sport, dport);
+ int high = ndpi_max(sport, dport);
+
+ node.default_port = low; /* Check server port first */
ret = ndpi_tfind(&node,
(proto == IPPROTO_TCP) ? (void*)&ndpi_struct->tcpRoot : (void*)&ndpi_struct->udpRoot,
ndpi_default_ports_tree_node_t_cmp);
if(ret == NULL) {
- node.default_port = dport;
+ node.default_port = high;
ret = ndpi_tfind(&node,
(proto == IPPROTO_TCP) ? (void*)&ndpi_struct->tcpRoot : (void*)&ndpi_struct->udpRoot,
ndpi_default_ports_tree_node_t_cmp);
@@ -2250,6 +2260,9 @@ void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *n
/* SIP */
init_sip_dissector(ndpi_struct, &a, detection_bitmask);
+ /* HEP */
+ init_hep_dissector(ndpi_struct, &a, detection_bitmask);
+
/* BITTORRENT */
init_bittorrent_dissector(ndpi_struct, &a, detection_bitmask);
@@ -2622,6 +2635,8 @@ void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *n
/* MPEGTS */
init_mpegts_dissector(ndpi_struct, &a, detection_bitmask);
+ /* UBNTAC2 */
+ init_ubntac2_dissector(ndpi_struct, &a, detection_bitmask);
/* ----------------------------------------------------------------- */
@@ -3418,23 +3433,30 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
} else
ret.protocol = flow->detected_protocol_stack[0];
-
- if((ret.master_protocol == NDPI_PROTOCOL_UNKNOWN) && flow->packet.iph) {
- struct in_addr pin = { flow->packet.iph->saddr };
-
- if((ret.master_protocol = ndpi_network_ptree_match(ndpi_struct, &pin)) == NDPI_PROTOCOL_UNKNOWN) {
- pin.s_addr = flow->packet.iph->daddr;
- ret.master_protocol = ndpi_network_ptree_match(ndpi_struct, &pin);
+ if((ret.protocol == NDPI_PROTOCOL_UNKNOWN)
+ && flow->packet.iph
+ && (!flow->host_already_guessed)) {
+
+ if((flow->guessed_host_proto_id = ndpi_network_ptree_match(ndpi_struct, (struct in_addr *)&flow->packet.iph->saddr)) == NDPI_PROTOCOL_UNKNOWN) {
+ flow->guessed_host_proto_id = ndpi_network_ptree_match(ndpi_struct, (struct in_addr *)&flow->packet.iph->daddr);
}
+
+ flow->host_already_guessed = 1;
+ }
+
+#if 0
- /* Swap proocols in case of success */
+ /* Swap protocols in case of success */
if(ret.master_protocol != NDPI_PROTOCOL_UNKNOWN) {
u_int16_t t = ret.master_protocol;
ret.master_protocol = ret.protocol;
ret.protocol = t;
}
- }
+#endif
+
+ if((ret.protocol == NDPI_PROTOCOL_UNKNOWN) && (ret.master_protocol != NDPI_PROTOCOL_UNKNOWN))
+ ret.protocol = flow->guessed_host_proto_id;
return(ret);
}
@@ -4239,11 +4261,11 @@ ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct
return(ret);
check_guessed_skype:
- addr.s_addr = shost;
+ addr.s_addr = htonl(shost);
if(ndpi_network_ptree_match(ndpi_struct, &addr) == NDPI_PROTOCOL_SKYPE) {
ret.protocol = NDPI_PROTOCOL_SKYPE;
} else {
- addr.s_addr = dhost;
+ addr.s_addr = htonl(dhost);
if(ndpi_network_ptree_match(ndpi_struct, &addr) == NDPI_PROTOCOL_SKYPE)
ret.protocol = NDPI_PROTOCOL_SKYPE;
}
diff --git a/src/lib/protocols/dcerpc.c b/src/lib/protocols/dcerpc.c
index 2537afd56..ec96d1287 100644
--- a/src/lib/protocols/dcerpc.c
+++ b/src/lib/protocols/dcerpc.c
@@ -18,7 +18,7 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with nDPI. If not, see <http://www.gnu.org/licenses/>.
- *
+ *
*/
@@ -35,20 +35,23 @@ static void ndpi_int_dcerpc_add_connection(struct ndpi_detection_module_struct
void ndpi_search_dcerpc(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
{
struct ndpi_packet_struct *packet = &flow->packet;
-
- if((packet->tcp != NULL)
- && (packet->payload_packet_len > 64)
- && ((ntohs(packet->tcp->source) == 135) || (ntohs(packet->tcp->dest) == 135))
+ u_int16_t len_packet = (packet->payload[9]<<8) | packet->payload[8];
+
+ if((packet->tcp != NULL)
+ && (packet->payload_packet_len >= 64)
&& (packet->payload[0] == 0x05) /* version 5 */
&& (packet->payload[2] < 16) /* Packet type */
- ) {
- NDPI_LOG(NDPI_PROTOCOL_DCERPC, ndpi_struct, NDPI_LOG_DEBUG, "DCERPC match\n");
+ && (len_packet == packet->payload_packet_len) /* Packet Length */
+ ) {
+ NDPI_LOG(NDPI_PROTOCOL_DCERPC, ndpi_struct, NDPI_LOG_DEBUG, "DCERPC match\n");
ndpi_int_dcerpc_add_connection(ndpi_struct, flow);
return;
}
- NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DCERPC);
+ if(packet->payload_packet_len>1){
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DCERPC);
+ }
}
diff --git a/src/lib/protocols/hep.c b/src/lib/protocols/hep.c
new file mode 100644
index 000000000..516e430e7
--- /dev/null
+++ b/src/lib/protocols/hep.c
@@ -0,0 +1,68 @@
+/*
+ * hep.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ * Copyright (C) 2011-15 - QXIP BV
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_HEP
+
+static void ndpi_int_hep_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_HEP, NDPI_PROTOCOL_UNKNOWN);
+}
+
+void ndpi_search_hep(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ const u_int8_t *packet_payload = packet->payload;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ NDPI_LOG(NDPI_PROTOCOL_HEP, ndpi_struct, NDPI_LOG_DEBUG, "searching for HEP.\n");
+ if (payload_len > 10) {
+ if (memcmp(packet_payload, "HEP3", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HEP, ndpi_struct, NDPI_LOG_DEBUG, "found HEP3.\n");
+ ndpi_int_hep_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_HEP, ndpi_struct, NDPI_LOG_DEBUG, "exclude HEP.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_HEP);
+}
+
+
+void init_hep_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
+{
+ ndpi_set_bitmask_protocol_detection("HEP", ndpi_struct, detection_bitmask, *id,
+ NDPI_PROTOCOL_HEP,
+ ndpi_search_hep,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+
+ *id += 1;
+}
+
+#endif
diff --git a/src/lib/protocols/kakaotalk_voice.c b/src/lib/protocols/kakaotalk_voice.c
index 38596e41d..daa97cc36 100644
--- a/src/lib/protocols/kakaotalk_voice.c
+++ b/src/lib/protocols/kakaotalk_voice.c
@@ -56,7 +56,7 @@ void ndpi_search_kakaotalk_voice(struct ndpi_detection_module_struct *ndpi_struc
}
}
- NDPI_LOG(NDPI_PROTOCOL_KAKAOTALK_VOICE, ndpi_struct, NDPI_LOG_DEBUG, "Exclude kakaotalk_voice.\n");
+ NDPI_LOG(NDPI_SERVICE_KAKAOTALK_VOICE, ndpi_struct, NDPI_LOG_DEBUG, "Exclude kakaotalk_voice.\n");
NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_SERVICE_KAKAOTALK_VOICE);
}
diff --git a/src/lib/protocols/mail_smtp.c b/src/lib/protocols/mail_smtp.c
index 37846930e..422ed0dc2 100644
--- a/src/lib/protocols/mail_smtp.c
+++ b/src/lib/protocols/mail_smtp.c
@@ -117,10 +117,10 @@ void ndpi_search_mail_smtp_tcp(struct ndpi_detection_module_struct
&& (packet->line[a].ptr[1] == 'T' || packet->line[a].ptr[1] == 't')
&& (packet->line[a].ptr[2] == 'A' || packet->line[a].ptr[2] == 'a')
&& (packet->line[a].ptr[3] == 'R' || packet->line[a].ptr[3] == 'r')
- && (packet->line[a].ptr[4] == 'T' || packet->line[a].ptr[0] == 't')
- && (packet->line[a].ptr[5] == 'T' || packet->line[a].ptr[1] == 't')
- && (packet->line[a].ptr[6] == 'L' || packet->line[a].ptr[2] == 'l')
- && (packet->line[a].ptr[7] == 'S' || packet->line[a].ptr[3] == 's')) {
+ && (packet->line[a].ptr[4] == 'T' || packet->line[a].ptr[4] == 't')
+ && (packet->line[a].ptr[5] == 'T' || packet->line[a].ptr[5] == 't')
+ && (packet->line[a].ptr[6] == 'L' || packet->line[a].ptr[6] == 'l')
+ && (packet->line[a].ptr[7] == 'S' || packet->line[a].ptr[7] == 's')) {
flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_STARTTLS;
}
}
diff --git a/src/lib/protocols/skype.c b/src/lib/protocols/skype.c
index 7f201569c..e3bd00332 100644
--- a/src/lib/protocols/skype.c
+++ b/src/lib/protocols/skype.c
@@ -40,8 +40,8 @@ u_int8_t is_skype_flow(struct ndpi_detection_module_struct *ndpi_struct,
Skype connections are identified by some SSL-like communications
without SSL certificate being exchanged
*/
- if(is_skype_host(ndpi_struct, ntohl(packet->iph->saddr))
- || is_skype_host(ndpi_struct, ntohl(packet->iph->daddr))) {
+ if(is_skype_host(ndpi_struct, packet->iph->saddr)
+ || is_skype_host(ndpi_struct, packet->iph->daddr)) {
return(1);
}
}
diff --git a/src/lib/protocols/steam.c b/src/lib/protocols/steam.c
index fe7b9d161..7ed0eae29 100644
--- a/src/lib/protocols/steam.c
+++ b/src/lib/protocols/steam.c
@@ -34,6 +34,7 @@ static void ndpi_int_steam_add_connection(struct ndpi_detection_module_struct *n
static void ndpi_check_steam_http(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
+ NDPI_PARSE_PACKET_LINE_INFO(ndpi_struct, flow, packet);
if (packet->user_agent_line.ptr != NULL
&& packet->user_agent_line.len >= 23
&& memcmp(packet->user_agent_line.ptr, "Valve/Steam HTTP Client", 23) == 0) {
diff --git a/src/lib/protocols/tcp_udp.c b/src/lib/protocols/tcp_udp.c
index 1eb9c8773..7ca276dca 100644
--- a/src/lib/protocols/tcp_udp.c
+++ b/src/lib/protocols/tcp_udp.c
@@ -37,9 +37,9 @@ u_int ndpi_search_tcp_or_udp_raw(struct ndpi_detection_module_struct *ndpi_struc
}
}
- if((rc = ndpi_host_ptree_match(ndpi_struct, saddr)) != NDPI_PROTOCOL_UNKNOWN) return(rc);
+ if((rc = ndpi_host_ptree_match(ndpi_struct, htonl(saddr))) != NDPI_PROTOCOL_UNKNOWN) return(rc);
- return(ndpi_host_ptree_match(ndpi_struct, daddr));
+ return(ndpi_host_ptree_match(ndpi_struct, htonl(daddr)));
}
void ndpi_search_tcp_or_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
diff --git a/src/lib/protocols/ubntac2.c b/src/lib/protocols/ubntac2.c
new file mode 100644
index 000000000..7763c18d1
--- /dev/null
+++ b/src/lib/protocols/ubntac2.c
@@ -0,0 +1,63 @@
+/*
+ * ubntac2.c
+ *
+ * Copyright (C) 2015 Thomas Fjellstrom
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_UBNTAC2
+
+static void ndpi_int_ubntac2_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_UBNTAC2, NDPI_PROTOCOL_UNKNOWN);
+}
+
+
+void ndpi_search_ubntac2(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_UBNTAC2, ndpi_struct, NDPI_LOG_TRACE, "UBNTAC2 detection... plen:%i %i:%i\n", packet->payload_packet_len, ntohs(packet->udp->source), ntohs(packet->udp->dest));
+
+ if (packet->payload_packet_len >= 135 &&
+ (packet->udp->source == htons(10001) || packet->udp->dest == htons(10001)) &&
+ memcmp(&(packet->payload[36]), "UBNT", 4) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_UBNTAC2, ndpi_struct, NDPI_LOG_DEBUG, "UBNT AirControl 2 request\n");
+
+ ndpi_int_ubntac2_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_UBNTAC2);
+}
+
+
+void init_ubntac2_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
+{
+ ndpi_set_bitmask_protocol_detection("UBNTAC2", ndpi_struct, detection_bitmask, *id,
+ NDPI_PROTOCOL_UBNTAC2,
+ ndpi_search_ubntac2,
+ NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+ *id += 1;
+}
+
+#endif
diff --git a/tests/pcap/webex.pcap b/tests/pcap/webex.pcap
new file mode 100644
index 000000000..82981bd0d
--- /dev/null
+++ b/tests/pcap/webex.pcap
Binary files differ
diff --git a/tests/result/NTPv3.pcap.out b/tests/result/NTPv3.pcap.out
index 91d817e5e..dcf9eafda 100644
--- a/tests/result/NTPv3.pcap.out
+++ b/tests/result/NTPv3.pcap.out
@@ -1,3 +1,3 @@
-NTP 1 90 1
+Quic 1 90 1
- 1 UDP 78.46.76.2:80 <-> 175.144.140.29:123 [proto: 9/NTP][1 pkts/90 bytes]
+ 1 UDP 78.46.76.2:80 <-> 175.144.140.29:123 [proto: 188/Quic][1 pkts/90 bytes]
diff --git a/tests/result/README.txt b/tests/result/README.txt
deleted file mode 100644
index 08992145b..000000000
--- a/tests/result/README.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Place here test results for pcaps used for regressions testing
-
-Example
-
-for pcap/myprotocol.pcap add result/myprotocol.result
diff --git a/tests/result/webex.pcap.out b/tests/result/webex.pcap.out
new file mode 100644
index 000000000..7d9c790f1
--- /dev/null
+++ b/tests/result/webex.pcap.out
@@ -0,0 +1,68 @@
+Unknown 16 1171 1
+HTTP 22 3182 2
+SSL_No_Cert 90 10682 5
+SSL 169 18825 18
+SIP 22 15356 1
+Google 17 6375 1
+Webex 1244 809312 29
+
+ 1 TCP 10.8.0.1:51135 <-> 62.109.224.120:443 [proto: 91/SSL][11 pkts/697 bytes]
+ 2 TCP 10.8.0.1:51155 <-> 62.109.224.120:443 [proto: 91.141/SSL.Webex][513 pkts/344086 bytes][SSL server: *.webex.com]
+ 3 TCP 10.8.0.1:51195 <-> 62.109.224.120:443 [proto: 91/SSL][5 pkts/353 bytes]
+ 4 TCP 10.8.0.1:51370 <-> 64.68.105.97:443 [proto: 91.141/SSL.Webex][16 pkts/7099 bytes][SSL server: *.webex.com]
+ 5 TCP 10.8.0.1:51833 <-> 62.109.229.158:443 [proto: 91/SSL][8 pkts/639 bytes]
+ 6 TCP 10.8.0.1:51839 <-> 62.109.229.158:443 [proto: 91/SSL][8 pkts/639 bytes]
+ 7 TCP 10.8.0.1:51857 <-> 62.109.229.158:443 [proto: 91.141/SSL.Webex][50 pkts/10360 bytes][SSL server: *.webex.com]
+ 8 TCP 10.8.0.1:51859 <-> 62.109.229.158:443 [proto: 91/SSL][3 pkts/182 bytes]
+ 9 TCP 10.8.0.1:41757 <-> 114.29.213.212:443 [proto: 91/SSL][11 pkts/697 bytes]
+ 10 TCP 10.8.0.1:47135 <-> 114.29.202.139:443 [proto: 91/SSL][11 pkts/697 bytes]
+ 11 TCP 10.8.0.1:47841 <-> 114.29.200.11:443 [proto: 91.141/SSL.Webex][11 pkts/4584 bytes][SSL server: *.webex.com]
+ 12 TCP 10.8.0.1:59757 <-> 78.46.237.91:80 [proto: 7/HTTP][10 pkts/1391 bytes][Host: cp.pushwoosh.com]
+ 13 TCP 107.20.242.44:443 <-> 10.133.206.47:59447 [proto: 91/SSL][3 pkts/174 bytes]
+ 14 TCP 10.8.0.1:55665 <-> 173.243.0.110:443 [proto: 91.141/SSL.Webex][22 pkts/6555 bytes][SSL server: *.webex.com]
+ 15 TCP 10.8.0.1:55669 <-> 173.243.0.110:443 [proto: 91.141/SSL.Webex][23 pkts/6641 bytes][SSL server: *.webex.com]
+ 16 TCP 10.8.0.1:55671 <-> 173.243.0.110:443 [proto: 91.141/SSL.Webex][22 pkts/6555 bytes][SSL server: *.webex.com]
+ 17 TCP 10.8.0.1:55687 <-> 173.243.0.110:443 [proto: 91.141/SSL.Webex][22 pkts/6555 bytes][SSL server: *.webex.com]
+ 18 TCP 10.8.0.1:37129 <-> 64.68.105.98:443 [proto: 91.141/SSL.Webex][18 pkts/7207 bytes][SSL server: *.webex.com]
+ 19 TCP 10.8.0.1:37139 <-> 64.68.105.98:443 [proto: 91/SSL][11 pkts/697 bytes]
+ 20 TCP 10.8.0.1:33511 <-> 80.74.110.68:443 [proto: 91/SSL][8 pkts/668 bytes]
+ 21 TCP 10.8.0.1:33551 <-> 80.74.110.68:443 [proto: 64/SSL_No_Cert][21 pkts/2530 bytes]
+ 22 TCP 10.8.0.1:33553 <-> 80.74.110.68:443 [proto: 64/SSL_No_Cert][20 pkts/2475 bytes]
+ 23 TCP 10.8.0.1:33559 <-> 80.74.110.68:443 [proto: 64/SSL_No_Cert][13 pkts/1733 bytes]
+ 24 TCP 10.8.0.1:41351 <-> 64.68.105.103:443 [proto: 91.141/SSL.Webex][9 pkts/905 bytes][SSL client: radcom.webex.com]
+ 25 TCP 10.8.0.1:41419 <-> 64.68.105.103:443 [proto: 91.141/SSL.Webex][14 pkts/8239 bytes][SSL server: *.webex.com]
+ 26 TCP 10.8.0.1:45814 <-> 62.109.231.3:443 [proto: 91.141/SSL.Webex][16 pkts/7968 bytes][SSL server: *.webex.com]
+ 27 TCP 10.8.0.1:51134 <-> 62.109.224.120:443 [proto: 91/SSL][11 pkts/697 bytes]
+ 28 TCP 10.8.0.1:51154 <-> 62.109.224.120:443 [proto: 91.141/SSL.Webex][105 pkts/19286 bytes][SSL server: *.webex.com]
+ 29 TCP 10.8.0.1:51190 <-> 62.109.224.120:443 [proto: 91/SSL][11 pkts/717 bytes]
+ 30 TCP 10.8.0.1:51194 <-> 62.109.224.120:443 [proto: 91.141/SSL.Webex][24 pkts/35888 bytes][SSL server: *.webex.com]
+ 31 TCP 10.8.0.1:52219 <-> 64.68.121.100:443 [proto: 91.141/SSL.Webex][15 pkts/5217 bytes][SSL server: *.webex.com]
+ 32 TCP 10.8.0.1:41726 <-> 114.29.213.212:443 [proto: 91/SSL][8 pkts/515 bytes]
+ 33 TCP 10.8.0.1:55969 <-> 64.68.121.99:443 [proto: 91.141/SSL.Webex][15 pkts/5217 bytes][SSL server: *.webex.com]
+ 34 TCP 10.8.0.1:57647 <-> 64.68.121.153:443 [proto: 91.141/SSL.Webex][14 pkts/7796 bytes][SSL server: *.webex.com]
+ 35 TCP 10.8.0.1:47116 <-> 114.29.202.139:443 [proto: 91.141/SSL.Webex][13 pkts/4692 bytes][SSL server: *.webex.com]
+ 36 TCP 10.8.0.1:59756 <-> 78.46.237.91:80 [proto: 7/HTTP][12 pkts/1791 bytes][Host: cp.pushwoosh.com]
+ 37 TCP 10.8.0.1:51646 <-> 114.29.204.49:443 [proto: 91.141/SSL.Webex][17 pkts/5293 bytes][SSL server: *.webex.com]
+ 38 TCP 10.8.0.1:51676 <-> 114.29.204.49:443 [proto: 91/SSL][11 pkts/697 bytes]
+ 39 TCP 10.8.0.1:52730 <-> 173.243.4.76:443 [proto: 91.141/SSL.Webex][17 pkts/7990 bytes][SSL server: *.webex.com]
+ 40 TCP 10.8.0.1:43433 <-> 216.58.208.40:443 [proto: 91.126/SSL.Google][17 pkts/6375 bytes][SSL client: ssl.google-analytics.com]
+ 41 TCP 10.8.0.1:47498 <-> 209.197.222.159:443 [proto: 91.141/SSL.Webex][14 pkts/7796 bytes][SSL server: *.webex.com]
+ 42 TCP 185.63.147.10:443 <-> 10.133.206.47:54651 [proto: 91/SSL][3 pkts/174 bytes]
+ 43 UDP 10.8.0.1:64538 <-> 172.16.1.75:5060 [proto: 100/SIP][22 pkts/15356 bytes]
+ 44 TCP 10.133.206.47:33459 <-> 80.74.110.68:443 [proto: 91/SSL][5 pkts/317 bytes]
+ 45 TCP 10.8.0.1:33512 <-> 80.74.110.68:443 [proto: 64/SSL_No_Cert][18 pkts/1972 bytes]
+ 46 TCP 10.8.0.1:33554 <-> 80.74.110.68:443 [proto: 64/SSL_No_Cert][18 pkts/1972 bytes]
+ 47 TCP 10.8.0.1:49048 <-> 23.44.253.243:443 [proto: 91.141/SSL.Webex][14 pkts/5202 bytes][SSL server: www.webex.com]
+ 48 TCP 10.8.0.1:41346 <-> 64.68.105.103:443 [proto: 91.141/SSL.Webex][95 pkts/92236 bytes][SSL client: radcom.webex.com]
+ 49 TCP 10.8.0.1:41348 <-> 64.68.105.103:443 [proto: 91.141/SSL.Webex][56 pkts/109696 bytes][SSL client: radcom.webex.com]
+ 50 TCP 10.8.0.1:41350 <-> 64.68.105.103:443 [proto: 91.141/SSL.Webex][11 pkts/1013 bytes][SSL client: radcom.webex.com]
+ 51 TCP 10.8.0.1:41354 <-> 64.68.105.103:443 [proto: 91.141/SSL.Webex][26 pkts/26384 bytes][SSL server: *.webex.com]
+ 52 TCP 10.8.0.1:41358 <-> 64.68.105.103:443 [proto: 91.141/SSL.Webex][38 pkts/42482 bytes][SSL server: *.webex.com]
+ 53 TCP 10.8.0.1:41386 <-> 64.68.105.103:443 [proto: 91.141/SSL.Webex][17 pkts/8401 bytes][SSL server: *.webex.com]
+ 54 TCP 10.8.0.1:41394 <-> 64.68.105.103:443 [proto: 91/SSL][11 pkts/697 bytes]
+ 55 TCP 10.8.0.1:46211 <-> 54.241.32.14:443 [proto: 91/SSL][30 pkts/9568 bytes][SSL client: api.crittercism.com]
+ 56 TCP 10.8.0.1:44492 <-> 64.68.104.140:443 [proto: 91.141/SSL.Webex][17 pkts/7969 bytes][SSL server: *.webex.com]
+
+
+Undetected flows:
+ 1 UDP 10.8.0.1:51772 <-> 62.109.229.158:9000 [proto: 0/Unknown][16 pkts/1171 bytes]