FB_init

Thursday, October 01, 2009

How to use the DnsQuery function (Windows Server 2008 R2)

There's a nice article on Microsoft's Support web site titled "How to use the DnsQuery function to resolve host names and host addresses with Visual C++ .NET" ( here ). The problem is that the signature of the DnsQuery Function has changed. The first argument takes a PCTSTR instead of a char * type.
I decided to rewrite the application using PCTSTR. Here's the new version:


#include //winsock
#include //DNS api's
#include //standard i/o
#include

//Usage of the program
void Usage(char *progname) {
fprintf(stderr,"Usage\n%s -n [HostName|IP Address] -t [Type] -s [DnsServerIp]\n",progname);
fprintf(stderr,"Where:\n\t\"HostName|IP Address\" is the name or IP address of the computer ");
fprintf(stderr,"of the record set being queried\n");
fprintf(stderr,"\t\"Type\" is the type of record set to be queried A or PTR\n");
fprintf(stderr,"\t\"DnsServerIp\"is the IP address of DNS server (in dotted decimal notation) ");
fprintf(stderr,"to which the query should be sent\n");
exit(1);
}


char* WChar2char(wchar_t * src, char * ppDest) {
size_t convertedChars = 0;
size_t origsize = wcslen(src) + 1;
wcstombs_s(&convertedChars, ppDest, origsize, src, _TRUNCATE);
return (char*)ppDest;
}

void Char2Wchar(char* src, wchar_t * ppDest) {
size_t convertedChars = 0;
size_t origsize = strlen(src) + 1;
mbstowcs_s(&convertedChars, ppDest, origsize, src, _TRUNCATE);
}

void ReverseIP(wchar_t* pIP)
{
wchar_t seps[1]; seps[0] = (wchar_t)'.';
wchar_t *token;
char pIPSec[4][4];
int i=0;
token = wcstok( pIP, seps);
while( token != NULL )
{
/* While there are "." characters in "string" */
sprintf(pIPSec[i],"%s", token);
/* Get next "." character: */
token = wcstok( NULL, seps );
i++;
}
swprintf(pIP,L"%s.%s.%s.%s.%s", pIPSec[3],pIPSec[2],pIPSec[1],pIPSec[0],"IN-ADDR.ARPA");
}


// the main function
void __cdecl main(int argc, char *argv[])
{
DNS_STATUS status; //Return value of DnsQuery_A() function.
PDNS_RECORD pDnsRecord; //Pointer to DNS_RECORD structure.
PIP4_ARRAY pSrvList = NULL; //Pointer to IP4_ARRAY structure.
WORD wType; //Type of the record to be queried.
wchar_t pOwnerName[255]; //Owner name to be queried.
wchar_t pReversedIP[255]; //Reversed IP address.
wchar_t DnsServIp[255]; //DNS server ip address.
DNS_FREE_TYPE freetype ;
freetype = DnsFreeRecordListDeep;
IN_ADDR ipaddr;
char * chOwnerName = NULL;

if(argc > 4) {
for(int i = 1; i < argc ; i++) {
if ( (argv[i][0] == '-') || (argv[i][0] == '/') ) {
switch(tolower(argv[i][1])) {
case 'n':
//pOwnername=
chOwnerName = argv[++i];
Char2Wchar(chOwnerName, (wchar_t *) pOwnerName);
break;
case 't':
if (!stricmp(argv[i+1], "A") )
wType = DNS_TYPE_A; //Query host records to resolve a name.
else if (!stricmp(argv[i+1], "PTR") )
{
//pOwnerName should be in "xxx.xxx.xxx.xxx" format
if(wcslen(pOwnerName)<=15)
{
//You must reverse the IP address to request a Reverse Lookup
//of a host name.
swprintf(pReversedIP,L"%s",pOwnerName);
ReverseIP(pReversedIP);
size_t sizeRev = wcslen(pReversedIP) + 1;
wcsncpy_s(pOwnerName, sizeRev, pOwnerName, 255);
//pOwnerName=pReversedIP;
wType = DNS_TYPE_PTR; //Query PTR records to resolve an IP address
}
else
{
Usage(argv[0]);
}
}
else
Usage(argv[0]);
i++;
break;

case 's':
// Allocate memory for IP4_ARRAY structure.
pSrvList = (PIP4_ARRAY) LocalAlloc(LPTR,sizeof(IP4_ARRAY));
if(!pSrvList){
printf("Memory allocation failed \n");
exit(1);
}
if(argv[++i]) {
wchar_t aarray[300];
Char2Wchar(argv[i], (wchar_t*)aarray);
wcscpy(DnsServIp,aarray);
char tmp[500];

pSrvList->AddrCount = 1;
pSrvList->AddrArray[0] = inet_addr(WChar2char(DnsServIp, (char*) tmp)); //DNS server IP address
break;
}

default:
Usage(argv[0]);
break;
}
}
else
Usage(argv[0]);
}
}
else
Usage(argv[0]);

// Calling function DnsQuery to query Host or PTR records
status = DnsQuery(pOwnerName, //Pointer to OwnerName.
wType, //Type of the record to be queried.
DNS_QUERY_BYPASS_CACHE, // Bypasses the resolver cache on the lookup.
pSrvList, //Contains DNS server IP address.
&pDnsRecord, //Resource record that contains the response.
NULL); //Reserved for future use.

if (status){
if(wType == DNS_TYPE_A)
printf("Failed to query the host record for %s and the error is %d \n", pOwnerName, status);
else
printf("Failed to query the PTR record and the error is %d \n", status);
} else {
if(wType == DNS_TYPE_A) {
//convert the Internet network address into a string
//in Internet standard dotted format.
ipaddr.S_un.S_addr = (pDnsRecord->Data.A.IpAddress);
printf("The IP address of the host %s is %s \n", pOwnerName,inet_ntoa(ipaddr));

// Free memory allocated for DNS records.
DnsRecordListFree(pDnsRecord, freetype);
}
else {
printf("The host name is %s \n",(pDnsRecord->Data.PTR.pNameHost));

// Free memory allocated for DNS records.
DnsRecordListFree(pDnsRecord, freetype);
}
}
LocalFree(pSrvList);
}




(keywords: DNS, DnsQuery, Windows Server 2008 R2 )

No comments: