ref: 272dec2602bfb557af9464d21426d195b8e8e1a5
dir: /dns.c/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <pcap.h>
#include "common.h"
int
parseDnsName(const u_char *pkt, char *buf, u_char len)
{
int section_header, i;
memset(buf, '\0', len);
/* skip first len byte, we can't replace it with '.' */
strncpy(buf, pkt+1, len);
for(i = 0 ; i < len ; i++)
{
section_header = pkt[i];
if(section_header == 0x0 || section_header == 0xc0)
break;
else
{
i += section_header;
buf[i] = '.';
}
}
buf[len] = '\0';
return 1;
}
/* len must be dns.len */
int
parseDnsCname(const u_char *pkt, Dns *d, uint len)
{
int section_header;
const u_char *pkt_head;
u_char next_header, *cname_head, namebuf[DNS_MAX_LEN];
pkt_head = pkt + pos;
cname_head = d->cname;
for(int i = 0 ; i < len ; i++)
{
section_header = pkt_head[i];
/* compressed */
if(section_header == 0xc0)
{
next_header = pkt_head[i + 1];
parseDnsName(pkt + d->start + next_header, namebuf, DNS_MAX_LEN);
cname_head = strchr(cname_head, '\0');
*cname_head++ = '.';
strncpy(cname_head, namebuf, DNS_MAX_LEN - (cname_head - d->cname));
break;
}
else if(section_header == 0x0)
break;
else
{
parseDnsName(pkt_head + i, namebuf, section_header);
cname_head = strchr(cname_head, '\0');
*cname_head++ = '.';
strncpy(cname_head, namebuf, section_header);
}
i += section_header;
}
return 1;
}
/*
* dns have some variable length fields,
* we need to keep our positon somewhere
*/
int
parseDns(const u_char *pkt, Dns *dns)
{
dns->start = pos;
get(pkt, DNS_ID, &dns->id);
get(pkt, DNS_FLAGS, &dns->flags);
get(pkt, DNS_COUNT_QUERIES, &dns->nQueries);
get(pkt, DNS_COUNT_ANSWERS, &dns->nAnswers);
get(pkt, DNS_COUNT_AUTH_RR, &dns->nAuthRR);
get(pkt, DNS_COUNT_ADD_RR, &dns->nAddRR);
parseDnsName(PKTHEAD, dns->domain, DNS_MAX_LEN);
/* first byte isn't counted. */
pos += strnlen(dns->domain, DNS_MAX_LEN) + 1;
get(pkt, DNS_TYPE, &dns->type);
get(pkt, DNS_CLASS, &dns->class);
if(dns->flags & DNS_ISRESP)
{
/* a resposnse, should have answers */
pos += DNS_BACKREF; /* skip domain name */
get(pkt, DNS_TYPE, &dns->type);
pos += DNS_CLASS; /* skip class */
/* we are in next packet */
get(pkt, DNS_TTL, &dns->ttl);
get(pkt, DNS_LEN, &dns->len);
}
else
return 1;
switch(dns->type)
{
case DNS_TYPE_A:
dns->ip[0] = pkt[pos++];
dns->ip[1] = pkt[pos++];
dns->ip[2] = pkt[pos++];
dns->ip[3] = pkt[pos++];
break;
case DNS_TYPE_AAAA:
get(pkt, 2, dns->ip6+0);
get(pkt, 2, dns->ip6+1);
get(pkt, 2, dns->ip6+2);
get(pkt, 2, dns->ip6+3);
get(pkt, 2, dns->ip6+4);
get(pkt, 2, dns->ip6+5);
get(pkt, 2, dns->ip6+6);
get(pkt, 2, dns->ip6+7);
break;
case DNS_TYPE_SOA:
case DNS_TYPE_CNAME:
memset(dns->cname, '\0', DNS_MAX_LEN);
parseDnsCname(pkt, dns, dns->len);
break;
case DNS_TYPE_MX:
break;
default:
err(1, "parseDns(): unknown type: %d", dns->type);
}
return 1;
}
void
printDns(Dns dns)
{
printf("dns query:\n"
"\tid: %d\tflags: %b (%x)\n"
"\tnQueries: %d\tnAnswers: %d\tnAuthRR: %d\tnAddRR: %d\n"
"\tdomain: %s (%p)\n\n"
"\ttype: %d (%s)\tclass: %s\n"
"\tttl: %x (%d)\tlen: %x (%d)\n",
dns.id, dns.flags, dns.flags,
dns.nQueries, dns.nAnswers, dns.nAuthRR, dns.nAddRR,
dns.domain, dns.domain,
dns.type, dnsTypeToStr(dns.type), dnsClassToStr(dns.class),
dns.ttl, dns.ttl, dns.len, dns.len);
if(dns.flags & DNS_ISRESP)
{
switch(dns.type)
{
case DNS_TYPE_A:
printf("\tip: %d.%d.%d.%d\n",
dns.ip[0], dns.ip[1], dns.ip[2], dns.ip[3]);
break;
case DNS_TYPE_AAAA:
printf("\tip6: %x:%x:%x:%x:%x:%x:%x:%x\n",
dns.ip6[0], dns.ip6[1], dns.ip6[2], dns.ip6[3],
dns.ip6[4], dns.ip6[5], dns.ip6[6], dns.ip6[7]);
break;
case DNS_TYPE_CNAME:
printf("\tcname: %s\n", dns.cname);
break;
case DNS_TYPE_SOA:
printf("\tsoa: %s\n", dns.cname);
break;
case DNS_TYPE_MX:
break;
default:
break;
}
}
}
char*
dnsClassToStr(uint16_t class)
{
switch(class)
{
case DNS_CLASS_IN:
return "IN";
default:
err(1, "dnsClassToStr(%d): unkown class", class);
return NULL;
}
}
char*
dnsTypeToStr(uint16_t type)
{
switch(type)
{
case DNS_TYPE_A:
return "A";
case DNS_TYPE_CNAME:
return "CNAME";
case DNS_TYPE_SOA:
return "SOA";
case DNS_TYPE_TXT:
return "TXT";
case DNS_TYPE_AAAA:
return "AAAA";
case DNS_TYPE_MX:
return "MX";
default:
err(1, "dnsTypeToStr(%d): unkown type", type);
return NULL;
}
}
Parser dnsParser = {
.name = "dns",
.parse = parseDns,
.print = printDns,
};