diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 8ff0d92e9c0..a92eaa0ef09 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -1222,6 +1222,7 @@ struct ndpi_flow_struct { u_int8_t num_queries, num_answers, reply_code, is_query; u_int16_t query_type, query_class, rsp_type; u_int32_t answer_ttl; + char answer_domain[256]; ndpi_ip_addr_t rsp_addr; /* The first address in a DNS response packet */ } dns; diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c index 51eb20eb570..15221cfc598 100644 --- a/src/lib/protocols/dns.c +++ b/src/lib/protocols/dns.c @@ -315,6 +315,41 @@ static int search_valid_dns(struct ndpi_detection_module_struct *ndpi_struct, )) { memcpy(&flow->protos.dns.rsp_addr, packet->payload + x, data_len); } + else if (rsp_type == 0x0c) + { + + // reverse dns lookup responses can have an address label as well as additional domain name labels + // since we already have the address from the query we just need the domain name + // we only process the first answer and grab its domain name + int an_index = 0; + // make sure to exit loop if x is a 00 octet or x exceeds the packet payload length or the length octet has first 2 bits set (domain name compressed) + while((packet->payload[x] != '\0') && (x < packet->payload_packet_len) && ((packet->payload[x] & 0xC0) != 0)) + { + int label_len = packet->payload[x]; // get 1st label len + + // if first char is number this is an address + // number can't be first char in domain name + // we only want to check the first label for an ip address + if (packet->payload[x+1] >= 0x30 && packet->payload[x+1] <= 0x39 && an_index == 0) + { + x += label_len + 1; // skip label len + address field + } + else + { + if (an_index + label_len < (int)(sizeof(flow->protos.dns.answer_domain)-1)) + { + strncat(flow->protos.dns.answer_domain, (char *)packet->payload + x + 1, label_len); // copy label section into string field + an_index += label_len; // increment index + flow->protos.dns.answer_domain[an_index] = '.'; // delimeter between label sections + an_index++; // increment index for delimeter + x += label_len + 1; // skip label len + address field + } + else + break; + } + } + flow->protos.dns.answer_domain[an_index - 1] = '\0'; // remove trailing '.' char and replace with null term + } } }