aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/ndpi_api.h3
-rw-r--r--src/lib/ndpi_main.c41
-rw-r--r--src/lib/protocols/dns.c247
3 files changed, 173 insertions, 118 deletions
diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h
index cf1f60d5e..34b1fed67 100644
--- a/src/include/ndpi_api.h
+++ b/src/include/ndpi_api.h
@@ -807,7 +807,8 @@ extern "C" {
int ndpi_flowv6_flow_hash(u_int8_t l4_proto, struct ndpi_in6_addr *src_ip, struct ndpi_in6_addr *dst_ip,
u_int16_t src_port, u_int16_t dst_port, u_int8_t icmp_type, u_int8_t icmp_code,
u_char *hash_buf, u_int8_t hash_buf_len);
-
+ u_int8_t ndpi_extra_dissection_possible(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow);
u_int8_t ndpi_is_safe_ssl_cipher(u_int32_t cipher);
const char* ndpi_cipher2str(u_int32_t cipher);
u_int16_t ndpi_guess_host_protocol_id(struct ndpi_detection_module_struct *ndpi_struct,
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index 380b622b3..cde2e13a9 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -6288,4 +6288,43 @@ int ndpi_flowv6_flow_hash(u_int8_t l4_proto, struct ndpi_in6_addr *src_ip, struc
return(0); /* OK */
}
-/* **************************************** */
+/* ******************************************************************** */
+
+/*
+ This function tells if it's possible to further dissect a given flow
+ 0 - All possible dissection has been completed
+ 1 - Additional dissection is possible
+*/
+u_int8_t ndpi_extra_dissection_possible(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
+
+#if 0
+ printf("[DEBUG] %s(%u.%u)\n", __FUNCTION__,
+ flow->detected_protocol_stack[0],
+ flow->detected_protocol_stack[1]);
+#endif
+
+ if(flow->check_extra_packets) return(1);
+
+ switch(flow->detected_protocol_stack[0]) {
+ case NDPI_PROTOCOL_TLS:
+ if(!flow->l4.tcp.tls_srv_cert_fingerprint_processed)
+ return(1);
+ break;
+
+ case NDPI_PROTOCOL_HTTP:
+ if(flow->host_server_name[0] == '\0')
+ return(1);
+ break;
+
+ case NDPI_PROTOCOL_DNS:
+ if((ndpi_struct->dns_dont_dissect_response == 0)
+ && (flow->host_server_name[0] == '\0'))
+ return(1);
+ break;
+ }
+
+ return(0);
+}
+
+/* ******************************************************************** */
diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c
index 4e3ffb5ed..b3df9b466 100644
--- a/src/lib/protocols/dns.c
+++ b/src/lib/protocols/dns.c
@@ -30,7 +30,7 @@
#define FLAGS_MASK 0x8000
-/* #define DNS_DEBUG 1 */
+// #define DNS_DEBUG 1
/* *********************************************** */
@@ -60,31 +60,36 @@ static u_int getNameLength(u_int i, const u_int8_t *payload, u_int payloadLen) {
}
}
/*
- allowed chars for dns names A-Z 0-9 _ -
- Perl script for generation map:
+ 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;
+ $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
+ 0x00000000,0x03ff2000,0x87fffffe,0x07fffffe,0,0,0,0
};
/* *********************************************** */
-static int search_valid_dns(struct ndpi_flow_struct *flow, struct ndpi_dns_packet_header *dns_header, int payload_offset, u_int8_t*is_query) {
+static int search_valid_dns(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ struct ndpi_dns_packet_header *dns_header,
+ int payload_offset, u_int8_t *is_query) {
int x = payload_offset;
- memcpy(dns_header, (struct ndpi_dns_packet_header*) &flow->packet.payload[x], sizeof(struct ndpi_dns_packet_header));
+ memcpy(dns_header, (struct ndpi_dns_packet_header*)&flow->packet.payload[x],
+ sizeof(struct ndpi_dns_packet_header));
dns_header->tr_id = ntohs(dns_header->tr_id);
dns_header->flags = ntohs(dns_header->flags);
dns_header->num_queries = ntohs(dns_header->num_queries);
dns_header->num_answers = ntohs(dns_header->num_answers);
dns_header->authority_rrs = ntohs(dns_header->authority_rrs);
dns_header->additional_rrs = ntohs(dns_header->additional_rrs);
+
x += sizeof(struct ndpi_dns_packet_header);
/* 0x0000 QUERY */
@@ -99,88 +104,93 @@ static int search_valid_dns(struct ndpi_flow_struct *flow, struct ndpi_dns_packe
if(*is_query) {
/* DNS Request */
if((dns_header->num_queries > 0) && (dns_header->num_queries <= NDPI_MAX_DNS_REQUESTS)
- && (((dns_header->flags & 0x2800) == 0x2800 /* Dynamic DNS Update */)
- || ((dns_header->num_answers == 0) && (dns_header->authority_rrs == 0)))) {
- /* This is a good query */
+ && (((dns_header->flags & 0x2800) == 0x2800 /* Dynamic DNS Update */)
+ || ((dns_header->num_answers == 0) && (dns_header->authority_rrs == 0)))) {
+ /* This is a good query */
while(x < flow->packet.payload_packet_len) {
if(flow->packet.payload[x] == '\0') {
x++;
flow->protos.dns.query_type = get16(&x, flow->packet.payload);
#ifdef DNS_DEBUG
NDPI_LOG_DBG2(ndpi_struct, "query_type=%2d\n", flow->protos.dns.query_type);
+ printf("[DNS] query_type=%d\n", flow->protos.dns.query_type);
#endif
- break;
- } else
- x++;
+
+ if(ndpi_struct->dns_dont_dissect_response)
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN);
+
+ break;
+ } else
+ x++;
}
} else
return(1 /* invalid */);
} else {
- /* DNS Reply */
- flow->protos.dns.reply_code = dns_header->flags & 0x0F;
-
- if((dns_header->num_queries > 0) && (dns_header->num_queries <= NDPI_MAX_DNS_REQUESTS) /* Don't assume that num_queries must be zero */
- && (((dns_header->num_answers > 0) && (dns_header->num_answers <= NDPI_MAX_DNS_REQUESTS))
- || ((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: 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) */ {
+ /* DNS Reply */
+ flow->protos.dns.reply_code = dns_header->flags & 0x0F;
+
+ if((dns_header->num_queries > 0) && (dns_header->num_queries <= NDPI_MAX_DNS_REQUESTS) /* Don't assume that num_queries must be zero */
+ && (((dns_header->num_answers > 0) && (dns_header->num_answers <= NDPI_MAX_DNS_REQUESTS))
+ || ((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: 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++;
+ }
- if(flow->packet.payload[x] != '\0') {
- while((x < flow->packet.payload_packet_len)
- && (flow->packet.payload[x] != '\0')) {
- x++;
- }
-
- x++;
- }
+ x++;
+ }
- x += 4;
+ x += 4;
- if(dns_header->num_answers > 0) {
- u_int16_t rsp_type;
- u_int16_t num;
+ if(dns_header->num_answers > 0) {
+ u_int16_t rsp_type;
+ u_int16_t num;
- for(num = 0; num < dns_header->num_answers; num++) {
- u_int16_t data_len;
+ for(num = 0; num < dns_header->num_answers; num++) {
+ u_int16_t data_len;
- if((x+6) >= flow->packet.payload_packet_len) {
- break;
- }
+ if((x+6) >= flow->packet.payload_packet_len) {
+ break;
+ }
- if((data_len = getNameLength(x, flow->packet.payload, flow->packet.payload_packet_len)) == 0) {
- break;
- } else
- x += data_len;
+ if((data_len = getNameLength(x, flow->packet.payload, flow->packet.payload_packet_len)) == 0) {
+ break;
+ } else
+ x += data_len;
- rsp_type = get16(&x, flow->packet.payload);
- flow->protos.dns.rsp_type = rsp_type;
+ 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);
+ /* 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 */
+ 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 */
+ || ((rsp_type == 0x1c) && (data_len == 16)) /* AAAA */
#endif
- )) {
- memcpy(&flow->protos.dns.rsp_addr, flow->packet.payload + x, data_len);
- }
- }
-
- break;
+ )) {
+ memcpy(&flow->protos.dns.rsp_addr, flow->packet.payload + x, data_len);
}
}
+
+ break;
}
- } else
- return(1 /* invalid */);
+ }
+ }
+ } else
+ return(1 /* invalid */);
}
/* Valid */
@@ -195,6 +205,7 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
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);
@@ -210,78 +221,82 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
if((s_port == 53 || d_port == 53 || d_port == 5355)
&& (flow->packet.payload_packet_len > sizeof(struct ndpi_dns_packet_header)+payload_offset)) {
- struct ndpi_dns_packet_header dns_header;
- int j = 0, max_len, off;
- int invalid = search_valid_dns(flow, &dns_header, payload_offset, &is_query);
+ struct ndpi_dns_packet_header dns_header;
+ int j = 0, max_len, off;
+ int invalid = search_valid_dns(ndpi_struct, flow, &dns_header, payload_offset, &is_query);
- if(invalid) {
- NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
- return;
- }
+ if(invalid) {
+ NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
+ return;
+ }
- /* extract host name server */
- max_len = sizeof(flow->host_server_name)-1;
- off = sizeof(struct ndpi_dns_packet_header) + payload_offset;
+ /* extract host name server */
+ 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++];
+ 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( (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++] = '.';
+ 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--;
- }
+ 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--;
}
- flow->host_server_name[j] = '\0';
+ }
+ 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 */
- }
+ 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_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);
- if(j > 0) {
- ndpi_protocol_match_result ret_match;
+ if(j > 0) {
+ ndpi_protocol_match_result ret_match;
- ndpi_match_host_subprotocol(ndpi_struct, flow,
- (char *)flow->host_server_name,
- strlen((const char*)flow->host_server_name),
- &ret_match,
- NDPI_PROTOCOL_DNS);
- }
+ 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
- );
+ 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_set_detected_protocol(ndpi_struct, flow, (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN);
- } else {
+ 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_set_detected_protocol(ndpi_struct, flow, (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN);
+ } else {
+ if((flow->packet.detected_protocol_stack[0] == NDPI_PROTOCOL_DNS)
+ || (flow->packet.detected_protocol_stack[1] == NDPI_PROTOCOL_DNS))
+ ;
+ 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)
-{
+void init_dns_dissector(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) {
ndpi_set_bitmask_protocol_detection("DNS", ndpi_struct, detection_bitmask, *id,
NDPI_PROTOCOL_DNS,
ndpi_search_dns,