基于单片机C语言的TCP/IP协议程序

源代码在线查看: dns.c

软件大小: 364 K
上传用户: flyhack007
关键词: TCP IP 单片机 C语言
下载地址: 免注册下载 普通下载 VIP

相关代码

				/**				 * DNS Resolution Code				 * @author Craig Graham				 * @date 07/11/2001				 * @file dns.c				 */								#include 				#include 				#include 				#include         /* for AF_INET */				#include 				#include 				#include 								#include "dns.h"								#define DNS_MAX_RETRY 5				#define DNS_CACHE_MAX 10								#define DNS_DEBUG 1								/** DNS lookup cache (used to avoid doing lookups for every connection) */				static DNS_CACHE cache[DNS_CACHE_MAX];				/** Index of next DNS cache slot to use */				static int cachePtr=0;				/** Query ID */				static unsigned short queryId=0x1234;								/**				 * Build up a DNS query packet header				 */				void dns_makeHeader(unsigned char packet[],DNS_OPCODE opcode)				{					unsigned short flags;					flags=(opcode									packet[0]=(queryId>>8)&0xff;					packet[1]=(queryId)&0xff;					packet[2]=(flags>>8)&0xff;					packet[3]=flags&0xff;					packet[4]=0; // questions count MSB					packet[5]=1; // questions count LSB					packet[6]=0; // answers count MSB					packet[7]=0; // answers count LSB					packet[8]=0; // authority count MSB					packet[9]=0; // authority count LSB					packet[10]=0; // additional count MSB					packet[11]=0; // additional count LSB					queryId++;				}								/**				 * Decode a DNS response packet header				 */				static void dns_decodeHeader(unsigned char packet[], DNS_HEADER *h)				{					h->id=(packet[0]					h->flags=(packet[2]					h->questionCount=(packet[4]					h->answerCount=(packet[6]					h->authorityCount=(packet[8]					h->additionalCount=(packet[10]				}								static char *encodeDotted(const char *name,char *output)				{					int l;					const char *startSegment;					while(*name)					{						l=0;						for(startSegment=name; (*name)&&(*name!='.'); name++)						{							l++;							output[l]=*name;						}						*output++=l;						output+=l;						if(*name)							name++;					}					*output++='\0';					return output;				}								static char *decodeDotted(char *packet, char *input, char *output)				{					int segLen;					unsigned short offset;					char *rtn=NULL;									while(1)					{						while((*input&(0xC0))==0xC0)						{							offset=((input[0]&~0xc0)							if(rtn==NULL)								rtn=&input[2];							input=&packet[offset];						}										segLen=*input++;						while(segLen--)							*output++=*input++;						if(!*input)							break;						*output++='.';					}					*output='\0';					return (rtn)?rtn:++input;				}								static int dns_sendQuery(DNS_CONTEXT *c)				{					unsigned char packet[1024],*p;					unsigned long l,pl;					struct sockaddr_in ns;					int ret;									pl=l=strlen(c->name);									dns_makeHeader(packet,DNS_QUERY);					p=encodeDotted(c->name,&packet[12]);					*p++=(DNS_T_A>>8); *p++=DNS_T_A&0xff; //type = host address query					*p++=0; *p++=1;	//class 1 - internet address									pl=((unsigned long)p)-(unsigned long)packet;									c->s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);					if(c->s					{				#if DNS_DEBUG						printf("dns_sendQuery: cann't create socket\n");				#endif						return -1;					}					memset(&ns, 0 , sizeof(ns)) ;					ns.sin_family = AF_INET ;	/* Using TCP/IP protocol */					ns.sin_port = htons(53) ;	/* converts to network short */					memcpy(&ns.sin_addr, c->ns, 4) ;									if (connect (c->s, (struct sockaddr *)&ns, sizeof(ns)) != 0)					{				#if DNS_DEBUG						printf("dns_sendQuery: cann't connect to socket\n");				#endif						return -2;					}									ret=write(c->s,packet,pl);					if(ret!=pl)					{				#if DNS_DEBUG						printf("dns_sendQuery: write failled\n");				#endif						close(c->s);						return -3;					}					return 0;				}								#if DNS_DEBUG				char recursionIndicator[100];				int recursionIndicatorI=0;				void incR(void)				{					recursionIndicator[recursionIndicatorI++]='|';					recursionIndicator[recursionIndicatorI++]=' ';					recursionIndicator[recursionIndicatorI]='\0';				}				void decR(void)				{					recursionIndicatorI-=2;					recursionIndicator[recursionIndicatorI]='\0';				}				#else				#define incR()				#define decR()				#endif								static int dns_getResponse(DNS_CONTEXT *c)				{					unsigned char packet[1024];					unsigned char name[1024],*p,*aS;					DNS_HEADER h;					int ret,cnt,gotAddress=0;					unsigned short qClass,aClass,aLength;					DNS_T_TYPE qType,aType;					unsigned long aTTL;					unsigned char aAddress[4];					struct timeval timeout;					fd_set readFds;					int retryCount=0;									timeout.tv_sec=2;					timeout.tv_usec=0;									while(!gotAddress)					{				__retry:						FD_ZERO(&readFds);						FD_SET(c->s,&readFds);						ret=select(c->s+1,&readFds,NULL,NULL, &timeout);						if(ret						{							// timeout or error, retry...				#if DNS_DEBUG							if(ret)								printf("%serror, retry\n",recursionIndicator);							else								printf("%stimeout, retry\n",recursionIndicator);				#endif							close(c->s);							retryCount++;							if(retryCount==DNS_MAX_RETRY)								return -4;											ret=dns_sendQuery(c);							if(ret)								return ret;							continue;						}										ret=read(c->s,packet,1024);						close(c->s);										if(ret>=12)						{							dns_decodeHeader(packet,&h);				#if DNS_DEBUG							printf("%sgot response from ns %d.%d.%d.%d : \n",recursionIndicator,c->ns[0],c->ns[1],c->ns[2],c->ns[3]);							printf("%s questionCount=%d\n",recursionIndicator,h.questionCount);							printf("%s answerCount=%d\n",recursionIndicator,h.answerCount);							printf("%s authorityCount=%d\n",recursionIndicator,h.authorityCount);				#endif							p=&packet[sizeof(DNS_HEADER)];							// process query section of packet							for(cnt=h.questionCount; cnt; cnt--)							{								p=decodeDotted(packet,p, name);								qType=(p[0]								qClass=(p[2]								p+=4;				#if DNS_DEBUG								printf("%squestion = \"%s\" type=%x class=%x\n",recursionIndicator,name,qType,qClass);				#endif							}							// process answer section of packet							aS=p;							for(cnt=h.answerCount; cnt; cnt--)							{								p=decodeDotted(packet, p, name);								aType=(p[0]								aClass=(p[2]								aTTL=(p[4]								aLength=(p[8]								if(aType==DNS_T_A)								{									// we've got an address, so we can return here....									c->addr[0]=p[10];									c->addr[1]=p[11];									c->addr[2]=p[12];									c->addr[3]=p[13];				#if DNS_DEBUG									printf("%sanswer: \"%s\" type=%x class=%x TTL=%lx address=%d.%d.%d.%d\n",recursionIndicator,												name,aType,aClass,aTTL,c->addr[0],c->addr[1],c->addr[2],c->addr[3]);				#endif									return 0;								}				#if DNS_DEBUG								printf("%sanswer: \"%s\" type=%x class=%x TTL=%lx\n",recursionIndicator,name,aType,aClass,aTTL);				#endif								p+=10+aLength;							}											// process authority section of packet							for(cnt=h.authorityCount; cnt; cnt--)							{								p=decodeDotted(packet, p, name);								aType=(p[0]								aClass=(p[2]								aTTL=(p[4]								aLength=(p[8]								p+=10;				#if DNS_DEBUG								printf("%sauthority: \"%s\" type=%x class=%x TTL=%lx\n",recursionIndicator,name,aType,aClass,aTTL);				#endif								if(aType==DNS_T_NS)								{									// Try to resolve authoritive nameserver for this address....									struct hostent *authoritiveServer;													p=decodeDotted(packet, p, name);				#if DNS_DEBUG									printf("%s           nameServer=\"%s\"\n",recursionIndicator,name);				#endif									if(strcmp(name,c->name))									{										authoritiveServer=gethostbyname(name);										if(authoritiveServer)										{											// we found the authoritive server, re-target our original request at the authoritive nameserver..											memcpy(c->ns,authoritiveServer->h_addr_list[0],4);				#if DNS_DEBUG											printf("%s!!!! trying authoritive server %s\n",recursionIndicator,name);				#endif											incR();											ret=dns_sendQuery(c);											if(!ret)											{												ret=dns_getResponse(c);												decR();												if(!ret)													return 0;				#if DNS_DEBUG												printf("%s!!!! server %s didn't respond :(\n",recursionIndicator,name);				#endif											}else{												decR();				#if DNS_DEBUG												printf("%s!!!! couldn't contact server %s :(\n",recursionIndicator,name);				#endif											}										}									}								}							}						}										ret=dns_sendQuery(c);						if(ret)							return ret;					}					return 0;				}								char nameserver[4]={195,184,228,6};								void setNameServer(const char *ns1, const char *ns2)				{					UI32 a=ntohl(inet_addr(ns1));					memcpy(nameserver,&a,4);				}								struct hostent *addCacheEntry(DNS_CONTEXT *c)				{					struct hostent *rtn;									// got a response, cache it and return the cache entry...					printf("dns lookup, got address for %s, caching in slot %d\n",c->name,cachePtr);					if(cache[cachePtr].name)						free(cache[cachePtr].name);					memcpy(&cache[cachePtr].in, c->addr, sizeof(cache[cachePtr].in));					cache[cachePtr].name=strdup(c->name);					cache[cachePtr].h.h_name = cache[cachePtr].name;					cache[cachePtr].h.h_addrtype = AF_INET;					cache[cachePtr].h.h_length = sizeof(cache[cachePtr].in);					cache[cachePtr].h.h_addr_list = (char **) cache[cachePtr].addr_list;					cache[cachePtr].addr_list[0]=&cache[cachePtr].in;					cache[cachePtr].addr_list[1]=NULL;					rtn=&cache[cachePtr].h;					if(++cachePtr==DNS_CACHE_MAX)						cachePtr=0;					return rtn;				}								struct hostent *getHostFromCache(const char *name)				{					int i;					// do dns cache lookup...					for(i=0; i					{						if((cache[i].name)&&(!strcmp(name,cache[i].name)))						{							printf("getHostFromCache(%s): got cached address in slot %d\n",name,i);							return &cache[i].h;						}					}					return NULL;				}								struct hostent *gethostbyaddr(const char *addr, int len, int type)				{					DNS_CONTEXT c;					if(inet_aton(addr,(struct in_addr*)&c.addr))					{						c.name=addr;						return addCacheEntry(&c);					}					return NULL;				}								struct hostent *gethostbyname(const char *name)				{					DNS_CONTEXT c;					int ret;					struct hostent *h;								#if DNS_DEBUG					printf("gethostbyname(%s)\n",name);				#endif									// try for cached address from a previous lookup...					h=getHostFromCache(name);					if(h)						return h;									// not a totally valid thing to do here, but we check for numeric address's					// here anyway...(makes higher level code simpler)					h=gethostbyaddr(name,4,1);					if(h)						return h;									// ok, it's not a numeric address and it's not in the DNS cache,					// so we'll have to do a proper DNS lookup...					c.name=name;					c.ns[0]=nameserver[0];					c.ns[1]=nameserver[1];					c.ns[2]=nameserver[2];					c.ns[3]=nameserver[3];									ret=dns_sendQuery(&c);					if(ret						return NULL;									ret=dns_getResponse(&c);					if(ret==0)					{						return addCacheEntry(&c);					}									return NULL;				}								void dns_init(void)				{					int i;				#if DNS_DEBUG					recursionIndicator[0]='\0';					recursionIndicatorI=0;				#endif					printf("dns_init()\n");					for(i=0; i					{						cache[i].name=NULL;					}				}											

相关资源