How can I capture dns packets in c?

I'm writing a packet sniffer program in c. Now it can only find HTTP packets but I want to make it in a way to get also DNS packets. I know DNS packets are UDP but I don't know how to identify DNS ones. Is there a specific thing in DNS packets to check to find them? I know port 53 is default port for DNS requests, but is it a reliable way to find them?

1 answer

  • answered 2020-08-03 21:17 person

    There is no good way to tell if a UDP packet contains DNS data: There is nothing in the UDP header, or IP header that directly tells you the data is DNS. However what you could do is first see if the source port in the UDP header is port 53 (DNS's standard UDP port) and second see if the data fits the data structure you're using to decode the header (most likely a struct). This is a very good question.

    To fit the packet to a strcut you can use the following code:

    This is the actual structure of a DNS header packet laid out in a struct in c:

    #pragma pack(push, 1)
    typedef struct 
    {
        uint16_t id; // identification number 2b
        
        uint8_t rd : 1; // recursion desired
        uint8_t tc : 1; // truncated message
        uint8_t aa : 1; // authoritive answer
        uint8_t opcode : 4; // purpose of message
        uint8_t qr : 1; // query/response flag
    
        uint8_t rcode : 4; // response code
        uint8_t cd : 1; // checking disabled
        uint8_t ad : 1; // authenticated data
        uint8_t z : 1; // its z! reserved
        uint8_t ra : 1; // recursion available 4b
    
        uint16_t q_count; // number of question entries 6b
        uint16_t ans_count; // number of answer entries 8b
        uint16_t auth_count; // number of authority entries 10b
        uint16_t add_count; // number of resource entries 12b
    }Dns_Header, *Dns_Header_P;
    #pragma pack(pop)
    

    To test this you can do this:

    Dns_Header_P header = (Dns_Header_P)capture;
    

    capture being a byte array with you DNS header.

    Depending on how you're capturing the packets and how you're storing them you might need to change the endianness of the struct. If you test this with your program and it doesn't seem to have the right data or the data is switched around let me know.