aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuca Deri <deri@ntop.org>2016-06-07 17:14:16 +0200
committerLuca Deri <deri@ntop.org>2016-06-07 17:14:16 +0200
commit0b7a392b302a606b60ad4d46dfcdc9930af338fa (patch)
treeb175f5ee4ae2ef6ae1cbc90d5667bb6e31f6303b /src
parent2379443ef55986604f77711caab5c3118a26f791 (diff)
Restored code harvested in
https://github.com/ntop/nDPI/commit/60e7e19dab72a37d57bc7854e702264e7d25886d#diff-0856ce19e6ed4e80946656d41f7edd65L135 DNS reply dissection can now be controlled by a preference as demonstrated in ndpiReader.c
Diffstat (limited to 'src')
-rw-r--r--src/include/ndpi_typedefs.h8
-rw-r--r--src/lib/protocols/dns.c186
2 files changed, 138 insertions, 56 deletions
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index 62a4f3083..8ec1453fc 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -849,8 +849,8 @@ struct ndpi_detection_module_struct {
ndpi_proto_defaults_t proto_defaults[NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS];
- u_int8_t http_dont_dissect_response:1;
- u_int8_t direction_detect_disable:1; /* disable internal detection of packet direction */
+ u_int8_t http_dont_dissect_response:1, dns_dissect_response:1,
+ direction_detect_disable:1; /* disable internal detection of packet direction */
};
struct ndpi_flow_struct {
@@ -911,8 +911,8 @@ struct ndpi_flow_struct {
/* the only fields useful for nDPI and ntopng */
struct {
- u_int8_t num_answers, ret_code;
- u_int16_t query_type;
+ u_int8_t num_queries, num_answers, reply_code;
+ u_int16_t query_type, query_class, rsp_type;
} dns;
struct {
diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c
index 98df46481..4c7f315c3 100644
--- a/src/lib/protocols/dns.c
+++ b/src/lib/protocols/dns.c
@@ -3,8 +3,6 @@
*
* Copyright (C) 2012-16 - ntop.org
*
- * Michele Campus - <campus@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
*
@@ -29,37 +27,60 @@
#define FLAGS_MASK 0x8000
-void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
-{
+/* #define DNS_DEBUG 1 */
+
+/* *********************************************** */
+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));
+}
+
+/* *********************************************** */
+
+static u_int getNameLength(u_int i, const u_int8_t *payload, u_int payloadLen) {
+ if(payload[i] == 0x00)
+ return(1);
+ else if(payload[i] == 0xC0)
+ return(2);
+ 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));
+ }
+}
+
+/* *********************************************** */
+
+void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
int x;
- u_int8_t is_query, ret_code;
- u_int16_t s_port = 0;
- u_int16_t d_port = 0;
+ u_int8_t is_query;
+ u_int16_t s_port = 0, d_port = 0;
NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "search DNS.\n");
- if(flow->packet.udp != NULL)
- {
+ if(flow->packet.udp != NULL) {
s_port = ntohs(flow->packet.udp->source);
d_port = ntohs(flow->packet.udp->dest);
x = 0;
- }
- else if(flow->packet.tcp != NULL) /* pkt size > 512 bytes */
- {
+ } 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;
- }
- else
- {
+ } else {
NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "exclude DNS.\n");
NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DNS);
}
if((s_port == 53 || d_port == 53 || d_port == 5355)
- && (flow->packet.payload_packet_len > sizeof(struct ndpi_dns_packet_header)))
- {
+ && (flow->packet.payload_packet_len > sizeof(struct ndpi_dns_packet_header))) {
struct ndpi_dns_packet_header dns_header;
int invalid = 0;
@@ -70,6 +91,7 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
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 */
if((dns_header.flags & FLAGS_MASK) == 0x0000)
@@ -87,33 +109,85 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
&& (((dns_header.flags & 0x2800) == 0x2800 /* Dynamic DNS Update */)
|| ((dns_header.num_answers == 0) && (dns_header.authority_rrs == 0)))) {
/* This is a good query */
+
+ if(dns_header.num_queries > 0) {
+ 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
+ printf("[%s:%d] query_type=%2d\n", __FILE__, __LINE__, flow->protos.dns.query_type);
+#endif
+ break;
+ } else
+ x++;
+ }
+ }
} else
invalid = 1;
+
+ if(ndpi_struct->dns_dissect_response)
+ return; /* The response will set the verdict */
} 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 */
- } else
- invalid = 1;
+ if(ndpi_struct->dns_dissect_response) {
+ x++;
+
+ if(flow->packet.payload[x] != '\0') {
+ while((x < flow->packet.payload_packet_len)
+ && (flow->packet.payload[x] != '\0')) {
+ x++;
+ }
+
+ x++;
+ }
+
+ x += 4;
+
+ 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;
+
+ 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;
+
+ rsp_type = get16(&x, flow->packet.payload);
+ flow->protos.dns.rsp_type = rsp_type;
+ break;
+ }
+ }
+ }
+ }
}
- }
- if(invalid) {
- NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "exclude DNS.\n");
- NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DNS);
- return;
- }
+ if(invalid) {
+ NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "exclude DNS.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DNS);
+ return;
+ }
- /* extract host name server */
- ret_code = (is_query == 0) ? 0 : (dns_header.flags & 0x0F);
- int j = 0;
- int off = sizeof(struct ndpi_dns_packet_header) + 1;
- while(flow->packet.payload[off] != '\0' && off < flow->packet.payload_packet_len)
- {
+ /* extract host name server */
+ int j = 0, off = sizeof(struct ndpi_dns_packet_header) + 1;
+
+ while(flow->packet.payload[off] != '\0' && off < flow->packet.payload_packet_len) {
flow->host_server_name[j] = flow->packet.payload[off];
if(j < strlen((char*)flow->host_server_name)) {
if(flow->host_server_name[j] < ' ')
@@ -121,31 +195,39 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
j++;
}
off++;
- }
- flow->host_server_name[j] = '\0';
+ }
+ flow->host_server_name[j] = '\0';
+
+ 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);
- flow->protos.dns.ret_code = ret_code;
+#ifdef DNS_DEBUG
+ printf("[%s:%d] [num_queries=%d][num_answers=%d][reply_code=%u][rsp_type=%u][host_server_name=%s]\n",
+ __FILE__, __LINE__,
+ 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(j > 0)
- ndpi_match_host_subprotocol(ndpi_struct, flow,
- (char *)flow->host_server_name,
- strlen((const char*)flow->host_server_name),
- NDPI_PROTOCOL_DNS);
+ if(j > 0)
+ ndpi_match_host_subprotocol(ndpi_struct, flow,
+ (char *)flow->host_server_name,
+ strlen((const char*)flow->host_server_name),
+ NDPI_PROTOCOL_DNS);
- 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(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "found DNS.\n");
- ndpi_set_detected_protocol(ndpi_struct, flow, (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN);
- } else {
- NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "exclude DNS.\n");
- NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DNS);
+ 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(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "found DNS.\n");
+ ndpi_set_detected_protocol(ndpi_struct, flow, (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "exclude DNS.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DNS);
+ }
}
- }
+ }
}
void init_dns_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)