Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add cname dissection to ndpi dns #7

Merged
merged 7 commits into from
Oct 25, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 39 additions & 44 deletions src/lib/protocols/dns.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,59 +297,54 @@ static int search_valid_dns(struct ndpi_detection_module_struct *ndpi_struct,

/* here x points to the response "class" field */
if((x+12) <= packet->payload_packet_len) {
x += 2;
uint32_t ttl = get32(&x,packet->payload);
flow->protos.dns.answer_ttl = ttl;
data_len = get16(&x, packet->payload);
x += 2;
uint32_t ttl = get32(&x,packet->payload);
flow->protos.dns.answer_ttl = ttl;
data_len = get16(&x, packet->payload);

if((x + data_len) <= packet->payload_packet_len) {
// printf("[rsp_type: %u][data_len: %u]\n", rsp_type, data_len);

if(rsp_type == 0x05 /* CNAME */) {
x += data_len;
continue; /* Skip CNAME */
}

if((((rsp_type == 0x1) && (data_len == 4)) /* A */
|| ((rsp_type == 0x1c) && (data_len == 16)) /* AAAA */
)) {
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] < 0x40)) // normal length octets can't be greater than 63 chars total 64 chars 1 for the length octet itself leaves 63
{
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
}
else if (rsp_type == 0x0c || rsp_type == 0x05) // reverse dns lookup and cname record processing
{

// 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] < 0x40)) // normal length octets can't be greater than 63 chars total 64 chars 1 for the length octet itself leaves 63
{
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 && rsp_type == 0x0c) // only perform this check on PTR records
{
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
}
}
}

Expand Down