WIZNet W5500 with additional enhancements

Fork of WIZnetInterface by WIZnet

Committer:
Helmut Tschemernjak
Date:
Mon Oct 09 19:58:19 2017 +0200
Revision:
34:7d44648ec5f2
Parent:
0:6f28332c466f
Added support for manual DNS server config or DHCP DNS config.
Now the DNS 8.8.8.8 is only a fallback if no DNS server is specified.
Replaced error() messages with printf() to avoid hanging code in error()

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Soohwan Kim 0:6f28332c466f 1 // DNSClient.cpp 2013/8/27
Soohwan Kim 0:6f28332c466f 2 #include "mbed.h"
Soohwan Kim 0:6f28332c466f 3 #include "mbed_debug.h"
Soohwan Kim 0:6f28332c466f 4 #include "DNSClient.h"
Soohwan Kim 0:6f28332c466f 5 #include "UDPSocket.h"
Soohwan Kim 0:6f28332c466f 6 #include "dnsname.h"
Soohwan Kim 0:6f28332c466f 7 #include "eth_arch.h"
Soohwan Kim 0:6f28332c466f 8
Soohwan Kim 0:6f28332c466f 9 #define DBG_DNS 0
Soohwan Kim 0:6f28332c466f 10
Soohwan Kim 0:6f28332c466f 11 #if DBG_DNS
Soohwan Kim 0:6f28332c466f 12 #define DBG2(...) do{debug("[DNS]%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); debug(__VA_ARGS__); } while(0);
Soohwan Kim 0:6f28332c466f 13 #else
Soohwan Kim 0:6f28332c466f 14 #define DBG2(...) while(0);
Soohwan Kim 0:6f28332c466f 15 #endif
Soohwan Kim 0:6f28332c466f 16
Soohwan Kim 0:6f28332c466f 17 DNSClient::DNSClient(const char* hostname) : m_state(MYNETDNS_START), m_udp(NULL) {
Soohwan Kim 0:6f28332c466f 18 m_hostname = hostname;
Soohwan Kim 0:6f28332c466f 19 }
Soohwan Kim 0:6f28332c466f 20
Soohwan Kim 0:6f28332c466f 21 DNSClient::DNSClient(Endpoint* pHost) : m_state(MYNETDNS_START), m_udp(NULL) {
Soohwan Kim 0:6f28332c466f 22 }
Soohwan Kim 0:6f28332c466f 23
Soohwan Kim 0:6f28332c466f 24 DNSClient::~DNSClient() {
Soohwan Kim 0:6f28332c466f 25 if (m_udp) {
Soohwan Kim 0:6f28332c466f 26 delete m_udp;
Soohwan Kim 0:6f28332c466f 27 }
Soohwan Kim 0:6f28332c466f 28 }
Soohwan Kim 0:6f28332c466f 29
Soohwan Kim 0:6f28332c466f 30 void DNSClient::callback()
Soohwan Kim 0:6f28332c466f 31 {
Soohwan Kim 0:6f28332c466f 32 uint8_t buf[512];
Soohwan Kim 0:6f28332c466f 33 Endpoint host;
Soohwan Kim 0:6f28332c466f 34 int len = m_udp->receiveFrom(host, (char*)buf, sizeof(buf));
Soohwan Kim 0:6f28332c466f 35 if (len < 0) {
Soohwan Kim 0:6f28332c466f 36 return;
Soohwan Kim 0:6f28332c466f 37 }
Soohwan Kim 0:6f28332c466f 38 if (memcmp(buf+0, m_id, 2) != 0) { //verify
Soohwan Kim 0:6f28332c466f 39 return;
Soohwan Kim 0:6f28332c466f 40 }
Soohwan Kim 0:6f28332c466f 41 int rcode = response(buf, len);
Soohwan Kim 0:6f28332c466f 42 if (rcode == 0) {
Soohwan Kim 0:6f28332c466f 43 m_state = MYNETDNS_OK;
Soohwan Kim 0:6f28332c466f 44 } else {
Soohwan Kim 0:6f28332c466f 45 m_state = MYNETDNS_NOTFOUND;
Soohwan Kim 0:6f28332c466f 46 }
Soohwan Kim 0:6f28332c466f 47 }
Soohwan Kim 0:6f28332c466f 48
Soohwan Kim 0:6f28332c466f 49 int DNSClient::response(uint8_t buf[], int size) {
Soohwan Kim 0:6f28332c466f 50 int rcode = buf[3] & 0x0f;
Soohwan Kim 0:6f28332c466f 51 if (rcode != 0) {
Soohwan Kim 0:6f28332c466f 52 return rcode;
Soohwan Kim 0:6f28332c466f 53 }
Soohwan Kim 0:6f28332c466f 54 int qdcount = buf[4]<<8|buf[5];
Soohwan Kim 0:6f28332c466f 55 int ancount = buf[6]<<8|buf[7];
Soohwan Kim 0:6f28332c466f 56 int pos = 12;
Soohwan Kim 0:6f28332c466f 57 while(qdcount-- > 0) {
Soohwan Kim 0:6f28332c466f 58 dnsname qname(buf);
Soohwan Kim 0:6f28332c466f 59 pos = qname.decode(pos); // qname
Soohwan Kim 0:6f28332c466f 60 pos += 4; // qtype qclass
Soohwan Kim 0:6f28332c466f 61 }
Soohwan Kim 0:6f28332c466f 62 while(ancount-- > 0) {
Soohwan Kim 0:6f28332c466f 63 dnsname name(buf);
Soohwan Kim 0:6f28332c466f 64 pos = name.decode(pos); // name
Soohwan Kim 0:6f28332c466f 65 int type = buf[pos]<<8|buf[pos+1];
Soohwan Kim 0:6f28332c466f 66 pos += 8; // type class TTL
Soohwan Kim 0:6f28332c466f 67 int rdlength = buf[pos]<<8|buf[pos+1]; pos += 2;
Soohwan Kim 0:6f28332c466f 68 int rdata_pos = pos;
Soohwan Kim 0:6f28332c466f 69 pos += rdlength;
Soohwan Kim 0:6f28332c466f 70 if (type == 1) { // A record
Soohwan Kim 0:6f28332c466f 71 ip = (buf[rdata_pos]<<24) | (buf[rdata_pos+1]<<16) | (buf[rdata_pos+2]<<8) | buf[rdata_pos+3];
Soohwan Kim 0:6f28332c466f 72 }
Soohwan Kim 0:6f28332c466f 73 #if DBG_DNS
Soohwan Kim 0:6f28332c466f 74 printf("%s", name.str.c_str());
Soohwan Kim 0:6f28332c466f 75 if (type == 1) {
Soohwan Kim 0:6f28332c466f 76 printf(" A %d.%d.%d.%d\n",
Soohwan Kim 0:6f28332c466f 77 buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]);
Soohwan Kim 0:6f28332c466f 78 } else if (type == 5) {
Soohwan Kim 0:6f28332c466f 79 dnsname rdname(buf);
Soohwan Kim 0:6f28332c466f 80 rdname.decode(rdata_pos);
Soohwan Kim 0:6f28332c466f 81 printf(" CNAME %s\n", rdname.str.c_str());
Soohwan Kim 0:6f28332c466f 82 } else {
Soohwan Kim 0:6f28332c466f 83 printf(" TYPE:%d", type);
Soohwan Kim 0:6f28332c466f 84 printfBytes(" RDATA:", &buf[rdata_pos], rdlength);
Soohwan Kim 0:6f28332c466f 85 }
Soohwan Kim 0:6f28332c466f 86 #endif
Soohwan Kim 0:6f28332c466f 87 }
Soohwan Kim 0:6f28332c466f 88 return rcode;
Soohwan Kim 0:6f28332c466f 89 }
Soohwan Kim 0:6f28332c466f 90
Soohwan Kim 0:6f28332c466f 91 int DNSClient::query(uint8_t buf[], int size, const char* hostname) {
Soohwan Kim 0:6f28332c466f 92 const uint8_t header[] = {
Soohwan Kim 0:6f28332c466f 93 0x00,0x00,0x01,0x00, // id=0x0000 QR=0 rd=1 opcode=0 rcode=0
Soohwan Kim 0:6f28332c466f 94 0x00,0x01,0x00,0x00, // qdcount=1 ancount=0
Soohwan Kim 0:6f28332c466f 95 0x00,0x00,0x00,0x00};// nscount=0 arcount=0
Soohwan Kim 0:6f28332c466f 96 const uint8_t tail[] = {0x00,0x01,0x00,0x01}; // qtype=A qclass=IN
Soohwan Kim 0:6f28332c466f 97 memcpy(buf, header, sizeof(header));
Soohwan Kim 0:6f28332c466f 98 int t = rand();
Soohwan Kim 0:6f28332c466f 99 m_id[0] = t>>8;
Soohwan Kim 0:6f28332c466f 100 m_id[1] = t;
Soohwan Kim 0:6f28332c466f 101 memcpy(buf, m_id, 2);
Soohwan Kim 0:6f28332c466f 102 dnsname qname(buf);
Soohwan Kim 0:6f28332c466f 103 int pos = qname.encode(sizeof(header), (char*)hostname);
Soohwan Kim 0:6f28332c466f 104 memcpy(buf+pos, tail, sizeof(tail));
Soohwan Kim 0:6f28332c466f 105 pos += sizeof(tail);
Soohwan Kim 0:6f28332c466f 106 return pos;
Soohwan Kim 0:6f28332c466f 107 }
Soohwan Kim 0:6f28332c466f 108
Soohwan Kim 0:6f28332c466f 109 void DNSClient::resolve(const char* hostname) {
Soohwan Kim 0:6f28332c466f 110 if (m_udp == NULL) {
Soohwan Kim 0:6f28332c466f 111 m_udp = new UDPSocket;
Soohwan Kim 0:6f28332c466f 112 }
Soohwan Kim 0:6f28332c466f 113 m_udp->init();
Soohwan Kim 0:6f28332c466f 114 m_udp->set_blocking(false);
Soohwan Kim 0:6f28332c466f 115 Endpoint server;
Helmut Tschemernjak 34:7d44648ec5f2 116
Helmut Tschemernjak 34:7d44648ec5f2 117 if (m_dnsServer) {
Helmut Tschemernjak 34:7d44648ec5f2 118 server.set_address(m_dnsServer, 53); // DNS
Helmut Tschemernjak 34:7d44648ec5f2 119 } else {
Helmut Tschemernjak 34:7d44648ec5f2 120 server.set_address("8.8.8.8", 53); // DNS
Helmut Tschemernjak 34:7d44648ec5f2 121 }
Soohwan Kim 0:6f28332c466f 122 m_udp->bind(rand()&0x7fff);
Soohwan Kim 0:6f28332c466f 123 uint8_t buf[256];
Soohwan Kim 0:6f28332c466f 124 int size = query(buf, sizeof(buf), hostname);
Soohwan Kim 0:6f28332c466f 125 #if DBG_DNS
Soohwan Kim 0:6f28332c466f 126 printf("hostname:[%s]\n", hostname);
Soohwan Kim 0:6f28332c466f 127 printHex(buf, size);
Soohwan Kim 0:6f28332c466f 128 #endif
Soohwan Kim 0:6f28332c466f 129 m_udp->sendTo(server, (char*)buf, size);
Soohwan Kim 0:6f28332c466f 130 m_interval.reset();
Soohwan Kim 0:6f28332c466f 131 m_interval.start();
Soohwan Kim 0:6f28332c466f 132 }
Soohwan Kim 0:6f28332c466f 133
Soohwan Kim 0:6f28332c466f 134 void DNSClient::poll() {
Soohwan Kim 0:6f28332c466f 135 #if DBG_DNS
Soohwan Kim 0:6f28332c466f 136 printf("%p m_state: %d, m_udp: %p\n", this, m_state, m_udp);
Soohwan Kim 0:6f28332c466f 137 wait_ms(400);
Soohwan Kim 0:6f28332c466f 138 #endif
Soohwan Kim 0:6f28332c466f 139 switch(m_state) {
Soohwan Kim 0:6f28332c466f 140 case MYNETDNS_START:
Soohwan Kim 0:6f28332c466f 141 m_retry = 0;
Soohwan Kim 0:6f28332c466f 142 resolve(m_hostname);
Soohwan Kim 0:6f28332c466f 143 m_state = MYNETDNS_PROCESSING;
Soohwan Kim 0:6f28332c466f 144 break;
Soohwan Kim 0:6f28332c466f 145 case MYNETDNS_PROCESSING:
Soohwan Kim 0:6f28332c466f 146 break;
Soohwan Kim 0:6f28332c466f 147 case MYNETDNS_NOTFOUND:
Soohwan Kim 0:6f28332c466f 148 break;
Soohwan Kim 0:6f28332c466f 149 case MYNETDNS_ERROR:
Soohwan Kim 0:6f28332c466f 150 break;
Soohwan Kim 0:6f28332c466f 151 case MYNETDNS_OK:
Soohwan Kim 0:6f28332c466f 152 DBG2("m_retry=%d, m_interval=%d\n", m_retry, m_interval.read_ms());
Soohwan Kim 0:6f28332c466f 153 break;
Soohwan Kim 0:6f28332c466f 154 }
Soohwan Kim 0:6f28332c466f 155 if (m_interval.read_ms() > 1000) {
Soohwan Kim 0:6f28332c466f 156 m_interval.stop();
Soohwan Kim 0:6f28332c466f 157 DBG2("timeout m_retry=%d\n", m_retry);
Soohwan Kim 0:6f28332c466f 158 if (++m_retry >= 2) {
Soohwan Kim 0:6f28332c466f 159 m_state = MYNETDNS_ERROR;
Soohwan Kim 0:6f28332c466f 160 } else {
Soohwan Kim 0:6f28332c466f 161 resolve(m_hostname);
Soohwan Kim 0:6f28332c466f 162 m_state = MYNETDNS_PROCESSING;
Soohwan Kim 0:6f28332c466f 163 }
Soohwan Kim 0:6f28332c466f 164 }
Soohwan Kim 0:6f28332c466f 165 }
Soohwan Kim 0:6f28332c466f 166
Helmut Tschemernjak 34:7d44648ec5f2 167 bool DNSClient::lookup(const char* hostname, uint32_t dnsServer) {
Soohwan Kim 0:6f28332c466f 168 m_hostname = hostname;
Helmut Tschemernjak 34:7d44648ec5f2 169 m_dnsServer = dnsServer;
Soohwan Kim 0:6f28332c466f 170 m_state = MYNETDNS_START;
Soohwan Kim 0:6f28332c466f 171 while(1) {
Soohwan Kim 0:6f28332c466f 172 poll();
Soohwan Kim 0:6f28332c466f 173 callback();
Soohwan Kim 0:6f28332c466f 174 if (m_state != MYNETDNS_PROCESSING) {
Soohwan Kim 0:6f28332c466f 175 break;
Soohwan Kim 0:6f28332c466f 176 }
Soohwan Kim 0:6f28332c466f 177 }
Soohwan Kim 0:6f28332c466f 178 return m_state == MYNETDNS_OK;
Soohwan Kim 0:6f28332c466f 179 }
Soohwan Kim 0:6f28332c466f 180