aboutsummaryrefslogtreecommitdiff
path: root/src/lib/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/protocols')
-rw-r--r--src/lib/protocols/apple_push.c30
-rw-r--r--src/lib/protocols/coap.c2
-rw-r--r--src/lib/protocols/dns.c115
-rw-r--r--src/lib/protocols/ftp_data.c50
-rw-r--r--src/lib/protocols/h323.c3
-rw-r--r--src/lib/protocols/http.c551
-rw-r--r--src/lib/protocols/mdns_proto.c31
-rw-r--r--src/lib/protocols/mining.c18
-rw-r--r--src/lib/protocols/modbus.c72
-rw-r--r--src/lib/protocols/ookla.c15
-rw-r--r--src/lib/protocols/quic.c8
-rw-r--r--src/lib/protocols/radius.c5
-rw-r--r--src/lib/protocols/ssl.c162
-rw-r--r--src/lib/protocols/whatsapp.c34
14 files changed, 538 insertions, 558 deletions
diff --git a/src/lib/protocols/apple_push.c b/src/lib/protocols/apple_push.c
index 6930dba86..45346e07b 100644
--- a/src/lib/protocols/apple_push.c
+++ b/src/lib/protocols/apple_push.c
@@ -31,20 +31,22 @@ static void ndpi_check_apple_push(struct ndpi_detection_module_struct *ndpi_stru
struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
- /* https://support.apple.com/en-us/HT203609 */
- if(((ntohl(packet->iph->saddr) & 0xFF000000 /* 255.0.0.0 */) == 0x11000000 /* 17.0.0.0/8 */)
- || ((ntohl(packet->iph->daddr) & 0xFF000000 /* 255.0.0.0 */) == 0x11000000 /* 17.0.0.0/8 */)) {
- u_int16_t apple_push_port = ntohs(5223);
- u_int16_t notification_apn_port = ntohs(2195);
- u_int16_t apn_feedback_port = ntohs(2196);
-
- if(((packet->tcp->source == apple_push_port) || (packet->tcp->dest == apple_push_port))
- || ((packet->tcp->source == notification_apn_port) || (packet->tcp->dest == notification_apn_port))
- || ((packet->tcp->source == apn_feedback_port) || (packet->tcp->dest == apn_feedback_port))
- ) {
- NDPI_LOG_INFO(ndpi_struct, "found apple_push\n");
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_APPLE_PUSH, NDPI_PROTOCOL_UNKNOWN);
- return;
+ if(packet->iph) {
+ /* https://support.apple.com/en-us/HT203609 */
+ if(((ntohl(packet->iph->saddr) & 0xFF000000 /* 255.0.0.0 */) == 0x11000000 /* 17.0.0.0/8 */)
+ || ((ntohl(packet->iph->daddr) & 0xFF000000 /* 255.0.0.0 */) == 0x11000000 /* 17.0.0.0/8 */)) {
+ u_int16_t apple_push_port = ntohs(5223);
+ u_int16_t notification_apn_port = ntohs(2195);
+ u_int16_t apn_feedback_port = ntohs(2196);
+
+ if(((packet->tcp->source == apple_push_port) || (packet->tcp->dest == apple_push_port))
+ || ((packet->tcp->source == notification_apn_port) || (packet->tcp->dest == notification_apn_port))
+ || ((packet->tcp->source == apn_feedback_port) || (packet->tcp->dest == apn_feedback_port))
+ ) {
+ NDPI_LOG_INFO(ndpi_struct, "found apple_push\n");
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_APPLE_PUSH, NDPI_PROTOCOL_UNKNOWN);
+ return;
+ }
}
}
diff --git a/src/lib/protocols/coap.c b/src/lib/protocols/coap.c
index 5ac8cb80e..cf5061bbe 100644
--- a/src/lib/protocols/coap.c
+++ b/src/lib/protocols/coap.c
@@ -129,7 +129,7 @@ void ndpi_search_coap (struct ndpi_detection_module_struct *ndpi_struct,
// check values in header
if(h->version == 1) {
if(h->type == CON || h->type == NO_CON || h->type == ACK || h->type == RST ) {
- if(h->tkl == 0 || h->tkl < 8) {
+ if(h->tkl < 8) {
if((h->code >= 0 && h->code <= 5) || (h->code >= 65 && h->code <= 69) ||
(h->code >= 128 && h->code <= 134) || (h->code >= 140 && h->code <= 143) ||
(h->code >= 160 && h->code <= 165)) {
diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c
index 90be9544c..1c2593feb 100644
--- a/src/lib/protocols/dns.c
+++ b/src/lib/protocols/dns.c
@@ -36,9 +36,9 @@
static u_int16_t get16(int *i, const u_int8_t *payload) {
u_int16_t v = *(u_int16_t*)&payload[*i];
-
+
(*i) += 2;
-
+
return(ntohs(v));
}
@@ -52,36 +52,50 @@ static u_int getNameLength(u_int i, const u_int8_t *payload, u_int payloadLen) {
else {
u_int8_t len = payload[i];
u_int8_t off = len + 1;
-
+
if(off == 0) /* Bad packet */
return(0);
else
return(off + getNameLength(i+off, payload, payloadLen));
}
}
+/*
+ allowed chars for dns names A-Z 0-9 _ -
+ Perl script for generation map:
+ my @M;
+ for(my $ch=0; $ch < 256; $ch++) {
+ $M[$ch >> 5] |= 1 << ($ch & 0x1f) if chr($ch) =~ /[a-z0-9_-]/i;
+ }
+ print join(',', map { sprintf "0x%08x",$_ } @M),"\n";
+ */
+static uint32_t dns_validchar[8] = {
+ 0x00000000,0x03ff2000,0x87fffffe,0x07fffffe,0,0,0,0
+};
/* *********************************************** */
void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
- int x;
+ int x, payload_offset;
u_int8_t is_query;
u_int16_t s_port = 0, d_port = 0;
-
+
NDPI_LOG_DBG(ndpi_struct, "search DNS\n");
if(flow->packet.udp != NULL) {
s_port = ntohs(flow->packet.udp->source);
d_port = ntohs(flow->packet.udp->dest);
- x = 0;
+ payload_offset = 0;
} else if(flow->packet.tcp != NULL) /* pkt size > 512 bytes */ {
s_port = ntohs(flow->packet.tcp->source);
d_port = ntohs(flow->packet.tcp->dest);
- x = 2;
+ payload_offset = 2;
} else {
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
return;
}
+ x = payload_offset;
+
if((s_port == 53 || d_port == 53 || d_port == 5355)
&& (flow->packet.payload_packet_len > sizeof(struct ndpi_dns_packet_header)+x)) {
struct ndpi_dns_packet_header dns_header;
@@ -106,6 +120,7 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
invalid = 1;
if(!invalid) {
+ int j = 0, max_len, off;
if(is_query) {
/* DNS Request */
if((dns_header.num_queries > 0) && (dns_header.num_queries <= NDPI_MAX_DNS_REQUESTS)
@@ -118,7 +133,7 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
if(flow->packet.payload[x] == '\0') {
x++;
flow->protos.dns.query_type = get16(&x, flow->packet.payload);
-#ifdef DNS_DEBUG
+#ifdef DNS_DEBUG
NDPI_LOG_DBG2(ndpi_struct, "query_type=%2d\n", flow->protos.dns.query_type);
#endif
break;
@@ -128,7 +143,6 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
}
} else
invalid = 1;
-
} else {
/* DNS Reply */
@@ -139,16 +153,18 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
|| ((dns_header.authority_rrs > 0) && (dns_header.authority_rrs <= NDPI_MAX_DNS_REQUESTS))
|| ((dns_header.additional_rrs > 0) && (dns_header.additional_rrs <= NDPI_MAX_DNS_REQUESTS)))
) {
- /* This is a good reply */
- if(ndpi_struct->dns_dissect_response) {
+ /* This is a good reply: we dissect it both for request and response */
+
+ /* Leave the statement below commented necessary in case of call to ndpi_get_partial_detection() */
+ /* if(ndpi_struct->dns_dont_dissect_response == 0) */ {
x++;
-
+
if(flow->packet.payload[x] != '\0') {
while((x < flow->packet.payload_packet_len)
&& (flow->packet.payload[x] != '\0')) {
x++;
}
-
+
x++;
}
@@ -160,7 +176,7 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
for(num = 0; num < dns_header.num_answers; num++) {
u_int16_t data_len;
-
+
if((x+6) >= flow->packet.payload_packet_len) {
break;
}
@@ -169,14 +185,31 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
break;
} else
x += data_len;
-
+
rsp_type = get16(&x, flow->packet.payload);
flow->protos.dns.rsp_type = rsp_type;
+
+ /* here x points to the response "class" field */
+ if((x+12) < flow->packet.payload_packet_len) {
+ x += 6;
+ data_len = get16(&x, flow->packet.payload);
+
+ if(((x + data_len) < flow->packet.payload_packet_len)
+ && (((rsp_type == 0x1) && (data_len == 4)) /* A */
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ || ((rsp_type == 0x1c) && (data_len == 16)) /* AAAA */
+#endif
+ )) {
+ memcpy(&flow->protos.dns.rsp_addr, flow->packet.payload + x, data_len);
+ }
+ }
+
break;
}
}
}
- }
+ } else
+ invalid = 1;
}
if(invalid) {
@@ -185,57 +218,61 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
}
/* extract host name server */
- int j = 0, max_len = sizeof(flow->host_server_name)-1, off = sizeof(struct ndpi_dns_packet_header) + 1;
-
- while(off < flow->packet.payload_packet_len && flow->packet.payload[off] != '\0') {
- flow->host_server_name[j] = flow->packet.payload[off];
- if(j < max_len) {
- if(flow->host_server_name[j] < ' ')
- flow->host_server_name[j] = '.';
- j++;
- } else
- break;
-
- off++;
+ max_len = sizeof(flow->host_server_name)-1;
+ off = sizeof(struct ndpi_dns_packet_header) + payload_offset;
+
+ while(j < max_len && off < flow->packet.payload_packet_len && flow->packet.payload[off] != '\0') {
+ uint8_t c,cl = flow->packet.payload[off++];
+ if( (cl & 0xc0) != 0 || // we not support compressed names in query
+ off + cl >= flow->packet.payload_packet_len) {
+ j = 0; break;
+ }
+ if(j && j < max_len) flow->host_server_name[j++] = '.';
+ while(j < max_len && cl != 0) {
+ c = flow->packet.payload[off++];
+ flow->host_server_name[j++] = dns_validchar[c >> 5] & (1 << (c & 0x1f)) ? c:'_';
+ cl--;
+ }
}
-
- if(is_query && ndpi_struct->dns_dissect_response)
- return; /* The response will set the verdict */
-
flow->host_server_name[j] = '\0';
+ if(is_query && (ndpi_struct->dns_dont_dissect_response == 0)) {
+ // dpi_set_detected_protocol(ndpi_struct, flow, (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN);
+ return; /* The response will set the verdict */
+ }
+
flow->protos.dns.num_queries = (u_int8_t)dns_header.num_queries,
- flow->protos.dns.num_answers = (u_int8_t) (dns_header.num_answers + dns_header.authority_rrs + dns_header.additional_rrs);
+ flow->protos.dns.num_answers = (u_int8_t) (dns_header.num_answers + dns_header.authority_rrs + dns_header.additional_rrs);
if(j > 0) {
ndpi_protocol_match_result ret_match;
-
- ndpi_match_host_subprotocol(ndpi_struct, flow,
+
+ ndpi_match_host_subprotocol(ndpi_struct, flow,
(char *)flow->host_server_name,
strlen((const char*)flow->host_server_name),
&ret_match,
NDPI_PROTOCOL_DNS);
}
-
+
#ifdef DNS_DEBUG
NDPI_LOG_DBG2(ndpi_struct, "[num_queries=%d][num_answers=%d][reply_code=%u][rsp_type=%u][host_server_name=%s]\n",
flow->protos.dns.num_queries, flow->protos.dns.num_answers,
flow->protos.dns.reply_code, flow->protos.dns.rsp_type, flow->host_server_name
);
#endif
-
+
if(flow->packet.detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
/**
Do not set the protocol with DNS if ndpi_match_host_subprotocol() has
matched a subprotocol
**/
- NDPI_LOG_INFO(ndpi_struct, "found DNS\n");
+ NDPI_LOG_INFO(ndpi_struct, "found DNS\n");
ndpi_set_detected_protocol(ndpi_struct, flow, (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN);
} else {
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
}
}
- }
+ }
}
void init_dns_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
diff --git a/src/lib/protocols/ftp_data.c b/src/lib/protocols/ftp_data.c
index 8d3e6fa8c..7c646c363 100644
--- a/src/lib/protocols/ftp_data.c
+++ b/src/lib/protocols/ftp_data.c
@@ -49,16 +49,22 @@ static int ndpi_match_ftp_data_directory(struct ndpi_detection_module_struct *nd
struct ndpi_packet_struct *packet = &flow->packet;
u_int32_t payload_len = packet->payload_packet_len;
- if((payload_len >= 4)
- && ((packet->payload[0] == '-') || (packet->payload[0] == 'd'))
- && ((packet->payload[1] == '-') || (packet->payload[1] == 'r'))
- && ((packet->payload[2] == '-') || (packet->payload[2] == 'w'))
- && ((packet->payload[3] == '-') || (packet->payload[3] == 'x'))) {
-
- return 1;
+ if(payload_len > 10) {
+ int i;
+
+ if(!((packet->payload[0] == '-') || (packet->payload[0] == 'd')))
+ return(0);
+
+ for(i=0; i<9; i += 3)
+ if(((packet->payload[1+i] == '-') || (packet->payload[1+i] == 'r'))
+ && ((packet->payload[2+i] == '-') || (packet->payload[2+i] == 'w'))
+ && ((packet->payload[3+i] == '-') || (packet->payload[3+i] == 'x'))) {
+ ;
+ } else
+ return 0;
}
- return 0;
+ return 1;
}
static int ndpi_match_file_header(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
@@ -220,16 +226,24 @@ static int ndpi_match_file_header(struct ndpi_detection_module_struct *ndpi_stru
static void ndpi_check_ftp_data(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
- if((packet->payload_packet_len > 0)
- && (ndpi_match_file_header(ndpi_struct, flow)
- || ndpi_match_ftp_data_directory(ndpi_struct, flow)
- || ndpi_match_ftp_data_port(ndpi_struct, flow)
- )
- ) {
- NDPI_LOG_INFO(ndpi_struct, "found FTP_DATA request\n");
- ndpi_int_ftp_data_add_connection(ndpi_struct, flow);
- } else
- NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
+ /*
+ Make sure we see the beginning of the connection as otherwise we might have
+ false positive results
+ */
+ if(flow->l4.tcp.seen_syn) {
+ if((packet->payload_packet_len > 0)
+ && (ndpi_match_file_header(ndpi_struct, flow)
+ || ndpi_match_ftp_data_directory(ndpi_struct, flow)
+ || ndpi_match_ftp_data_port(ndpi_struct, flow)
+ )
+ ) {
+ NDPI_LOG_INFO(ndpi_struct, "found FTP_DATA request\n");
+ ndpi_int_ftp_data_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
}
void ndpi_search_ftp_data(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
diff --git a/src/lib/protocols/h323.c b/src/lib/protocols/h323.c
index ddbcdadf3..d407c981b 100644
--- a/src/lib/protocols/h323.c
+++ b/src/lib/protocols/h323.c
@@ -31,8 +31,7 @@ void ndpi_search_h323(struct ndpi_detection_module_struct *ndpi_struct, struct n
/* H323 */
if(packet->payload_packet_len >= 3
&& (packet->payload[0] == 0x03)
- && (packet->payload[1] == 0x00)
- && (packet->payload[2] == 0x00)) {
+ && (packet->payload[1] == 0x00)) {
struct tpkt *t = (struct tpkt*)packet->payload;
u_int16_t len = ntohs(t->len);
diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c
index 09b816129..33ef9e2ed 100644
--- a/src/lib/protocols/http.c
+++ b/src/lib/protocols/http.c
@@ -26,116 +26,43 @@
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_HTTP
#include "ndpi_api.h"
-#include "lruc.h"
-
-/* global variables used for 1kxun protocol and iqiyi service */
+#include <stdlib.h>
static void ndpi_int_http_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
u_int16_t category) {
-
+#ifdef DEBUG
+ printf("[%s] [http_dont_dissect_response: %u]->> %s\n", __FUNCTION__,
+ ndpi_struct->http_dont_dissect_response, flow->http.response_status_code);
+#endif
+
if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
/* This is HTTP and it is not a sub protocol (e.g. skype or dropbox) */
ndpi_search_tcp_or_udp(ndpi_struct, flow);
/* If no custom protocol has been detected */
-
if(flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) {
ndpi_int_reset_protocol(flow);
- ndpi_set_detected_protocol(ndpi_struct, flow, flow->guessed_host_protocol_id, NDPI_PROTOCOL_HTTP);
+ flow->http_upper_protocol = flow->guessed_host_protocol_id, flow->http_lower_protocol = NDPI_PROTOCOL_HTTP;
} else
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_HTTP, NDPI_PROTOCOL_UNKNOWN);
-
- flow->http_detected = 1, flow->guessed_category = category;
- }
-}
-
-#ifdef NDPI_CONTENT_CATEGORY_FLASH
-static void flash_check_http_payload(struct ndpi_detection_module_struct
- *ndpi_struct, struct ndpi_flow_struct *flow)
-{
- struct ndpi_packet_struct *packet = &flow->packet;
- const u_int8_t *pos;
-
- if(packet->empty_line_position_set == 0 || (packet->empty_line_position + 10) > (packet->payload_packet_len))
- return;
-
- pos = &packet->payload[packet->empty_line_position] + 2;
-
- if(memcmp(pos, "FLV", 3) == 0 && pos[3] == 0x01 && (pos[4] == 0x01 || pos[4] == 0x04 || pos[4] == 0x05)
- && pos[5] == 0x00 && pos[6] == 0x00 && pos[7] == 0x00 && pos[8] == 0x09) {
-
- NDPI_LOG_INFO(ndpi_struct, "found Flash content in HTTP\n");
- ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_CONTENT_CATEGORY_FLASH);
- }
-}
-#endif
-
-#ifdef NDPI_CONTENT_CATEGORY_AVI
-static void avi_check_http_payload(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
-{
- struct ndpi_packet_struct *packet = &flow->packet;
-
-
- NDPI_LOG_DBG2(ndpi_struct, "called avi_check_http_payload: %u %u %u\n",
- packet->empty_line_position_set, flow->l4.tcp.http_empty_line_seen, packet->empty_line_position);
-
- if(packet->empty_line_position_set == 0 && flow->l4.tcp.http_empty_line_seen == 0)
- return;
-
- if(packet->empty_line_position_set != 0 && ((packet->empty_line_position + 20) > (packet->payload_packet_len))
- && flow->l4.tcp.http_empty_line_seen == 0) {
- flow->l4.tcp.http_empty_line_seen = 1;
- return;
- }
+ flow->http_upper_protocol = NDPI_PROTOCOL_HTTP, flow->http_lower_protocol = NDPI_PROTOCOL_UNKNOWN;
- if(flow->l4.tcp.http_empty_line_seen == 1) {
- if(packet->payload_packet_len > 20 && memcmp(packet->payload, "RIFF", 4) == 0
- && memcmp(packet->payload + 8, "AVI LIST", 8) == 0) {
- NDPI_LOG_INFO(ndpi_struct, "found Avi content in HTTP\n");
- ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_CONTENT_CATEGORY_AVI);
+ if(ndpi_struct->http_dont_dissect_response)
+ ndpi_set_detected_protocol(ndpi_struct, flow, flow->http_upper_protocol, flow->http_lower_protocol);
+ else {
+ flow->detected_protocol_stack[0] = NDPI_PROTOCOL_UNKNOWN, flow->detected_protocol_stack[1] = NDPI_PROTOCOL_UNKNOWN;
+ flow->packet.detected_protocol_stack[0] = NDPI_PROTOCOL_UNKNOWN, flow->packet.detected_protocol_stack[1] = NDPI_PROTOCOL_UNKNOWN;
}
- flow->l4.tcp.http_empty_line_seen = 0;
- return;
- }
-
- /**
- for reference see http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/htm/avirifffilereference.asp
- **/
- if(packet->empty_line_position_set != 0) {
-
- u_int32_t p = packet->empty_line_position + 2;
-
- // check for avi header
- NDPI_LOG_DBG2(ndpi_struct, "p = %u\n", p);
-
- if((p + 16) <= packet->payload_packet_len && memcmp(&packet->payload[p], "RIFF", 4) == 0
- && memcmp(&packet->payload[p + 8], "AVI LIST", 8) == 0) {
- NDPI_LOG_INFO(ndpi_struct, "found Avi content in HTTP\n");
- ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_CONTENT_CATEGORY_AVI);
+ } else {
+ if((!ndpi_struct->http_dont_dissect_response) && (flow->http.response_status_code == 0)) {
+ flow->http_upper_protocol = flow->detected_protocol_stack[0], flow->http_lower_protocol = flow->detected_protocol_stack[1];
+ flow->detected_protocol_stack[0] = NDPI_PROTOCOL_UNKNOWN, flow->detected_protocol_stack[1] = NDPI_PROTOCOL_UNKNOWN;
+ flow->packet.detected_protocol_stack[0] = NDPI_PROTOCOL_UNKNOWN, flow->packet.detected_protocol_stack[1] = NDPI_PROTOCOL_UNKNOWN;
}
}
-}
-#endif
-
-static void teamviewer_check_http_payload(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
-{
- struct ndpi_packet_struct *packet = &flow->packet;
- const u_int8_t *pos;
-
- NDPI_LOG_DBG2(ndpi_struct, "called teamviewer_check_http_payload: %u %u %u\n",
- packet->empty_line_position_set, flow->l4.tcp.http_empty_line_seen, packet->empty_line_position);
-
- if(packet->empty_line_position_set == 0 || (packet->empty_line_position + 5) > (packet->payload_packet_len))
- return;
-
- pos = &packet->payload[packet->empty_line_position] + 2;
- if(pos[0] == 0x17 && pos[1] == 0x24) {
- NDPI_LOG_INFO(ndpi_struct, "found TeamViewer content in HTTP\n");
- ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TEAMVIEWER);
- }
+ flow->http_detected = 1, flow->guessed_category = category;
}
static void rtsp_parse_packet_acceptline(struct ndpi_detection_module_struct
@@ -171,10 +98,10 @@ static void setHttpUserAgent(struct ndpi_detection_module_struct *ndpi_struct,
static void parseHttpSubprotocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
if((flow->l4.tcp.http_stage == 0) || (flow->http.url && flow->http_detected)) {
- char *double_col = strchr((char*)flow->host_server_name, ':');
- ndpi_protocol_match_result ret_match;
-
- if(double_col) double_col[0] = '\0';
+ char *double_col = strchr((char*)flow->host_server_name, ':');
+ ndpi_protocol_match_result ret_match;
+
+ if(double_col) double_col[0] = '\0';
/**
NOTE
@@ -198,6 +125,14 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
struct ndpi_packet_struct *packet = &flow->packet;
u_int8_t a;
+ if((!ndpi_struct->http_dont_dissect_response) && flow->http_detected && (flow->http.response_status_code != 0)) {
+ ndpi_set_detected_protocol(ndpi_struct, flow, flow->http_upper_protocol, flow->http_lower_protocol);
+#ifdef DEBUG
+ printf("[%s] [http_dont_dissect_response: %u]->> %s\n",
+ __FUNCTION__, ndpi_struct->http_dont_dissect_response, flow->http.response_status_code);
+#endif
+ return;
+ }
#if defined(NDPI_PROTOCOL_1KXUN) || defined(NDPI_PROTOCOL_IQIYI)
/* PPStream */
@@ -222,7 +157,9 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
}
#endif
- if(!ndpi_struct->http_dont_dissect_response) {
+ /* Leave the statement below commented necessary in case of call to ndpi_get_partial_detection() */
+
+ /* if(!ndpi_struct->http_dont_dissect_response) */ {
if((flow->http.url == NULL)
&& (packet->http_url_name.len > 0)
&& (packet->host_line.len > 0)) {
@@ -238,25 +175,25 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
}
if(flow->packet.http_method.len < 3)
- flow->http.method = HTTP_METHOD_UNKNOWN;
+ flow->http.method = NDPI_HTTP_METHOD_UNKNOWN;
else {
switch(flow->packet.http_method.ptr[0]) {
- case 'O': flow->http.method = HTTP_METHOD_OPTIONS; break;
- case 'G': flow->http.method = HTTP_METHOD_GET; break;
- case 'H': flow->http.method = HTTP_METHOD_HEAD; break;
+ case 'O': flow->http.method = NDPI_HTTP_METHOD_OPTIONS; break;
+ case 'G': flow->http.method = NDPI_HTTP_METHOD_GET; break;
+ case 'H': flow->http.method = NDPI_HTTP_METHOD_HEAD; break;
case 'P':
switch(flow->packet.http_method.ptr[1]) {
- case 'O': flow->http.method = HTTP_METHOD_POST; break;
- case 'U': flow->http.method = HTTP_METHOD_PUT; break;
+ case 'O': flow->http.method = NDPI_HTTP_METHOD_POST; break;
+ case 'U': flow->http.method = NDPI_HTTP_METHOD_PUT; break;
}
break;
- case 'D': flow->http.method = HTTP_METHOD_DELETE; break;
- case 'T': flow->http.method = HTTP_METHOD_TRACE; break;
- case 'C': flow->http.method = HTTP_METHOD_CONNECT; break;
+ case 'D': flow->http.method = NDPI_HTTP_METHOD_DELETE; break;
+ case 'T': flow->http.method = NDPI_HTTP_METHOD_TRACE; break;
+ case 'C': flow->http.method = NDPI_HTTP_METHOD_CONNECT; break;
default:
- flow->http.method = HTTP_METHOD_UNKNOWN;
+ flow->http.method = NDPI_HTTP_METHOD_UNKNOWN;
break;
}
}
@@ -277,8 +214,8 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
if(packet->user_agent_line.ptr != NULL && packet->user_agent_line.len != 0) {
/**
Format examples:
- Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) ....
- Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:54.0) Gecko/20100101 Firefox/54.0
+ Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) ....
+ Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:54.0) Gecko/20100101 Firefox/54.0
*/
if(packet->user_agent_line.len > 7) {
char ua[256];
@@ -308,22 +245,22 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
if(token && (token[0] == ' ')) token++; /* Skip space */
if(token
- && ((strcmp(token, "U") == 0)
- || (strncmp(token, "MSIE", 4) == 0))) {
- token = strsep(&parent, ";");
- if(token && (token[0] == ' ')) token++; /* Skip space */
+ && ((strcmp(token, "U") == 0)
+ || (strncmp(token, "MSIE", 4) == 0))) {
+ token = strsep(&parent, ";");
+ if(token && (token[0] == ' ')) token++; /* Skip space */
- if(token && (strncmp(token, "Update", 6) == 0)) {
- token = strsep(&parent, ";");
+ if(token && (strncmp(token, "Update", 6) == 0)) {
+ token = strsep(&parent, ";");
- if(token && (token[0] == ' ')) token++; /* Skip space */
+ if(token && (token[0] == ' ')) token++; /* Skip space */
- if(token && (strncmp(token, "AOL", 3) == 0)) {
+ if(token && (strncmp(token, "AOL", 3) == 0)) {
- token = strsep(&parent, ";");
- if(token && (token[0] == ' ')) token++; /* Skip space */
- }
- }
+ token = strsep(&parent, ";");
+ if(token && (token[0] == ' ')) token++; /* Skip space */
+ }
+ }
}
}
@@ -340,7 +277,7 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
}
NDPI_LOG_DBG2(ndpi_struct, "User Agent Type line found %.*s\n",
- packet->user_agent_line.len, packet->user_agent_line.ptr);
+ packet->user_agent_line.len, packet->user_agent_line.ptr);
}
/* check for host line */
@@ -348,37 +285,37 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
u_int len;
NDPI_LOG_DBG2(ndpi_struct, "HOST line found %.*s\n",
- packet->host_line.len, packet->host_line.ptr);
+ packet->host_line.len, packet->host_line.ptr);
/* call ndpi_match_host_subprotocol to see if there is a match with known-host HTTP subprotocol */
if((ndpi_struct->http_dont_dissect_response) || flow->http_detected) {
ndpi_protocol_match_result ret_match;
-
+
ndpi_match_host_subprotocol(ndpi_struct, flow,
(char*)packet->host_line.ptr,
packet->host_line.len,
&ret_match,
NDPI_PROTOCOL_HTTP);
}
-
+
/* Copy result for nDPI apps */
if(!ndpi_struct->disable_metadata_export) {
len = ndpi_min(packet->host_line.len, sizeof(flow->host_server_name)-1);
strncpy((char*)flow->host_server_name, (char*)packet->host_line.ptr, len);
flow->host_server_name[len] = '\0';
}
-
+
flow->server_id = flow->dst;
if(packet->forwarded_line.ptr) {
- len = ndpi_min(packet->forwarded_line.len, sizeof(flow->protos.http.nat_ip)-1);
- if(!ndpi_struct->disable_metadata_export) {
- strncpy((char*)flow->protos.http.nat_ip, (char*)packet->forwarded_line.ptr, len);
- flow->protos.http.nat_ip[len] = '\0';
- }
+ len = ndpi_min(packet->forwarded_line.len, sizeof(flow->protos.http.nat_ip)-1);
+ if(!ndpi_struct->disable_metadata_export) {
+ strncpy((char*)flow->protos.http.nat_ip, (char*)packet->forwarded_line.ptr, len);
+ flow->protos.http.nat_ip[len] = '\0';
+ }
}
- if(ndpi_struct->http_dont_dissect_response)
+ if(!ndpi_struct->http_dont_dissect_response)
parseHttpSubprotocol(ndpi_struct, flow);
/**
@@ -403,26 +340,28 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
&& ((ndpi_struct->http_dont_dissect_response) || flow->http_detected)
&& (packet->http_origin.len > 0)) {
ndpi_protocol_match_result ret_match;
-
+
ndpi_match_host_subprotocol(ndpi_struct, flow,
(char *)packet->http_origin.ptr,
packet->http_origin.len,
&ret_match,
NDPI_PROTOCOL_HTTP);
}
-
+
if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) {
if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_HTTP) {
- NDPI_LOG_INFO(ndpi_struct, "found HTTP/%s\n",
- ndpi_get_proto_name(ndpi_struct, packet->detected_protocol_stack[0]));
+ NDPI_LOG_INFO(ndpi_struct, "found HTTP/%s\n",
+ ndpi_get_proto_name(ndpi_struct, packet->detected_protocol_stack[0]));
ndpi_int_http_add_connection(ndpi_struct, flow, packet->detected_protocol_stack[0]);
return; /* We have identified a sub-protocol so we're done */
}
}
}
+#if 0
if(!ndpi_struct->http_dont_dissect_response && flow->http_detected)
parseHttpSubprotocol(ndpi_struct, flow);
+#endif
if(flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN)
flow->guessed_protocol_id = NDPI_PROTOCOL_HTTP;
@@ -430,50 +369,31 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
/* check for accept line */
if(packet->accept_line.ptr != NULL) {
NDPI_LOG_DBG2(ndpi_struct, "Accept line found %.*s\n",
- packet->accept_line.len, packet->accept_line.ptr);
+ packet->accept_line.len, packet->accept_line.ptr);
if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask,
NDPI_PROTOCOL_RTSP) != 0) {
rtsp_parse_packet_acceptline(ndpi_struct, flow);
}
}
- /* search for line startin with "Icy-MetaData" */
- for (a = 0; a < packet->parsed_lines; a++) {
- if(packet->line[a].len > 11 && memcmp(packet->line[a].ptr, "Icy-MetaData", 12) == 0) {
- NDPI_LOG_INFO(ndpi_struct, "found MPEG: Icy-MetaData\n");
- ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_CONTENT_CATEGORY_MPEG);
- return;
- }
- }
-
if(packet->content_line.ptr != NULL && packet->content_line.len != 0) {
NDPI_LOG_DBG2(ndpi_struct, "Content Type line found %.*s\n",
- packet->content_line.len, packet->content_line.ptr);
+ packet->content_line.len, packet->content_line.ptr);
if((ndpi_struct->http_dont_dissect_response) || flow->http_detected) {
ndpi_protocol_match_result ret_match;
-
+
ndpi_match_content_subprotocol(ndpi_struct, flow,
(char*)packet->content_line.ptr, packet->content_line.len,
&ret_match, NDPI_PROTOCOL_HTTP);
}
}
-}
-static void check_http_payload(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
-{
- NDPI_LOG_DBG2(ndpi_struct, "called check_http_payload\n");
-
-#ifdef NDPI_CONTENT_CATEGORY_FLASH
- if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_CONTENT_CATEGORY_FLASH) != 0)
- flash_check_http_payload(ndpi_struct, flow);
-#endif
-#ifdef NDPI_CONTENT_CATEGORY_AVI
- if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_CONTENT_CATEGORY_AVI) != 0)
- avi_check_http_payload(ndpi_struct, flow);
-#endif
+ ndpi_int_http_add_connection(ndpi_struct, flow, packet->detected_protocol_stack[0]);
+}
- teamviewer_check_http_payload(ndpi_struct, flow);
+static void check_http_payload(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ /* Add here your paylod code check */
}
/**
@@ -486,22 +406,22 @@ static void check_http_payload(struct ndpi_detection_module_struct *ndpi_struct,
#define STATIC_STRING_L(a) {.str=a, .len=sizeof(a)-1 }
static struct l_string {
- const char *str;
- size_t len;
+ const char *str;
+ size_t len;
} http_methods[] = {
- STATIC_STRING_L("GET "),
- STATIC_STRING_L("POST "),
- STATIC_STRING_L("OPTIONS "),
- STATIC_STRING_L("HEAD "),
- STATIC_STRING_L("PUT "),
- STATIC_STRING_L("DELETE "),
- STATIC_STRING_L("CONNECT "),
- STATIC_STRING_L("PROPFIND "),
- STATIC_STRING_L("REPORT ") };
+ STATIC_STRING_L("GET "),
+ STATIC_STRING_L("POST "),
+ STATIC_STRING_L("OPTIONS "),
+ STATIC_STRING_L("HEAD "),
+ STATIC_STRING_L("PUT "),
+ STATIC_STRING_L("DELETE "),
+ STATIC_STRING_L("CONNECT "),
+ STATIC_STRING_L("PROPFIND "),
+ STATIC_STRING_L("REPORT ") };
static const char *http_fs = "CDGHOPR";
static uint8_t non_ctrl(uint8_t c) {
- return c < 32 ? '.':c;
+ return c < 32 ? '.':c;
}
static u_int16_t http_request_url_offset(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
@@ -510,9 +430,9 @@ static u_int16_t http_request_url_offset(struct ndpi_detection_module_struct *nd
int i;
NDPI_LOG_DBG2(ndpi_struct, "====>>>> HTTP: %c%c%c%c [len: %u]\n",
- non_ctrl(packet->payload[0]), non_ctrl(packet->payload[1]),
- non_ctrl(packet->payload[2]), non_ctrl(packet->payload[3]),
- packet->payload_packet_len);
+ non_ctrl(packet->payload[0]), non_ctrl(packet->payload[1]),
+ non_ctrl(packet->payload[2]), non_ctrl(packet->payload[3]),
+ packet->payload_packet_len);
/* Check first char */
if(!strchr(http_fs,packet->payload[0])) return 0;
@@ -520,43 +440,24 @@ static u_int16_t http_request_url_offset(struct ndpi_detection_module_struct *nd
FIRST PAYLOAD PACKET FROM CLIENT
**/
for(i=0; i < sizeof(http_methods)/sizeof(http_methods[0]); i++) {
- if(packet->payload_packet_len >= http_methods[i].len &&
- memcmp(packet->payload,http_methods[i].str,http_methods[i].len) == 0) {
- NDPI_LOG_DBG2(ndpi_struct, "HTTP: %sFOUND\n",http_methods[i].str);
- return http_methods[i].len;
- }
+ if(packet->payload_packet_len >= http_methods[i].len &&
+ memcmp(packet->payload,http_methods[i].str,http_methods[i].len) == 0) {
+ NDPI_LOG_DBG2(ndpi_struct, "HTTP: %sFOUND\n",http_methods[i].str);
+ return http_methods[i].len;
+ }
}
return 0;
}
static void http_bitmask_exclude_other(struct ndpi_flow_struct *flow)
{
-#ifdef NDPI_CONTENT_CATEGORY_MPEG
- NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_CATEGORY_MPEG);
-#endif
-#ifdef NDPI_CONTENT_CATEGORY_QUICKTIME
- NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_CATEGORY_QUICKTIME);
-#endif
-#ifdef NDPI_CONTENT_CATEGORY_WINDOWSMEDIA
- NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_CATEGORY_WINDOWSMEDIA);
-#endif
-#ifdef NDPI_CONTENT_CATEGORY_REALMEDIA
- NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_CATEGORY_REALMEDIA);
-#endif
-#ifdef NDPI_CONTENT_CATEGORY_AVI
- NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_CATEGORY_AVI);
-#endif
-#ifdef NDPI_CONTENT_CATEGORY_OGG
- NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_CATEGORY_OGG);
-#endif
-
NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_XBOX);
}
/*************************************************************************************************/
static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct,
- struct ndpi_flow_struct *flow) {
+ struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
u_int16_t filename_start; /* the filename in the request method line, e.g., "GET filename_start..."*/
@@ -576,6 +477,20 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
if(packet->payload_packet_len >= 7 && memcmp(packet->payload, "HTTP/1.", 7) == 0) {
NDPI_LOG_INFO(ndpi_struct, "found HTTP response\n");
+
+ if(packet->payload_packet_len >= 12) {
+ char buf[4];
+
+ /* Set server HTTP response code */
+ strncpy(buf, (char*)&packet->payload[9], 3);
+ buf[3] = '\0';
+
+ flow->http.response_status_code = atoi(buf);
+ /* https://en.wikipedia.org/wiki/List_of_HTTP_status_codes */
+ if((flow->http.response_status_code < 100) || (flow->http.response_status_code > 509))
+ flow->http.response_status_code = 0; /* Out of range */
+ }
+
ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
check_content_type_and_change_protocol(ndpi_struct, flow);
return;
@@ -586,7 +501,7 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
flow->l4.tcp.http_stage = 1;
return;
}
-
+
if((packet->payload_packet_len == 40) && (flow->l4.tcp.http_stage == 0)) {
/*
-> QR O06L0072-6L91-4O43-857J-K8OO172L6L51
@@ -600,11 +515,11 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
&& (packet->payload[21] == '-')
&& (packet->payload[26] == '-')
&& (packet->payload[39] == 0x0A)
- )
- flow->l4.tcp.http_stage = 1;
- return;
+ )
+ flow->l4.tcp.http_stage = 1;
+ return;
}
-
+
if((packet->payload_packet_len == 23) && (memcmp(packet->payload, "<policy-file-request/>", 23) == 0)) {
/*
<policy-file-request/>
@@ -617,35 +532,31 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_OOKLA, NDPI_PROTOCOL_UNKNOWN);
if(ndpi_struct->ookla_cache == NULL)
- ndpi_struct->ookla_cache = lruc_new(4*1024, 1024);
+ ndpi_struct->ookla_cache = ndpi_lru_cache_init(1024);
- if(ndpi_struct->ookla_cache != NULL) {
- u_int8_t *dummy = (u_int8_t*)ndpi_malloc(sizeof(u_int8_t));
-
- if(dummy) {
- if(packet->tcp->source == htons(8080))
- lruc_set((lruc*)ndpi_struct->ookla_cache, (void*)&packet->iph->saddr, 4, dummy, 1);
- else
- lruc_set((lruc*)ndpi_struct->ookla_cache, (void*)&packet->iph->daddr, 4, dummy, 1);
- }
+ if(packet->iph != NULL && ndpi_struct->ookla_cache != NULL) {
+ if(packet->tcp->source == htons(8080))
+ ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, packet->iph->saddr);
+ else
+ ndpi_lru_add_to_cache(ndpi_struct->ookla_cache, packet->iph->daddr);
}
return;
}
-
+
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
http_bitmask_exclude_other(flow);
return;
}
NDPI_LOG_DBG2(ndpi_struct,
- "Filename HTTP found: %d, we look for line info..\n", filename_start);
+ "Filename HTTP found: %d, we look for line info..\n", filename_start);
ndpi_parse_packet_line_info(ndpi_struct, flow);
if(packet->parsed_lines <= 1) {
NDPI_LOG_DBG2(ndpi_struct,
- "Found just one line, we will look further for the next packet...\n");
+ "Found just one line, we will look further for the next packet...\n");
packet->http_method.ptr = packet->line[0].ptr;
packet->http_method.len = filename_start - 1;
@@ -656,10 +567,10 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
}
NDPI_LOG_DBG2(ndpi_struct,
- "Found more than one line, we look further for the next packet...\n");
+ "Found more than one line, we look further for the next packet...\n");
if(packet->line[0].len >= (9 + filename_start)
- && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) { /* Request line complete. Ex. "GET / HTTP/1.1" */
+ && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) { /* Request line complete. Ex. "GET / HTTP/1.1" */
packet->http_url_name.ptr = &packet->payload[filename_start];
packet->http_url_name.len = packet->line[0].len - (filename_start + 9);
@@ -669,14 +580,13 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
// Set the HTTP requested version: 0=HTTP/1.0 and 1=HTTP/1.1
if(memcmp(&packet->line[0].ptr[packet->line[0].len - 1], "1", 1) == 0)
- flow->http.request_version = 1;
+ flow->http.request_version = 1;
else
- flow->http.request_version = 0;
+ flow->http.request_version = 0;
/* Set the first found headers in request */
flow->http.num_request_headers = packet->http_num_headers;
-
/* Check for Ookla */
if((packet->referer_line.len > 0)
&& ndpi_strnstr((const char *)packet->referer_line.ptr, "www.speedtest.net", packet->referer_line.len)) {
@@ -686,22 +596,22 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
/* Check for additional field introduced by Steam */
int x = 1;
if(packet->line[x].len >= 11 && (memcmp(packet->line[x].ptr, "x-steam-sid", 11)) == 0) {
- NDPI_LOG_INFO(ndpi_struct, "found STEAM\n");
- ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_STEAM);
- check_content_type_and_change_protocol(ndpi_struct, flow);
- return;
+ NDPI_LOG_INFO(ndpi_struct, "found STEAM\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_STEAM);
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+ return;
}
/* Check for additional field introduced by Facebook */
x = 1;
while(packet->line[x].len != 0) {
- if(packet->line[x].len >= 12 && (memcmp(packet->line[x].ptr, "X-FB-SIM-HNI", 12)) == 0) {
- NDPI_LOG_INFO(ndpi_struct, "found FACEBOOK\n");
- ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_FACEBOOK);
- check_content_type_and_change_protocol(ndpi_struct, flow);
- return;
- }
- x++;
+ if(packet->line[x].len >= 12 && (memcmp(packet->line[x].ptr, "X-FB-SIM-HNI", 12)) == 0) {
+ NDPI_LOG_INFO(ndpi_struct, "found FACEBOOK\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_FACEBOOK);
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+ return;
+ }
+ x++;
}
#if defined(NDPI_PROTOCOL_1KXUN) || defined(NDPI_PROTOCOL_IQIYI)
@@ -746,23 +656,23 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
}
}
#endif
-
+
if((packet->http_url_name.len > 7)
- && (!strncmp((const char*) packet->http_url_name.ptr, "http://", 7))) {
+ && (!strncmp((const char*) packet->http_url_name.ptr, "http://", 7))) {
NDPI_LOG_INFO(ndpi_struct, "found HTTP_PROXY\n");
ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP_PROXY);
check_content_type_and_change_protocol(ndpi_struct, flow);
}
if(filename_start == 8 && (memcmp(packet->payload, "CONNECT ", 8) == 0)) {
- /* nathan@getoffmalawn.com */
+ /* nathan@getoffmalawn.com */
NDPI_LOG_INFO(ndpi_struct, "found HTTP_CONNECT\n");
ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP_CONNECT);
check_content_type_and_change_protocol(ndpi_struct, flow);
}
NDPI_LOG_DBG2(ndpi_struct,
- "HTTP START Found, we will look for sub-protocols (content and host)...\n");
+ "HTTP START Found, we will look for sub-protocols (content and host)...\n");
if(packet->host_line.ptr != NULL) {
/**
@@ -775,11 +685,11 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
if(ndpi_struct->http_dont_dissect_response) {
if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) /* No subprotocol found */
NDPI_LOG_INFO(ndpi_struct, "found HTTP\n");
- ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
} else {
flow->http_detected = 1;
NDPI_LOG_DBG2(ndpi_struct,
- "HTTP START Found, we will look further for the response...\n");
+ "HTTP START Found, we will look further for the response...\n");
flow->l4.tcp.http_stage = packet->packet_direction + 1; // packet_direction 0: stage 1, packet_direction 1: stage 2
}
@@ -790,23 +700,21 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
http_bitmask_exclude_other(flow);
-
} else if((flow->l4.tcp.http_stage == 1) || (flow->l4.tcp.http_stage == 2)) {
-
NDPI_LOG_DBG2(ndpi_struct, "HTTP stage %u: \n", flow->l4.tcp.http_stage);
-
+
if((packet->payload_packet_len == 34) && (flow->l4.tcp.http_stage == 1)) {
if((packet->payload[5] == ' ') && (packet->payload[9] == ' ')) {
goto ookla_found;
}
}
-
+
if((packet->payload_packet_len > 6) && memcmp(packet->payload, "HELLO ", 6) == 0) {
- /* This looks like Ookla */
+ /* This looks like Ookla */
goto ookla_found;
} else
- NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_OOKLA);
-
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_OOKLA);
+
/**
At first check, if this is for sure a response packet (in another direction. If not, if HTTP is detected do nothing now and return,
otherwise check the second packet for the HTTP request
@@ -817,7 +725,7 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
return;
NDPI_LOG_DBG2(ndpi_struct,
- " SECOND PAYLOAD TRAFFIC FROM CLIENT, FIRST PACKET MIGHT HAVE BEEN HTTP...UNKNOWN TRAFFIC, HERE FOR HTTP again.. \n");
+ " SECOND PAYLOAD TRAFFIC FROM CLIENT, FIRST PACKET MIGHT HAVE BEEN HTTP...UNKNOWN TRAFFIC, HERE FOR HTTP again.. \n");
ndpi_parse_packet_line_info(ndpi_struct, flow);
@@ -839,14 +747,14 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
}
// http://www.slideshare.net/DSPIP/rtsp-analysis-wireshark
if(packet->line[0].len >= 9
- && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) {
+ && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) {
NDPI_LOG_INFO(ndpi_struct, "found HTTP\n");
ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
check_content_type_and_change_protocol(ndpi_struct, flow);
NDPI_LOG_DBG2(ndpi_struct,
- "HTTP START Found in 2. packet, we will look further for the response....\n");
+ "HTTP START Found in 2. packet, we will look further for the response....\n");
flow->http_detected = 1;
}
@@ -879,9 +787,8 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
ndpi_parse_packet_line_info(ndpi_struct, flow);
check_content_type_and_change_protocol(ndpi_struct, flow);
- if(packet->packet_direction == 1 /* server -> client */){
- flow->http.num_response_headers += packet->http_num_headers; /* flow structs are initialized with zeros */
- }
+ if(packet->packet_direction == 1 /* server -> client */)
+ flow->http.num_response_headers += packet->http_num_headers; /* flow structs are initialized with zeros */
if(packet->empty_line_position_set != 0 || flow->l4.tcp.http_empty_line_seen == 1) {
NDPI_LOG_DBG2(ndpi_struct, "empty line. check_http_payload\n");
@@ -905,8 +812,8 @@ void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struct,
}
if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) {
- return;
- }
+ return;
+ }
NDPI_LOG_DBG(ndpi_struct, "search HTTP\n");
ndpi_check_http_tcp(ndpi_struct, flow);
@@ -917,7 +824,7 @@ void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struct,
ndpi_http_method ndpi_get_http_method(struct ndpi_detection_module_struct *ndpi_mod,
struct ndpi_flow_struct *flow) {
if(!flow)
- return(HTTP_METHOD_UNKNOWN);
+ return(NDPI_HTTP_METHOD_UNKNOWN);
else
return(flow->http.method);
}
@@ -935,7 +842,7 @@ char* ndpi_get_http_url(struct ndpi_detection_module_struct *ndpi_mod,
/* ********************************* */
char* ndpi_get_http_content_type(struct ndpi_detection_module_struct *ndpi_mod,
- struct ndpi_flow_struct *flow) {
+ struct ndpi_flow_struct *flow) {
if((!flow) || (!flow->http.content_type))
return("");
else
@@ -953,130 +860,4 @@ void init_http_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int
SAVE_DETECTION_BITMASK_AS_UNKNOWN,
ADD_TO_DETECTION_BITMASK);
*id += 1;
-
-#if 0
- ndpi_set_bitmask_protocol_detection("HTTP_Proxy", ndpi_struct, detection_bitmask, *id,
- NDPI_PROTOCOL_HTTP_PROXY,
- ndpi_search_http_tcp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
- SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
- *id += 1;
-
-#ifdef NDPI_CONTENT_CATEGORY_MPEG
- ndpi_set_bitmask_protocol_detection("MPEG", ndpi_struct, detection_bitmask, *id,
- NDPI_CONTENT_CATEGORY_MPEG,
- ndpi_search_http_tcp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
- NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
-
- *id += 1;
-#endif
-#ifdef NDPI_CONTENT_CATEGORY_FLASH
- ndpi_set_bitmask_protocol_detection("Flash", ndpi_struct, detection_bitmask, *id,
- NDPI_CONTENT_CATEGORY_FLASH,
- ndpi_search_http_tcp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
- NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
- *id += 1;
-#endif
-#ifdef NDPI_CONTENT_CATEGORY_QUICKTIME
- ndpi_set_bitmask_protocol_detection("QuickTime", ndpi_struct, detection_bitmask, *id,
- NDPI_CONTENT_CATEGORY_QUICKTIME,
- ndpi_search_http_tcp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
- NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
- *id += 1;
-#endif
-#ifdef NDPI_CONTENT_CATEGORY_REALMEDIA
- ndpi_set_bitmask_protocol_detection("RealMedia", ndpi_struct, detection_bitmask, *id,
- NDPI_CONTENT_CATEGORY_REALMEDIA,
- ndpi_search_http_tcp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
- NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
- *id += 1;
-#endif
-#ifdef NDPI_CONTENT_CATEGORY_WINDOWSMEDIA
- ndpi_set_bitmask_protocol_detection("WindowsMedia", ndpi_struct, detection_bitmask, *id,
- NDPI_CONTENT_CATEGORY_WINDOWSMEDIA,
- ndpi_search_http_tcp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
- NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
- *id += 1;
-#endif
-#ifdef NDPI_CONTENT_CATEGORY_MMS
- ndpi_set_bitmask_protocol_detection("MMS", ndpi_struct, detection_bitmask, *id,
- NDPI_CONTENT_CATEGORY_MMS,
- ndpi_search_http_tcp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
- NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
- *id += 1;
-#endif
-
- ndpi_set_bitmask_protocol_detection("Xbox", ndpi_struct, detection_bitmask, *id,
- NDPI_PROTOCOL_XBOX,
- ndpi_search_http_tcp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
- NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
- *id += 1;
-
- ndpi_set_bitmask_protocol_detection("QQ", ndpi_struct, detection_bitmask, *id,
- NDPI_PROTOCOL_QQ,
- ndpi_search_http_tcp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
- NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
- *id += 1;
-
-#ifdef NDPI_CONTENT_CATEGORY_AVI
- ndpi_set_bitmask_protocol_detection("AVI", ndpi_struct, detection_bitmask, *id,
- NDPI_CONTENT_CATEGORY_AVI,
- ndpi_search_http_tcp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
- NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
- *id += 1;
-#endif
-#ifdef NDPI_CONTENT_CATEGORY_OGG
- ndpi_set_bitmask_protocol_detection("OggVorbis", ndpi_struct, detection_bitmask, *id,
- NDPI_CONTENT_CATEGORY_OGG,
- ndpi_search_http_tcp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
- NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
- *id += 1;
-#endif
-
- /* Update excluded protocol bitmask */
- NDPI_BITMASK_SET(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask,
- ndpi_struct->callback_buffer[a].detection_bitmask);
-
- /*Delete protocol from excluded protocol bitmask*/
- NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask, NDPI_PROTOCOL_UNKNOWN);
-
- NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask, NDPI_PROTOCOL_QQ);
-
-#ifdef NDPI_CONTENT_CATEGORY_FLASH
- NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask, NDPI_CONTENT_CATEGORY_FLASH);
-#endif
-
- NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask, NDPI_CONTENT_CATEGORY_MMS);
-
- NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask, NDPI_PROTOCOL_XBOX);
-
- NDPI_BITMASK_SET(ndpi_struct->generic_http_packet_bitmask, ndpi_struct->callback_buffer[a].detection_bitmask);
-
- NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->generic_http_packet_bitmask, NDPI_PROTOCOL_UNKNOWN);
-
- /* Update callback_buffer index */
- a++;
-
-#endif
}
diff --git a/src/lib/protocols/mdns_proto.c b/src/lib/protocols/mdns_proto.c
index 77bdf4208..75eab720b 100644
--- a/src/lib/protocols/mdns_proto.c
+++ b/src/lib/protocols/mdns_proto.c
@@ -63,21 +63,19 @@ static int ndpi_int_check_mdns_payload(struct ndpi_detection_module_struct
struct ndpi_packet_struct *packet = &flow->packet;
struct mdns_header *h = (struct mdns_header*)packet->payload;
u_int16_t questions = ntohs(h->questions), answers = ntohs(h->answers);
+
+ if((questions > NDPI_MAX_MDNS_REQUESTS)
+ || (answers > NDPI_MAX_MDNS_REQUESTS))
+ return(0);
- if(((packet->payload[2] & 0x80) == 0)
- && (questions <= NDPI_MAX_MDNS_REQUESTS)
- && (answers <= NDPI_MAX_MDNS_REQUESTS)) {
+ if((packet->payload[2] & 0x80) == 0) {
NDPI_LOG_INFO(ndpi_struct, "found MDNS with question query\n");
return 1;
- }
- else if(((packet->payload[2] & 0x80) != 0)
- && (questions == 0)
- && (answers <= NDPI_MAX_MDNS_REQUESTS)
- && (answers != 0)) {
+ } else if((packet->payload[2] & 0x80) != 0) {
char answer[256];
int i, j, len;
- for(i=13, j=0; (packet->payload[i] != 0) && (i < packet->payload_packet_len) && (i < (sizeof(answer)-1)); i++)
+ for(i=13, j=0; (i < packet->payload_packet_len) && (i < (sizeof(answer)-1)) && (packet->payload[i] != 0); i++)
answer[j++] = (packet->payload[i] < 13) ? '.' : packet->payload[i];
answer[j] = '\0';
@@ -100,8 +98,6 @@ static int ndpi_int_check_mdns_payload(struct ndpi_detection_module_struct
void ndpi_search_mdns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
{
struct ndpi_packet_struct *packet = &flow->packet;
- u_int16_t dport;
-
NDPI_LOG_DBG(ndpi_struct, "search MDNS\n");
/**
@@ -111,15 +107,13 @@ void ndpi_search_mdns(struct ndpi_detection_module_struct *ndpi_struct, struct n
/* check if UDP packet */
if(packet->udp != NULL) {
/* read destination port */
- dport = ntohs(packet->udp->dest);
+ u_int16_t sport = ntohs(packet->udp->source);
+ u_int16_t dport = ntohs(packet->udp->dest);
/* check standard MDNS ON port 5353 */
- if(dport == 5353 && packet->payload_packet_len >= 12) {
- /* mdns protocol must have destination address 224.0.0.251 */
- if(packet->iph != NULL /* && ntohl(packet->iph->daddr) == 0xe00000fb */) {
-
- NDPI_LOG_INFO(ndpi_struct, "found MDNS with destination address 224.0.0.251 (=0xe00000fb)\n");
-
+ if(((dport == 5353) || (sport == 5353))
+ && (packet->payload_packet_len >= 12)) {
+ if(packet->iph != NULL) {
if(ndpi_int_check_mdns_payload(ndpi_struct, flow) == 1) {
ndpi_int_mdns_add_connection(ndpi_struct, flow);
return;
@@ -141,6 +135,7 @@ void ndpi_search_mdns(struct ndpi_detection_module_struct *ndpi_struct, struct n
#endif
}
}
+
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
}
diff --git a/src/lib/protocols/mining.c b/src/lib/protocols/mining.c
index ec094e7d3..b4361e270 100644
--- a/src/lib/protocols/mining.c
+++ b/src/lib/protocols/mining.c
@@ -44,9 +44,12 @@ void ndpi_search_mining_tcp(struct ndpi_detection_module_struct *ndpi_struct,
if((*to_match == magic) || (*to_match == magic1)) {
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MINING, NDPI_PROTOCOL_UNKNOWN);
}
- } if(ndpi_strnstr((const char *)packet->payload, "\"eth1.0\"", packet->payload_packet_len)
- || ndpi_strnstr((const char *)packet->payload, "\"worker\"", packet->payload_packet_len)
- || ndpi_strnstr((const char *)packet->payload, "\"id\"", packet->payload_packet_len)) {
+ } if(ndpi_strnstr((const char *)packet->payload, "{", packet->payload_packet_len)
+ && (
+ ndpi_strnstr((const char *)packet->payload, "\"eth1.0\"", packet->payload_packet_len)
+ || ndpi_strnstr((const char *)packet->payload, "\"worker\":", packet->payload_packet_len)
+ /* || ndpi_strnstr((const char *)packet->payload, "\"id\":", packet->payload_packet_len) - Removed as too generic */
+ )) {
/*
Ethereum
@@ -55,9 +58,12 @@ void ndpi_search_mining_tcp(struct ndpi_detection_module_struct *ndpi_struct,
{"worker": "", "jsonrpc": "2.0", "params": [], "id": 3, "method": "eth_getWork"}
*/
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MINING, NDPI_PROTOCOL_UNKNOWN);
- } else if(ndpi_strnstr((const char *)packet->payload, "\"method\"", packet->payload_packet_len)
- || ndpi_strnstr((const char *)packet->payload, "\"blob\"", packet->payload_packet_len)
- || ndpi_strnstr((const char *)packet->payload, "\"id\"", packet->payload_packet_len)) {
+ } else if(ndpi_strnstr((const char *)packet->payload, "{", packet->payload_packet_len)
+ && (ndpi_strnstr((const char *)packet->payload, "\"method\":", packet->payload_packet_len)
+ || ndpi_strnstr((const char *)packet->payload, "\"blob\":", packet->payload_packet_len)
+ /* || ndpi_strnstr((const char *)packet->payload, "\"id\":", packet->payload_packet_len) - Removed as too generic */
+ )
+ ) {
/*
ZCash
diff --git a/src/lib/protocols/modbus.c b/src/lib/protocols/modbus.c
new file mode 100644
index 000000000..2a6dd2a49
--- /dev/null
+++ b/src/lib/protocols/modbus.c
@@ -0,0 +1,72 @@
+
+/*
+ * modbus.c
+ *
+ * Copyright (C) 2018 - ntop.org
+ *
+ * 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_protocol_ids.h"
+#include "ndpi_api.h"
+
+#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_MODBUS
+
+void ndpi_search_modbus_tcp(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ NDPI_LOG_DBG(ndpi_struct, "search Modbus\n");
+ u_int16_t modbus_port = htons(502); // port used by modbus
+
+ /* Check connection over TCP */
+
+ if(packet->tcp) {
+ /* The payload of Modbus-TCP segment must be at least 8 bytes (7 bytes of header application
+ packet plus 1 byte of minimum payload of application packet)
+ */
+ if((packet->payload_packet_len >= 8)
+ &&((packet->tcp->dest == modbus_port) || (packet->tcp->source == modbus_port))) {
+ // Modbus uses the port 502
+ u_int16_t modbus_len = htons(*((u_int16_t*)&packet->payload[4]));
+
+ // the fourth parameter of the payload is the length of the segment
+ if((modbus_len-1) == (packet->payload_packet_len - 7 /* ModbusTCP header len */)) {
+ NDPI_LOG_INFO(ndpi_struct, "found MODBUS\n");
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_MODBUS, NDPI_PROTOCOL_UNKNOWN);
+ return;
+ }
+ }
+ }
+ NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
+
+}
+
+
+
+void init_modbus_dissector(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) {
+
+ ndpi_set_bitmask_protocol_detection("Modbus", ndpi_struct, detection_bitmask, *id,
+ NDPI_PROTOCOL_MODBUS,
+ ndpi_search_modbus_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+ *id += 1;
+}
diff --git a/src/lib/protocols/ookla.c b/src/lib/protocols/ookla.c
index b1eb295a7..06d97e216 100644
--- a/src/lib/protocols/ookla.c
+++ b/src/lib/protocols/ookla.c
@@ -22,34 +22,32 @@
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_OOKLA
#include "ndpi_api.h"
-#include "lruc.h"
void ndpi_search_ookla(struct ndpi_detection_module_struct* ndpi_struct, struct ndpi_flow_struct* flow) {
struct ndpi_packet_struct* packet = &flow->packet;
u_int32_t addr = 0;
void *value;
-
+
NDPI_LOG_DBG(ndpi_struct, "Ookla detection\n");
-
+
if(packet->tcp->source == htons(8080))
addr = packet->iph->saddr;
else if(packet->tcp->dest == htons(8080))
addr = packet->iph->daddr;
else
goto ookla_exclude;
-
+
if(ndpi_struct->ookla_cache != NULL) {
- if(lruc_get(ndpi_struct->ookla_cache, &addr, sizeof(addr), &value) == LRUC_NO_ERROR) {
- /* Don't remove it as it can be used for other connections */
+ if(ndpi_lru_find_cache(ndpi_struct->ookla_cache, addr, 0 /* Don't remove it as it can be used for other connections */)) {
NDPI_LOG_INFO(ndpi_struct, "found ookla tcp connection\n");
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_OOKLA, NDPI_PROTOCOL_UNKNOWN);
return;
- }
+ }
}
ookla_exclude:
- NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
+ NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
}
void init_ookla_dissector(struct ndpi_detection_module_struct *ndpi_struct,
@@ -63,4 +61,3 @@ void init_ookla_dissector(struct ndpi_detection_module_struct *ndpi_struct,
*id += 1;
}
-
diff --git a/src/lib/protocols/quic.c b/src/lib/protocols/quic.c
index e28db634a..d14538e0d 100644
--- a/src/lib/protocols/quic.c
+++ b/src/lib/protocols/quic.c
@@ -22,6 +22,10 @@
*
*/
+#if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
+#include <sys/endian.h>
+#endif
+
#include "ndpi_protocol_ids.h"
#define NDPI_CURRENT_PROTO NDPI_PROTOCOL_QUIC
@@ -96,8 +100,8 @@ void ndpi_search_quic(struct ndpi_detection_module_struct *ndpi_struct,
&& (packet->payload[i+1] == 'N')
&& (packet->payload[i+2] == 'I')
&& (packet->payload[i+3] == 0)) {
- u_int32_t offset = *((u_int32_t*)&packet->payload[i+4]);
- u_int32_t prev_offset = *((u_int32_t*)&packet->payload[i-4]);
+ u_int32_t offset = le32toh(*((u_int32_t*)&packet->payload[i+4]));
+ u_int32_t prev_offset = le32toh(*((u_int32_t*)&packet->payload[i-4]));
int len = offset-prev_offset;
int sni_offset = i+prev_offset+1;
diff --git a/src/lib/protocols/radius.c b/src/lib/protocols/radius.c
index 1c85f48d7..209e71177 100644
--- a/src/lib/protocols/radius.c
+++ b/src/lib/protocols/radius.c
@@ -39,10 +39,13 @@ static void ndpi_check_radius(struct ndpi_detection_module_struct *ndpi_struct,
if(packet->udp != NULL) {
struct radius_header *h = (struct radius_header*)packet->payload;
+ /* RFC2865: The minimum length is 20 and maximum length is 4096. */
+ if((payload_len < 20) || (payload_len > 4096))
+ return;
if((payload_len > sizeof(struct radius_header))
&& (h->code > 0)
- && (h->code <= 5)
+ && (h->code <= 13)
&& (ntohs(h->len) == payload_len)) {
NDPI_LOG_INFO(ndpi_struct, "Found radius\n");
ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_RADIUS, NDPI_PROTOCOL_UNKNOWN);
diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c
index 25d535a57..05988a8d4 100644
--- a/src/lib/protocols/ssl.c
+++ b/src/lib/protocols/ssl.c
@@ -28,6 +28,7 @@
#include "ndpi_api.h"
// #define CERTIFICATE_DEBUG 1
+
#define NDPI_MAX_SSL_REQUEST_SIZE 10000
/* Skype.c */
@@ -150,9 +151,10 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
#ifdef CERTIFICATE_DEBUG
{
- static u_int8_t id = 0;
-
- NDPI_LOG_DBG2(ndpi_struct,"-> [%u] %02X\n", ++id, packet->payload[0] & 0xFF);
+ u_int16_t ssl_version = (packet->payload[1] << 8) + packet->payload[2];
+ u_int16_t ssl_len = (packet->payload[3] << 8) + packet->payload[4];
+
+ printf("SSL Record [version: 0x%02X][len: %u]\n", ssl_version, ssl_len);
}
#endif
@@ -174,10 +176,18 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
if(total_len > 4) {
int i;
- if(handshake_protocol == 0x02 || handshake_protocol == 0xb /* Server Hello and Certificate message types are interesting for us */) {
+#ifdef CERTIFICATE_DEBUG
+ printf("SSL [len: %u][handshake_protocol: %02X]\n", packet->payload_packet_len, handshake_protocol);
+#endif
+
+ if((handshake_protocol == 0x02)
+ || (handshake_protocol == 0xb) /* Server Hello and Certificate message types are interesting for us */) {
u_int num_found = 0;
- flow->l4.tcp.ssl_seen_server_cert = 1;
+ if(handshake_protocol == 0x02)
+ flow->l4.tcp.ssl_seen_server_cert = 1;
+ else
+ flow->l4.tcp.ssl_seen_certificate = 1;
/* Check after handshake protocol header (5 bytes) and message header (4 bytes) */
for(i = 9; i < packet->payload_packet_len-3; i++) {
@@ -215,11 +225,11 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
break;
} else if(buffer[j] == '.') {
num_dots++;
- if(num_dots >=2) break;
+ if(num_dots >=1) break;
}
}
- if(num_dots >= 2) {
+ if(num_dots >= 1) {
if(!ndpi_struct->disable_metadata_export) {
stripCertificateTrailer(buffer, buffer_len);
snprintf(flow->protos.stun_ssl.ssl.server_certificate,
@@ -232,8 +242,7 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
}
} else if(handshake_protocol == 0x01 /* Client Hello */) {
u_int offset, base_offset = 43;
- if (base_offset + 2 <= packet->payload_packet_len)
- {
+ if(base_offset + 2 <= packet->payload_packet_len) {
u_int16_t session_id_len = packet->payload[base_offset];
if((session_id_len+base_offset+2) <= total_len) {
@@ -335,25 +344,94 @@ int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
return(0); /* Not found */
}
+void getSSLorganization(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ char *buffer, int buffer_len) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if(packet->payload[0] != 0x16 /* Handshake */)
+ return;
+
+ u_int16_t total_len = (packet->payload[3] << 8) + packet->payload[4] + 5 /* SSL Header */;
+ u_int8_t handshake_protocol = packet->payload[5]; /* handshake protocol a bit misleading, it is message type according TLS specs */
+
+ if(handshake_protocol != 0x02 && handshake_protocol != 0xb /* Server Hello and Certificate message types are interesting for us */)
+ return;
+
+ /* Truncate total len, search at least in incomplete packet */
+ if(total_len > packet->payload_packet_len)
+ total_len = packet->payload_packet_len;
+
+ memset(buffer, 0, buffer_len);
+
+ /* Check after handshake protocol header (5 bytes) and message header (4 bytes) */
+ u_int num_found = 0;
+ u_int i, j;
+ for(i = 9; i < packet->payload_packet_len-4; i++) {
+ /* Organization OID: 2.5.4.10 */
+ if((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x0a)) {
+ u_int8_t type_tag = packet->payload[i+3]; // 0x0c: utf8string / 0x13: printable_string
+ u_int8_t server_len = packet->payload[i+4];
+
+ num_found++;
+ /* what we want is subject certificate, so we bypass the issuer certificate */
+ if(num_found != 2) continue;
+
+ // packet is truncated... further inspection is not needed
+ if(i+4+server_len >= packet->payload_packet_len) {
+ break;
+ }
+
+ char *server_org = (char*)&packet->payload[i+5];
+
+ u_int len = (u_int)ndpi_min(server_len, buffer_len-1);
+ strncpy(buffer, server_org, len);
+ buffer[len] = '\0';
+
+ // check if organization string are all printable
+ u_int8_t is_printable = 1;
+ for (j = 0; j < len; j++) {
+ if(!ndpi_isprint(buffer[j])) {
+ is_printable = 0;
+ break;
+ }
+ }
+
+ if(is_printable == 1) {
+ snprintf(flow->protos.stun_ssl.ssl.server_organization,
+ sizeof(flow->protos.stun_ssl.ssl.server_organization), "%s", buffer);
+#ifdef CERTIFICATE_DEBUG
+ printf("Certificate origanization: %s\n", flow->protos.stun_ssl.ssl.server_organization);
+#endif
+ }
+ }
+ }
+}
+
int sslTryAndRetrieveServerCertificate(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
/* consider only specific SSL packets (handshake) */
if((packet->payload_packet_len > 9) && (packet->payload[0] == 0x16)) {
char certificate[64];
+ char organization[64];
int rc;
certificate[0] = '\0';
rc = getSSLcertificate(ndpi_struct, flow, certificate, sizeof(certificate));
packet->ssl_certificate_num_checks++;
- if (rc > 0) {
+ if(rc > 0) {
+ // try fetch server organization once server certificate is found
+ organization[0] = '\0';
+ getSSLorganization(ndpi_struct, flow, organization, sizeof(organization));
+
packet->ssl_certificate_detected++;
- if ((flow->l4.tcp.ssl_seen_server_cert == 1) && (flow->protos.stun_ssl.ssl.server_certificate[0] != '\0'))
+ if((flow->l4.tcp.ssl_seen_server_cert == 1) && (flow->protos.stun_ssl.ssl.server_certificate[0] != '\0'))
/* 0 means we're done processing extra packets (since we found what we wanted) */
return 0;
}
/* Client hello, Server Hello, and certificate packets probably all checked in this case */
- if ((packet->ssl_certificate_num_checks >= 3)
+ if((packet->ssl_certificate_num_checks >= 3)
&& (flow->l4.tcp.seen_syn)
&& (flow->l4.tcp.seen_syn_ack)
&& (flow->l4.tcp.seen_ack) /* We have seen the 3-way handshake */)
@@ -369,7 +447,7 @@ int sslTryAndRetrieveServerCertificate(struct ndpi_detection_module_struct *ndpi
void sslInitExtraPacketProcessing(int caseNum, struct ndpi_flow_struct *flow) {
flow->check_extra_packets = 1;
/* 0 is the case for waiting for the server certificate */
- if (caseNum == 0) {
+ if(caseNum == 0) {
/* At most 7 packets should almost always be enough to find the server certificate if it's there */
flow->max_extra_packets_to_check = 7;
flow->extra_packets_func = sslTryAndRetrieveServerCertificate;
@@ -405,7 +483,8 @@ int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_s
/* 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
* a few more packets. */
- 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'))) {
+ 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);
}
@@ -418,11 +497,13 @@ int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_s
return(rc);
}
- if(((packet->ssl_certificate_num_checks >= 2)
+ if(((packet->ssl_certificate_num_checks >= 3)
&& flow->l4.tcp.seen_syn
&& flow->l4.tcp.seen_syn_ack
&& flow->l4.tcp.seen_ack /* We have seen the 3-way handshake */)
- || ((flow->l4.tcp.ssl_seen_server_cert == 1) && (flow->protos.stun_ssl.ssl.server_certificate[0] != '\0'))
+ || ((flow->l4.tcp.ssl_seen_certificate == 1)
+ && (flow->l4.tcp.ssl_seen_server_cert == 1)
+ && (flow->protos.stun_ssl.ssl.server_certificate[0] != '\0'))
/* || ((flow->l4.tcp.ssl_seen_client_cert == 1) && (flow->protos.stun_ssl.ssl.client_certificate[0] != '\0')) */
) {
ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL);
@@ -432,8 +513,7 @@ int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_s
return(0);
}
-static void ssl_mark_and_payload_search_for_other_protocols(struct
- ndpi_detection_module_struct
+static void ssl_mark_and_payload_search_for_other_protocols(struct ndpi_detection_module_struct
*ndpi_struct, struct ndpi_flow_struct *flow)
{
struct ndpi_packet_struct *packet = &flow->packet;
@@ -510,16 +590,16 @@ static void ssl_mark_and_payload_search_for_other_protocols(struct
/* SSL without certificate (Skype, Ultrasurf?) */
NDPI_LOG_INFO(ndpi_struct, "found ssl NO_CERT\n");
ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL_NO_CERT);
- } else
+ } else if(packet->ssl_certificate_num_checks >= 3) {
NDPI_LOG_INFO(ndpi_struct, "found ssl\n");
- ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL);
+ ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL);
+ }
}
}
static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow) {
-
struct ndpi_packet_struct *packet = &flow->packet;
if((packet->payload_packet_len >= 5)
@@ -559,7 +639,7 @@ static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct
}
}
- if((packet->payload_packet_len > temp && packet->payload_packet_len > 100) && packet->payload_packet_len > 9) {
+ if((packet->payload_packet_len > temp) && (packet->payload_packet_len > 100)) {
/* the server hello may be split into small packets and the certificate has its own SSL Record
* so temp contains only the length for the first ServerHello block */
u_int32_t cert_start;
@@ -647,27 +727,25 @@ void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struc
NDPI_LOG_DBG(ndpi_struct, "search ssl\n");
- {
- /* Check if this is whatsapp first (this proto runs over port 443) */
- if((packet->payload_packet_len > 5)
- && ((packet->payload[0] == 'W')
- && (packet->payload[1] == 'A')
- && (packet->payload[4] == 0)
- && (packet->payload[2] <= 9)
- && (packet->payload[3] <= 9))) {
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN);
- return;
- } else if((packet->payload_packet_len == 4)
- && (packet->payload[0] == 'W')
- && (packet->payload[1] == 'A')) {
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN);
+ /* Check if this is whatsapp first (this proto runs over port 443) */
+ if((packet->payload_packet_len > 5)
+ && ((packet->payload[0] == 'W')
+ && (packet->payload[1] == 'A')
+ && (packet->payload[4] == 0)
+ && (packet->payload[2] <= 9)
+ && (packet->payload[3] <= 9))) {
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN);
+ return;
+ } else if((packet->payload_packet_len == 4)
+ && (packet->payload[0] == 'W')
+ && (packet->payload[1] == 'A')) {
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN);
+ return;
+ } else {
+ /* No whatsapp, let's try SSL */
+ if(sslDetectProtocolFromCertificate(ndpi_struct, flow) > 0)
return;
- } else {
- /* No whatsapp, let's try SSL */
- if(sslDetectProtocolFromCertificate(ndpi_struct, flow) > 0)
- return;
- }
- }
+ }
if(packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 0) {
NDPI_LOG_DBG2(ndpi_struct, "first ssl packet\n");
diff --git a/src/lib/protocols/whatsapp.c b/src/lib/protocols/whatsapp.c
index 6964a8e0e..608e6576e 100644
--- a/src/lib/protocols/whatsapp.c
+++ b/src/lib/protocols/whatsapp.c
@@ -26,34 +26,26 @@
void ndpi_search_whatsapp(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
- u_int8_t whatsapp_sequence[] = {
+ static u_int8_t whatsapp_sequence[] = {
0x45, 0x44, 0x0, 0x01, 0x0, 0x0, 0x02, 0x08,
0x0, 0x57, 0x41, 0x02, 0x0, 0x0, 0x0
};
NDPI_LOG_DBG(ndpi_struct, "search WhatsApp\n");
- if(flow->l4.tcp.wa_matched_so_far == 0) {
- if(memcmp(packet->payload, whatsapp_sequence, packet->payload_packet_len)) {
- NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
- } else
- flow->l4.tcp.wa_matched_so_far = packet->payload_packet_len;
+ if(flow->l4.tcp.wa_matched_so_far < sizeof(whatsapp_sequence)) {
+ size_t match_len = sizeof(whatsapp_sequence) - flow->l4.tcp.wa_matched_so_far;
+ if(packet->payload_packet_len < match_len)
+ match_len = packet->payload_packet_len;
- return;
- } else {
- if(memcmp(packet->payload, &whatsapp_sequence[flow->l4.tcp.wa_matched_so_far],
- sizeof(whatsapp_sequence)-flow->l4.tcp.wa_matched_so_far))
- NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
- else
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN);
-
- return;
- }
-
- if((packet->payload_packet_len > 240)
- && (memcmp(packet->payload, whatsapp_sequence, sizeof(whatsapp_sequence)) == 0)) {
- NDPI_LOG_INFO(ndpi_struct, "found WhatsApp\n");
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN);
+ if(!memcmp(packet->payload, &whatsapp_sequence[flow->l4.tcp.wa_matched_so_far], match_len)) {
+ flow->l4.tcp.wa_matched_so_far += match_len;
+ if(flow->l4.tcp.wa_matched_so_far == sizeof(whatsapp_sequence)) {
+ NDPI_LOG_INFO(ndpi_struct, "found WhatsApp\n");
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_WHATSAPP, NDPI_PROTOCOL_UNKNOWN);
+ }
+ return;
+ }
}
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);