Read DNS using sockets

This is a discussion on Read DNS using sockets within the Networking/Device Communication forums, part of the General Programming Boards category; Dear all I hope you are fine. i have a question regarding socket programming, sorry but i am new in ...

  1. #1
    Registered User
    Join Date
    Jun 2010
    Posts
    2

    Read DNS using sockets

    Dear all

    I hope you are fine. i have a question regarding socket programming, sorry but i am new in this area.

    I am making a program with libpcap filtering the DNS traffic from a client or from my PC. I successfully made the program using C language and libpcap API. But i want to go further and read the kind of Resource Record or data that is being interchanged between the user and the DNS server, in other words the request.

    I understand that DNS use UDP as to perform the communications. But I can not find how to read the payload where i can find the Resource Records (RR) (Like A RR, MX RR, etc ).

    Could anybody give me an idea how to read that data or which is the correct procedure to read the payload of the filtered traffic, according to the RFC 1035 is a comparison between pre-defined values.

    I hope you could help me.

    Thank you very much.

    ArturoD

  2. #2
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    What exactly are you having trouble with? The RFC you mentioned, RFC 1035, details the DNS protocol, and sounds like it is what you want.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  3. #3
    Registered User kryptkat's Avatar
    Join Date
    Dec 2002
    Posts
    638
    i believe you are looking for

    Code:
    	/* Walk through the linked list of DNS records... */
    	for (pRecord = pRecordList; pRecord != NULL; pRecord = pRecord->pNext)
    you get output like
    Code:
    Enter Hostname to Lookup : http://cboard.cprogramming.com
    
    Sending Packet...Sent
    Receiving answer...Received.
    The response contains :
     1 Questions.
     2 Answers.
     0 Authoritative Servers.
     0 Additional records.
    
    Name  :  http://cboard.cprogramming.com has IPv4 address :  207.69.131.20
    Name  :  http://cboard.cprogramming.com has IPv4 address :  207.69.131.21
    
    C:\>
    as example.

  4. #4
    Registered User
    Join Date
    Jun 2010
    Posts
    2
    Hello Kryptkat and Cactus Hugger

    Thank you very much for your answers.

    About Cactus Hugger question, yes you are right the RFC is quite detailed about the fields of the DNS packet. My problem is the implementation of a sniffer that can get the information contained there.

    About Kryptkat answer. Well, what i know is as i mentioned before, a program that could allowed me to sniff in the packets that are being transmitted using the UDP port 53 (DNS), for that reason I am using libpcap as a filter of such packets.

    also i am using libdnet in order to get the UDP header lenght (UDP_HDR_LEN), I already made ap rogram but i have still the problem of sniff the details of the packet.

    What i want to read basically is the type Resource Record that was use in that packet, for instance: A Record, PTR Record, NS record or MX record.

    Of course the class IN.

    That's the information I want to gather from the packet filtering.

    I send you the code I have made so far.

    Code:
    #include </usr/include/pcap.h>
    #include </usr/include/stdio.h>
    #include </usr/include/time.h>
    #include </usr/include/stdlib.h>
    #include </usr/include/errno.h>
    #define _USE_BSD
    #define __FAVOR_BSD
    #include </usr/include/memory.h>
    #include </usr/include/netinet/ip.h>
    #include </usr/include/netinet/tcp.h>
    #include </usr/include/linux/udp.h>
    #include </usr/include/dnet.h>
    
    /* Offsets of fields in the DNS header. */
    #define	DNS_ID		0
    #define	DNS_FLAGS	2
    #define	DNS_QUEST	4
    #define	DNS_ANS		6
    #define	DNS_AUTH	8
    #define	DNS_ADD		10
    
    /* Length of DNS header. */
    #define	DNS_HDRLEN	12
    
    //Type field of Query and Answer
    #define T_A	1 /* host address */
    #define T_NS	2 /* authoritative server */
    #define T_CNAME	5 /* canonical name */
    #define T_SOA	6 /* start of authority zone */
    #define T_PTR	12 /* domain name pointer */
    #define T_MX	15 /* mail routing information */
    
    	/* I have to define the DNS header because I don't where the hell is!!!! */
    	//DNS header structure
    	struct DNS_HEADER
    	{
    	unsigned short id; // identification number
    	unsigned char rd :1; // recursion desired
    	unsigned char tc :1; // truncated message
    	unsigned char aa :1; // authoritive answer
    	unsigned char opcode :4; // purpose of message
    	unsigned char qr :1; // query/response flag
    	 
    	unsigned char rcode :4; // response code
    	unsigned char cd :1; // checking disabled
    	unsigned char ad :1; // authenticated data
    	unsigned char z :1; // its z! reserved
    	unsigned char ra :1; // recursion available
    	 
    	unsigned short q_count; // number of question entries
    	unsigned short ans_count; // number of answer entries
    	unsigned short auth_count; // number of authority entries
    	unsigned short add_count; // number of resource entries
    	};
    	 
    //Constant sized fields of query structure
    	struct QUESTION
    	{
    		unsigned short qtype;
    		unsigned short qclass;
    	};
    	 
    //Constant sized fields of the resource record structure
    	struct R_DATA
    	{
    		unsigned short type;
    		unsigned short _class;
    		unsigned int ttl;
    		unsigned short data_len;
    	};
    	 
    //Pointers to resource record contents
    	struct RES_RECORD
    	{
    		unsigned char *name;
    		struct R_DATA *resource;
    		unsigned char *rdata;
    	};
    	 
    //Structure of a Query
    	typedef struct
    	{
    		unsigned char *name;
    		struct QUESTION *ques;
    	} QUERY;
    
    
    
    //Callback function, it will be called everytime a package is received
    void my_callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char* packet)
    {
    	struct ether_header *eptr;
    	struct tcphdr *tcphdr;
    	struct udphdr *udphdr;
    	struct DNS_HEADER *DNS_HEADER=&DNS_HEADER;
    	struct QUESTION *QUESTION=&QUESTION;
    	struct res_sym *res_sym;
    	char TYPE;
    	struct dns *dns;
    	unsigned offset = 0;
    	time_t t;
    	struct tm *tstruct;
    	t=time(NULL);
    	tstruct=localtime(&t);
    	char timer [80];
    	strftime (timer,80,"%a %b %d %Y %T",tstruct);
    
    	/* Buffer needed to store the DNS packet */
    
    	struct RES_RECORD answers,auth,addit;
    	struct QUERY name, ques;
    
    	/* The pointer will point to the Ethernet header at the beggining of the packet */
    
    	eptr = (struct ether_header *) packet;
    	
    	/* We extract the IP header, therefore we have to move the processed Ethernet header
    	in order to find the information we want */
    
    	struct ip *ipc;
    
    	offset += ETH_HDR_LEN;
    	ipc = (struct ip *)(packet + offset);
    
    	/* We check the TCP protocol, the value of "Protocol" in the IP frame is checked according to the 
    	8 bit value */
    
    	switch (ipc->ip_p) 
    	
    	{
    	case 1:
    		printf ("ICMP\n");
    		return; //ICMP protocol
    	case 6:
    		printf ("TCP\n");
    		return; //TCP protocol
    	case 17:
    		printf ("UDP\n");
    		break; //UDP Protocol
    	default:
    		printf ("Unknown\n");
    		return; //Unknown protocol
    	} 
    	
    	//lenght of the ip header to be added to the ethernet header
    	offset += (ipc->ip_hl)*4;
    	udphdr = (struct udphdr *)(packet + offset);
    
    	offset += UDP_HDR_LEN;
    
    	/* pointing to the DNS */
    
    	dns = (struct DNS_HEADER *)(packet + offset);
    
    	offset += DNS_HDRLEN;
    
    	/*Printing QR Code*/
    
    	
    	switch (DNS_HEADER->qr)
    	{
    	case 0:
    	printf("QR Code is Query\t");
    	break;	
    
    	case 1:
    	printf("QR Code is Answer\t");
    	break;
    	}
    		
    	//printf("%s%18s\t%d\t%18s\t%d\t%s\n",timer,inet_ntoa(ipc->ip_src),ntohs(udphdr->source),inet_ntoa(ipc->ip_dst),ntohs(udphdr->dest));
    So far I was able to get the Query code. In the filtering I've made in my PC is always Query code, but according to the DNS structure, I have to skip the "name" area in order to get the type and class information.

    Could it be possible for you guys to give me clue about how to do it?, I've been going around this specific topic for few days.

    Thank you very much.

    Regards,

    ArturoD

  5. #5
    Registered User kryptkat's Avatar
    Join Date
    Dec 2002
    Posts
    638
    it has been a while since i used libpcap and do not recall if it has its own defines like the winapi .... try windns.h

    Code:
    /* fixdns.c */
    
    #include <windns.h>
    /* or equivalent pcapdns.h */
    
    /*  set your path in .cfg or ide */
    
    #include <pcap.h>
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <memory.h>
    #include <ip.h>
    #include <tcp.h>
    #include <udp.h>
    #include <dnet.h>
    
    #define _USE_BSD
    #define __FAVOR_BSD	 
    
    
    //Callback function, it will be called everytime a package is received
    void my_callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char* packet)
    {
    	struct ether_header *eptr;
    	struct tcphdr *tcphdr;
    	struct udphdr *udphdr;
    	struct DNS_HEADER *DNS_HEADER=&DNS_HEADER;
    	struct QUESTION *QUESTION=&QUESTION;
    	struct res_sym *res_sym;
    	char TYPE;
    	struct dns *dns;
    	unsigned offset = 0;
    	time_t t;
    	struct tm *tstruct;
    	t=time(NULL);
    	tstruct=localtime(&t);
    	char timer [80];
    	strftime (timer,80,"%a %b %d %Y %T",tstruct);
    
    	/* Buffer needed to store the DNS packet */
    
    	struct RES_RECORD answers,auth,addit;
    	struct QUERY name, ques;
    
    	/* The pointer will point to the Ethernet header at the beggining of the packet */
    
    	eptr = (struct ether_header *) packet;
    	
    	/* We extract the IP header, therefore we have to move the processed Ethernet header
    	in order to find the information we want */
    
    	struct ip *ipc;
    
    	offset += ETH_HDR_LEN;
    	ipc = (struct ip *)(packet + offset);
    
    	/* We check the TCP protocol, the value of "Protocol" in the IP frame is checked according to the 
    	8 bit value */
    
    	switch (ipc->ip_p) 
    	
    	{
    	case 1:
    		printf ("ICMP\n");
    		return; //ICMP protocol
    	case 6:
    		printf ("TCP\n");
    		return; //TCP protocol
    	case 17:
    		printf ("UDP\n");
    		break; //UDP Protocol
    	default:
    		printf ("Unknown\n");
    		return; //Unknown protocol
    	} 
    	
    	//lenght of the ip header to be added to the ethernet header
    	offset += (ipc->ip_hl)*4;
    	udphdr = (struct udphdr *)(packet + offset);
    
    	offset += UDP_HDR_LEN;
    
    	/* pointing to the DNS */
    
    	dns = (struct DNS_HEADER *)(packet + offset);
    
    	offset += DNS_HDRLEN;
    
    	/*Printing QR Code*/
    
    	
    	switch (DNS_HEADER->qr)
    	{
    	case 0:
    	printf("QR Code is Query\t");
    	break;	
    
    	case 1:
    	printf("QR Code is Answer\t");
    	break;
    	}
    		
    	printf("%s%18s\t%d\t%18s\t%d\t%s\n",timer,inet_ntoa(ipc->ip_src),ntohs(udphdr->source),inet_ntoa(ipc->ip_dst),ntohs(udphdr->dest));
    also note that i do not have libpcap do to hd crash. oh wait yes i do....

    Code:
    #ifndef _COMMON_H
    #define _COMMON_H
    
    #define FORMAT_CAP      1
    #define FORMAT_IVS      2
    #define FORMAT_IVS2     3
    
    #define TCPDUMP_MAGIC           0xA1B2C3D4
    #define TCPDUMP_CIGAM           0xD4C3B2A1
    #define IVSONLY_MAGIC           "\xBF\xCA\x84\xD4"
    #define IVS2_MAGIC              "\xAE\x78\xD1\xFF"
    #define IVS2_EXTENSION		"ivs"
    #define IVS2_VERSION             1
    
    #define PCAP_VERSION_MAJOR      2
    #define PCAP_VERSION_MINOR      4
    
    #define LINKTYPE_ETHERNET       1
    #define LINKTYPE_IEEE802_11     105
    #define LINKTYPE_PRISM_HEADER   119
    #define LINKTYPE_RADIOTAP_HDR   127
    
    #define uchar  unsigned char
    #define ushort unsigned short
    #define uint   unsigned int
    #define ulong  unsigned long
    
    #define SWAP32(x)       \
        x = ( ( ( x >> 24 ) & 0x000000FF ) | \
              ( ( x >>  8 ) & 0x0000FF00 ) | \
              ( ( x <<  8 ) & 0x00FF0000 ) | \
              ( ( x << 24 ) & 0xFF000000 ) );
    
    //BSSID const. length of 6 bytes; can be together with all the other types
    #define IVS2_BSSID	0x0001
    
    //ESSID var. length; alone, or with BSSID
    #define IVS2_ESSID	0x0002
    
    //wpa structure, const. length; alone, or with BSSID
    #define IVS2_WPA	0x0004
    
    //IV+IDX+KEYSTREAM, var. length; alone or with BSSID
    #define IVS2_XOR	0x0008
    
    /* [IV+IDX][i][l][XOR_1]..[XOR_i][weight]                                                        *
     * holds i possible keystreams for the same IV with a length of l for each keystream (l max 32)  *
     * and an array "int weight[16]" at the end                                                      */
    #define IVS2_PTW        0x0010
    
    //unencrypted packet
    #define IVS2_CLR        0x0020
    
    struct pcap_file_header
    {
        uint magic;
        ushort version_major;
        ushort version_minor;
        int thiszone;
        uint sigfigs;
        uint snaplen;
        uint linktype;
    };
    
    struct pcap_pkthdr
    {
        int tv_sec;
        int tv_usec;
        uint caplen;
        uint len;
    };
    
    struct ivs2_filehdr
    {
        unsigned short version;
    };
    
    struct ivs2_pkthdr
    {
        unsigned short  flags;
        unsigned short  len;
    };
    
    #endif /* common.h */
    have a look.... you need to go through it an make sure everything matches up.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 9
    Last Post: 06-17-2008, 12:38 PM
  2. Weird read input or bad printf output?
    By ChaoticMachiner in forum C Programming
    Replies: 3
    Last Post: 05-04-2008, 04:40 PM
  3. I am lost on how to read from file and output to file?
    By vicvic2477 in forum C++ Programming
    Replies: 4
    Last Post: 02-27-2005, 11:52 AM
  4. Read Array pro!!Plz help!!
    By Supra in forum C Programming
    Replies: 2
    Last Post: 03-04-2002, 03:49 PM
  5. Help! Can't read decimal number
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 09-07-2001, 03:09 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21