// 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;
}