ref: 3ae7a83327799e2ba7f3358dde826749c5b728a2
dir: /dns.c/
/* * notes: * we dont parse compressed names very well. */ #include <stdio.h> #include <stdint.h> #include <string.h> #include <pcap.h> #include "common.h" /* * pos must be after data length, before size of first string * len must be dns.len */ int parseDnsCname(const u_char *pkt, u_char cname[255], uint pos, uint len) { int section_header, cname_head = 0; const u_char *pkt_head; pkt_head = pkt + pos; for(int i = 0 ; i < len ; i++) { section_header = pkt_head[i]; /* compressed, we'r too lazy to handle it */ if(section_header == 0xc0 || section_header == 0x0) break; /* not compressed, regular size */ strncpy(cname + cname_head, pkt_head + i + 1, section_header); i += section_header; cname_head += section_header; cname[cname_head++] = '.'; } return 1; } /* * dns have some variable length fields, * we need to keep our positon somewhere */ int parseDns(const u_char *pkt, Dns *dns) { int section_header; int pos = 0; int name_head = 0; dns->id = get2(pkt + pos); pos += DNS_ID; dns->flags = get2(pkt + pos); pos += DNS_FLAGS; dns->nQueries = get2(pkt + pos); pos += DNS_COUNT_QUERIES; dns->nAnswers = get2(pkt + pos); pos += DNS_COUNT_ANSWERS; dns->nAuthRR = get2(pkt + pos); pos += DNS_COUNT_AUTH_RR; dns->nAddRR = get2(pkt + pos); pos += DNS_COUNT_ADD_RR; memset(dns->domain, '\0', sizeof(dns->domain)); for(int i = 0 ; i < sizeof(dns->domain) ; i++) { section_header = pkt[pos]; pos++; if(section_header == 0x0) break; strncpy(dns->domain + name_head, pkt + pos, section_header); name_head += section_header; dns->domain[name_head++] = '.'; pos += section_header; } dns->type = get2(pkt + pos); pos += DNS_TYPE; dns->class = get2(pkt + pos); pos += DNS_CLASS; if(dns->flags & DNS_ISRESP) { /* a resposnse, should have answers */ pos += DNS_BACKREF; /* skip domain name */ pos += DNS_TYPE; /* skip type */ pos += DNS_CLASS; /* skip class */ /* we are in next packet */ dns->ttl = get4(pkt + pos); pos += DNS_TTL; dns->len = get2(pkt + pos); pos += 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: dns->ip6[0] = get2(pkt + pos); pos += 2; dns->ip6[1] = get2(pkt + pos); pos += 2; dns->ip6[2] = get2(pkt + pos); pos += 2; dns->ip6[3] = get2(pkt + pos); pos += 2; dns->ip6[4] = get2(pkt + pos); pos += 2; dns->ip6[5] = get2(pkt + pos); pos += 2; dns->ip6[6] = get2(pkt + pos); pos += 2; dns->ip6[7] = get2(pkt + pos); pos += 2; break; case DNS_TYPE_CNAME: memset(dns->cname, '\0', sizeof(dns->domain)); parseDnsCname(pkt, dns->cname, pos, dns->len); break; case DNS_TYPE_MX: break; default: err(1, "parseDnsQuery(%d) unknown type", 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" "\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_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_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 = { .parse = parseDns, .print = printDns, };