diff options
-rw-r--r-- | src/lib/protocols/dns.c | 157 |
1 files changed, 80 insertions, 77 deletions
diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c index b9cd1a9cb..4e3ffb5ed 100644 --- a/src/lib/protocols/dns.c +++ b/src/lib/protocols/dns.c @@ -72,84 +72,57 @@ static u_int getNameLength(u_int i, const u_int8_t *payload, u_int payloadLen) { 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, 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); - 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); - 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; - int invalid = 0; - - 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 */ - if((dns_header.flags & FLAGS_MASK) == 0x0000) - is_query = 1; - /* 0x8000 RESPONSE */ - else if((dns_header.flags & FLAGS_MASK) == 0x8000) - is_query = 0; - else - 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) - && (((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); +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) { + int x = payload_offset; + + 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 */ + if((dns_header->flags & FLAGS_MASK) == 0x0000) + *is_query = 1; + /* 0x8000 RESPONSE */ + else if((dns_header->flags & FLAGS_MASK) == 0x8000) + *is_query = 0; + else + return(1 /* invalid */); + + 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 */ + 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); + NDPI_LOG_DBG2(ndpi_struct, "query_type=%2d\n", flow->protos.dns.query_type); #endif - break; - } else - x++; - } - } else - invalid = 1; - } else { + break; + } else + x++; + } + } else + return(1 /* invalid */); + } else { /* DNS Reply */ + flow->protos.dns.reply_code = dns_header->flags & 0x0F; - 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))) + 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 */ @@ -168,11 +141,11 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd x += 4; - if(dns_header.num_answers > 0) { + if(dns_header->num_answers > 0) { u_int16_t rsp_type; u_int16_t num; - for(num = 0; num < dns_header.num_answers; num++) { + for(num = 0; num < dns_header->num_answers; num++) { u_int16_t data_len; if((x+6) >= flow->packet.payload_packet_len) { @@ -207,8 +180,39 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd } } } else - invalid = 1; - } + return(1 /* invalid */); + } + + /* Valid */ + return(0); +} + +/* *********************************************** */ + +void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { + int 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); + 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); + payload_offset = 2; + } else { + NDPI_EXCLUDE_PROTO(ndpi_struct, flow); + return; + } + + 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); if(invalid) { NDPI_EXCLUDE_PROTO(ndpi_struct, flow); @@ -273,7 +277,6 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd } else { NDPI_EXCLUDE_PROTO(ndpi_struct, flow); } - } } } |