cdnsbindresolv

DNS: retrieving host IP address using resolv.h


I'm trying to understand DNS queries using the resolv.h library in BIND. I'm struggling trying to parse an IP address from RRs returned by ns_parserr(). I can successfully parse authoritative NS using the code provided by https://docstore.mik.ua/orelly/networking_2ndEd/dns/ch15_02.htm , but I can't seem to be able to obtain the A type records and print them. Mainly because I don't know how IP addresses are codified inside the ns_rr structure. Looking at the implementation, RDATA are of const u_char * type. How to get the IP out of this record?

int main (int argc, char * argv[])
{
     union {
        HEADER hdr;              
        u_char buf[NS_PACKETSZ]; 
    } response;                  
    int responseLen;             
    res_init();
    ns_msg handle;
    responseLen =res_query(argv[1],ns_c_in,ns_t_a,(u_char *)&response,sizeof(response));
    if (responseLen<0)
        exit(-1);
    if (ns_initparse(response.buf, responseLen, &handle)<0)
    {
        fprintf(stderr, "ERROR PARSING RESPONSE....");
        perror("damn");
        exit(-1);

    }
    ns_rr rr;
    int rrnum;
    ns_sect section=ns_s_an;
    for (rrnum=0;rrnum<(ns_msg_count(handle,section));rrnum++)
    {
        if (ns_parserr(&handle,ns_s_an,rrnum,&rr)<0)
        {
            fprintf(stderr, "ERROR PARSING RRs");
            exit(-1);
        }   

        if (ns_rr_type(rr)==ns_t_a)
        {
            [WHAT TO DO HERE?]
        }
    }
    return 0;   
}

I usually try to fix these things by myself, but there are not many information about the resolv.h library on the internet, except for the cited source. Thank you all for you support, I appreciate that.


Solution

  • You have to parse the resource record data in ns_rr yourself; the format is described in rfc1035 (see here, the A rdata format is in section 3.4.1)

    In your [WHAT TO DO HERE?], you could for example parse the A rdata and print the IP like this:

    struct in_addr in;
    memcpy(&in.s_addr, ns_rr_rdata(rr), sizeof(in.s_addr));
    fprintf(stderr, "%s IN A %s\n", ns_rr_name(rr), inet_ntoa(in));
    

    If you want to support other resource record types you will have to familiarize yourself with their specific format.