Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
DNSClient.cpp
00001 // DNSClient.cpp 2013/8/27 00002 #include "mbed.h" 00003 #include "mbed_debug.h" 00004 #include "DNSClient.h" 00005 #include "UDPSocket.h" 00006 #include "dnsname.h" 00007 #include "wiznet.h" 00008 00009 #if DBG_DNS 00010 #define DBG2(...) do{debug("[DNS]%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); debug(__VA_ARGS__); } while(0); 00011 #else 00012 #define DBG2(...) while(0); 00013 #endif 00014 00015 static SocketAddress theDnsServer; 00016 00017 DNSClient::DNSClient() : m_state(MYNETDNS_START), m_udp(NULL) { 00018 m_ns = NULL; 00019 00020 //default to google 00021 theDnsServer.set_ip_address("8.8.8.8"); // DNS 00022 theDnsServer.set_port(53); // DNS 00023 } 00024 00025 DNSClient::DNSClient(NetworkStack *ns, const char* hostname) : m_state(MYNETDNS_START), m_udp(NULL) { 00026 m_hostname = hostname; 00027 m_ns = ns; 00028 00029 //default to google 00030 theDnsServer.set_ip_address("8.8.8.8"); // DNS 00031 theDnsServer.set_port(53); // DNS 00032 } 00033 00034 DNSClient::DNSClient(NetworkStack *ns, SocketAddress* pHost) : m_state(MYNETDNS_START), m_udp(NULL) { 00035 m_ns = ns; 00036 00037 //default to google 00038 theDnsServer.set_ip_address("8.8.8.8"); // DNS 00039 theDnsServer.set_port(53); // DNS 00040 } 00041 00042 DNSClient::~DNSClient() { 00043 if (m_udp) { 00044 delete m_udp; 00045 } 00046 } 00047 00048 int DNSClient::setup(NetworkStack *ns) { 00049 m_ns = ns; 00050 return 0; 00051 } 00052 00053 bool DNSClient::set_server(const char* serverip, int port) { 00054 theDnsServer.set_ip_address(serverip); 00055 theDnsServer.set_port(port); 00056 return true; 00057 } 00058 00059 void DNSClient::callback() 00060 { 00061 uint8_t buf[512]; 00062 SocketAddress host; 00063 int len = m_udp->recvfrom(&host, (char*)buf, sizeof(buf)); 00064 if (len < 0) { 00065 return; 00066 } 00067 if (memcmp(buf+0, m_id, 2) != 0) { //verify 00068 return; 00069 } 00070 00071 int rcode = response(buf, len); 00072 if (rcode == 0) { 00073 m_state = MYNETDNS_OK; 00074 } else { 00075 m_state = MYNETDNS_NOTFOUND; 00076 } 00077 } 00078 00079 int DNSClient::response(uint8_t buf[], int size) { 00080 int rcode = buf[3] & 0x0f; 00081 if (rcode != 0) { 00082 return rcode; 00083 } 00084 int qdcount = buf[4]<<8|buf[5]; 00085 int ancount = buf[6]<<8|buf[7]; 00086 int pos = 12; 00087 while(qdcount-- > 0) { 00088 dnsname qname(buf); 00089 pos = qname.decode(pos); // qname 00090 pos += 4; // qtype qclass 00091 } 00092 while(ancount-- > 0) { 00093 dnsname name(buf); 00094 pos = name.decode(pos); // name 00095 int type = buf[pos]<<8|buf[pos+1]; 00096 pos += 8; // type class TTL 00097 int rdlength = buf[pos]<<8|buf[pos+1]; pos += 2; 00098 int rdata_pos = pos; 00099 pos += rdlength; 00100 if (type == 1) { // A record 00101 m_ip = (buf[rdata_pos]<<24) | (buf[rdata_pos+1]<<16) | (buf[rdata_pos+2]<<8) | buf[rdata_pos+3]; 00102 sprintf(m_ipaddr, "%d.%d.%d.%d", buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]); 00103 } 00104 #if DBG_DNS 00105 printf("%s", name.str.c_str()); 00106 if (type == 1) { 00107 printf(" A %d.%d.%d.%d\n", 00108 buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]); 00109 } else if (type == 5) { 00110 dnsname rdname(buf); 00111 rdname.decode(rdata_pos); 00112 printf(" CNAME %s\n", rdname.str.c_str()); 00113 } else { 00114 printf(" TYPE:%d", type); 00115 printfBytes(" RDATA:", &buf[rdata_pos], rdlength); 00116 } 00117 #endif 00118 } 00119 return rcode; 00120 } 00121 00122 int DNSClient::query(uint8_t buf[], int size, const char* hostname) { 00123 const uint8_t header[] = { 00124 0x00,0x00,0x01,0x00, // id=0x0000 QR=0 rd=1 opcode=0 rcode=0 00125 0x00,0x01,0x00,0x00, // qdcount=1 ancount=0 00126 0x00,0x00,0x00,0x00};// nscount=0 arcount=0 00127 const uint8_t tail[] = {0x00,0x01,0x00,0x01}; // qtype=A qclass=IN 00128 memcpy(buf, header, sizeof(header)); 00129 int t = rand(); 00130 m_id[0] = t>>8; 00131 m_id[1] = t; 00132 memcpy(buf, m_id, 2); 00133 dnsname qname(buf); 00134 int pos = qname.encode(sizeof(header), (char*)hostname); 00135 memcpy(buf+pos, tail, sizeof(tail)); 00136 pos += sizeof(tail); 00137 return pos; 00138 } 00139 00140 void DNSClient::resolve(const char* hostname) { 00141 if (m_udp == NULL) { 00142 m_udp = new UDPSocket; 00143 m_udp->open(m_ns); 00144 } 00145 m_udp->set_blocking(false); 00146 m_udp->bind(rand()&0x7fff); 00147 uint8_t buf[256]; 00148 int size = query(buf, sizeof(buf), hostname); 00149 #if DBG_DNS 00150 printf("hostname:[%s]\n", hostname); 00151 printHex(buf, size); 00152 #endif 00153 m_udp->sendto(theDnsServer, (char*)buf, size); 00154 m_interval.reset(); 00155 m_interval.start(); 00156 } 00157 00158 void DNSClient::poll() { 00159 #if DBG_DNS 00160 printf("%p m_state: %d, m_udp: %p\n", this, m_state, m_udp); 00161 wait_ms(400); 00162 #endif 00163 switch(m_state) { 00164 case MYNETDNS_START: 00165 m_retry = 0; 00166 resolve(m_hostname); 00167 m_state = MYNETDNS_PROCESSING; 00168 break; 00169 case MYNETDNS_PROCESSING: 00170 break; 00171 case MYNETDNS_NOTFOUND: 00172 break; 00173 case MYNETDNS_ERROR: 00174 break; 00175 case MYNETDNS_OK: 00176 DBG2("m_retry=%d, m_interval=%d\n", m_retry, m_interval.read_ms()); 00177 break; 00178 } 00179 if (m_interval.read_ms() > 1000) { 00180 m_interval.stop(); 00181 DBG2("timeout m_retry=%d\n", m_retry); 00182 if (++m_retry >= 2) { 00183 m_state = MYNETDNS_ERROR; 00184 } else { 00185 resolve(m_hostname); 00186 m_state = MYNETDNS_PROCESSING; 00187 } 00188 } 00189 } 00190 00191 //tests for a valid IP address, returns 0 if invalid IP address format, returns ip address if valid 00192 static uint32_t 00193 isValidIP(const char* ip) { 00194 int i1, i2, i3, i4; 00195 int len = strlen(ip); 00196 00197 if (len < 7) return 0; 00198 00199 //count the number of dots, there must be 3 00200 int dotcount = 0; 00201 for (int i = 0; i < len; i++) { 00202 if (ip[i] == '.' ) dotcount++; 00203 } 00204 00205 //there must be exactly 3 dots 00206 if (dotcount != 3) return 0; 00207 00208 sscanf((char*)ip, "%d.%d.%d.%d", &i1, &i2, &i3, &i4); 00209 00210 if (strlen(ip) <= 16 && (i1 >= 0 && i1 <= 255) && (i2 >= 0 && i2 <= 255) && 00211 (i3 >= 0 && i3 <= 255) && (i4 >= 0 && i4 <= 255)) { 00212 return ((i1<<24) | (i2<<16) | (i3<<8) | i4); 00213 } 00214 return 0; 00215 } 00216 00217 bool DNSClient::lookup(const char* hostname) { 00218 m_hostname = hostname; 00219 00220 uint32_t ip = isValidIP(hostname); 00221 00222 //check if hostname is an IP address 00223 if (ip > 0) { 00224 //if it is already an IP address just return immediately 00225 m_ip = ip; 00226 strcpy(m_ipaddr, hostname); 00227 m_state = MYNETDNS_OK; 00228 return true; 00229 } 00230 00231 m_state = MYNETDNS_START; 00232 while(1) { 00233 poll(); 00234 callback(); 00235 if (m_state != MYNETDNS_PROCESSING) { 00236 break; 00237 } 00238 } 00239 00240 if (m_udp) { 00241 delete m_udp; 00242 m_udp = NULL; 00243 } 00244 return m_state == MYNETDNS_OK; 00245 }
Generated on Sun Jul 17 2022 22:06:25 by
1.7.2