ref: 13738d2aa200eeb5859525225ec1d7bec7e8134e
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];
int debug;
void
dnsReader(u_char *args, const struct pcap_pkthdr *header, const u_char *pkt)
{
static int packets = 1;
Ether e;
Pkt p;
Udp udp;
Tcp tcp;
Dns dns;
pos = 0;
parseEther(pkt, &e);
parsePkt(pkt, &p);
if(p.proto == IPPROTO_UDP)
{
parseUdp(pkt, &udp);
}
else if(p.proto == IPPROTO_TCP)
{
parseTcp(pkt, &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;
}
pos += 2; /* there is a dns-over-tcp len field we ignore */
}
else
err(1, "dnsReader(): unknown proto: %#x (%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, &dns);
printf("\n==================%3d ==================\n", packets++);
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, dnsReader, NULL);
pcap_freecode(&dnsfilter);
pcap_close(handle);
return 0;
}