SlideShare a Scribd company logo
1 of 15
//2 codes, as presented to Dr. Amjad<br />//client side<br />#include quot;
stdafx.hquot;
<br />#ifndef unix<br />#define WIN32<br />#include <windows.h><br />#include <winsock.h><br />#include <io.h><br />#else<br />#define closesocket close<br />#include <sys/types.h><br />#include <sys/socket.h><br />#include <netinet/in.h><br />#include <arpa/inet.h><br />#include <netdb.h><br />#endif<br />#include <stdio.h><br />#include <string.h><br />#define PROTOPORT       53            /* default protocol port number */<br />   <br />char ServerIP[] = quot;
127.0.0.3quot;
;<br />void analyse_response(char* response);<br />void main() //here we will get what the user wants, then we will reformat what he typed in a useful DNS query<br />{<br />        struct  hostent  *IPAddrServer;/* pointer to a host table entry */<br />        struct  protoent *UDP_Protocol;  /* pointer to a protocol table entry   */<br />        struct  sockaddr_in SockAddrInToServer, SockAddrInFromServer;  /*IP, port, family*/<br />        int     ClientSocket;              /* socket descriptor                   */<br />        int     port;            /* protocol port number                */<br />        char    *host;           /* pointer to host name                */<br />        int     n,i;               /* number of characters read           */<br />char    response[512]={''};       <br />char    buf[512]={''},b1[255];       /* b1 buffer for data from the user. buf is the good reformatting for DNS usage *//*size of 'buf' and 'response' should be bigger than 512, as a max UDP message should*/<br />#ifdef WIN32<br />        WSADATA wsaData;<br />        WSAStartup(0x0101, &wsaData);<br />#endif<br />        memset((char *)&SockAddrInToServer,0,sizeof(SockAddrInToServer));/* clear client sockaddr structure */<br />        SockAddrInToServer.sin_family = AF_INET;/* set family to Internet     */<br />        port = PROTOPORT;                      <br />        SockAddrInToServer.sin_port = htons((u_short)port);/* set port number */<br />        /* Convert host name to equivalent IP address and copy to SockAddrInToServer. */<br />host = ServerIP;<br />        IPAddrServer = gethostbyname(host);//now here comes a new worker thread...<br />        if ( ((char *)IPAddrServer) == NULL ) <br />{<br />             fprintf(stderr,quot;
invalid host: %squot;
, host);<br />             getchar();<br />             exit(1);<br />        }<br />        memcpy(&SockAddrInToServer.sin_addr, IPAddrServer->h_addr, IPAddrServer->h_length);<br />        /* Map UDP transport protocol name to protocol number. */<br />        if ( ((int)(UDP_Protocol = getprotobyname(quot;
udpquot;
))) == 0) <br />{<br />             fprintf(stderr, quot;
cannot map "
udp"
 to protocol numberquot;
);<br />             getchar();<br />             exit(1);<br />        }<br />        /* Create a socket. */<br />        ClientSocket = socket(PF_INET, SOCK_DGRAM, UDP_Protocol->p_proto);<br />        if (ClientSocket < 0) <br />{<br />             fprintf(stderr, quot;
socket creation failedquot;
);<br />             getchar();<br />             exit(1);<br />        }<br />printf(quot;
You can start by requesting the DNS server.quot;
);<br />char b2[255]; /* b2 is to get the hotmail, com, yahoo, mail, msn, ... from user input */<br />int j, k, t, l, firstpart;<br />char question[255]={''}; //so strlen(question)==0<br />int h = sizeof(struct sockaddr);<br />char header[255]={0,0,1,0,0,1,0,0,0,0,0,0}; //this is our desired header, but the last 0's won't be distinguished from the remaining of the of header, because all the remaining is also 0 or ''<br />unsigned short id_short = 0;<br />char *id;<br />id=(char*) &id_short;<br />int how_many_times = 0;<br />while(1)<br />{<br />how_many_times++;<br />printf(quot;
your number %d request, please:quot;
,how_many_times);<br />for (i=0;i<255;i++) //this is for cleaning, we clean many arrays.<br />b1[i]=0;<br /> <br />scanf(quot;
%squot;
,&b1); //assuming something like www.hotmail.com<br />//gets(b1); //also we can use gets<br />//The following is the reformatting of b1 in order to make a useful DNS query<br />//making the header<br />header[0] = *(id+1);<br />header[1] = *id;<br />//your header is made of 12 elements<br />//there you go your wonderful header<br />//now, making the Question<br />for (i=0; i<255; i++)<br />question[i] = 0;<br />for (i=0; i<255; i++)<br />b2[i] = 0;<br />i=0; j=0; k=0; t=0; l=0; firstpart=0;<br />while(i<strlen(b1)+1)<br />{if (0==strlen(b1) || b1[0]=='.') <br />break; <br />if (b1[i-1]=='.' && b1[i]!='.')<br />j=i;<br />if (b1[i]=='.' || b1[i]=='')<br />{<br />for(t=0; t<255; t++)<br />b2[t]=0; //not '0' <br />t=0;<br />for (k=j; k<i; k++)<br />{<br />b2[t]=b1[k];<br />t++;<br />}<br />question[strlen(question)]=t; //feeling safe that no truncated part like www or hotmail would be longer than 63! because the upper 2 bits of this specific byte must be 0's  <br />strcat(question,b2);<br />}<br />i++;<br />}<br />if (strlen(question)>255) //the idea of this condition could be found in page 9 in RFC 1035<br />{<br />printf(quot;
The name you entered must be smaller. You can retry. Thanksquot;
);<br />break;<br />}<br />//of course there is the 'root' left, which is a null byte. simply the strlen(question) would be itself + 1 <br />//now let's add QType and QClass<br />question[strlen(question)+2]=1;<br />question[strlen(question)+4]=1;<br />//there you go your wonderful Question made of strlen(question) + 5 elements.<br />//now putting everything together in buf<br />for (i=0; i<12; i++)//10 is the lengh of the header<br />buf[i]=header[i];<br />for (i=12; i < (strlen(question)+17); i++)<br />buf[i]=question[i-12];<br />if (strlen(buf)>512) //the idea of this condition is from page 31 of RFC 1035<br />{<br />//in fact it's the whole UDP message and not only the entered name<br />printf(quot;
The name you entered must be smaller. You can retry. Thanksquot;
);<br />break;<br />}<br />n = sendto(ClientSocket, buf, sizeof(buf), 0,(sockaddr *)&SockAddrInToServer,h);<br />for (i=0; i<512; i++)<br />buf[i]=0;<br />for (i=0;i<512;i++)<br />response[i]=0;<br />n = recvfrom(ClientSocket, response, sizeof(response), 0, (sockaddr *)&SockAddrInFromServer,&h);<br />analyse_response(response);<br />id_short++;<br />//if (id_short==2^16-1)<br />}<br />        /* Close the socket. */<br />        closesocket(ClientSocket);<br />        /* Terminate the client program gracefully. */<br />getchar();<br />        exit(0);<br />}<br />void analyse_response(char* response)<br />{<br />char aa1 = response[0]; //we want to interchange the values of header id bytes. The final aim of this is to have a correct value of id_short<br />response[0] = response[1];<br />response[1]= aa1;<br />unsigned short *id_short;<br />id_short=(unsigned short*) response;<br />//we can get them back as before, but why bother.<br />printf(quot;
The gathered info for your number %d request are the following:quot;
,*id_short + 1);//one limitation of using id_short is that user here tries more than (2^16 - 1) times, so the 2^16 th time would be 0 not 2^16. <br />if ((response[2]&2)==2) printf(quot;
Message is truncated, so we're expecting a malicious resultquot;
); //we mean here: header->third byte->second bit<br />if ((response[3]&128)==0) printf(quot;
Expecting a malicious result, since resursion was not availablequot;
);<br />if ((response[3]&16)==16) printf(quot;
Expecting a malicious result, since there was a format errorquot;
);<br />if ((response[3]&32)==32) printf(quot;
Server Failurequot;
);//because of this case, you may create in the DNS server another socket for clients complains...<br />if ((response[3]&48)==48) printf(quot;
Name errorquot;
);<br />if ((response[3]&64)==64) printf(quot;
Not Implementedquot;
);<br />if ((response[3]&80)==80) printf(quot;
Server refused to perform operationquot;
);<br />unsigned short ANCOUNT = *(response + 7);<br />//now, determining the end of the question section <br />char a = 1;//here I want whatever value <br />int End_Of_Question = 12;<br />while (a!=0)<br />{<br />a = response[End_Of_Question];<br />End_Of_Question++;<br />}//now End_Of_Question is the first byte of QTYPE<br />End_Of_Question = End_Of_Question + 4;<br />//now End Of question section is reached, and End_Of_Question is the first byte in the Answer section<br />//now beginnig with the Answer section<br />int nameLengh = 0;<br />char *name = response + End_Of_Question; //quot;
namequot;
 belongs to NAME, not to the question section <br />while(*(name + nameLengh)!=0)//no need to this loop, but no harm<br />nameLengh++;<br />// the 0 value of *(name + nameLengh) could have 2 meanings, it may belong to NAME (e.g in case no compression) or to TYPE (e.g in case of compression so we don't need a 0 in NAME because it would be mentionned in the QNAME, and from another hand the higher order byte of TYPE is 0 because values of TYPE goes from 1 to 16)<br />char *b = name; //b will pass over all the response <br />short count=0;<br />while (count < ANCOUNT)<br />{<br />count++;<br />char NAME_field[512]={''};<br />int ii=0;<br />for (ii=0;ii<512;ii++)//cleaning NAME_field<br />NAME_field[ii]=0;<br />int NAME_field_lengh = 0;<br />int name1Lengh;<br />while ( ((*b & 192) != 192) && (*b != 0) ) //in this loop: no compression. The condition (*b != 0) is not meant for the first time we enter the loop; it's meant if there was no pointer and the 0 exits explicitly in NAME. I don't know if the 0 _in case it appeared here_ could not belong to NAME.<br />{//192 in binary is 11000000<br />name1Lengh = 0;<br />while(name1Lengh<*b)<br />{<br />NAME_field[NAME_field_lengh + name1Lengh] = *(b + name1Lengh + 1);<br />name1Lengh++;<br />}<br />NAME_field_lengh = NAME_field_lengh + name1Lengh;<br />NAME_field[NAME_field_lengh]='.';<br />NAME_field_lengh++;<br />b = b + *b + 1;<br />}<br />//now in case we have a pointer<br />char *name1 = b;//this assigement in case there is a pointer inside a pointer (or more generally pointer inside a pointer inside a pointer inside ..., and for this general case we made name2)<br />while (((*name1 & 192) == 192) )<br />{<br />char ab[3];<br />ab[0] = *(name1 + 1);<br />ab[1] = *name1 & 63; //63 in binary is 00111111<br />unsigned short *pointer_value = (unsigned short*) ab;<br />//char * name2 = name1;<br />name1 = response + *pointer_value;<br />while((*name1)!=0 && (*name1 & 192)!=192) //the condition is for the case if inside one pointer there is another pointer to somewhere else<br />{<br />name1Lengh = 0;<br />while (name1Lengh < (*name1) )<br />{<br />NAME_field[NAME_field_lengh + name1Lengh] = *(name1 + name1Lengh + 1);<br />name1Lengh++;<br />}<br />name1 = name1 + *name1 + 1;<br />NAME_field_lengh = NAME_field_lengh + name1Lengh;<br />NAME_field[NAME_field_lengh]='.';<br />NAME_field_lengh++;<br />}<br />//name2 = name2 + 2;//this is not needed since we assume that after a pointer there is no useful info to add to NAME_field, and surely some more code should be added and we may use recursivity<br />}<br />if (name1 != b)//this means we entered the pointer loop<br />b = b + 2;<br />//now beginning with TYPE<br />//now *b = 0<br />if (*(b+1)==0)//means b is part of NAME and represents root<br />b=b+1;<br />//now b is part of TYPE<br />char TYPE[10]={''};<br />switch ( *(b+1) )<br />{<br />         case 1:<br />            TYPE[0]='A';<br />            break;<br />         case 2:<br />            TYPE[0]='N';TYPE[1]='S';<br />            break;<br /> case 3:<br />            TYPE[0]='M';TYPE[1]='D';<br />            break;<br /> case 4:<br />            TYPE[0]='M';TYPE[1]='F';<br />            break;<br /> case 5:<br />            TYPE[0]='C';TYPE[1]='N';TYPE[2]='A';TYPE[3]='M';TYPE[4]='E';<br />            break;<br /> case 6:<br />            TYPE[0]='S';TYPE[1]='O';TYPE[2]='A';<br />            break;<br /> case 7:<br />            TYPE[0]='M';TYPE[1]='B';<br />            break;<br /> case 8:<br />            TYPE[0]='M';TYPE[1]='G';<br />            break;<br /> case 9:<br />            TYPE[0]='M';TYPE[1]='R';<br />            break;<br /> case 10:<br />            TYPE[0]='N';TYPE[1]='U';TYPE[2]='L';TYPE[3]='L';<br />            break;<br /> case 11:<br />            TYPE[0]='W';TYPE[1]='K';TYPE[2]='S';<br />            break;<br /> case 12:<br />            TYPE[0]='P';TYPE[1]='T';TYPE[2]='R';<br />            break;<br /> case 13:<br />            TYPE[0]='H';TYPE[1]='I';TYPE[2]='N';TYPE[3]='F';TYPE[4]='O';<br />            break;<br /> case 14:<br />            TYPE[0]='M';TYPE[1]='I';TYPE[2]='N';TYPE[3]='F';TYPE[4]='O';<br />            break;<br /> case 15:<br />            TYPE[0]='M';TYPE[1]='X';<br />            break;<br /> case 16:<br />            TYPE[0]='T';TYPE[1]='X';TYPE[2]='T';<br />            break;<br />}<br />//now beginning with CLASS<br />b=b+3; //now b is the lower byte of CLASS<br />char CLASS[3]={''};<br />switch (*b)<br />{<br />         case 1:<br />            CLASS[0]='I';CLASS[1]='N';<br />            break;<br /> case 2:<br />            CLASS[0]='C';CLASS[1]='S';<br />            break;<br /> case 3:<br />            CLASS[0]='C';CLASS[1]='H';<br />            break;<br /> case 4:<br />            CLASS[0]='H';CLASS[1]='S';<br />            break;<br />}<br />//now TTL<br />b = b + 4;//now b is at the lower byte of TTL section<br />char aa2[6];<br />aa2[0] = *b & 255; aa2[1] = *(b-1) & 255; aa2[2] = *(b-2) & 255; aa2[3] = *(b-3) & 255;<br />unsigned int *TTL = (unsigned int*) aa2;<br />//now *TTL is the time<br />//now the RDLENGTH<br />int aa3[3];<br />b = b + 2;//now b is at the lower byte of RDLENGTH section<br />aa3[0] = *b; aa3[1] = *(b-1);<br />unsigned short *RDLENGTH = (unsigned short*) aa3;<br />//now *RDLENGTH is the length of the RDATA<br />//now the RDATA, it's so similar to Name, but it's good to use RDLENGTH as well, since we don't know if RDATA _in case it's explicit_ ends with 0 (root) or no!<br />b = b + 1;<br />char RDATA_field[512]={''};<br />for (ii=0;ii<512;ii++) //cleaning RDATA_field<br />RDATA_field[ii]=0;<br />short RDLENGTH_count = 0;<br />if ( TYPE[0]=='C' && TYPE[1]=='N' && TYPE[2]=='A' && TYPE[3]=='M' && TYPE[4]=='E')<br />{<br />int RDATA_field_lengh = 0;<br />int RDATA1Lengh;<br />while ( ((*b & 192) != 192) && (*b != 0) && (RDLENGTH_count < *RDLENGTH)) //in this loop: no compression. The condition (*b != 0) is not meant for the first time we enter the loop; it's meant if there was no pointer and the 0 exits explicitly in RDATA. I don't know if the 0 _in case it appeared here_ could not belong to RDATA.<br />{//192 in binary is 11000000<br />RDATA1Lengh = 0;<br />while(RDATA1Lengh<*b)<br />{<br />RDATA_field[RDATA_field_lengh + RDATA1Lengh] = *(b + RDATA1Lengh + 1);<br />RDATA1Lengh++;<br />}<br />RDLENGTH_count = RDLENGTH_count + *b + 1;<br />RDATA_field_lengh = RDATA_field_lengh + RDATA1Lengh;<br />RDATA_field[RDATA_field_lengh]='.';<br />RDATA_field_lengh++;<br />b = b + *b + 1;<br />}<br />//in case of a pointer<br />char *RDATA1 = b;<br />while ((*RDATA1 & 192) == 192 && (RDLENGTH_count < *RDLENGTH))//the second condition is very important, e.g. in case of a first attempt to enter and the pointer belonged to another RR<br />{<br />char ab[3];<br />ab[0] = *(RDATA1+1);<br />ab[1] = *RDATA1 & 63; //63 in binary is 00111111<br />unsigned short *pointer_value = (unsigned short*) ab;<br />RDATA1 = response + *pointer_value;<br />while(*RDATA1!=0 && (*RDATA1 & 192)!=192)//consider this non-handeled case: the pointer pointed to a another RDATA-section-explicit-text where it ends (but not with 0, nor with a pointer) with the logic of RDLENGTH<br />{<br />RDATA1Lengh = 0;<br />while ( RDATA1Lengh < (*RDATA1) )<br />{<br />RDATA_field[RDATA_field_lengh + RDATA1Lengh] = *(RDATA1 + RDATA1Lengh + 1);<br />RDATA1Lengh++;<br />}<br />RDATA1 = RDATA1 + *RDATA1 + 1;<br />RDATA_field_lengh = RDATA_field_lengh + RDATA1Lengh;<br />RDATA_field[RDATA_field_lengh]='.';<br />RDATA_field_lengh++;<br />}<br />RDLENGTH_count = RDLENGTH_count + 2;<br />} <br />if (RDATA1 != b)//this means we entered the pointer loop<br />b = b + 2;<br />if ( *b == 0 && (RDLENGTH_count == *RDLENGTH-1) )//for both previous cases<br />{<br />b = b + 1;<br />RDLENGTH_count = *RDLENGTH;<br />}<br />//the last '.' in RDATA_field in our program should be put, and there is no restriction for it except being entered only in the first loop and not the second, and (also) if RDLENGTH_count = *RDLENGTH<br />if ( (RDATA1 == b) && (RDLENGTH_count == *RDLENGTH) )<br />RDATA_field[RDATA_field_lengh-1]=0;<br />//now appearing this RR to the client<br />printf(quot;
%s%s%s%d%squot;
, NAME_field, TYPE, CLASS, *TTL, RDATA_field);<br />}<br />if (TYPE[0]=='A')<br />{<br />//it is supposed now that *b is 4, referring to the IP address<br />unsigned short ab1,ab2,ab3,ab4;<br />ab1=*b; ab2=*(b+1); ab3=*(b+2); ab4=*(b+3); //the format of the IP address is like ab1.ab2.ab3.ab4<br />b = b + 4;<br />//now appearing this RR to the client<br />printf(quot;
%s%s%s%d%d.%d.%d.%dquot;
, NAME_field, TYPE, CLASS, *TTL, ab1 & 255 , ab2 & 255 , ab3 & 255 , ab4 & 255 );<br />}<br />}<br />}<br />//server side<br />#include quot;
stdafx.hquot;
<br />#include <iostream><br />#include <process.h><br />/* server.c - code for example DNS program that uses udp */<br />#ifndef unix<br />#include <windows.h><br />#include <winsock.h><br />#include <io.h><br />#else<br />#define closesocket close<br />#include <sys/types.h><br />#include <sys/socket.h><br />#include <netinet/in.h><br />#include <arpa/inet.h><br />#include <netdb.h><br />#endif<br />#include <stdio.h><br />#include <string.h><br />#include <stdlib.h><br />#include <malloc.h><br />#define PROTOPORT       53            /* 53 is the default protocol port number which corresponds to 13568*/<br />char MyIP_4ClientSide[] = quot;
127.0.0.3quot;
;//127.0.0.1 corresponds to 16777343and     127.0.0.2 corresponds to 33554559<br />char OuterServerIP[] = quot;
8.8.4.4quot;
;//208.67.222.222 corresponds to 3739108304//208.67.220.220 corresponds to 3705422800<br />//8.8.8.8 corresponds to 134744072//8.8.4.4 correposnds to 67373064<br />char    response[512]={''};//512 is the exact value that must be for max size of a UDP message<br />struct  sockaddr_in SockAddrIn_ToOuterDNSServerSide, SockAddrIn_Used4ClientSide, SockAddrInFromOuterDNS;  /*IP, port, family*/<br />int     ClientSideSocket, OuterDNSServerSideSocket;              /* 2 socket descriptors, both of them correspond to this DNS server, i.e it's very true that both of them are for the same 1 system, but for technical reasons we'll only bind the client side */<br />//please note that SockAddrIn_GottenFromClient is a pointer in serverThread and a struct variable in main, Why one pointer and another variable? this is due to restriction in the function serverThread. Why SockAddrIn_GottenFromClient is not public? because ...<br />void serverThread(void* psd)<br />{<br />char *buf1= (char*)psd;<br />char *buf2= (char*)psd + 512;<br />struct  sockaddr_in *SockAddrIn_GottenFromClient =(struct sockaddr_in*) buf2;<br />char buf[512];<br />int i;<br />for (i=0;i<512;i++)<br />buf[i]=*(buf1+i);<br />int n;<br />int h = sizeof(struct sockaddr);<br />printf(quot;
Towards Sending to DNS with id: %d %dquot;
,buf[0],buf[1]);<br />n = sendto(OuterDNSServerSideSocket, buf, sizeof(buf), 0, (sockaddr *)&SockAddrIn_ToOuterDNSServerSide,h);<br />printf(quot;
Towards Receiving from DNS with id: %d %dquot;
,buf[0],buf[1]);<br />n = recvfrom(OuterDNSServerSideSocket, response, sizeof(response), 0, (sockaddr *)&SockAddrInFromOuterDNS,&h);//here the port is 13568=53*2^8<br />printf(quot;
Towards Replying back to app with id: %d %dquot;
,response[0],response[1]);<br />n = sendto(ClientSideSocket, response, sizeof(response), 0,(sockaddr *)SockAddrIn_GottenFromClient,h);//here the port could be 45780=178*2^8+212 and it changes always<br />printf(quot;
End of thread with id: %d %dquot;
,response[0],response[1]);<br />}<br />void main()<br />{<br />struct  sockaddr_in SockAddrIn_GottenFromClient;<br />        struct  hostent  *IPAddr_4ClientSide, *IPAddr_of_OuterDNSServer;/* pointer to a host table entry */<br />        struct  protoent *UDP_Protocol;  /* pointer to a protocol table entry   */<br />        int     port;            /* protocol port number                */<br />        char    *host, buf[512];           /* pointer to host name, not important */<br />        int     n,i,j;               /* number of characters read           */<br />#ifdef WIN32<br />        WSADATA wsaData;<br />        WSAStartup(0x0101, &wsaData);<br />#endif<br />//************************************We'll start now by working on the Outer DNS Server Side<br />//one other possible good name of SockAddrIn_ToOuterDNSServerSide is quot;
SockAddrIn_OfOuterDNSServerSidequot;
<br />memset((char *)&SockAddrIn_ToOuterDNSServerSide,0,sizeof(SockAddrIn_ToOuterDNSServerSide));/* clear client sockaddr structure */<br />        SockAddrIn_ToOuterDNSServerSide.sin_family = AF_INET;/* set family to Internet     */<br />        port = PROTOPORT;                              <br />        SockAddrIn_ToOuterDNSServerSide.sin_port = htons((u_short)port);/* set port number */<br />        host = OuterServerIP;<br />        <br />        /* Convert host name to equivalent IP address and copy to SockAddrIn_ToOuterDNSServerSide. */<br />        IPAddr_of_OuterDNSServer = gethostbyname(host); //actually here there should be an error handling in case of failure in the function gethostbyname....................<br />        memcpy(&SockAddrIn_ToOuterDNSServerSide.sin_addr, IPAddr_of_OuterDNSServer->h_addr, IPAddr_of_OuterDNSServer->h_length);<br />        /* Map UDP transport protocol name to protocol number. */<br />        if ( ((int)(UDP_Protocol = getprotobyname(quot;
udpquot;
))) == 0) <br />{<br />             fprintf(stderr, quot;
cannot map "
udp"
 to protocol numberquot;
);<br />             getchar();<br />             exit(1);<br />        }<br />        /* Create a socket. */<br />        OuterDNSServerSideSocket = socket(PF_INET, SOCK_DGRAM, UDP_Protocol->p_proto);<br />        if (OuterDNSServerSideSocket < 0) <br />{<br />                fprintf(stderr, quot;
socket creation failedquot;
);<br />                getchar();<br />                exit(1);<br />        }<br />//no binding is done for the Outer DNS Server side, it's automatic<br />//*********************************So, now we're done of the Outer DNS Server side<br />//################################# Now working on the Client side<br />/* Create a socket. */<br />        ClientSideSocket = socket(PF_INET, SOCK_DGRAM, UDP_Protocol->p_proto);<br />        if (ClientSideSocket < 0) <br />{<br />                fprintf(stderr, quot;
socket creation failedquot;
);<br />                getchar();<br />                exit(1);<br />        }<br />//now defining SockAddrIn_Used4ClientSide to use it in Binding only, and to let the Server realise for the Client the IP that I want as a client part<br />memset((char *)&SockAddrIn_Used4ClientSide,0,sizeof(SockAddrIn_Used4ClientSide));/* clear Client sockaddr structure */<br />        SockAddrIn_Used4ClientSide.sin_family = AF_INET;/* set family to Internet     */<br />//port=port+1;<br />SockAddrIn_Used4ClientSide.sin_port = htons((u_short)port);/* set port number */<br />//SockAddrIn_Used4ClientSide.sin_addr.s_addr = INADDR_ANY; //INADDR_ANY<br />IPAddr_4ClientSide = gethostbyname(MyIP_4ClientSide);<br />        if ( ((char *)IPAddr_4ClientSide) == NULL ) <br />{                <br />fprintf(stderr,quot;
invalid host: %squot;
, host);<br />            getchar();<br />            exit(1);<br />        }<br />        memcpy(&SockAddrIn_Used4ClientSide.sin_addr, IPAddr_4ClientSide->h_addr, IPAddr_4ClientSide->h_length);<br />        /* Bind a local address to the socket */<br />int hh=0;<br />hh=bind(ClientSideSocket, (struct sockaddr *)&SockAddrIn_Used4ClientSide, sizeof(SockAddrIn_Used4ClientSide));<br />//int __stdcall bind(SOCKET s, const sockaddr *addr, int namelen)<br />        if (hh < 0) <br />{<br />                fprintf(stderr,quot;
bind failedquot;
);<br />                exit(1);<br />        }<br />//################################### Done with the client side<br />        /* Repeatedly read data from socket and write to user's screen. */<br />int h = sizeof(struct sockaddr);<br />//receiving from client<br />int how_many_times=0;<br />while(1)<br />{ <br />for (i=0;i<512;i++)<br />buf[i]=0;<br />how_many_times++; char first_time[3]=quot;
stquot;
,other_times[3]=quot;
thquot;
;<br />printf(quot;
Towards receiving from app, with %d%s timequot;
,how_many_times,(how_many_times==1)?first_time:other_times);<br />n = recvfrom(ClientSideSocket, buf, sizeof(buf), 0, (sockaddr *)&SockAddrIn_GottenFromClient,&h);<br />//for the administrator of this DNS, we can let him see the IP address of the client<br />printf (quot;
A request has came with the following characteristics:Port number:%dquot;
,ntohs(SockAddrIn_GottenFromClient.sin_port));<br />printf (quot;
IP address: %squot;
,inet_ntoa(SockAddrIn_GottenFromClient.sin_addr));<br />char *buf1=(char*)malloc(512+sizeof(SockAddrIn_GottenFromClient)); //what is the free keyword???<br />for (j=0;j<512;j++)<br />*(buf1+j)=buf[j];<br />char *a= (char*)&SockAddrIn_GottenFromClient;<br />for (j=512;j<512+sizeof(SockAddrIn_GottenFromClient);j++)<br />*(buf1+j)= *(a +j-512);<br />long kk=(long)buf1;<br />printf(quot;
Now I received sth from app with the header id: %d %dquot;
,buf[0],buf[1]);<br />_beginthread(serverThread, 0, (void*)kk);<br />}<br />        /* Close the socket. */<br />        closesocket(OuterDNSServerSideSocket);<br />closesocket(ClientSideSocket);<br />        /* Terminate the client program gracefully. */<br />getchar();<br />        exit(0);<br />}<br />
Dns server clients (actual program)
Dns server clients (actual program)
Dns server clients (actual program)
Dns server clients (actual program)
Dns server clients (actual program)
Dns server clients (actual program)
Dns server clients (actual program)
Dns server clients (actual program)
Dns server clients (actual program)
Dns server clients (actual program)
Dns server clients (actual program)
Dns server clients (actual program)
Dns server clients (actual program)
Dns server clients (actual program)

More Related Content

What's hot

Rust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Rust: код может быть одновременно безопасным и быстрым, Степан КольцовRust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Rust: код может быть одновременно безопасным и быстрым, Степан КольцовYandex
 
C++ L03-Control Structure
C++ L03-Control StructureC++ L03-Control Structure
C++ L03-Control StructureMohammad Shaker
 
Implementing Software Machines in Go and C
Implementing Software Machines in Go and CImplementing Software Machines in Go and C
Implementing Software Machines in Go and CEleanor McHugh
 
C++ L02-Conversion+enum+Operators
C++ L02-Conversion+enum+OperatorsC++ L02-Conversion+enum+Operators
C++ L02-Conversion+enum+OperatorsMohammad Shaker
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...ssuserd6b1fd
 
Implementing Software Machines in C and Go
Implementing Software Machines in C and GoImplementing Software Machines in C and Go
Implementing Software Machines in C and GoEleanor McHugh
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5  b...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5  b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...ssuserd6b1fd
 
c++ program for Railway reservation
c++ program for Railway reservationc++ program for Railway reservation
c++ program for Railway reservationSwarup Kumar Boro
 

What's hot (20)

C++ L04-Array+String
C++ L04-Array+StringC++ L04-Array+String
C++ L04-Array+String
 
Binomial heap
Binomial heapBinomial heap
Binomial heap
 
Rust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Rust: код может быть одновременно безопасным и быстрым, Степан КольцовRust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Rust: код может быть одновременно безопасным и быстрым, Степан Кольцов
 
c programming
c programmingc programming
c programming
 
C++ L03-Control Structure
C++ L03-Control StructureC++ L03-Control Structure
C++ L03-Control Structure
 
Whispered secrets
Whispered secretsWhispered secrets
Whispered secrets
 
Good Code
Good CodeGood Code
Good Code
 
Implementing Software Machines in Go and C
Implementing Software Machines in Go and CImplementing Software Machines in Go and C
Implementing Software Machines in Go and C
 
Whispered secrets
Whispered secretsWhispered secrets
Whispered secrets
 
C++ L02-Conversion+enum+Operators
C++ L02-Conversion+enum+OperatorsC++ L02-Conversion+enum+Operators
C++ L02-Conversion+enum+Operators
 
c programming
c programmingc programming
c programming
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...
 
Implementing Software Machines in C and Go
Implementing Software Machines in C and GoImplementing Software Machines in C and Go
Implementing Software Machines in C and Go
 
C++ L06-Pointers
C++ L06-PointersC++ L06-Pointers
C++ L06-Pointers
 
Unit 3
Unit 3 Unit 3
Unit 3
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5  b...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5  b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
 
c++ program for Railway reservation
c++ program for Railway reservationc++ program for Railway reservation
c++ program for Railway reservation
 
Go a crash course
Go   a crash courseGo   a crash course
Go a crash course
 
01c shell
01c shell01c shell
01c shell
 
C++ L09-Classes Part2
C++ L09-Classes Part2C++ L09-Classes Part2
C++ L09-Classes Part2
 

Viewers also liked

Dns server clients (actual program)
Dns server clients (actual program)Dns server clients (actual program)
Dns server clients (actual program)Youssef Dirani
 
Qahol ayat 8
Qahol ayat 8Qahol ayat 8
Qahol ayat 8Miz Belle
 
GWAVACon 2013: Filr Pilot
GWAVACon 2013: Filr PilotGWAVACon 2013: Filr Pilot
GWAVACon 2013: Filr PilotGWAVA
 
Mt. Ephraim Technology Presentation 2-17-12
Mt. Ephraim Technology Presentation 2-17-12Mt. Ephraim Technology Presentation 2-17-12
Mt. Ephraim Technology Presentation 2-17-12brassmom
 
Buiilding a corruption free society
Buiilding a corruption free societyBuiilding a corruption free society
Buiilding a corruption free societyOnike Rahaman
 
Chapter 2-radar equation
Chapter 2-radar equationChapter 2-radar equation
Chapter 2-radar equationRima Assaf
 
Make an equivalent of 2 parallel coils
Make an equivalent of 2 parallel coilsMake an equivalent of 2 parallel coils
Make an equivalent of 2 parallel coilsYoussef Dirani
 
The Near Future of CSS
The Near Future of CSSThe Near Future of CSS
The Near Future of CSSRachel Andrew
 
Classroom Management Tips for Kids and Adolescents
Classroom Management Tips for Kids and AdolescentsClassroom Management Tips for Kids and Adolescents
Classroom Management Tips for Kids and AdolescentsShelly Sanchez Terrell
 
The Buyer's Journey - by Chris Lema
The Buyer's Journey - by Chris LemaThe Buyer's Journey - by Chris Lema
The Buyer's Journey - by Chris LemaChris Lema
 
The Presentation Come-Back Kid
The Presentation Come-Back KidThe Presentation Come-Back Kid
The Presentation Come-Back KidEthos3
 

Viewers also liked (14)

Dns server clients (actual program)
Dns server clients (actual program)Dns server clients (actual program)
Dns server clients (actual program)
 
Ch 16 and 18
Ch 16 and 18Ch 16 and 18
Ch 16 and 18
 
Qahol ayat 8
Qahol ayat 8Qahol ayat 8
Qahol ayat 8
 
GWAVACon 2013: Filr Pilot
GWAVACon 2013: Filr PilotGWAVACon 2013: Filr Pilot
GWAVACon 2013: Filr Pilot
 
Sigurniji internet
Sigurniji internet Sigurniji internet
Sigurniji internet
 
Mt. Ephraim Technology Presentation 2-17-12
Mt. Ephraim Technology Presentation 2-17-12Mt. Ephraim Technology Presentation 2-17-12
Mt. Ephraim Technology Presentation 2-17-12
 
Buiilding a corruption free society
Buiilding a corruption free societyBuiilding a corruption free society
Buiilding a corruption free society
 
Web services
Web servicesWeb services
Web services
 
Chapter 2-radar equation
Chapter 2-radar equationChapter 2-radar equation
Chapter 2-radar equation
 
Make an equivalent of 2 parallel coils
Make an equivalent of 2 parallel coilsMake an equivalent of 2 parallel coils
Make an equivalent of 2 parallel coils
 
The Near Future of CSS
The Near Future of CSSThe Near Future of CSS
The Near Future of CSS
 
Classroom Management Tips for Kids and Adolescents
Classroom Management Tips for Kids and AdolescentsClassroom Management Tips for Kids and Adolescents
Classroom Management Tips for Kids and Adolescents
 
The Buyer's Journey - by Chris Lema
The Buyer's Journey - by Chris LemaThe Buyer's Journey - by Chris Lema
The Buyer's Journey - by Chris Lema
 
The Presentation Come-Back Kid
The Presentation Come-Back KidThe Presentation Come-Back Kid
The Presentation Come-Back Kid
 

Similar to Dns server clients (actual program)

#include stdio.h#include systypes.h#include syssocket.h
#include stdio.h#include systypes.h#include syssocket.h#include stdio.h#include systypes.h#include syssocket.h
#include stdio.h#include systypes.h#include syssocket.hSilvaGraf83
 
#include stdio.h#include systypes.h#include syssocket.h
#include stdio.h#include systypes.h#include syssocket.h#include stdio.h#include systypes.h#include syssocket.h
#include stdio.h#include systypes.h#include syssocket.hMoseStaton39
 
Computer Networks Lab File
Computer Networks Lab FileComputer Networks Lab File
Computer Networks Lab FileKandarp Tiwari
 
Udp socket programming(Florian)
Udp socket programming(Florian)Udp socket programming(Florian)
Udp socket programming(Florian)Flor Ian
 
Socket Programming Intro.pptx
Socket  Programming Intro.pptxSocket  Programming Intro.pptx
Socket Programming Intro.pptxssuserc4a497
 
Lab Assignment 4 CSE330 Spring 2014 Skeleton Code for ex.docx
 Lab Assignment 4 CSE330 Spring 2014  Skeleton Code for ex.docx Lab Assignment 4 CSE330 Spring 2014  Skeleton Code for ex.docx
Lab Assignment 4 CSE330 Spring 2014 Skeleton Code for ex.docxMARRY7
 
proxyc CSAPP Web proxy NAME IMPORTANT Giv.pdf
  proxyc  CSAPP Web proxy   NAME    IMPORTANT Giv.pdf  proxyc  CSAPP Web proxy   NAME    IMPORTANT Giv.pdf
proxyc CSAPP Web proxy NAME IMPORTANT Giv.pdfajay1317
 
Multithreaded sockets c++11
Multithreaded sockets c++11Multithreaded sockets c++11
Multithreaded sockets c++11Russell Childs
 
Maker All - Executive Presentation
Maker All - Executive PresentationMaker All - Executive Presentation
Maker All - Executive PresentationDiogoFalcao
 
Shell to be modified#include stdlib.h #include unistd.h .pdf
Shell to be modified#include stdlib.h #include unistd.h .pdfShell to be modified#include stdlib.h #include unistd.h .pdf
Shell to be modified#include stdlib.h #include unistd.h .pdfclarityvision
 
Can you finish and write the int main for the code according to the in.pdf
Can you finish and write the int main for the code according to the in.pdfCan you finish and write the int main for the code according to the in.pdf
Can you finish and write the int main for the code according to the in.pdfaksachdevahosymills
 
tp socket en C.pdf
tp socket en C.pdftp socket en C.pdf
tp socket en C.pdfYoussefJamma
 

Similar to Dns server clients (actual program) (20)

#include stdio.h#include systypes.h#include syssocket.h
#include stdio.h#include systypes.h#include syssocket.h#include stdio.h#include systypes.h#include syssocket.h
#include stdio.h#include systypes.h#include syssocket.h
 
#include stdio.h#include systypes.h#include syssocket.h
#include stdio.h#include systypes.h#include syssocket.h#include stdio.h#include systypes.h#include syssocket.h
#include stdio.h#include systypes.h#include syssocket.h
 
Computer Networks Lab File
Computer Networks Lab FileComputer Networks Lab File
Computer Networks Lab File
 
Udp socket programming(Florian)
Udp socket programming(Florian)Udp socket programming(Florian)
Udp socket programming(Florian)
 
Socket Programming Intro.pptx
Socket  Programming Intro.pptxSocket  Programming Intro.pptx
Socket Programming Intro.pptx
 
Lab Assignment 4 CSE330 Spring 2014 Skeleton Code for ex.docx
 Lab Assignment 4 CSE330 Spring 2014  Skeleton Code for ex.docx Lab Assignment 4 CSE330 Spring 2014  Skeleton Code for ex.docx
Lab Assignment 4 CSE330 Spring 2014 Skeleton Code for ex.docx
 
Basic socket programming
Basic socket programmingBasic socket programming
Basic socket programming
 
Socket System Calls
Socket System CallsSocket System Calls
Socket System Calls
 
Sysprog17
Sysprog17Sysprog17
Sysprog17
 
proxyc CSAPP Web proxy NAME IMPORTANT Giv.pdf
  proxyc  CSAPP Web proxy   NAME    IMPORTANT Giv.pdf  proxyc  CSAPP Web proxy   NAME    IMPORTANT Giv.pdf
proxyc CSAPP Web proxy NAME IMPORTANT Giv.pdf
 
Socket programming in c
Socket programming in cSocket programming in c
Socket programming in c
 
Multithreaded sockets c++11
Multithreaded sockets c++11Multithreaded sockets c++11
Multithreaded sockets c++11
 
Maker All - Executive Presentation
Maker All - Executive PresentationMaker All - Executive Presentation
Maker All - Executive Presentation
 
part2
part2part2
part2
 
Shell to be modified#include stdlib.h #include unistd.h .pdf
Shell to be modified#include stdlib.h #include unistd.h .pdfShell to be modified#include stdlib.h #include unistd.h .pdf
Shell to be modified#include stdlib.h #include unistd.h .pdf
 
Can you finish and write the int main for the code according to the in.pdf
Can you finish and write the int main for the code according to the in.pdfCan you finish and write the int main for the code according to the in.pdf
Can you finish and write the int main for the code according to the in.pdf
 
sockets
socketssockets
sockets
 
About Go
About GoAbout Go
About Go
 
tp socket en C.pdf
tp socket en C.pdftp socket en C.pdf
tp socket en C.pdf
 
UDP.yash
UDP.yashUDP.yash
UDP.yash
 

Dns server clients (actual program)

  • 1. //2 codes, as presented to Dr. Amjad<br />//client side<br />#include quot; stdafx.hquot; <br />#ifndef unix<br />#define WIN32<br />#include <windows.h><br />#include <winsock.h><br />#include <io.h><br />#else<br />#define closesocket close<br />#include <sys/types.h><br />#include <sys/socket.h><br />#include <netinet/in.h><br />#include <arpa/inet.h><br />#include <netdb.h><br />#endif<br />#include <stdio.h><br />#include <string.h><br />#define PROTOPORT 53 /* default protocol port number */<br /> <br />char ServerIP[] = quot; 127.0.0.3quot; ;<br />void analyse_response(char* response);<br />void main() //here we will get what the user wants, then we will reformat what he typed in a useful DNS query<br />{<br /> struct hostent *IPAddrServer;/* pointer to a host table entry */<br /> struct protoent *UDP_Protocol; /* pointer to a protocol table entry */<br /> struct sockaddr_in SockAddrInToServer, SockAddrInFromServer; /*IP, port, family*/<br /> int ClientSocket; /* socket descriptor */<br /> int port; /* protocol port number */<br /> char *host; /* pointer to host name */<br /> int n,i; /* number of characters read */<br />char response[512]={''}; <br />char buf[512]={''},b1[255]; /* b1 buffer for data from the user. buf is the good reformatting for DNS usage *//*size of 'buf' and 'response' should be bigger than 512, as a max UDP message should*/<br />#ifdef WIN32<br /> WSADATA wsaData;<br /> WSAStartup(0x0101, &wsaData);<br />#endif<br /> memset((char *)&SockAddrInToServer,0,sizeof(SockAddrInToServer));/* clear client sockaddr structure */<br /> SockAddrInToServer.sin_family = AF_INET;/* set family to Internet */<br /> port = PROTOPORT; <br /> SockAddrInToServer.sin_port = htons((u_short)port);/* set port number */<br /> /* Convert host name to equivalent IP address and copy to SockAddrInToServer. */<br />host = ServerIP;<br /> IPAddrServer = gethostbyname(host);//now here comes a new worker thread...<br /> if ( ((char *)IPAddrServer) == NULL ) <br />{<br /> fprintf(stderr,quot; invalid host: %squot; , host);<br /> getchar();<br /> exit(1);<br /> }<br /> memcpy(&SockAddrInToServer.sin_addr, IPAddrServer->h_addr, IPAddrServer->h_length);<br /> /* Map UDP transport protocol name to protocol number. */<br /> if ( ((int)(UDP_Protocol = getprotobyname(quot; udpquot; ))) == 0) <br />{<br /> fprintf(stderr, quot; cannot map " udp" to protocol numberquot; );<br /> getchar();<br /> exit(1);<br /> }<br /> /* Create a socket. */<br /> ClientSocket = socket(PF_INET, SOCK_DGRAM, UDP_Protocol->p_proto);<br /> if (ClientSocket < 0) <br />{<br /> fprintf(stderr, quot; socket creation failedquot; );<br /> getchar();<br /> exit(1);<br /> }<br />printf(quot; You can start by requesting the DNS server.quot; );<br />char b2[255]; /* b2 is to get the hotmail, com, yahoo, mail, msn, ... from user input */<br />int j, k, t, l, firstpart;<br />char question[255]={''}; //so strlen(question)==0<br />int h = sizeof(struct sockaddr);<br />char header[255]={0,0,1,0,0,1,0,0,0,0,0,0}; //this is our desired header, but the last 0's won't be distinguished from the remaining of the of header, because all the remaining is also 0 or ''<br />unsigned short id_short = 0;<br />char *id;<br />id=(char*) &id_short;<br />int how_many_times = 0;<br />while(1)<br />{<br />how_many_times++;<br />printf(quot; your number %d request, please:quot; ,how_many_times);<br />for (i=0;i<255;i++) //this is for cleaning, we clean many arrays.<br />b1[i]=0;<br /> <br />scanf(quot; %squot; ,&b1); //assuming something like www.hotmail.com<br />//gets(b1); //also we can use gets<br />//The following is the reformatting of b1 in order to make a useful DNS query<br />//making the header<br />header[0] = *(id+1);<br />header[1] = *id;<br />//your header is made of 12 elements<br />//there you go your wonderful header<br />//now, making the Question<br />for (i=0; i<255; i++)<br />question[i] = 0;<br />for (i=0; i<255; i++)<br />b2[i] = 0;<br />i=0; j=0; k=0; t=0; l=0; firstpart=0;<br />while(i<strlen(b1)+1)<br />{if (0==strlen(b1) || b1[0]=='.') <br />break; <br />if (b1[i-1]=='.' && b1[i]!='.')<br />j=i;<br />if (b1[i]=='.' || b1[i]=='')<br />{<br />for(t=0; t<255; t++)<br />b2[t]=0; //not '0' <br />t=0;<br />for (k=j; k<i; k++)<br />{<br />b2[t]=b1[k];<br />t++;<br />}<br />question[strlen(question)]=t; //feeling safe that no truncated part like www or hotmail would be longer than 63! because the upper 2 bits of this specific byte must be 0's <br />strcat(question,b2);<br />}<br />i++;<br />}<br />if (strlen(question)>255) //the idea of this condition could be found in page 9 in RFC 1035<br />{<br />printf(quot; The name you entered must be smaller. You can retry. Thanksquot; );<br />break;<br />}<br />//of course there is the 'root' left, which is a null byte. simply the strlen(question) would be itself + 1 <br />//now let's add QType and QClass<br />question[strlen(question)+2]=1;<br />question[strlen(question)+4]=1;<br />//there you go your wonderful Question made of strlen(question) + 5 elements.<br />//now putting everything together in buf<br />for (i=0; i<12; i++)//10 is the lengh of the header<br />buf[i]=header[i];<br />for (i=12; i < (strlen(question)+17); i++)<br />buf[i]=question[i-12];<br />if (strlen(buf)>512) //the idea of this condition is from page 31 of RFC 1035<br />{<br />//in fact it's the whole UDP message and not only the entered name<br />printf(quot; The name you entered must be smaller. You can retry. Thanksquot; );<br />break;<br />}<br />n = sendto(ClientSocket, buf, sizeof(buf), 0,(sockaddr *)&SockAddrInToServer,h);<br />for (i=0; i<512; i++)<br />buf[i]=0;<br />for (i=0;i<512;i++)<br />response[i]=0;<br />n = recvfrom(ClientSocket, response, sizeof(response), 0, (sockaddr *)&SockAddrInFromServer,&h);<br />analyse_response(response);<br />id_short++;<br />//if (id_short==2^16-1)<br />}<br /> /* Close the socket. */<br /> closesocket(ClientSocket);<br /> /* Terminate the client program gracefully. */<br />getchar();<br /> exit(0);<br />}<br />void analyse_response(char* response)<br />{<br />char aa1 = response[0]; //we want to interchange the values of header id bytes. The final aim of this is to have a correct value of id_short<br />response[0] = response[1];<br />response[1]= aa1;<br />unsigned short *id_short;<br />id_short=(unsigned short*) response;<br />//we can get them back as before, but why bother.<br />printf(quot; The gathered info for your number %d request are the following:quot; ,*id_short + 1);//one limitation of using id_short is that user here tries more than (2^16 - 1) times, so the 2^16 th time would be 0 not 2^16. <br />if ((response[2]&2)==2) printf(quot; Message is truncated, so we're expecting a malicious resultquot; ); //we mean here: header->third byte->second bit<br />if ((response[3]&128)==0) printf(quot; Expecting a malicious result, since resursion was not availablequot; );<br />if ((response[3]&16)==16) printf(quot; Expecting a malicious result, since there was a format errorquot; );<br />if ((response[3]&32)==32) printf(quot; Server Failurequot; );//because of this case, you may create in the DNS server another socket for clients complains...<br />if ((response[3]&48)==48) printf(quot; Name errorquot; );<br />if ((response[3]&64)==64) printf(quot; Not Implementedquot; );<br />if ((response[3]&80)==80) printf(quot; Server refused to perform operationquot; );<br />unsigned short ANCOUNT = *(response + 7);<br />//now, determining the end of the question section <br />char a = 1;//here I want whatever value <br />int End_Of_Question = 12;<br />while (a!=0)<br />{<br />a = response[End_Of_Question];<br />End_Of_Question++;<br />}//now End_Of_Question is the first byte of QTYPE<br />End_Of_Question = End_Of_Question + 4;<br />//now End Of question section is reached, and End_Of_Question is the first byte in the Answer section<br />//now beginnig with the Answer section<br />int nameLengh = 0;<br />char *name = response + End_Of_Question; //quot; namequot; belongs to NAME, not to the question section <br />while(*(name + nameLengh)!=0)//no need to this loop, but no harm<br />nameLengh++;<br />// the 0 value of *(name + nameLengh) could have 2 meanings, it may belong to NAME (e.g in case no compression) or to TYPE (e.g in case of compression so we don't need a 0 in NAME because it would be mentionned in the QNAME, and from another hand the higher order byte of TYPE is 0 because values of TYPE goes from 1 to 16)<br />char *b = name; //b will pass over all the response <br />short count=0;<br />while (count < ANCOUNT)<br />{<br />count++;<br />char NAME_field[512]={''};<br />int ii=0;<br />for (ii=0;ii<512;ii++)//cleaning NAME_field<br />NAME_field[ii]=0;<br />int NAME_field_lengh = 0;<br />int name1Lengh;<br />while ( ((*b & 192) != 192) && (*b != 0) ) //in this loop: no compression. The condition (*b != 0) is not meant for the first time we enter the loop; it's meant if there was no pointer and the 0 exits explicitly in NAME. I don't know if the 0 _in case it appeared here_ could not belong to NAME.<br />{//192 in binary is 11000000<br />name1Lengh = 0;<br />while(name1Lengh<*b)<br />{<br />NAME_field[NAME_field_lengh + name1Lengh] = *(b + name1Lengh + 1);<br />name1Lengh++;<br />}<br />NAME_field_lengh = NAME_field_lengh + name1Lengh;<br />NAME_field[NAME_field_lengh]='.';<br />NAME_field_lengh++;<br />b = b + *b + 1;<br />}<br />//now in case we have a pointer<br />char *name1 = b;//this assigement in case there is a pointer inside a pointer (or more generally pointer inside a pointer inside a pointer inside ..., and for this general case we made name2)<br />while (((*name1 & 192) == 192) )<br />{<br />char ab[3];<br />ab[0] = *(name1 + 1);<br />ab[1] = *name1 & 63; //63 in binary is 00111111<br />unsigned short *pointer_value = (unsigned short*) ab;<br />//char * name2 = name1;<br />name1 = response + *pointer_value;<br />while((*name1)!=0 && (*name1 & 192)!=192) //the condition is for the case if inside one pointer there is another pointer to somewhere else<br />{<br />name1Lengh = 0;<br />while (name1Lengh < (*name1) )<br />{<br />NAME_field[NAME_field_lengh + name1Lengh] = *(name1 + name1Lengh + 1);<br />name1Lengh++;<br />}<br />name1 = name1 + *name1 + 1;<br />NAME_field_lengh = NAME_field_lengh + name1Lengh;<br />NAME_field[NAME_field_lengh]='.';<br />NAME_field_lengh++;<br />}<br />//name2 = name2 + 2;//this is not needed since we assume that after a pointer there is no useful info to add to NAME_field, and surely some more code should be added and we may use recursivity<br />}<br />if (name1 != b)//this means we entered the pointer loop<br />b = b + 2;<br />//now beginning with TYPE<br />//now *b = 0<br />if (*(b+1)==0)//means b is part of NAME and represents root<br />b=b+1;<br />//now b is part of TYPE<br />char TYPE[10]={''};<br />switch ( *(b+1) )<br />{<br /> case 1:<br /> TYPE[0]='A';<br /> break;<br /> case 2:<br /> TYPE[0]='N';TYPE[1]='S';<br /> break;<br /> case 3:<br /> TYPE[0]='M';TYPE[1]='D';<br /> break;<br /> case 4:<br /> TYPE[0]='M';TYPE[1]='F';<br /> break;<br /> case 5:<br /> TYPE[0]='C';TYPE[1]='N';TYPE[2]='A';TYPE[3]='M';TYPE[4]='E';<br /> break;<br /> case 6:<br /> TYPE[0]='S';TYPE[1]='O';TYPE[2]='A';<br /> break;<br /> case 7:<br /> TYPE[0]='M';TYPE[1]='B';<br /> break;<br /> case 8:<br /> TYPE[0]='M';TYPE[1]='G';<br /> break;<br /> case 9:<br /> TYPE[0]='M';TYPE[1]='R';<br /> break;<br /> case 10:<br /> TYPE[0]='N';TYPE[1]='U';TYPE[2]='L';TYPE[3]='L';<br /> break;<br /> case 11:<br /> TYPE[0]='W';TYPE[1]='K';TYPE[2]='S';<br /> break;<br /> case 12:<br /> TYPE[0]='P';TYPE[1]='T';TYPE[2]='R';<br /> break;<br /> case 13:<br /> TYPE[0]='H';TYPE[1]='I';TYPE[2]='N';TYPE[3]='F';TYPE[4]='O';<br /> break;<br /> case 14:<br /> TYPE[0]='M';TYPE[1]='I';TYPE[2]='N';TYPE[3]='F';TYPE[4]='O';<br /> break;<br /> case 15:<br /> TYPE[0]='M';TYPE[1]='X';<br /> break;<br /> case 16:<br /> TYPE[0]='T';TYPE[1]='X';TYPE[2]='T';<br /> break;<br />}<br />//now beginning with CLASS<br />b=b+3; //now b is the lower byte of CLASS<br />char CLASS[3]={''};<br />switch (*b)<br />{<br /> case 1:<br /> CLASS[0]='I';CLASS[1]='N';<br /> break;<br /> case 2:<br /> CLASS[0]='C';CLASS[1]='S';<br /> break;<br /> case 3:<br /> CLASS[0]='C';CLASS[1]='H';<br /> break;<br /> case 4:<br /> CLASS[0]='H';CLASS[1]='S';<br /> break;<br />}<br />//now TTL<br />b = b + 4;//now b is at the lower byte of TTL section<br />char aa2[6];<br />aa2[0] = *b & 255; aa2[1] = *(b-1) & 255; aa2[2] = *(b-2) & 255; aa2[3] = *(b-3) & 255;<br />unsigned int *TTL = (unsigned int*) aa2;<br />//now *TTL is the time<br />//now the RDLENGTH<br />int aa3[3];<br />b = b + 2;//now b is at the lower byte of RDLENGTH section<br />aa3[0] = *b; aa3[1] = *(b-1);<br />unsigned short *RDLENGTH = (unsigned short*) aa3;<br />//now *RDLENGTH is the length of the RDATA<br />//now the RDATA, it's so similar to Name, but it's good to use RDLENGTH as well, since we don't know if RDATA _in case it's explicit_ ends with 0 (root) or no!<br />b = b + 1;<br />char RDATA_field[512]={''};<br />for (ii=0;ii<512;ii++) //cleaning RDATA_field<br />RDATA_field[ii]=0;<br />short RDLENGTH_count = 0;<br />if ( TYPE[0]=='C' && TYPE[1]=='N' && TYPE[2]=='A' && TYPE[3]=='M' && TYPE[4]=='E')<br />{<br />int RDATA_field_lengh = 0;<br />int RDATA1Lengh;<br />while ( ((*b & 192) != 192) && (*b != 0) && (RDLENGTH_count < *RDLENGTH)) //in this loop: no compression. The condition (*b != 0) is not meant for the first time we enter the loop; it's meant if there was no pointer and the 0 exits explicitly in RDATA. I don't know if the 0 _in case it appeared here_ could not belong to RDATA.<br />{//192 in binary is 11000000<br />RDATA1Lengh = 0;<br />while(RDATA1Lengh<*b)<br />{<br />RDATA_field[RDATA_field_lengh + RDATA1Lengh] = *(b + RDATA1Lengh + 1);<br />RDATA1Lengh++;<br />}<br />RDLENGTH_count = RDLENGTH_count + *b + 1;<br />RDATA_field_lengh = RDATA_field_lengh + RDATA1Lengh;<br />RDATA_field[RDATA_field_lengh]='.';<br />RDATA_field_lengh++;<br />b = b + *b + 1;<br />}<br />//in case of a pointer<br />char *RDATA1 = b;<br />while ((*RDATA1 & 192) == 192 && (RDLENGTH_count < *RDLENGTH))//the second condition is very important, e.g. in case of a first attempt to enter and the pointer belonged to another RR<br />{<br />char ab[3];<br />ab[0] = *(RDATA1+1);<br />ab[1] = *RDATA1 & 63; //63 in binary is 00111111<br />unsigned short *pointer_value = (unsigned short*) ab;<br />RDATA1 = response + *pointer_value;<br />while(*RDATA1!=0 && (*RDATA1 & 192)!=192)//consider this non-handeled case: the pointer pointed to a another RDATA-section-explicit-text where it ends (but not with 0, nor with a pointer) with the logic of RDLENGTH<br />{<br />RDATA1Lengh = 0;<br />while ( RDATA1Lengh < (*RDATA1) )<br />{<br />RDATA_field[RDATA_field_lengh + RDATA1Lengh] = *(RDATA1 + RDATA1Lengh + 1);<br />RDATA1Lengh++;<br />}<br />RDATA1 = RDATA1 + *RDATA1 + 1;<br />RDATA_field_lengh = RDATA_field_lengh + RDATA1Lengh;<br />RDATA_field[RDATA_field_lengh]='.';<br />RDATA_field_lengh++;<br />}<br />RDLENGTH_count = RDLENGTH_count + 2;<br />} <br />if (RDATA1 != b)//this means we entered the pointer loop<br />b = b + 2;<br />if ( *b == 0 && (RDLENGTH_count == *RDLENGTH-1) )//for both previous cases<br />{<br />b = b + 1;<br />RDLENGTH_count = *RDLENGTH;<br />}<br />//the last '.' in RDATA_field in our program should be put, and there is no restriction for it except being entered only in the first loop and not the second, and (also) if RDLENGTH_count = *RDLENGTH<br />if ( (RDATA1 == b) && (RDLENGTH_count == *RDLENGTH) )<br />RDATA_field[RDATA_field_lengh-1]=0;<br />//now appearing this RR to the client<br />printf(quot; %s%s%s%d%squot; , NAME_field, TYPE, CLASS, *TTL, RDATA_field);<br />}<br />if (TYPE[0]=='A')<br />{<br />//it is supposed now that *b is 4, referring to the IP address<br />unsigned short ab1,ab2,ab3,ab4;<br />ab1=*b; ab2=*(b+1); ab3=*(b+2); ab4=*(b+3); //the format of the IP address is like ab1.ab2.ab3.ab4<br />b = b + 4;<br />//now appearing this RR to the client<br />printf(quot; %s%s%s%d%d.%d.%d.%dquot; , NAME_field, TYPE, CLASS, *TTL, ab1 & 255 , ab2 & 255 , ab3 & 255 , ab4 & 255 );<br />}<br />}<br />}<br />//server side<br />#include quot; stdafx.hquot; <br />#include <iostream><br />#include <process.h><br />/* server.c - code for example DNS program that uses udp */<br />#ifndef unix<br />#include <windows.h><br />#include <winsock.h><br />#include <io.h><br />#else<br />#define closesocket close<br />#include <sys/types.h><br />#include <sys/socket.h><br />#include <netinet/in.h><br />#include <arpa/inet.h><br />#include <netdb.h><br />#endif<br />#include <stdio.h><br />#include <string.h><br />#include <stdlib.h><br />#include <malloc.h><br />#define PROTOPORT 53 /* 53 is the default protocol port number which corresponds to 13568*/<br />char MyIP_4ClientSide[] = quot; 127.0.0.3quot; ;//127.0.0.1 corresponds to 16777343and 127.0.0.2 corresponds to 33554559<br />char OuterServerIP[] = quot; 8.8.4.4quot; ;//208.67.222.222 corresponds to 3739108304//208.67.220.220 corresponds to 3705422800<br />//8.8.8.8 corresponds to 134744072//8.8.4.4 correposnds to 67373064<br />char response[512]={''};//512 is the exact value that must be for max size of a UDP message<br />struct sockaddr_in SockAddrIn_ToOuterDNSServerSide, SockAddrIn_Used4ClientSide, SockAddrInFromOuterDNS; /*IP, port, family*/<br />int ClientSideSocket, OuterDNSServerSideSocket; /* 2 socket descriptors, both of them correspond to this DNS server, i.e it's very true that both of them are for the same 1 system, but for technical reasons we'll only bind the client side */<br />//please note that SockAddrIn_GottenFromClient is a pointer in serverThread and a struct variable in main, Why one pointer and another variable? this is due to restriction in the function serverThread. Why SockAddrIn_GottenFromClient is not public? because ...<br />void serverThread(void* psd)<br />{<br />char *buf1= (char*)psd;<br />char *buf2= (char*)psd + 512;<br />struct sockaddr_in *SockAddrIn_GottenFromClient =(struct sockaddr_in*) buf2;<br />char buf[512];<br />int i;<br />for (i=0;i<512;i++)<br />buf[i]=*(buf1+i);<br />int n;<br />int h = sizeof(struct sockaddr);<br />printf(quot; Towards Sending to DNS with id: %d %dquot; ,buf[0],buf[1]);<br />n = sendto(OuterDNSServerSideSocket, buf, sizeof(buf), 0, (sockaddr *)&SockAddrIn_ToOuterDNSServerSide,h);<br />printf(quot; Towards Receiving from DNS with id: %d %dquot; ,buf[0],buf[1]);<br />n = recvfrom(OuterDNSServerSideSocket, response, sizeof(response), 0, (sockaddr *)&SockAddrInFromOuterDNS,&h);//here the port is 13568=53*2^8<br />printf(quot; Towards Replying back to app with id: %d %dquot; ,response[0],response[1]);<br />n = sendto(ClientSideSocket, response, sizeof(response), 0,(sockaddr *)SockAddrIn_GottenFromClient,h);//here the port could be 45780=178*2^8+212 and it changes always<br />printf(quot; End of thread with id: %d %dquot; ,response[0],response[1]);<br />}<br />void main()<br />{<br />struct sockaddr_in SockAddrIn_GottenFromClient;<br /> struct hostent *IPAddr_4ClientSide, *IPAddr_of_OuterDNSServer;/* pointer to a host table entry */<br /> struct protoent *UDP_Protocol; /* pointer to a protocol table entry */<br /> int port; /* protocol port number */<br /> char *host, buf[512]; /* pointer to host name, not important */<br /> int n,i,j; /* number of characters read */<br />#ifdef WIN32<br /> WSADATA wsaData;<br /> WSAStartup(0x0101, &wsaData);<br />#endif<br />//************************************We'll start now by working on the Outer DNS Server Side<br />//one other possible good name of SockAddrIn_ToOuterDNSServerSide is quot; SockAddrIn_OfOuterDNSServerSidequot; <br />memset((char *)&SockAddrIn_ToOuterDNSServerSide,0,sizeof(SockAddrIn_ToOuterDNSServerSide));/* clear client sockaddr structure */<br /> SockAddrIn_ToOuterDNSServerSide.sin_family = AF_INET;/* set family to Internet */<br /> port = PROTOPORT; <br /> SockAddrIn_ToOuterDNSServerSide.sin_port = htons((u_short)port);/* set port number */<br /> host = OuterServerIP;<br /> <br /> /* Convert host name to equivalent IP address and copy to SockAddrIn_ToOuterDNSServerSide. */<br /> IPAddr_of_OuterDNSServer = gethostbyname(host); //actually here there should be an error handling in case of failure in the function gethostbyname....................<br /> memcpy(&SockAddrIn_ToOuterDNSServerSide.sin_addr, IPAddr_of_OuterDNSServer->h_addr, IPAddr_of_OuterDNSServer->h_length);<br /> /* Map UDP transport protocol name to protocol number. */<br /> if ( ((int)(UDP_Protocol = getprotobyname(quot; udpquot; ))) == 0) <br />{<br /> fprintf(stderr, quot; cannot map " udp" to protocol numberquot; );<br /> getchar();<br /> exit(1);<br /> }<br /> /* Create a socket. */<br /> OuterDNSServerSideSocket = socket(PF_INET, SOCK_DGRAM, UDP_Protocol->p_proto);<br /> if (OuterDNSServerSideSocket < 0) <br />{<br /> fprintf(stderr, quot; socket creation failedquot; );<br /> getchar();<br /> exit(1);<br /> }<br />//no binding is done for the Outer DNS Server side, it's automatic<br />//*********************************So, now we're done of the Outer DNS Server side<br />//################################# Now working on the Client side<br />/* Create a socket. */<br /> ClientSideSocket = socket(PF_INET, SOCK_DGRAM, UDP_Protocol->p_proto);<br /> if (ClientSideSocket < 0) <br />{<br /> fprintf(stderr, quot; socket creation failedquot; );<br /> getchar();<br /> exit(1);<br /> }<br />//now defining SockAddrIn_Used4ClientSide to use it in Binding only, and to let the Server realise for the Client the IP that I want as a client part<br />memset((char *)&SockAddrIn_Used4ClientSide,0,sizeof(SockAddrIn_Used4ClientSide));/* clear Client sockaddr structure */<br /> SockAddrIn_Used4ClientSide.sin_family = AF_INET;/* set family to Internet */<br />//port=port+1;<br />SockAddrIn_Used4ClientSide.sin_port = htons((u_short)port);/* set port number */<br />//SockAddrIn_Used4ClientSide.sin_addr.s_addr = INADDR_ANY; //INADDR_ANY<br />IPAddr_4ClientSide = gethostbyname(MyIP_4ClientSide);<br /> if ( ((char *)IPAddr_4ClientSide) == NULL ) <br />{ <br />fprintf(stderr,quot; invalid host: %squot; , host);<br /> getchar();<br /> exit(1);<br /> }<br /> memcpy(&SockAddrIn_Used4ClientSide.sin_addr, IPAddr_4ClientSide->h_addr, IPAddr_4ClientSide->h_length);<br /> /* Bind a local address to the socket */<br />int hh=0;<br />hh=bind(ClientSideSocket, (struct sockaddr *)&SockAddrIn_Used4ClientSide, sizeof(SockAddrIn_Used4ClientSide));<br />//int __stdcall bind(SOCKET s, const sockaddr *addr, int namelen)<br /> if (hh < 0) <br />{<br /> fprintf(stderr,quot; bind failedquot; );<br /> exit(1);<br /> }<br />//################################### Done with the client side<br /> /* Repeatedly read data from socket and write to user's screen. */<br />int h = sizeof(struct sockaddr);<br />//receiving from client<br />int how_many_times=0;<br />while(1)<br />{ <br />for (i=0;i<512;i++)<br />buf[i]=0;<br />how_many_times++; char first_time[3]=quot; stquot; ,other_times[3]=quot; thquot; ;<br />printf(quot; Towards receiving from app, with %d%s timequot; ,how_many_times,(how_many_times==1)?first_time:other_times);<br />n = recvfrom(ClientSideSocket, buf, sizeof(buf), 0, (sockaddr *)&SockAddrIn_GottenFromClient,&h);<br />//for the administrator of this DNS, we can let him see the IP address of the client<br />printf (quot; A request has came with the following characteristics:Port number:%dquot; ,ntohs(SockAddrIn_GottenFromClient.sin_port));<br />printf (quot; IP address: %squot; ,inet_ntoa(SockAddrIn_GottenFromClient.sin_addr));<br />char *buf1=(char*)malloc(512+sizeof(SockAddrIn_GottenFromClient)); //what is the free keyword???<br />for (j=0;j<512;j++)<br />*(buf1+j)=buf[j];<br />char *a= (char*)&SockAddrIn_GottenFromClient;<br />for (j=512;j<512+sizeof(SockAddrIn_GottenFromClient);j++)<br />*(buf1+j)= *(a +j-512);<br />long kk=(long)buf1;<br />printf(quot; Now I received sth from app with the header id: %d %dquot; ,buf[0],buf[1]);<br />_beginthread(serverThread, 0, (void*)kk);<br />}<br /> /* Close the socket. */<br /> closesocket(OuterDNSServerSideSocket);<br />closesocket(ClientSideSocket);<br /> /* Terminate the client program gracefully. */<br />getchar();<br /> exit(0);<br />}<br />