ref: 16d016b87e7783cecedb1078c1327fa1244da4d7
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, };