NetworkServices with NUCLEO-L476RG and W5500 by SeeedStudio stack.

Dependents:   coap-example Borsch coap-example

Fork of NetworkServices by AMETEK Powervar

Committer:
sgnezdov
Date:
Wed Jul 05 18:34:39 2017 +0000
Revision:
17:c976088bf39d
Parent:
15:14382459c8b7
Changed setup interface to take MAC address, because W5500 may use software defined MAC when obtaining IP.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dgriffin65 15:14382459c8b7 1 // DNSClient.cpp 2013/8/27
dgriffin65 15:14382459c8b7 2 #include "mbed.h"
dgriffin65 15:14382459c8b7 3 #include "mbed_debug.h"
dgriffin65 15:14382459c8b7 4 #include "DNSClient.h"
dgriffin65 15:14382459c8b7 5 #include "UDPSocket.h"
dgriffin65 15:14382459c8b7 6 #include "dnsname.h"
dgriffin65 15:14382459c8b7 7 #include "wiznet.h"
dgriffin65 15:14382459c8b7 8
dgriffin65 15:14382459c8b7 9 #if DBG_DNS
dgriffin65 15:14382459c8b7 10 #define DBG2(...) do{debug("[DNS]%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); debug(__VA_ARGS__); } while(0);
dgriffin65 15:14382459c8b7 11 #else
dgriffin65 15:14382459c8b7 12 #define DBG2(...) while(0);
dgriffin65 15:14382459c8b7 13 #endif
dgriffin65 15:14382459c8b7 14
dgriffin65 15:14382459c8b7 15 static SocketAddress theDnsServer;
dgriffin65 15:14382459c8b7 16
dgriffin65 15:14382459c8b7 17 DNSClient::DNSClient() : m_state(MYNETDNS_START), m_udp(NULL) {
dgriffin65 15:14382459c8b7 18 m_ns = NULL;
dgriffin65 15:14382459c8b7 19
dgriffin65 15:14382459c8b7 20 //default to google
dgriffin65 15:14382459c8b7 21 theDnsServer.set_ip_address("8.8.8.8"); // DNS
dgriffin65 15:14382459c8b7 22 theDnsServer.set_port(53); // DNS
dgriffin65 15:14382459c8b7 23 }
dgriffin65 15:14382459c8b7 24
dgriffin65 15:14382459c8b7 25 DNSClient::DNSClient(NetworkStack *ns, const char* hostname) : m_state(MYNETDNS_START), m_udp(NULL) {
dgriffin65 15:14382459c8b7 26 m_hostname = hostname;
dgriffin65 15:14382459c8b7 27 m_ns = ns;
dgriffin65 15:14382459c8b7 28
dgriffin65 15:14382459c8b7 29 //default to google
dgriffin65 15:14382459c8b7 30 theDnsServer.set_ip_address("8.8.8.8"); // DNS
dgriffin65 15:14382459c8b7 31 theDnsServer.set_port(53); // DNS
dgriffin65 15:14382459c8b7 32 }
dgriffin65 15:14382459c8b7 33
dgriffin65 15:14382459c8b7 34 DNSClient::DNSClient(NetworkStack *ns, SocketAddress* pHost) : m_state(MYNETDNS_START), m_udp(NULL) {
dgriffin65 15:14382459c8b7 35 m_ns = ns;
dgriffin65 15:14382459c8b7 36
dgriffin65 15:14382459c8b7 37 //default to google
dgriffin65 15:14382459c8b7 38 theDnsServer.set_ip_address("8.8.8.8"); // DNS
dgriffin65 15:14382459c8b7 39 theDnsServer.set_port(53); // DNS
dgriffin65 15:14382459c8b7 40 }
dgriffin65 15:14382459c8b7 41
dgriffin65 15:14382459c8b7 42 DNSClient::~DNSClient() {
dgriffin65 15:14382459c8b7 43 if (m_udp) {
dgriffin65 15:14382459c8b7 44 delete m_udp;
dgriffin65 15:14382459c8b7 45 }
dgriffin65 15:14382459c8b7 46 }
dgriffin65 15:14382459c8b7 47
dgriffin65 15:14382459c8b7 48 int DNSClient::setup(NetworkStack *ns) {
dgriffin65 15:14382459c8b7 49 m_ns = ns;
dgriffin65 15:14382459c8b7 50 return 0;
dgriffin65 15:14382459c8b7 51 }
dgriffin65 15:14382459c8b7 52
dgriffin65 15:14382459c8b7 53 bool DNSClient::set_server(const char* serverip, int port) {
dgriffin65 15:14382459c8b7 54 theDnsServer.set_ip_address(serverip);
dgriffin65 15:14382459c8b7 55 theDnsServer.set_port(port);
dgriffin65 15:14382459c8b7 56 return true;
dgriffin65 15:14382459c8b7 57 }
dgriffin65 15:14382459c8b7 58
dgriffin65 15:14382459c8b7 59 void DNSClient::callback()
dgriffin65 15:14382459c8b7 60 {
dgriffin65 15:14382459c8b7 61 uint8_t buf[512];
dgriffin65 15:14382459c8b7 62 SocketAddress host;
dgriffin65 15:14382459c8b7 63 int len = m_udp->recvfrom(&host, (char*)buf, sizeof(buf));
dgriffin65 15:14382459c8b7 64 if (len < 0) {
dgriffin65 15:14382459c8b7 65 return;
dgriffin65 15:14382459c8b7 66 }
dgriffin65 15:14382459c8b7 67 if (memcmp(buf+0, m_id, 2) != 0) { //verify
dgriffin65 15:14382459c8b7 68 return;
dgriffin65 15:14382459c8b7 69 }
dgriffin65 15:14382459c8b7 70
dgriffin65 15:14382459c8b7 71 int rcode = response(buf, len);
dgriffin65 15:14382459c8b7 72 if (rcode == 0) {
dgriffin65 15:14382459c8b7 73 m_state = MYNETDNS_OK;
dgriffin65 15:14382459c8b7 74 } else {
dgriffin65 15:14382459c8b7 75 m_state = MYNETDNS_NOTFOUND;
dgriffin65 15:14382459c8b7 76 }
dgriffin65 15:14382459c8b7 77 }
dgriffin65 15:14382459c8b7 78
dgriffin65 15:14382459c8b7 79 int DNSClient::response(uint8_t buf[], int size) {
dgriffin65 15:14382459c8b7 80 int rcode = buf[3] & 0x0f;
dgriffin65 15:14382459c8b7 81 if (rcode != 0) {
dgriffin65 15:14382459c8b7 82 return rcode;
dgriffin65 15:14382459c8b7 83 }
dgriffin65 15:14382459c8b7 84 int qdcount = buf[4]<<8|buf[5];
dgriffin65 15:14382459c8b7 85 int ancount = buf[6]<<8|buf[7];
dgriffin65 15:14382459c8b7 86 int pos = 12;
dgriffin65 15:14382459c8b7 87 while(qdcount-- > 0) {
dgriffin65 15:14382459c8b7 88 dnsname qname(buf);
dgriffin65 15:14382459c8b7 89 pos = qname.decode(pos); // qname
dgriffin65 15:14382459c8b7 90 pos += 4; // qtype qclass
dgriffin65 15:14382459c8b7 91 }
dgriffin65 15:14382459c8b7 92 while(ancount-- > 0) {
dgriffin65 15:14382459c8b7 93 dnsname name(buf);
dgriffin65 15:14382459c8b7 94 pos = name.decode(pos); // name
dgriffin65 15:14382459c8b7 95 int type = buf[pos]<<8|buf[pos+1];
dgriffin65 15:14382459c8b7 96 pos += 8; // type class TTL
dgriffin65 15:14382459c8b7 97 int rdlength = buf[pos]<<8|buf[pos+1]; pos += 2;
dgriffin65 15:14382459c8b7 98 int rdata_pos = pos;
dgriffin65 15:14382459c8b7 99 pos += rdlength;
dgriffin65 15:14382459c8b7 100 if (type == 1) { // A record
dgriffin65 15:14382459c8b7 101 m_ip = (buf[rdata_pos]<<24) | (buf[rdata_pos+1]<<16) | (buf[rdata_pos+2]<<8) | buf[rdata_pos+3];
dgriffin65 15:14382459c8b7 102 sprintf(m_ipaddr, "%d.%d.%d.%d", buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]);
dgriffin65 15:14382459c8b7 103 }
dgriffin65 15:14382459c8b7 104 #if DBG_DNS
dgriffin65 15:14382459c8b7 105 printf("%s", name.str.c_str());
dgriffin65 15:14382459c8b7 106 if (type == 1) {
dgriffin65 15:14382459c8b7 107 printf(" A %d.%d.%d.%d\n",
dgriffin65 15:14382459c8b7 108 buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]);
dgriffin65 15:14382459c8b7 109 } else if (type == 5) {
dgriffin65 15:14382459c8b7 110 dnsname rdname(buf);
dgriffin65 15:14382459c8b7 111 rdname.decode(rdata_pos);
dgriffin65 15:14382459c8b7 112 printf(" CNAME %s\n", rdname.str.c_str());
dgriffin65 15:14382459c8b7 113 } else {
dgriffin65 15:14382459c8b7 114 printf(" TYPE:%d", type);
dgriffin65 15:14382459c8b7 115 printfBytes(" RDATA:", &buf[rdata_pos], rdlength);
dgriffin65 15:14382459c8b7 116 }
dgriffin65 15:14382459c8b7 117 #endif
dgriffin65 15:14382459c8b7 118 }
dgriffin65 15:14382459c8b7 119 return rcode;
dgriffin65 15:14382459c8b7 120 }
dgriffin65 15:14382459c8b7 121
dgriffin65 15:14382459c8b7 122 int DNSClient::query(uint8_t buf[], int size, const char* hostname) {
dgriffin65 15:14382459c8b7 123 const uint8_t header[] = {
dgriffin65 15:14382459c8b7 124 0x00,0x00,0x01,0x00, // id=0x0000 QR=0 rd=1 opcode=0 rcode=0
dgriffin65 15:14382459c8b7 125 0x00,0x01,0x00,0x00, // qdcount=1 ancount=0
dgriffin65 15:14382459c8b7 126 0x00,0x00,0x00,0x00};// nscount=0 arcount=0
dgriffin65 15:14382459c8b7 127 const uint8_t tail[] = {0x00,0x01,0x00,0x01}; // qtype=A qclass=IN
dgriffin65 15:14382459c8b7 128 memcpy(buf, header, sizeof(header));
dgriffin65 15:14382459c8b7 129 int t = rand();
dgriffin65 15:14382459c8b7 130 m_id[0] = t>>8;
dgriffin65 15:14382459c8b7 131 m_id[1] = t;
dgriffin65 15:14382459c8b7 132 memcpy(buf, m_id, 2);
dgriffin65 15:14382459c8b7 133 dnsname qname(buf);
dgriffin65 15:14382459c8b7 134 int pos = qname.encode(sizeof(header), (char*)hostname);
dgriffin65 15:14382459c8b7 135 memcpy(buf+pos, tail, sizeof(tail));
dgriffin65 15:14382459c8b7 136 pos += sizeof(tail);
dgriffin65 15:14382459c8b7 137 return pos;
dgriffin65 15:14382459c8b7 138 }
dgriffin65 15:14382459c8b7 139
dgriffin65 15:14382459c8b7 140 void DNSClient::resolve(const char* hostname) {
dgriffin65 15:14382459c8b7 141 if (m_udp == NULL) {
dgriffin65 15:14382459c8b7 142 m_udp = new UDPSocket;
dgriffin65 15:14382459c8b7 143 m_udp->open(m_ns);
dgriffin65 15:14382459c8b7 144 }
dgriffin65 15:14382459c8b7 145 m_udp->set_blocking(false);
dgriffin65 15:14382459c8b7 146 m_udp->bind(rand()&0x7fff);
dgriffin65 15:14382459c8b7 147 uint8_t buf[256];
dgriffin65 15:14382459c8b7 148 int size = query(buf, sizeof(buf), hostname);
dgriffin65 15:14382459c8b7 149 #if DBG_DNS
dgriffin65 15:14382459c8b7 150 printf("hostname:[%s]\n", hostname);
dgriffin65 15:14382459c8b7 151 printHex(buf, size);
dgriffin65 15:14382459c8b7 152 #endif
dgriffin65 15:14382459c8b7 153 m_udp->sendto(theDnsServer, (char*)buf, size);
dgriffin65 15:14382459c8b7 154 m_interval.reset();
dgriffin65 15:14382459c8b7 155 m_interval.start();
dgriffin65 15:14382459c8b7 156 }
dgriffin65 15:14382459c8b7 157
dgriffin65 15:14382459c8b7 158 void DNSClient::poll() {
dgriffin65 15:14382459c8b7 159 #if DBG_DNS
dgriffin65 15:14382459c8b7 160 printf("%p m_state: %d, m_udp: %p\n", this, m_state, m_udp);
dgriffin65 15:14382459c8b7 161 wait_ms(400);
dgriffin65 15:14382459c8b7 162 #endif
dgriffin65 15:14382459c8b7 163 switch(m_state) {
dgriffin65 15:14382459c8b7 164 case MYNETDNS_START:
dgriffin65 15:14382459c8b7 165 m_retry = 0;
dgriffin65 15:14382459c8b7 166 resolve(m_hostname);
dgriffin65 15:14382459c8b7 167 m_state = MYNETDNS_PROCESSING;
dgriffin65 15:14382459c8b7 168 break;
dgriffin65 15:14382459c8b7 169 case MYNETDNS_PROCESSING:
dgriffin65 15:14382459c8b7 170 break;
dgriffin65 15:14382459c8b7 171 case MYNETDNS_NOTFOUND:
dgriffin65 15:14382459c8b7 172 break;
dgriffin65 15:14382459c8b7 173 case MYNETDNS_ERROR:
dgriffin65 15:14382459c8b7 174 break;
dgriffin65 15:14382459c8b7 175 case MYNETDNS_OK:
dgriffin65 15:14382459c8b7 176 DBG2("m_retry=%d, m_interval=%d\n", m_retry, m_interval.read_ms());
dgriffin65 15:14382459c8b7 177 break;
dgriffin65 15:14382459c8b7 178 }
dgriffin65 15:14382459c8b7 179 if (m_interval.read_ms() > 1000) {
dgriffin65 15:14382459c8b7 180 m_interval.stop();
dgriffin65 15:14382459c8b7 181 DBG2("timeout m_retry=%d\n", m_retry);
dgriffin65 15:14382459c8b7 182 if (++m_retry >= 2) {
dgriffin65 15:14382459c8b7 183 m_state = MYNETDNS_ERROR;
dgriffin65 15:14382459c8b7 184 } else {
dgriffin65 15:14382459c8b7 185 resolve(m_hostname);
dgriffin65 15:14382459c8b7 186 m_state = MYNETDNS_PROCESSING;
dgriffin65 15:14382459c8b7 187 }
dgriffin65 15:14382459c8b7 188 }
dgriffin65 15:14382459c8b7 189 }
dgriffin65 15:14382459c8b7 190
dgriffin65 15:14382459c8b7 191 //tests for a valid IP address, returns 0 if invalid IP address format, returns ip address if valid
dgriffin65 15:14382459c8b7 192 static uint32_t
dgriffin65 15:14382459c8b7 193 isValidIP(const char* ip) {
dgriffin65 15:14382459c8b7 194 int i1, i2, i3, i4;
dgriffin65 15:14382459c8b7 195 int len = strlen(ip);
dgriffin65 15:14382459c8b7 196
dgriffin65 15:14382459c8b7 197 if (len < 7) return 0;
dgriffin65 15:14382459c8b7 198
dgriffin65 15:14382459c8b7 199 //count the number of dots, there must be 3
dgriffin65 15:14382459c8b7 200 int dotcount = 0;
dgriffin65 15:14382459c8b7 201 for (int i = 0; i < len; i++) {
dgriffin65 15:14382459c8b7 202 if (ip[i] == '.' ) dotcount++;
dgriffin65 15:14382459c8b7 203 }
dgriffin65 15:14382459c8b7 204
dgriffin65 15:14382459c8b7 205 //there must be exactly 3 dots
dgriffin65 15:14382459c8b7 206 if (dotcount != 3) return 0;
dgriffin65 15:14382459c8b7 207
dgriffin65 15:14382459c8b7 208 sscanf((char*)ip, "%d.%d.%d.%d", &i1, &i2, &i3, &i4);
dgriffin65 15:14382459c8b7 209
dgriffin65 15:14382459c8b7 210 if (strlen(ip) <= 16 && (i1 >= 0 && i1 <= 255) && (i2 >= 0 && i2 <= 255) &&
dgriffin65 15:14382459c8b7 211 (i3 >= 0 && i3 <= 255) && (i4 >= 0 && i4 <= 255)) {
dgriffin65 15:14382459c8b7 212 return ((i1<<24) | (i2<<16) | (i3<<8) | i4);
dgriffin65 15:14382459c8b7 213 }
dgriffin65 15:14382459c8b7 214 return 0;
dgriffin65 15:14382459c8b7 215 }
dgriffin65 15:14382459c8b7 216
dgriffin65 15:14382459c8b7 217 bool DNSClient::lookup(const char* hostname) {
dgriffin65 15:14382459c8b7 218 m_hostname = hostname;
dgriffin65 15:14382459c8b7 219
dgriffin65 15:14382459c8b7 220 uint32_t ip = isValidIP(hostname);
dgriffin65 15:14382459c8b7 221
dgriffin65 15:14382459c8b7 222 //check if hostname is an IP address
dgriffin65 15:14382459c8b7 223 if (ip > 0) {
dgriffin65 15:14382459c8b7 224 //if it is already an IP address just return immediately
dgriffin65 15:14382459c8b7 225 m_ip = ip;
dgriffin65 15:14382459c8b7 226 strcpy(m_ipaddr, hostname);
dgriffin65 15:14382459c8b7 227 m_state = MYNETDNS_OK;
dgriffin65 15:14382459c8b7 228 return true;
dgriffin65 15:14382459c8b7 229 }
dgriffin65 15:14382459c8b7 230
dgriffin65 15:14382459c8b7 231 m_state = MYNETDNS_START;
dgriffin65 15:14382459c8b7 232 while(1) {
dgriffin65 15:14382459c8b7 233 poll();
dgriffin65 15:14382459c8b7 234 callback();
dgriffin65 15:14382459c8b7 235 if (m_state != MYNETDNS_PROCESSING) {
dgriffin65 15:14382459c8b7 236 break;
dgriffin65 15:14382459c8b7 237 }
dgriffin65 15:14382459c8b7 238 }
dgriffin65 15:14382459c8b7 239
dgriffin65 15:14382459c8b7 240 if (m_udp) {
dgriffin65 15:14382459c8b7 241 delete m_udp;
dgriffin65 15:14382459c8b7 242 m_udp = NULL;
dgriffin65 15:14382459c8b7 243 }
dgriffin65 15:14382459c8b7 244 return m_state == MYNETDNS_OK;
dgriffin65 15:14382459c8b7 245 }