DNS Query Code in C with winsock
DNS Query
Its no new fact that when we type a web address in our browser a dns request is immediately send by our browser to a DNS server to get the IP address of that web address.In winsock applications we achieve this by gethostbyname() and things are pretty simple.In this article we shall do this simple thing without the help of gethostbyname().We shall be sending DNS queries and receive the reply and extract the ipv4 address of the specified hostname.
DNS packets
RFC 1035 shows the structure of DNS message as follows
+---------------------+ | Header | +---------------------+ | Question | the question for the name server +---------------------+ | Answer | RRs answering the question +---------------------+ | Authority | RRs pointing toward an authority +---------------------+ | Additional | RRs holding additional information +---------------------+
Pretty simple to understand that queries wont have the answer, authority and additional fields.Packets are ofcourse UDP and DNS servers feel comfortable to operate on port 53. So the first thing is to send a query containing the hostname.
Next task is to receive the reply which is expected to contain the information we are expecting. DNS queries are used for a variety of purpose. Apart from getting the ipv4 address of a host we also use DNS for getting the mail exchange/server of a specified domain and etc. All type of queries and response packets are build nearly on the same structure depicted above.
When a DNS server replies it sends the question as it is and along with that are a bunch of RR’s or resource records.All RR’s stand in a queue and certain fields of the header tell that how many of the RR’s are answers , how many authority and how many additionals.
DNS Header
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ID | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QDCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ANCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | NSCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ARCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Let go through each of the fields of the header :
ID - A 16 bit identifier assigned by the program that generated the query. This identifier is copied in the corresponding reply and can be used by the client to match up replies with queries. Generate a random 16 bit number for each request.
QR - A one bit field that specifies whether this message is a query (0), or a response (1). Obviously,
you should use 0 for your requests, and expect to see a 1 in the response you receive.
OPCODE - A four bit field that specifies kind of query in this message. Use 0 to indicate a standard query.
AA Authoritative Answer - this bit is only meaningful in responses, and specifies that the responding name server is an authority for the domain name in question section. You should use this bit to report whether or not the response you receive is authoritative.
TC TrunCation - specifies that this message was truncated. For this project, you must exit and return an error if you receive a response that is truncated.
RD Recursion Desired - this bit directs the name server to pursue the query recursively. You should use 1, representing that you desire recursion.
RA Recursion Available - this be is set or cleared in a response, and denotes whether recursive query support is available in the name server. Recursive query support is optional. You must exit and return an error if you receive a response that indicates the server does not support recursion.
Z Reserved for future use. Set this field to 0.
RCODE Response code - this 4 bit field is set as part of responses. The values have the following interpretation:
0 : No error condition
1 : Format error - The name server was unable to interpret the query.
2 : Server failure - The name server was unable to process this query due to a problem with the name server.
3 : Name Error - Meaningful only for responses from an authoritative name server, this code signifies that the domain name referenced in the query does not exist.
4 : Not Implemented - The name server does not support the requested kind of query.
5 : Refused - The name server refuses to perform the specified operation for policy reasons. You should set this field to 0, and should assert an error if you receive a response indicating an error condition. You should treat 3 differently, as this represents the case where a requested name doesn’t exist.
QDCOUNT - an unsigned 16 bit integer specifying the number of entries in the question section. Set this field to 1 to indicate one question.
ANCOUNT - an unsigned 16 bit integer specifying the number of resource records in the answer section. Set this field to 0 , indicating you are not providing any answers.
NSCOUNT - an unsigned 16 bit integer specifying the number of name server resource records in the authority records section. Set this field to 0, and should ignore any response entries in this section.
ARCOUNT - an unsigned 16 bit integer specifying the number of resource records in the additional records section. Set this field to 0, and should ignore any response entries in this section.
For further reading checkup the relevant RFC.
A DNS packet typically looks like this Header-Query-RR-RR-RR-RR-RR-RR.....................
A Query structure looks like this
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / QNAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QTYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QCLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Note : QNAME is a variable length field to fit the hostname
QCLASS should be 1 since we are on internet
QTYPE determines what you want to know ; ipv4 address , mx etc.
Resource Record(RR) field looks like this
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / / / NAME / | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | CLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TTL | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | RDLENGTH | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| / RDATA / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Note again : NAME and RDATA are variable length field
Type field tells how RDATA relates to NAME. e.g. if TYPE is 1 then RDATA contains the ipv4 address of the NAME.
That’s all about the structures we need.
DNS Compression Scheme
1. In DNS query and responses www.google.com is represented as 3www6google3com0 << hope you got it :)
if u didnt get that send me a mail ;)
2. And there is a compression scheme followed which is like this -> if google.com were to occur 10 times in the packet then it will written as google.com for the first time and after that a pointer will be placed at every next occurence of google.com to the position offset of the beginning of the first occurence.The starting of the dns header being the offset 0. For example if www.google.com is written starting at a offset of say 12 and some where later
ns.google.com is to be written then it will be written as ns.16 which means point to offset 16(where g of google is).To implement this pointer technique 2 bytes are used where the first 2 bits are 1 and the rest 14 bits are the offset. So for 16 as offset the number u wud need is 1100000000000000 + 1000 <<thats it.
Code
The structure for DNS header
typedef struct
{
unsigned short id; // identification number
unsigned char rd :1; // recursion desired
unsigned char tc :1; // truncated message
unsigned char aa :1; // authoritive answer
unsigned char opcode :4; // purpose of message
unsigned char qr :1; // query/response flag
unsigned char rcode :4; // response code
unsigned char cd :1; // checking disabled
unsigned char ad :1; // authenticated data
unsigned char z :1; // its z! reserved
unsigned char ra :1; // recursion available
unsigned short q_count; // number of question entries
unsigned short ans_count; // number of answer entries
unsigned short auth_count; // number of authority entries
unsigned short add_count; // number of resource entries
} DNS_HEADER;
Structure for the query ( we wont keep the name in this structure since size
is variable)
In the above structure the rd , tc , aa and opcode are in reverse order. This is due to the difference in the endian-ness of local machine and network. Local machines are little endian but network format is big endian. So fields have to be reversed in groups of 8 bit or 1 byte. Have a closer look at this in the structure.
typedef struct
{
unsigned short qtype;
unsigned short qclass;
} QUESTION;
Resource Record
typedef struct
{
unsigned short type;
unsigned short _class;
unsigned int ttl;
unsigned short data_len;
} R_DATA;
Once again name and rdata have been kept out.
These two structures will help
typedef struct
{
unsigned char *name;
R_DATA *resource;
unsigned char *rdata;
} RES_RECORD;
typedef struct
{
unsigned char *name;
QUESTION *ques;
} QUERY;
The working will be like
SOCKET s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); //UDP packet for DNS queries
RES_RECORD answers[20],auth[20],addit[20]; //the replies from the DNS server
sockaddr_in dest;
dest.sin_family=AF_INET;
dest.sin_port=htons(53);
dest.sin_addr.s_addr=inet_addr(dns_servers[0]); //use the first dns server
unsigned char buf[65536],*qname,*reader;
DNS_HEADER *dns = NULL;
QUESTION *qinfo = NULL;
//Set the DNS structure to standard queries
dns=(DNS_HEADER*)&buf;
//set up the header
dns->id = (unsigned short)htons(GetCurrentProcessId());
dns->qr = 0; //This is a query
dns->opcode = 0; //This is a standard query
dns->aa = 0; //Not Authoritative
dns->tc = 0; //This message is not truncated
dns->rd = 1; //Recursion Desired
dns->ra = 0; //Recursion not available! hey we dont have it (lol)
dns->z = 0;
dns->ad = 0;
dns->cd = 0;
dns->rcode = 0;
dns->q_count = htons(1); //we have only 1 question
dns->ans_count = 0;
dns->auth_count = 0;
dns->add_count = 0;
//point to the query portion
qname =(unsigned char*)&buf[sizeof(DNS_HEADER)];
ChangetoDnsNameFormat(qname,host);
qinfo =(QUESTION*)&buf[sizeof(DNS_HEADER) + (strlen((const char*)qname) + 1)];
//fill it
qinfo->qtype = htons(1); //we are requesting the ipv4 address
qinfo->qclass = htons(1); //its internet (lol)
sendto(s,(char*)buf,sizeof(DNS_HEADER) + (strlen((const char*)qname)+1) +
sizeof(QUESTION),0,(sockaddr*)&dest,sizeof(dest))==SOCKET_ERROR)
int i=sizeof(dest);
recvfrom (s,(char*)buf,65536,0,(sockaddr*)&dest,&i);
dns=(DNS_HEADER*)buf;
//move ahead of the dns header and the query field
reader=&buf[sizeof(DNS_HEADER) + (strlen((const char*)qname)+1) +
sizeof(QUESTION)];
printf("nThe response contains : ");
printf("n %d Questions.",ntohs(dns->q_count));
printf("n %d Answers.",ntohs(dns->ans_count));
printf("n %d Authoritative Servers.",ntohs(dns->auth_count));
printf("n %d Additional records.nn",ntohs(dns->add_count));
//reading answers
int stop=0;
for(i=0;i<ntohs(dns->ans_count);i++)
{
answers[i].name=ReadName(reader,buf,stop);
reader+=stop;
answers[i].resource=(R_DATA*)(reader);
reader+=sizeof(R_DATA);
if(ntohs(answers[i].resource->type)==1)
{
answers[i].rdata=new unsigned char[ntohs(answers[i].resource->data_len)];
for(int j=0;j<ntohs(answers[i].resource->data_len);j++)
answers[i].rdata[j]=reader[j];
answers[i].rdata[ntohs(answers[i].resource->data_len)]='';
reader+=ntohs(answers[i].resource->data_len);
}
else
{
answers[i].rdata=ReadName(reader,buf,stop);
reader+=stop;
}
}
and so on....
The IP address in the rdata section will be as numbers which must be converted
to a string and then to the dotted format using inet_ntoa like this
sockaddr_in a;
long *p;
p=(long*)addit[i].rdata;
a.sin_addr.s_addr=(*p);
printf("has IPv4 address : %s",inet_ntoa(a.sin_addr));
Authority resource records and Additional resource records need to be read just like Answer RRs. ChangetoDnsNameFormat(qname,host) function will convert the normal www.google.com in host to 3www6google3com0 and store the result in qname.
The ReadName() functions reads a NAME for query and RR blocks keeping in mind the compression strategy.
Another function RetrieveDnsServersFromRegistry() in dns.cpp retrieves the DNS server IP’s stored in the system. DNS servers are stored in the registry. HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces contains the subkeys for the interfaces and each may contain a field called nameserver whose value will have the dns server fed by either you or stored dynamically in case of dialup connections.multiple DNS ip’s may be present in one nameserver entry and then they are separated by a comma or simply a space.
dfelippa read this post on codeproject and suggested and made some improvements to the code which include :
1. Better memory management
2. Support for MX Query
He modified the code and put up the new code at :
http://www.infologika.com.br/public/dnsquery_main.cpp
Check it out!
Source Code :
Windows :
//DNS Query Program
//Dated : 26/2/2007
//Header Files
#include "winsock2.h"
#include "windows.h"
#include "stdio.h"
#include "conio.h"
#pragma comment(lib,"ws2_32.lib") //Winsock Library
//List of DNS Servers registered on the system
char dns_servers[10][100];
//Type field of Query and Answer
#define T_A 1 /* host address */
#define T_NS 2 /* authoritative server */
#define T_CNAME 5 /* canonical name */
#define T_SOA 6 /* start of authority zone */
#define T_PTR 12 /* domain name pointer */
#define T_MX 15 /* mail routing information */
//Function Declarations
void ngethostbyname (unsigned char*);
void ChangetoDnsNameFormat (unsigned char*,unsigned char*);
unsigned char* ReadName (unsigned char*,unsigned char*,int*);
void RetrieveDnsServersFromRegistry(void);
unsigned char* PrepareDnsQueryPacket (unsigned char*);
//DNS header structure
struct DNS_HEADER
{
unsigned short id; // identification number
unsigned char rd :1; // recursion desired
unsigned char tc :1; // truncated message
unsigned char aa :1; // authoritive answer
unsigned char opcode :4; // purpose of message
unsigned char qr :1; // query/response flag
unsigned char rcode :4; // response code
unsigned char cd :1; // checking disabled
unsigned char ad :1; // authenticated data
unsigned char z :1; // its z! reserved
unsigned char ra :1; // recursion available
unsigned short q_count; // number of question entries
unsigned short ans_count; // number of answer entries
unsigned short auth_count; // number of authority entries
unsigned short add_count; // number of resource entries
};
//Constant sized fields of query structure
struct QUESTION
{
unsigned short qtype;
unsigned short qclass;
};
//Constant sized fields of the resource record structure
#pragma pack(push, 1)
struct R_DATA
{
unsigned short type;
unsigned short _class;
unsigned int ttl;
unsigned short data_len;
};
#pragma pack(pop)
//Pointers to resource record contents
struct RES_RECORD
{
unsigned char *name;
struct R_DATA *resource;
unsigned char *rdata;
};
//Structure of a Query
typedef struct
{
unsigned char *name;
struct QUESTION *ques;
} QUERY;
int main() //do you know what is int main() ?
{
unsigned char hostname[100];
RetrieveDnsServersFromRegistry();
WSADATA firstsock;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&firstsock) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.");
printf("\nEnter Hostname to Lookup : ");
gets((char*)hostname);
ngethostbyname(hostname);
_getch();
return 0;
}
void ngethostbyname(unsigned char *host)
{
unsigned char buf[65536],*qname,*reader;
int i , j , stop;
SOCKET s;
struct sockaddr_in a;
struct RES_RECORD answers[20],auth[20],addit[20]; //the replies from the DNS server
struct sockaddr_in dest;
struct DNS_HEADER *dns = NULL;
struct QUESTION *qinfo = NULL;
s = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); //UDP packet for DNS queries
//Configure the sockaddress structure with information of DNS server
dest.sin_family=AF_INET;
dest.sin_port=htons(53);
//Set the dns server
if(strlen(dns_servers[0]) > 0)
{
//Use the dns server found on system
dest.sin_addr.s_addr=inet_addr(dns_servers[0]);
}
else
{
//Use the open dns servers - 208.67.222.222 and 208.67.220.220
dest.sin_addr.s_addr=inet_addr("208.67.222.222");
}
//Set the DNS structure to standard queries
dns = (struct DNS_HEADER *)&buf;
dns->id = (unsigned short) htons(GetCurrentProcessId());
dns->qr = 0; //This is a query
dns->opcode = 0; //This is a standard query
dns->aa = 0; //Not Authoritative
dns->tc = 0; //This message is not truncated
dns->rd = 1; //Recursion Desired
dns->ra = 0; //Recursion not available! hey we dont have it (lol)
dns->z = 0;
dns->ad = 0;
dns->cd = 0;
dns->rcode = 0;
dns->q_count = htons(1); //we have only 1 question
dns->ans_count = 0;
dns->auth_count = 0;
dns->add_count = 0;
//point to the query portion
qname =(unsigned char*)&buf[sizeof(struct DNS_HEADER)];
ChangetoDnsNameFormat(qname,host);
qinfo =(struct QUESTION*)&buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname) + 1)]; //fill it
qinfo->qtype = htons(1); //we are requesting the ipv4 address
qinfo->qclass = htons(1); //its internet (lol)
printf("\nSending Packet...");
if(sendto(s,(char*)buf,sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION),0,(struct sockaddr*)&dest,sizeof(dest))==SOCKET_ERROR)
{
printf("%d error",WSAGetLastError());
}
printf("Sent");
i=sizeof(dest);
printf("\nReceiving answer...");
if(recvfrom (s,(char*)buf,65536,0,(struct sockaddr*)&dest,&i)==SOCKET_ERROR)
{
printf("Failed. Error Code : %d",WSAGetLastError());
}
printf("Received.");
dns=(struct DNS_HEADER*)buf;
//move ahead of the dns header and the query field
reader=&buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION)];
printf("\nThe response contains : ");
printf("\n %d Questions.",ntohs(dns->q_count));
printf("\n %d Answers.",ntohs(dns->ans_count));
printf("\n %d Authoritative Servers.",ntohs(dns->auth_count));
printf("\n %d Additional records.\n\n",ntohs(dns->add_count));
//reading answers
stop=0;
for(i=0;i<ntohs(dns->ans_count);i++)
{
answers[i].name=ReadName(reader,buf,&stop);
reader = reader + stop;
answers[i].resource = (struct R_DATA*)(reader);
reader = reader + sizeof(struct R_DATA);
if(ntohs(answers[i].resource->type) == 1) //if its an ipv4 address
{
answers[i].rdata = (unsigned char*)malloc(ntohs(answers[i].resource->data_len));
for(j=0 ; j<ntohs(answers[i].resource->data_len) ; j++)
answers[i].rdata[j]=reader[j];
answers[i].rdata[ntohs(answers[i].resource->data_len)] = '\0';
reader = reader + ntohs(answers[i].resource->data_len);
}
else
{
answers[i].rdata = ReadName(reader,buf,&stop);
reader = reader + stop;
}
}
//read authorities
for(i=0;i<ntohs(dns->auth_count);i++)
{
auth[i].name=ReadName(reader,buf,&stop);
reader+=stop;
auth[i].resource=(struct R_DATA*)(reader);
reader+=sizeof(struct R_DATA);
auth[i].rdata=ReadName(reader,buf,&stop);
reader+=stop;
}
//read additional
for(i=0;i<ntohs(dns->add_count);i++)
{
addit[i].name=ReadName(reader,buf,&stop);
reader+=stop;
addit[i].resource=(struct R_DATA*)(reader);
reader+=sizeof(struct R_DATA);
if(ntohs(addit[i].resource->type)==1)
{
addit[i].rdata = (unsigned char*)malloc(ntohs(addit[i].resource->data_len));
for(j=0;j<ntohs(addit[i].resource->data_len);j++)
addit[i].rdata[j]=reader[j];
addit[i].rdata[ntohs(addit[i].resource->data_len)]='\0';
reader+=ntohs(addit[i].resource->data_len);
}
else
{
addit[i].rdata=ReadName(reader,buf,&stop);
reader+=stop;
}
}
//print answers
for(i=0;i<ntohs(dns->ans_count);i++)
{
//printf("\nAnswer : %d",i+1);
printf("Name : %s ",answers[i].name);
if(ntohs(answers[i].resource->type)==1) //IPv4 address
{
long *p;
p=(long*)answers[i].rdata;
a.sin_addr.s_addr=(*p); //working without ntohl
printf("has IPv4 address : %s",inet_ntoa(a.sin_addr));
}
if(ntohs(answers[i].resource->type)==5) //Canonical name for an alias
{
printf("has alias name : %s",answers[i].rdata);
}
printf("\n");
}
//print authorities
for(i=0;i<ntohs(dns->auth_count);i++)
{
//printf("\nAuthorities : %d",i+1);
printf("Name : %s ",auth[i].name);
if(ntohs(auth[i].resource->type)==2)
{
printf("has authoritative nameserver : %s",auth[i].rdata);
}
printf("\n");
}
//print additional resource records
for(i=0;i<ntohs(dns->add_count);i++)
{
//printf("\nAdditional : %d",i+1);
printf("Name : %s ",addit[i].name);
if(ntohs(addit[i].resource->type)==1)
{
long *p;
p=(long*)addit[i].rdata;
a.sin_addr.s_addr=(*p); //working without ntohl
printf("has IPv4 address : %s",inet_ntoa(a.sin_addr));
}
printf("\n");
}
return;
}
unsigned char* ReadName(unsigned char* reader,unsigned char* buffer,int* count)
{
unsigned char *name;
unsigned int p=0,jumped=0,offset;
int i , j;
*count = 1;
name = (unsigned char*)malloc(256);
name[0]='\0';
//read the names in 3www6google3com format
while(*reader!=0)
{
if(*reader>=192)
{
offset = (*reader)*256 + *(reader+1) - 49152; //49152 = 11000000 00000000 ;)
reader = buffer + offset - 1;
jumped = 1; //we have jumped to another location so counting wont go up!
}
else
{
name[p++]=*reader;
}
reader=reader+1;
if(jumped==0) *count = *count + 1; //if we havent jumped to another location then we can count up
}
name[p]='\0'; //string complete
if(jumped==1)
{
*count = *count + 1; //number of steps we actually moved forward in the packet
}
//now convert 3www6google3com0 to www.google.com
for(i=0;i<(int)strlen((const char*)name);i++)
{
p=name[i];
for(j=0;j<(int)p;j++)
{
name[i]=name[i+1];
i=i+1;
}
name[i]='.';
}
name[i-1]='\0'; //remove the last dot
return name;
}
//Retrieve the DNS servers from the registry
void RetrieveDnsServersFromRegistry()
{
HKEY hkey=0;
char name[256];
char *path = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
char *fullpath[256];
unsigned long s=sizeof(name);
int dns_count=0 , err , i , j;
HKEY inter;
unsigned long count;
//Open the registry folder
RegOpenKeyEx(HKEY_LOCAL_MACHINE , path , 0 , KEY_READ , &hkey );
//how many interfaces
RegQueryInfoKey(hkey, 0 , 0 , 0 , &count , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
for(i=0 ; i<count ; i++)
{
s=256;
//Get the interface subkey name
RegEnumKeyEx(hkey , i , (char*)name , &s , 0 , 0 , 0 , 0 );
//Make the full path
strcpy((char*)fullpath,path);
strcat((char*)fullpath,"\\");
strcat((char*)fullpath,name);
//Open the full path name
RegOpenKeyEx(HKEY_LOCAL_MACHINE , (const char*)fullpath , 0 , KEY_READ , &inter );
//Extract the value in Nameserver field
s=256;
err=RegQueryValueEx(inter , "NameServer" , 0 , 0 , (unsigned char*)name , &s );
if(err==ERROR_SUCCESS && strlen(name)>0)
{
strcpy(dns_servers[dns_count++],name);
}
}
for(i=0;i<dns_count;i++)
{
for(j=0;j<strlen(dns_servers[i]);j++)
{
if(dns_servers[i][j]==',' || dns_servers[i][j]==' ')
{
strcpy(dns_servers[dns_count++] , dns_servers[i]+j+1);
dns_servers[i][j] = 0;
}
}
}
printf("\nThe following DNS Servers were found on your system...");
for(i=0;i<dns_count;i++)
{
printf("\n%d) %s",i+1,dns_servers[i]);
}
}
//this will convert www.google.com to 3www6google3com ;got it :)
void ChangetoDnsNameFormat(unsigned char* dns,unsigned char* host)
{
int lock=0 , i;
strcat((char*)host,".");
for(i=0 ; i<(int)strlen((char*)host) ; i++)
{
if(host[i]=='.')
{
*dns++=i-lock;
for(;lock<i;lock++)
{
*dns++=host[lock];
}
lock++; //or lock=i+1;
}
}
*dns++='\0';
}
Output
Here is a sample output from the above program
The following DNS Servers were found on your system... 1) 208.67.222.222 2) 208.67.220.220 Initialising Winsock...Initialised. Enter Hostname to Lookup : www.google.com Sending Packet...Sent Receiving answer...Received. The response contains : 1 Questions. 6 Answers. 4 Authoritative Servers. 4 Additional records. Name : www.google.com has alias name : www.l.google.com Name : www.l.google.com has IPv4 address : 74.125.235.16 Name : www.l.google.com has IPv4 address : 74.125.235.17 Name : www.l.google.com has IPv4 address : 74.125.235.18 Name : www.l.google.com has IPv4 address : 74.125.235.19 Name : www.l.google.com has IPv4 address : 74.125.235.20 Name : google.com has authoritative nameserver : ns4.google.com Name : google.com has authoritative nameserver : ns1.google.com Name : google.com has authoritative nameserver : ns3.google.com Name : google.com has authoritative nameserver : ns2.google.com Name : ns1.google.com has IPv4 address : 216.239.32.10 Name : ns2.google.com has IPv4 address : 216.239.34.10 Name : ns3.google.com has IPv4 address : 216.239.36.10 Name : ns4.google.com has IPv4 address : 216.239.38.10
If you get error the error message : "Sending Packet…10049 error" then check if there are any DNS servers in your Network configuration and that the above program is able to list them like this :
The following DNS Servers were found on your system... 1) 208.67.222.222 2) 208.67.220.220
If no DNS servers are found then error 10049 will come.
Update
The code has not been fixed from the 10049 winsock error. If no dns servers are found then the open dns server 208.67.222.222 will be used.
Download Source
http://www.binarytides.com/blog_files/dns_query/dns_query.cpp
For Linux version of the code check :
http://www.binarytides.com/blog/dns-query-code-in-c-with-linux-sockets/
Related Posts
-
Fourty
-
Fourty
-
doicanhden
-
Keshav
-
Nik
-
Nik
-
-
saeed
-
brian
-
-
cristian_gog
-
Razvan
-
brian
-
Razvan
-
-
-
brian
-
Rat’s
-
bilal
-
http://harmyder.wordpress.com yola
-
http://www.techparadise.info janmejai
-
Vicky.
-
Leo
-
Genuis
-
Andrew Smith
-
John Smith
-
Andrew Smith
-
Adrian
-
Deepanshu
-
Aaron
-
Aaron
-
sevcio
-
Alessandro I.
-
dannie
-
mona
-
http://www.funwall.net larkou
-
Sanarita Holmes
-
Nicolas Goles
-
Anonymous