aboutsummaryrefslogtreecommitdiff
path: root/src/lib/protocols/dns.c
diff options
context:
space:
mode:
authorLuca Deri <deri@ntop.org>2019-09-26 23:50:02 +0200
committerLuca Deri <deri@ntop.org>2019-09-26 23:50:02 +0200
commit17f560a1cd5a539bf8940072bac05ccbf3b547f9 (patch)
treed647cc792cb15f1700ece1c7e95fb2bb14713439 /src/lib/protocols/dns.c
parent194cdcf581f7d405fca191f99eedcb734e68f5ec (diff)
Added ndpi_extra_dissection_possible() API call
Diffstat (limited to 'src/lib/protocols/dns.c')
-rw-r--r--src/lib/protocols/dns.c247
1 files changed, 131 insertions, 116 deletions
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,