DNS MX records

Dizzzy_Dozzzer said:
Hi,
In FreeBSD c++ programming we can get basic DNS info using gethostbyname(3) function, but I could not find out how can I get domain MX records?

You would use the low-level resolver interface, like so:

Code:
// Save this as MXLookup.cpp

// Standard C includes
#include <stdlib.h>
#include <stdio.h>

#include <netinet/in.h>
#include <resolv.h>


// constants
#define defaultBufferSize  4096


// types
typedef struct MXRecord *MXPtr, **MXRef;
typedef struct MXRecord
{
   int  pref;
   char name[NS_MAXDNAME];
} MXRecord;


typedef struct MXRecordList *MXListPtr;
typedef struct MXRecordList
{
   int   count;
   MXPtr entry[];
} MXRecordList;


// code for looking up the MX hosts for a given domain
// returns an array of MXRecords sorted by preferences
int MXCompare(const void *A, const void *B)
{
   int a = (*(MXRef)A)->pref;
   int b = (*(MXRef)B)->pref;

   if (a < b)
      return -1;
   else if (a > b)
      return  1;
   else
      return  0;
}

MXListPtr MXLookup(const char *domainName)
{
   int i, responseLen, resourceRecordCount;
   unsigned char response[defaultBufferSize];

   ns_msg    msgHandle;
   ns_rr     resourceRecord;

   MXPtr     MX;
   MXListPtr MXList = (MXListPtr)malloc(sizeof(int)); MXList->count = 0;

   if ((responseLen = res_query(domainName, ns_c_in, ns_t_mx, response, defaultBufferSize)) > 0)
      if (ns_initparse(response, responseLen, &msgHandle) == 0)
      {
         resourceRecordCount = ns_msg_count(msgHandle, ns_s_an);
         for(i = 0; i < resourceRecordCount; i++)
         {
            if (ns_parserr(&msgHandle, ns_s_an, i, &resourceRecord) == 0 && ns_rr_type(resourceRecord) == ns_t_mx)
            {
               MXList = (MXListPtr)realloc(MXList, sizeof(int) + (MXList->count + 1)*sizeof(MXPtr));
               MXList->entry[MXList->count++] = MX = (MXPtr)calloc(1, sizeof(MXRecord));
               MX->pref = ns_get16(ns_rr_rdata(resourceRecord));
               ns_name_uncompress(ns_msg_base(msgHandle), ns_msg_end(msgHandle), ns_rr_rdata(resourceRecord) + NS_INT16SZ, MX->name, NS_MAXDNAME);
            }
         }
      }

   if (MXList->count > 1)
      qsort(&MXList->entry[0], MXList->count, sizeof(MXPtr), MXCompare);
   return MXList;
}

void MXListFree(MXListPtr MXList)
{
   int i;

   for (i = 0; i < MXList->count; i++)
      free(MXList->entry[i]);
   free(MXList);
}



int main(int argc, const char *argv[])
{
   if (argc > 1)
   {
      int i;

      MXListPtr MXList = MXLookup(argv[1]);

      for (i = 0; i < MXList->count; i++)
         printf("%4d   %s\n", MXList->entry[i]->pref, MXList->entry[i]->name);

      MXListFree(MXList);
   }

   return 0;
}

This is basically pure C, but it compiles as C++, so you could easily wrap this into a class, or keep it as is.

$ c++ MXLookup.cpp -o MXLookup
$ MXLookup gmail.com
Code:
   5   gmail-smtp-in.l.google.com
  10   alt1.gmail-smtp-in.l.google.com
  20   alt2.gmail-smtp-in.l.google.com
  30   alt3.gmail-smtp-in.l.google.com
  40   alt4.gmail-smtp-in.l.google.com
 
rolfheinrich, thanks a lot!
That is really I was looking for.
And thanks for spending your time to code that amount for me.
 
Dizzzy_Dozzzer said:
... for spending your time to code that amount for me.

Didn't spend so much time. I copied this from a running tool of mine.
 
Back
Top