Search code examples
csocketsunixdnslibresolv

How to query a server and get the MX, A, NS records


I'm trying to get the A, MX and NS A server record as follows:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <resolv.h>
#include <netdb.h>

#define N 4096

int main (int argc, char *argv[])
{
    u_char nsbuf[N];
    char dispbuf[N];
    ns_msg msg;
    ns_rr rr;
    int i, l;

    if (argc < 2) {
        printf ("Usage: %s <domain>\n", argv[0]);
        exit (1);
    }

    // HEADER
    printf("Domain : %s\n", argv[1]);
    // ------

    // A RECORD
    printf("A records : \n");
    l = res_query(argv[1], ns_c_any, ns_t_a, nsbuf, sizeof(nsbuf));
    if (l < 0)
    {
      perror(argv[1]);
    }
    ns_initparse(nsbuf, l, &msg);
    l = ns_msg_count(msg, ns_s_an);
    for (i = 0; i < l; i++)
    {
      ns_parserr(&msg, ns_s_an, 0, &rr);
      ns_sprintrr(&msg, &rr, NULL, NULL, dispbuf, sizeof(dispbuf));
      printf("\t%s \n", dispbuf);
    }
    //------------


    // MX RECORD
    printf("MX records : \n");
    l = res_query(argv[1], ns_c_any, ns_t_mx, nsbuf, sizeof(nsbuf));
    if (l < 0)
    {
      perror(argv[1]);
    }
    else
    {
#ifdef USE_PQUERY
      /* this will give lots of detailed info on the request and reply */
      res_pquery(&_res, nsbuf, l, stdout);
#else
      /* just grab the MX answer info */
      ns_initparse(nsbuf, l, &msg);
      l = ns_msg_count(msg, ns_s_an);
      for (i = 0; i < l; i++)
      {
        ns_parserr(&msg, ns_s_an, i, &rr);
        ns_sprintrr(&msg, &rr, NULL, NULL, dispbuf, sizeof(dispbuf));
        printf ("\t%s\n", dispbuf);
      }
#endif
    }
    // ---------

    // NS RECORD
    printf("NS records : \n");
    l = res_query(argv[1], ns_c_any, ns_t_ns, nsbuf, sizeof(nsbuf));
    if (l < 0)
    {
      perror(argv[1]);
    }
    ns_initparse(nsbuf, l, &msg);
    l = ns_msg_count(msg, ns_s_an);
    for (i = 0; i < l; i++)
    {
      ns_parserr(&msg, ns_s_an, 0, &rr);
      ns_sprintrr(&msg, &rr, NULL, NULL, dispbuf, sizeof(dispbuf));
      printf("\t%s \n", dispbuf);
    }
    // ---------
    return 0;
}

On request receive a lot of the same, that is, the same A records. The same with the NS records. What am I doing wrong? Example :

Domain : mail.ru
A records :
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
        mail.ru.                22S IN A        94.100.191.207
MX records :
        mail.ru.                1m57s IN MX     10 mxs.mail.ru.
NS records :
        mail.ru.                1m50s IN NS     ns.mail.ru.
        mail.ru.                1m50s IN NS     ns.mail.ru.
        mail.ru.                1m50s IN NS     ns.mail.ru.
        mail.ru.                1m50s IN NS     ns.mail.ru.
        mail.ru.                1m50s IN NS     ns.mail.ru.
        mail.ru.                1m50s IN NS     ns.mail.ru.

Please help.


Solution

  • In this call:

      ns_parserr(&msg, ns_s_an, 0, &rr);
    

    The third argument is the index of the record you want to retrieve. So in your case it should be:

      ns_parserr(&msg, ns_s_an, i, &rr);
    

    Just tried your code with that minor fix, and it works as expected:

    Domain : mail.ru
    A records : 
        mail.ru.        5S IN A     94.100.191.248 
        mail.ru.        5S IN A     94.100.191.249 
        mail.ru.        5S IN A     94.100.191.250 
        mail.ru.        5S IN A     94.100.191.201 
        mail.ru.        5S IN A     94.100.191.202 
        mail.ru.        5S IN A     94.100.191.203 
        mail.ru.        5S IN A     94.100.191.204 
        mail.ru.        5S IN A     94.100.191.205 
        mail.ru.        5S IN A     94.100.191.206 
        mail.ru.        5S IN A     94.100.191.207 
        mail.ru.        5S IN A     94.100.191.208 
        mail.ru.        5S IN A     94.100.191.209 
        mail.ru.        5S IN A     94.100.191.210 
        mail.ru.        5S IN A     94.100.191.241 
        mail.ru.        5S IN A     94.100.191.242 
        mail.ru.        5S IN A     94.100.191.243 
        mail.ru.        5S IN A     94.100.191.244 
        mail.ru.        5S IN A     94.100.191.245 
        mail.ru.        5S IN A     94.100.191.246 
        mail.ru.        5S IN A     94.100.191.247 
    MX records : 
        mail.ru.        7m14s IN MX 10 mxs.mail.ru.
    NS records : 
        mail.ru.        3m35s IN NS ns2.mail.ru. 
        mail.ru.        3m35s IN NS ns.mail.ru. 
        mail.ru.        3m35s IN NS ns4.mail.ru. 
        mail.ru.        3m35s IN NS ns5.mail.ru. 
        mail.ru.        3m35s IN NS ns1.mail.ru. 
        mail.ru.        3m35s IN NS ns3.mail.ru.