00001
00002 #include <mem.h>
00003 #include <string.h>
00004 #include <stdio.h>
00005 #include <ctype.h>
00006
00007 #include "clib/tcpip.h"
00008 #include "inet/dns.h"
00009
00010
00011
00012
00013 #define DNS_PORT 53 // Well known DNS port
00014
00015
00016 static unsigned int ident;
00017
00018 #define BUFSIZE 600
00019
00020 #define RRBUF 200
00021
00022 typedef struct dn_rr_struct {
00023 char rrname[RRBUF];
00024 unsigned int rrtype;
00025 unsigned int rrclass;
00026 unsigned long rrttl;
00027 char rrrdata[RRBUF];
00028 } dn_rr;
00029
00030
00031 #define DN_TYPE_A 1
00032 #define DN_TYPE_NS 2
00033 #define DN_TYPE_CNAME 5
00034 #define DN_TYPE_MX 15
00035
00036
00037 #define DN_CLASS_IN 1
00038
00039
00040 #ifdef MONITOR
00041
00042 void packetmonitor(int len2, char *buffer)
00043 {
00044 int j,i,k;
00045
00046 j=0;
00047 for(i=0;i<len2;i++)
00048 {
00049 if(j==0)
00050 {
00051 printf("\n\r%3X ",i);
00052 }
00053 printf("%02X ",buffer[i]&0xff);
00054 j++;
00055 if(j==16)
00056 {
00057 for(k=0;k<j;k++)
00058 {
00059 if(isprint(buffer[i-j+k+1]&0xff))
00060 printf("%c",buffer[i-j+k+1]&0xff);
00061 else
00062 printf(".");
00063 }
00064 j=0;
00065 }
00066 }
00067 i--;
00068 for(k=0;k<j;k++)
00069 {
00070 if(isprint(buffer[i-j+k+1]&0xff))
00071 printf("%c",buffer[i-j+k+1]&0xff);
00072 else
00073 printf(".");
00074 }
00075 j=0;
00076 }
00077 #endif
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 int dn_uncompress(char *dest, int len, char *packet, char *name)
00089 {
00090 int nlen, nlenok;
00091 unsigned int u;
00092
00093
00094 *dest= 0;
00095 nlen=nlenok= 0;
00096 while(*name) {
00097 if((*name&0xc0) == 0xc0) {
00098 u= ((*name&0x3f)<<8) + (*(name+1));
00099 if(packet+u > name)
00100 return -1;
00101 name=packet+u;
00102 if(nlenok == 0) {
00103 nlen+= 2;
00104 nlenok= 1;
00105 }
00106 }
00107 else {
00108 if(*name > (len-2))
00109 return -1;
00110 len-= *name;
00111 strncat(dest,name+1,*name);
00112 if(nlenok == 0) {
00113 nlen+=*name+1;
00114 }
00115 name+= *name+1;
00116 if(*name) {
00117 len--;
00118 strcat(dest,".");
00119 }
00120 }
00121 }
00122 if(nlenok == 0)
00123 nlen++;
00124 return nlen;
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 int dn_unpackrr(dn_rr *rr, char *packet, char *message)
00136 {
00137 int i;
00138 unsigned int u;
00139
00140 if((i=dn_uncompress(rr->rrname,RRBUF,packet,message)) == -1)
00141 return -1;
00142 message+=i;
00143 rr->rrtype= ((*message)<<8) + (*(message+1));
00144 message+=2;
00145 rr->rrclass= ((*message)<<8) + (*(message+1));
00146 message+=2;
00147 rr->rrttl=((*message)<<24)&0xff000000L;
00148 rr->rrttl+=((*(message+1))<<16)&0xff0000L;
00149 rr->rrttl+=((*(message+2))<<8)&0xff00;
00150 rr->rrttl+=((*(message+3)))&0xff;
00151 message+=4;
00152 u= ((*message)<<8) + (*(message+1));
00153 message+=2;
00154 switch(rr->rrtype) {
00155 case DN_TYPE_CNAME:
00156 case DN_TYPE_NS:
00157 if(dn_uncompress(rr->rrrdata,RRBUF,packet,message) == -1)
00158 return -1;
00159 break;
00160
00161 case DN_TYPE_MX: *(rr->rrrdata)=*message;
00162 *(rr->rrrdata+1)=*(message+1);
00163 message+=2;
00164 if(dn_uncompress(rr->rrrdata+2,RRBUF-2,packet,message) == -1)
00165 return -1;
00166 break;
00167
00168 case DN_TYPE_A: if(rr->rrclass == DN_CLASS_IN) {
00169 *(rr->rrrdata)=*message;
00170 *(rr->rrrdata+1)=*(message+1);
00171 *(rr->rrrdata+2)=*(message+2);
00172 *(rr->rrrdata+3)=*(message+3);
00173 *(rr->rrrdata+4)=0;
00174 }
00175 else
00176 return -2;
00177 break;
00178 default: *(rr->rrrdata)=0;
00179 }
00180 return u+i+10;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 static int packdomain(char * dest, const char *src)
00190 {
00191 int i,n,cnt;
00192
00193 n=strlen(src);
00194 dest[n+1]=0;
00195
00196 cnt=0;
00197 for (i=n; i>0; i--)
00198 {
00199 if (src[i-1]=='.')
00200 {
00201 dest[i]=cnt;
00202 cnt=0;
00203 }
00204 else
00205 {
00206 dest[i]=src[i-1];
00207 cnt++;
00208 }
00209 }
00210 dest[0]=cnt;
00211 return n+2;
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 int gethostbyname( const char *dnsServerIP,
00227 const char *domainName,
00228 unsigned long *ttl,
00229 unsigned long *IP,
00230 char *dest)
00231 {
00232 unsigned char buffer[BUFSIZE+1];
00233 int sd,error;
00234 struct sockaddr_in addr;
00235 int i,j,k,len1,len2,nRR;
00236
00237 dn_rr myrr;
00238
00239 #ifdef TRACE
00240 char s[200];
00241 printf("\r\ndns server: %s Host: %s\r\n",dnsServerIP,domainName);
00242 #endif
00243
00244 setmem(buffer,BUFSIZE,0);
00245
00246
00247 if (++ident>126) ident=1;
00248 buffer[0]=(ident>>8);
00249 buffer[1]=(ident&0xff);
00250
00251 buffer[2]=1;
00252 buffer[3]=0;
00253
00254 buffer[4]=0;
00255 buffer[5]=1;
00256
00257 len1=12;
00258 len1+=packdomain((char *)&buffer[12],domainName);
00259 buffer[len1++]=0; buffer[len1++]=1;
00260 buffer[len1++]=0; buffer[len1++]=1;
00261
00262 #ifdef TRACE
00263 printf("Request holds %d bytes\r\n",len1);
00264 for (i=0; i<len1; i++) printf(" %X",buffer[i]&0x00ff);
00265 #endif
00266
00267 sd=opensocket(SOCK_DGRAM,&error);
00268 if (sd==API_ERROR) {
00269 printf("\r\nError %d opening socket\r\n",error);
00270 return 0;
00271 }
00272
00273 addr.sin_family = AF_INET;
00274 if(inet_addr((char *)dnsServerIP, &addr.sin_addr.s_addr)) {
00275 printf("\r\nError converting DNS Server address %s \r\n",dnsServerIP);
00276 printf("\r\nIP %lX",addr.sin_addr.s_addr);
00277 return 0;
00278 }
00279 addr.sin_port=htons(DNS_PORT);
00280
00281 if ( API_ERROR==sendto(sd, (char *)buffer, len1, MSG_BLOCKING, (const struct sockaddr * )&addr, &error))
00282 {
00283 printf("\r\nError %d sending data in line %d\r\n",error,__LINE__);
00284 closesocket(sd,&error);
00285 return 0;
00286 }
00287
00288 api_sleep(100);
00289
00290 len2=recvfrom(sd, (char *)buffer, BUFSIZE, MSG_TIMEOUT, 10000,(struct sockaddr *)&addr,&error);
00291 closesocket(sd,&error);
00292 if (len2<=len1)
00293 {
00294 printf("\r\nError %d receiving data\r\n",error);
00295 return 0;
00296 }
00297
00298 #ifdef MONITOR
00299 packetmonitor(len2, buffer);
00300 #endif
00301 #ifdef TRACE
00302 printf("\r\nReceived %d bytes\r\n",len2);
00303 printf("Header:");
00304 for (i=0; i<12; i++)
00305 printf(" %X",buffer[i]&0xff);
00306 printf("\r\n");
00307 #endif
00308
00309
00310
00311
00312 nRR=buffer[6];
00313 nRR=(nRR<<8)+buffer[7];
00314 #ifdef TRACE
00315 printf("\r\nGot %d answers",nRR);
00316 #endif
00317
00318
00319 i=len1;
00320
00321 k=1;
00322 while(nRR--) {
00323
00324 if((j=dn_unpackrr(&myrr, (char *)buffer,(char *)&buffer[i])) == -1) {
00325 printf("\r\nError in answer section from DNS-server");
00326 return 0;
00327 }
00328 #ifdef TRACE
00329 printf("\r\nA%i: name=%s type=%i class=%i ttl=%lu",k++,myrr.rrname,myrr.rrtype, myrr.rrclass, myrr.rrttl);
00330 if(myrr.rrtype == DN_TYPE_CNAME)
00331 printf(" cname=%s",myrr.rrrdata);
00332 #endif
00333 if(myrr.rrtype == DN_TYPE_A && myrr.rrclass == DN_CLASS_IN) {
00334 k= -1;
00335 break;
00336 }
00337 i+=j;
00338 }
00339 if (k != -1) {
00340 return 0;
00341 }
00342 memcpy((void *)IP,(void *)myrr.rrrdata,4);
00343 *ttl=myrr.rrttl;
00344 InetToAscii(IP,dest);
00345 return 1;
00346 }