Dns server clients (actual program)

474 views

Published on

  • Be the first to comment

  • Be the first to like this

Dns server clients (actual program)

  1. 1. //2 codes, as presented to Dr. Amjad<br />//client side<br />#include "stdafx.h"<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[] = "127.0.0.3";<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]={'0'}; <br />char buf[512]={'0'},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,"invalid host: %sn", 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("udp"))) == 0) <br />{<br /> fprintf(stderr, "cannot map "udp" to protocol number");<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, "socket creation failedn");<br /> getchar();<br /> exit(1);<br /> }<br />printf("You can start by requesting the DNS server.n");<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]={'0'}; //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 '0'<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("nyour number %d request, please:nt",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("%s",&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]=='0')<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("The name you entered must be smaller. You can retry. Thanks");<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("The name you entered must be smaller. You can retry. Thanks");<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("nThe gathered info for your number %d request are the following:n",*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("tMessage is truncated, so we're expecting a malicious resultn"); //we mean here: header->third byte->second bit<br />if ((response[3]&128)==0) printf("tExpecting a malicious result, since resursion was not availablen");<br />if ((response[3]&16)==16) printf("tExpecting a malicious result, since there was a format errorn");<br />if ((response[3]&32)==32) printf("tServer Failuren");//because of this case, you may create in the DNS server another socket for clients complains...<br />if ((response[3]&48)==48) printf("tName errorn");<br />if ((response[3]&64)==64) printf("tNot Implementedn");<br />if ((response[3]&80)==80) printf("tServer refused to perform operationn");<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; //"name" 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]={'0'};<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]={'0'};<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]={'0'};<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]={'0'};<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("%st%st%st%dt%snn", 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("%st%st%st%dt%d.%d.%d.%dnn", NAME_field, TYPE, CLASS, *TTL, ab1 & 255 , ab2 & 255 , ab3 & 255 , ab4 & 255 );<br />}<br />}<br />}<br />//server side<br />#include "stdafx.h"<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[] = "127.0.0.3";//127.0.0.1 corresponds to 16777343and 127.0.0.2 corresponds to 33554559<br />char OuterServerIP[] = "8.8.4.4";//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]={'0'};//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("Towards Sending to DNS with id: %d %dnn",buf[0],buf[1]);<br />n = sendto(OuterDNSServerSideSocket, buf, sizeof(buf), 0, (sockaddr *)&SockAddrIn_ToOuterDNSServerSide,h);<br />printf("Towards Receiving from DNS with id: %d %dnn",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("Towards Replying back to app with id: %d %dnn",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("End of thread with id: %d %dnn",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 "SockAddrIn_OfOuterDNSServerSide"<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("udp"))) == 0) <br />{<br /> fprintf(stderr, "cannot map "udp" to protocol number");<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, "socket creation failedn");<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, "socket creation failedn");<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,"invalid host: %sn", 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,"bind failedn");<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]="st",other_times[3]="th";<br />printf("Towards receiving from app, with %d%s timen",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 ("nA request has came with the following characteristics:ntPort number:%dn",ntohs(SockAddrIn_GottenFromClient.sin_port));<br />printf ("tIP address: %sn",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("Now I received sth from app with the header id: %d %dnn",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 />

×