Tiny DNS Resolver
Dependencies: EthernetNetIf mbed
TinyResolver.cpp
00001 /* 00002 * mbed Tiny DNS Resolver 00003 * Copyright (c) 2011 Hiroshi Suga 00004 * Released under the MIT License: http://mbed.org/license/mit 00005 */ 00006 00007 /** @file 00008 * @brief Tiny DNS Resolver 00009 */ 00010 00011 #include "mbed.h" 00012 #include "EthernetNetIf.h" 00013 #include "UDPSocket.h" 00014 #include "TinyResolver.h" 00015 00016 // host to network short 00017 #define htons( x ) ( (( (x) << 8 ) & 0xFF00) | (( (x) >> 8 ) & 0x00FF) ) 00018 #define ntohs( x ) htons(x) 00019 // host to network long 00020 #define htonl( x ) ( (( (x) << 24 ) & 0xFF000000) \ 00021 | (( (x) << 8 ) & 0x00FF0000) \ 00022 | (( (x) >> 8 ) & 0x0000FF00) \ 00023 | (( (x) >> 24 ) & 0x000000FF) ) 00024 #define ntohl( x ) htonl(x) 00025 00026 extern EthernetNetIf eth; 00027 static UDPSocket *dns; 00028 static volatile unsigned long dnsaddr; 00029 static volatile unsigned long id; 00030 00031 int createDnsRequest (char *name, char *buf) { 00032 struct DnsHeader *dnsHeader; 00033 struct DnsQuestionEnd *dnsEnd; 00034 int len, num; 00035 00036 id ++; 00037 dnsHeader = (struct DnsHeader*)buf; 00038 dnsHeader->id = htons(id); 00039 dnsHeader->flags = htons(0x100); 00040 dnsHeader->questions = htons(1); 00041 dnsHeader->answers = 0; 00042 dnsHeader->authorities = 0; 00043 dnsHeader->additional = 0; 00044 00045 len = sizeof(struct DnsHeader); 00046 while ((num = (int)strchr(name, '.')) != NULL) { 00047 num = num - (int)name; 00048 buf[len] = num; 00049 len ++; 00050 strncpy(&buf[len], name, num); 00051 name = name + num + 1; 00052 len = len + num; 00053 } 00054 00055 if ((num = strlen(name)) != NULL) { 00056 buf[len] = num; 00057 len ++; 00058 strncpy(&buf[len], name, num); 00059 len = len + num; 00060 } 00061 buf[len] = 0; 00062 len ++; 00063 00064 dnsEnd = (struct DnsQuestionEnd *)&buf[len]; 00065 dnsEnd->type = htons(DNS_QUERY_A); 00066 dnsEnd->clas = htons(DNS_CLASS_IN); 00067 00068 return len + sizeof(struct DnsQuestionEnd); 00069 } 00070 00071 int getDnsResponse (const char *buf, int len, uint32_t *addr) { 00072 int i; 00073 struct DnsHeader *dnsHeader; 00074 struct DnsAnswer *dnsAnswer; 00075 00076 // header 00077 dnsHeader = (struct DnsHeader*)buf; 00078 if (ntohs(dnsHeader->id) != id || (ntohs(dnsHeader->flags) & 0x800f) != 0x8000) { 00079 return -1; 00080 } 00081 00082 // skip question 00083 for (i = sizeof(struct DnsHeader); buf[i] && i < len; i ++); 00084 i = i + 1 + sizeof(struct DnsQuestionEnd); 00085 00086 // answer 00087 while (i < len) { 00088 dnsAnswer = (struct DnsAnswer*)&buf[i]; 00089 00090 if (dnsAnswer->clas != htons(DNS_CLASS_IN)) { 00091 return -1; 00092 } 00093 00094 i = i + sizeof(struct DnsAnswer); 00095 if (dnsAnswer->type == htons(DNS_QUERY_A)) { 00096 // A record 00097 *addr = ((uint32_t)buf[i] << 24) + ((uint32_t)buf[i + 1] << 16) + ((uint32_t)buf[i + 2] << 8) + (uint32_t)buf[i + 3]; 00098 return 0; 00099 } 00100 // next answer 00101 i = i + dnsAnswer->length; 00102 } 00103 00104 return -1; 00105 } 00106 00107 void isr_dns (UDPSocketEvent e) { 00108 char buf[512]; 00109 Host dsthost; 00110 int len; 00111 00112 if (e == UDPSOCKET_READABLE) { 00113 // recv responce; 00114 len = dns->recvfrom(buf, sizeof(buf), &dsthost); 00115 #ifdef DEBUG 00116 for (int i = 0; i < len; i ++) { 00117 printf(" %02x", (unsigned char)buf[i]); 00118 } 00119 puts("\r"); 00120 #endif 00121 if (len >= sizeof(struct DnsHeader)) { 00122 getDnsResponse(buf, len, (uint32_t*)&dnsaddr); 00123 } 00124 } 00125 } 00126 00127 int getHostByName (IpAddr nameserver, const char *name, uint32_t *addr) { 00128 UDPSocketErr err; 00129 Host myhost, dnshost; 00130 char buf[100]; 00131 int i, len; 00132 00133 // localhost 00134 if (!strcmp(name, "localhost")) { 00135 *addr = 0x0f000001; 00136 return 0; 00137 } 00138 00139 dnsaddr = 0; 00140 dns = new UDPSocket; 00141 dns->setOnEvent(isr_dns); 00142 00143 // bind 00144 myhost.setIp(eth.getIp()); 00145 myhost.setPort(DNS_SRC_PORT); 00146 err = dns->bind(myhost); 00147 if (err != UDPSOCKET_OK) goto exit; 00148 00149 // send request 00150 dnshost.setIp(nameserver); 00151 dnshost.setPort(DNS_PORT); 00152 len = createDnsRequest((char*)name, buf); 00153 #ifdef DEBUG 00154 for (int i = 0; i < len; i ++) { 00155 printf(" %02x", (unsigned char)buf[i]); 00156 } 00157 puts("\r"); 00158 #endif 00159 dns->sendto(buf, len, &dnshost); 00160 00161 // wait responce 00162 for (i = 0; i < DNS_TIMEOUT / 10; i ++) { 00163 if (dnsaddr) { 00164 // responce 00165 *addr = dnsaddr; 00166 break; 00167 } 00168 if (i % 500 == 499) { 00169 // retry 00170 dns->sendto(buf, len, &dnshost); 00171 } 00172 Net::poll(); 00173 wait_ms(10); 00174 } 00175 00176 exit: 00177 dns->resetOnEvent(); 00178 delete dns; 00179 00180 return dnsaddr ? 0 : -1; 00181 }
Generated on Wed Jul 13 2022 09:29:18 by 1.7.2