Linux query DNS sample _c language

Source: Internet
Author: User
Tags auth pack reserved strlen strtok nameserver truncated htons

Dns.c

Copy Code code as follows:



/*


* DNS Query Program on Linux


*


* author:ismdeep@live.com


*


* */


Header Files


#include <stdio.h>//printf


#include <string.h>//strlen


#include <stdlib.h>//malloc


#include <sys/socket.h>//you know what


#include <arpa/inet.h>//inet_addr, Inet_ntoa, Ntohs etc


#include <netinet/in.h>


#include <unistd.h>//getpid

List of DNS Servers registered on the system
Char dns_servers[10][100];
int dns_server_count = 0;
Types of DNS resource records:)

#define T_A 1//ipv4 Address
#define T_NS 2//nameserver
#define T_CNAME 5//canonical name
#define T_SOA 6/* Start of authority zone * *
#define T_PTR/* Domain name pointer * *
#define T_MX//mail Server

Function prototypes
void Ngethostbyname (unsigned char*, int);
void Changetodnsnameformat (unsigned char*,unsigned char*);
unsigned char* readname (unsigned char*,unsigned char*,int*);
void Get_dns_servers ();

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 (int argc, char *argv[])
{
unsigned char hostname[100];

Get the DNS servers from the resolv.conf file
Get_dns_servers ();

Get the hostname from the terminal
printf ("Enter Hostname to Lookup:");
scanf ("%s", hostname);

Now get the IP of this hostname, A record
Ngethostbyname (hostname, t_a);

return 0;
}

/*
* Perform a DNS query by sending a packet
* */
void Ngethostbyname (unsigned char *host, int query_type)
{
unsigned char buf[65536],*qname,*reader;
int I, J, stop, 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;

printf ("Resolving%s", host);

s = socket (af_inet, SOCK_DGRAM, IPPROTO_UDP); UDP Packet for DNS queries

dest.sin_family = af_inet;
Dest.sin_port = Htons (53);
DEST.SIN_ADDR.S_ADDR = inet_addr (Dns_servers[0]); DNS servers

Set the DNS structure to standard queries
DNS = (struct Dns_header *) &buf;

Dns->id = (unsigned short) htons (Getpid ());
DNS->QR = 0; This is a query
Dns->opcode = 0; This is a standard query
DNS->AA = 0; Not authoritative
DNS->TC = 0; This was 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 (Query_type); Type of the query, A, MX, CNAME, NS etc
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)) < 0)
{
Perror ("SendTo failed");
}
printf ("Done");

Receive the answer
i = sizeof dest;
printf ("\nreceiving answer ...");
if (Recvfrom (S, (char*) buf, 65536, 0, (struct sockaddr*) &dest, (socklen_t*) &i) < 0)
{
Perror ("Recvfrom failed");
}
printf ("Done");

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));

Start 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 a 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)] = ';

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)]= ';
Reader+=ntohs (Addit[i].resource->data_len);
}
Else
{
Addit[i].rdata=readname (Reader,buf,&stop);
Reader+=stop;
}
}

Print answers
printf ("\nanswer Records:%d \ n", Ntohs (Dns->ans_count));
for (I=0 i < Ntohs (dns->ans_count); i++)
{
printf ("Name:%s", answers[i].name);

if (Ntohs (answers[i].resource->type) = = t_a)//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
 printf ("\nauthoritive Records:%d \ n", Ntohs (Dns->auth_count));
 for (I=0 i < Ntohs (dns->auth_count); i++)
 {

  printf ("Name:%s", Auth[i].name) ;
  if (Ntohs (auth[i].resource->type) ==2)
  {
   printf ("has NameServer:%s ", auth[i].rdata);
  }
  printf ("\ n");
 }

Print Additional resource records
printf ("\nadditional Records:%d \ n", Ntohs (Dns->add_count));
for (I=0 i < Ntohs (dns->add_count); i++)
{
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);
printf ("Has IPV4 address:%s", Inet_ntoa (A.SIN_ADDR));
}
printf ("\ n");
}
Return
}

/*
*
* */
u_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]= ' ";

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]= ' "; 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]= ';//remove the last dot
 return name;
}

/*
 * get the DNS servers from/etc/resolv.conf file on Linux
 * */
void get_dns_servers ()
{
 file *FP;
 char line[200], *p;
 if ((fp = fopen ("/etc/resolv.conf", "r") = = NULL)
 {
  printf ("Failed opening/etc/ resolv.conf file \ n ");
 }

 while (fgets, FP)
 {
  if (line[0] = = ' # ')
  {
    continue;
  }
  if (line, nameserver, ten) = = 0)
  {
   p = strtok (line, ""); Br>   p = Strtok (NULL, "");

   //p The now is the DNS IP:)
   //????
  }
 }

 strcpy (dns_servers[0], "208.67.222.222");
 strcpy (Dns_servers[1], "208.67.220.220");
}

/*
* This'll 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 < strlen ((char*) host); i++)
{
if (host[i]== '. ')
{
*dns++ = I-lock;
for (; lock<i;lock++)
{
*dns++=host[lock];
}
lock++; or lock=i+1;
}
}
*dns++= ' ";
}

Dns.c

Copy Code code as follows:



/*


* DNS Query Program on Linux


*


* author:ismdeep@live.com


*


* */


Header Files


#include &lt;stdio.h&gt;//printf


#include &lt;string.h&gt;//strlen


#include &lt;stdlib.h&gt;//malloc


#include &lt;sys/socket.h&gt;//you know what


#include &lt;arpa/inet.h&gt;//inet_addr, Inet_ntoa, Ntohs etc


#include &lt;netinet/in.h&gt;


#include &lt;unistd.h&gt;//getpid

List of DNS Servers registered on the system
Char dns_servers[10][100];
int dns_server_count = 0;
Types of DNS resource records:)

#define T_A 1//ipv4 Address
#define T_NS 2//nameserver
#define T_CNAME 5//canonical name
#define T_SOA 6/* Start of authority zone * *
#define T_PTR/* Domain name pointer * *
#define T_MX//mail Server

Function prototypes
void Ngethostbyname (unsigned char*, int);
void Changetodnsnameformat (unsigned char*,unsigned char*);
unsigned char* readname (unsigned char*,unsigned char*,int*);
void Get_dns_servers ();

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 (int argc, char *argv[])
{
unsigned char hostname[100];

Get the DNS servers from the resolv.conf file
Get_dns_servers ();

Get the hostname from the terminal
printf ("Enter Hostname to Lookup:");
scanf ("%s", hostname);

Now get the IP of this hostname, A record
Ngethostbyname (hostname, t_a);

return 0;
}

/*
* Perform a DNS query by sending a packet
* */
void Ngethostbyname (unsigned char *host, int query_type)
{
unsigned char buf[65536],*qname,*reader;
int I, J, stop, 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;

printf ("Resolving%s", host);

s = socket (af_inet, SOCK_DGRAM, IPPROTO_UDP); UDP Packet for DNS queries

dest.sin_family = af_inet;
Dest.sin_port = Htons (53);
DEST.SIN_ADDR.S_ADDR = inet_addr (Dns_servers[0]); DNS servers

Set the DNS structure to standard queries
DNS = (struct Dns_header *) &buf;

Dns->id = (unsigned short) htons (Getpid ());
DNS->QR = 0; This is a query
Dns->opcode = 0; This is a standard query
DNS->AA = 0; Not authoritative
DNS->TC = 0; This was 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 (Query_type); Type of the query, A, MX, CNAME, NS etc
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)) < 0)
{
Perror ("SendTo failed");
}
printf ("Done");

Receive the answer
i = sizeof dest;
printf ("\nreceiving answer ...");
if (Recvfrom (S, (char*) buf, 65536, 0, (struct sockaddr*) &dest, (socklen_t*) &i) < 0)
{
Perror ("Recvfrom failed");
}
printf ("Done");

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));

Start 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 a 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)] = ';

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)]= ';
Reader+=ntohs (Addit[i].resource->data_len);
}
Else
{
Addit[i].rdata=readname (Reader,buf,&stop);
Reader+=stop;
}
}

Print answers
printf ("\nanswer Records:%d \ n", Ntohs (Dns->ans_count));
for (I=0 i < Ntohs (dns->ans_count); i++)
{
printf ("Name:%s", answers[i].name);

if (Ntohs (answers[i].resource->type) = = t_a)//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
 printf ("\nauthoritive Records:%d \ n", Ntohs (Dns->auth_count));
 for (I=0 i < Ntohs (dns->auth_count); i++)
 {

  printf ("Name:%s", Auth[i].name) ;
  if (Ntohs (auth[i].resource->type) ==2)
  {
   printf ("has NameServer:%s ", auth[i].rdata);
  }
  printf ("\ n");
 }

Print Additional resource records
printf ("\nadditional Records:%d \ n", Ntohs (Dns->add_count));
for (I=0 i < Ntohs (dns->add_count); i++)
{
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);
printf ("Has IPV4 address:%s", Inet_ntoa (A.SIN_ADDR));
}
printf ("\ n");
}
Return
}

/*
*
* */
u_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]= ' ";

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]= ' "; 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]= ';//remove the last dot
 return name;
}

/*
 * get the DNS servers from/etc/resolv.conf file on Linux
 * */
void get_dns_servers ()
{
 file *FP;
 char line[200], *p;
 if ((fp = fopen ("/etc/resolv.conf", "r") = = NULL)
 {
  printf ("Failed opening/etc/ resolv.conf file \ n ");
 }

 while (fgets, FP)
 {
  if (line[0] = = ' # ')
  {
    continue;
  }
  if (line, nameserver, ten) = = 0)
  {
   p = strtok (line, ""); Br>   p = Strtok (NULL, "");

   //p The now is the DNS IP:)
   //????
  }
 }

 strcpy (dns_servers[0], "208.67.222.222");
 strcpy (Dns_servers[1], "208.67.220.220");
}

/*
* This'll 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 < strlen ((char*) host); i++)
{
if (host[i]== '. ')
{
*dns++ = I-lock;
for (; lock<i;lock++)
{
*dns++=host[lock];
}
lock++; or lock=i+1;
}
}
*dns++= ' ";
}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.