ref: 1766db24dfb733bd1f574bf0882527356f177397
dir: /dnsparser.c/
/* * program to parse dns packets, * it assumes packets are not sent over qinq or vxlan or jumbo frames * or avian carriers */ #include <stdio.h> #include <pcap.h> #include <stdint.h> #include <string.h> #include "common.h" struct bpf_program dnsfilter; char errbuf[PCAP_ERRBUF_SIZE]; /* magic happens here! */ void dns_reader(u_char *args, const struct pcap_pkthdr *header, const u_char *pkt) { static int packets = 1; int head = 0; Ether e; Pkt p; Udp udp; Tcp tcp; Dns dns; printf("\n==================%3d ==================\n", packets++); parseEther(pkt + head, &e); head += ETHER_LEN; parsePkt(pkt + head, &p); head += p.headerlen; if(p.proto == IPPROTO_UDP) { parseUdp(pkt + head, &udp); head += UDP_SIZE; } else if(p.proto == IPPROTO_TCP) { parseTcp(pkt + head, &tcp); /* reduce the noise */ if(tcp.flags & (TCP_FLAG_FIN|TCP_FLAG_SYN|TCP_FLAG_ACK) && !(tcp.flags & TCP_FLAG_PSH)) { printf("skipped noise\n"); return; } head += tcp.offset; head += 2; /* there is a dns-over-tcp len field we ignore */ } else err(1, "dns_reader(): unknown proto: %d", p.proto); if(debug) { fprintf(stderr, "DEBUG: "); for(int i = 0 ; i < header->caplen ; i++) fprintf(stderr, "%d: 0x%x\t", i, pkt[i]); fprintf(stderr, "\n"); } parseDns(pkt + head, &dns); printf("frame info:\n" "\tlen: %d\tcaplen: %d\n" "\ttimeval.tv_sec: %ld\ttimeval.tv_usec: %ld\n", header->len, header->caplen, header->ts.tv_sec, header->ts.tv_usec); printEther(e); printPkt(p); if(p.proto == IPPROTO_UDP) printUdp(udp); else if(p.proto == IPPROTO_TCP) printTcp(tcp); printDns(dns); } int main(int argc, char **argv) { pcap_t *handle; if(argc != 2) err(1, "%s: usage: %s file.pcap", argv[0], argv[0]); pcap_init(PCAP_CHAR_ENC_LOCAL, errbuf); handle = pcap_open_offline(argv[1], errbuf); if(handle == NULL) err(1, "%s: unable to open: %s", argv[0], argv[1]); if (pcap_compile(handle, &dnsfilter, "src port 53", 0, PCAP_NETMASK_UNKNOWN) == -1) err(1, "%s: failed to compile the expr: %s\n", argv[0], pcap_geterr(handle)); if (pcap_setfilter(handle, &dnsfilter) == -1) err(1, "%s: failed to install filter: %s\n", argv[0], pcap_geterr(handle)); pcap_loop(handle, -1, dns_reader, NULL); pcap_freecode(&dnsfilter); pcap_close(handle); return 0; }