Showing posts with label ns_parserr. Show all posts
Showing posts with label ns_parserr. Show all posts

Thursday, 21 August 2014

Using C/C++ Resolver API - DNS IP Switch Over

  Explanation:


Usually for obtaining IP Address of a remote host makes us to use gethostbyname() function call.
It actually gets the IP Address by looking up the DNS. But but…. This happens for the first time only, next time onward's it reads the IP Address from the cache i.e. maintained by “nscd”. 
Till the time it is available their the request is fulfilled. Once the cache is cleared, again DNS look up is performed.

So consider the case where our software is making gethostbyname() call & suddenly a switch over is made at DNS. But as our software is reading the IP address from the cache thus we are unaware of the switch. 
In this case it is possible that the software keeps on requesting the old IP, till the cache is not cleared & a fresh look up call is made.
To avoid such scenario, C/C++ has an inbuilt library i.e. “resolver api (libresolv.a/libresolv.so)”. 

It has the required function calls which do the DNS lookup & provide the required info like IP addresses, hostname, Start of Authority Record, Name-server’s list etc.. etc…..
This API is really powerful & useful utility. If someone has used DIG Command than one can easily relate to this as well.
All the options available with DIG, can be performed with this Resolver API as well.

Eg: This sample program prints the IP Address for the provided hostname.

#include<cstdlib>
#include<iostream>
#include<string>
#include <algorithm>

using namespace std;

int main(int argc, char **argv){ 
    u_char nsbuf[NS_PACKETSZ]; /* Response Buffer NS_PACKETSZ=512 ( maximum packet size) */
    char dispbuf[4096];         /* buffer to display the resource record */
    char ipadd[INET_ADDRSTRLEN]; /* saves the Host Address for IPv4 */
    string readall;

    ns_msg msg; /* handle for response message */
    ns_rr rr; /* expanded resource record */
    int i, j, l;

    char * hostname=argv[1];

    /*
     * Look up the records for the given domain name.
     * We expect the domain name to be a fully qualified, so
     * we use res_query(  ).  If we'd wanted the resolver search
     * algorithm, we would have used res_search(  ) instead.
     */
         //l=res_search (argv[i], ns_c_any, ns_t_a, nsbuf, sizeof (nsbuf));
        l = res_query ( hostname, /* domain name   */
                        ns_c_any,  /* Internet class records     */
                        ns_t_a,  /* Look up Host address */
                        nsbuf,  /*response buffer*/
                        sizeof (nsbuf)  /*buffer size    */
                       );

        if (l < 0) {
            perror (hostname);
        } else {

        /*
         * Initialize a handle to this response.  The handle will
         * be used later to extract information from the response.
         */

            ns_initparse (nsbuf, l, &msg);

         /* Count total answers received in the record. */
            l = ns_msg_count (msg, ns_s_an);

        for (j = 0; j < l; j++) {
        /*
         * Expand the answer section record into rr.
        */
                ns_parserr (&msg, ns_s_an, j, &rr);

                 /* fill the buffer with the record data */
                ns_sprintrr (&msg, &rr, NULL, NULL, dispbuf, sizeof (dispbuf));

/*              ns_sprintrrf(ns_msg_base(msg), ns_msg_size(msg),ns_rr_name(rr), ns_rr_class(rr), 
ns_rr_type(rr),ns_rr_ttl(rr), ns_rr_rdata(rr), ns_rr_rdlen(rr),NULL, NULL, dispbuf,sizeof(dispbuf));
              printf ("%s\n", dispbuf);
*/
                cout<<dispbuf<<endl;

        /* Get the Host IP Address */
inet_ntop(AF_INET,ns_rr_rdata(rr),ipadd,INET_ADDRSTRLEN);

//              printf("%s\n",ipadd);

                readall += ipadd;
                readall.erase(remove(readall.begin(), readall.end(), '\n'), readall.end());
                readall.append(";");
                //cout<<ipadd<<endl;

            }
        cout<<readall<<endl;
  } 

}

Complie & Link: g++ socket.cpp -o socket_pgm /usr/lib64/libresolv.a 

 Execute: ./socket_pgm <hostname>
               ./socket_pgm www.google.com



More Info: man resolver


Enjoy............. :-)