Tiny DNS Resolver
Dependencies: EthernetNetIf mbed
Revision 0:477d4e2f281a, committed 2011-07-21
- Comitter:
- okini3939
- Date:
- Thu Jul 21 16:53:11 2011 +0000
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EthernetNetIf.lib Thu Jul 21 16:53:11 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/donatien/code/EthernetNetIf/#bc7df6da7589
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TinyResolver.cpp Thu Jul 21 16:53:11 2011 +0000 @@ -0,0 +1,181 @@ +/* + * mbed Tiny DNS Resolver + * Copyright (c) 2011 Hiroshi Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +/** @file + * @brief Tiny DNS Resolver + */ + +#include "mbed.h" +#include "EthernetNetIf.h" +#include "UDPSocket.h" +#include "TinyResolver.h" + +// host to network short +#define htons( x ) ( (( (x) << 8 ) & 0xFF00) | (( (x) >> 8 ) & 0x00FF) ) +#define ntohs( x ) htons(x) +// host to network long +#define htonl( x ) ( (( (x) << 24 ) & 0xFF000000) \ + | (( (x) << 8 ) & 0x00FF0000) \ + | (( (x) >> 8 ) & 0x0000FF00) \ + | (( (x) >> 24 ) & 0x000000FF) ) +#define ntohl( x ) htonl(x) + +extern EthernetNetIf eth; +static UDPSocket *dns; +static volatile unsigned long dnsaddr; +static volatile unsigned long id; + +int createDnsRequest (char *name, char *buf) { + struct DnsHeader *dnsHeader; + struct DnsQuestionEnd *dnsEnd; + int len, num; + + id ++; + dnsHeader = (struct DnsHeader*)buf; + dnsHeader->id = htons(id); + dnsHeader->flags = htons(0x100); + dnsHeader->questions = htons(1); + dnsHeader->answers = 0; + dnsHeader->authorities = 0; + dnsHeader->additional = 0; + + len = sizeof(struct DnsHeader); + while ((num = (int)strchr(name, '.')) != NULL) { + num = num - (int)name; + buf[len] = num; + len ++; + strncpy(&buf[len], name, num); + name = name + num + 1; + len = len + num; + } + + if ((num = strlen(name)) != NULL) { + buf[len] = num; + len ++; + strncpy(&buf[len], name, num); + len = len + num; + } + buf[len] = 0; + len ++; + + dnsEnd = (struct DnsQuestionEnd *)&buf[len]; + dnsEnd->type = htons(DNS_QUERY_A); + dnsEnd->clas = htons(DNS_CLASS_IN); + + return len + sizeof(struct DnsQuestionEnd); +} + +int getDnsResponse (const char *buf, int len, uint32_t *addr) { + int i; + struct DnsHeader *dnsHeader; + struct DnsAnswer *dnsAnswer; + + // header + dnsHeader = (struct DnsHeader*)buf; + if (ntohs(dnsHeader->id) != id || (ntohs(dnsHeader->flags) & 0x800f) != 0x8000) { + return -1; + } + + // skip question + for (i = sizeof(struct DnsHeader); buf[i] && i < len; i ++); + i = i + 1 + sizeof(struct DnsQuestionEnd); + + // answer + while (i < len) { + dnsAnswer = (struct DnsAnswer*)&buf[i]; + + if (dnsAnswer->clas != htons(DNS_CLASS_IN)) { + return -1; + } + + i = i + sizeof(struct DnsAnswer); + if (dnsAnswer->type == htons(DNS_QUERY_A)) { + // A record + *addr = ((uint32_t)buf[i] << 24) + ((uint32_t)buf[i + 1] << 16) + ((uint32_t)buf[i + 2] << 8) + (uint32_t)buf[i + 3]; + return 0; + } + // next answer + i = i + dnsAnswer->length; + } + + return -1; +} + +void isr_dns (UDPSocketEvent e) { + char buf[512]; + Host dsthost; + int len; + + if (e == UDPSOCKET_READABLE) { + // recv responce; + len = dns->recvfrom(buf, sizeof(buf), &dsthost); +#ifdef DEBUG + for (int i = 0; i < len; i ++) { + printf(" %02x", (unsigned char)buf[i]); + } + puts("\r"); +#endif + if (len >= sizeof(struct DnsHeader)) { + getDnsResponse(buf, len, (uint32_t*)&dnsaddr); + } + } +} + +int getHostByName (IpAddr nameserver, const char *name, uint32_t *addr) { + UDPSocketErr err; + Host myhost, dnshost; + char buf[100]; + int i, len; + + // localhost + if (!strcmp(name, "localhost")) { + *addr = 0x0f000001; + return 0; + } + + dnsaddr = 0; + dns = new UDPSocket; + dns->setOnEvent(isr_dns); + + // bind + myhost.setIp(eth.getIp()); + myhost.setPort(DNS_SRC_PORT); + err = dns->bind(myhost); + if (err != UDPSOCKET_OK) goto exit; + + // send request + dnshost.setIp(nameserver); + dnshost.setPort(DNS_PORT); + len = createDnsRequest((char*)name, buf); +#ifdef DEBUG + for (int i = 0; i < len; i ++) { + printf(" %02x", (unsigned char)buf[i]); + } + puts("\r"); +#endif + dns->sendto(buf, len, &dnshost); + + // wait responce + for (i = 0; i < DNS_TIMEOUT / 10; i ++) { + if (dnsaddr) { + // responce + *addr = dnsaddr; + break; + } + if (i % 500 == 499) { + // retry + dns->sendto(buf, len, &dnshost); + } + Net::poll(); + wait_ms(10); + } + +exit: + dns->resetOnEvent(); + delete dns; + + return dnsaddr ? 0 : -1; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TinyResolver.h Thu Jul 21 16:53:11 2011 +0000 @@ -0,0 +1,65 @@ +/* + * mbed Tiny DNS Resolver + * Copyright (c) 2011 Hiroshi Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +/** @file + * @brief Tiny DNS Resolver + */ + +#ifndef TinyResolver_h +#define TinyResolver_h + +#include <inttypes.h> + +#define DEBUG + +#define DNS_PORT 53 +#define DNS_SRC_PORT 1234 +#define DNS_TIMEOUT 15000 // ms + +// dns +#define DNS_QUERY_A 1 +#define DNS_QUERY_NS 2 +#define DNS_QUERY_CNAME 5 +#define DNS_QUERY_PTR 12 +#define DNS_QUERY_MX 15 +#define DNS_QUERY_AAAA 28 +#define DNS_QUERY_ANY 255 +#define DNS_CLASS_IN 1 + +struct DnsHeader { + uint16_t id; + uint16_t flags; + uint16_t questions; + uint16_t answers; + uint16_t authorities; + uint16_t additional; +}; + +struct DnsQuestionEnd { + uint16_t type; + uint16_t clas; +}; + +struct DnsAnswer { + uint16_t name; + uint16_t type; + uint16_t clas; + uint32_t ttl; + uint16_t length; +} __attribute__((packed)); + +int createDnsRequest (char *name, char *buf); +int getDnsResponse (const char *buf, int len, uint32_t *addr); + +/** resolv host by name + * @param nameserver DNS server + * @param name hostname + * @param addr IP address (return) + * @return 0:success, -1:failue + */ +int getHostByName (IpAddr nameserver, const char *name, uint32_t *addr); + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Jul 21 16:53:11 2011 +0000 @@ -0,0 +1,26 @@ +#include "mbed.h" +#include "EthernetNetIf.h" +#include "TinyResolver.h" + +DigitalOut myled(LED1); +Serial pc(USBTX, USBRX); +EthernetNetIf eth; + +int main () { + EthernetErr ethErr; + uint32_t addr; + + myled = 1; + + ethErr = eth.setup(); + if(ethErr) { + return -1; + } + + getHostByName(IpAddr(192,168,1,1), "mbed.org", &addr); + + printf("IP address: %d.%d.%d.%d\r\n", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); + + myled = 0; + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Jul 21 16:53:11 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912