DnsQuery for NetworkSocketAPI
Fork of DnsQuery by
Embed:
(wiki syntax)
Show/hide line numbers
DnsQuery.cpp
00001 /* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de) 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00005 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00006 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00007 * furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 #include "DnsQuery.h" 00019 #include <stdio.h> 00020 #include <string.h> 00021 00022 00023 #define DNS_COUNT (sizeof DNS_IPS / sizeof DNS_IPS[0]) 00024 const char *DNS_IPS[] = { 00025 "8.8.8.8", 00026 "209.244.0.3", 00027 "84.200.69.80", 00028 "8.26.56.26", 00029 "208.67.222.222" 00030 }; 00031 00032 static bool isIP(const char *host) 00033 { 00034 int i; 00035 00036 for (i = 0; host[i]; i++) { 00037 if (!(host[i] >= '0' && host[i] <= '9') && host[i] != '.') { 00038 return false; 00039 } 00040 } 00041 00042 // Ending with '.' garuntees host 00043 if (i > 0 && host[i-1] == '.') { 00044 return false; 00045 } 00046 00047 return true; 00048 } 00049 00050 00051 static bool parseRR(uint8_t *resp, int &c, char *adr) 00052 { 00053 int n = 0; 00054 while((n=resp[c++]) != 0) { 00055 if ((n & 0xc0) != 0) { 00056 // This is a link 00057 c++; 00058 break; 00059 } else { 00060 // skip this segment, not interested in string domain names 00061 c+= n; 00062 } 00063 } 00064 00065 int TYPE = (((int)resp[c])<<8) + resp[c+1]; 00066 int CLASS = (((int)resp[c+2])<<8) + resp[c+3]; 00067 int RDLENGTH = (((int)resp[c+8])<<8) + resp[c+9]; 00068 00069 c+= 10; 00070 if ((CLASS == 1) && (TYPE == 1)) { 00071 sprintf(adr,"%d.%d.%d.%d", resp[c], resp[c+1], resp[c+2], resp[c+3]); 00072 c+= RDLENGTH; 00073 return true; 00074 } 00075 c+= RDLENGTH; 00076 00077 return false; 00078 } 00079 00080 00081 static bool resolve(unsigned char *resp, char *ipaddress) 00082 { 00083 00084 int ID = (((int)resp[0]) <<8) + resp[1]; 00085 int QR = resp[2] >>7; 00086 int Opcode = (resp[2]>>3) & 0x0F; 00087 int RCODE = (resp[3] & 0x0F); 00088 int ANCOUNT = (((int)resp[6])<<8)+ resp[7]; 00089 00090 if ((ID != 1) || (QR != 1) || (Opcode != 0) || (RCODE != 0)) { 00091 return false; 00092 } 00093 00094 int c = 12; 00095 int d; 00096 // Skip domain question 00097 while( (d=resp[c++]) != 0) { 00098 c+=d; 00099 } 00100 c+= 4; // skip QTYPE and QCLASS 00101 00102 // Here comes the resource record 00103 for (int ans = 0 ; ans < ANCOUNT; ans++) { 00104 if (parseRR(resp, c, ipaddress)) { 00105 return true; 00106 } 00107 } 00108 00109 return false; 00110 } 00111 00112 static int32_t query(UDPSocket *socket, const SocketAddress &addr, const char *hostname, char *ipaddress) 00113 { 00114 int len = 0; 00115 if (hostname == NULL) { 00116 return false; 00117 } 00118 len = strlen(hostname); 00119 if ((len > 128) || (len == 0)) { 00120 return false; 00121 } 00122 00123 int packetlen = /* size of HEADER structure */ 12 + /* size of QUESTION Structure */5 + len + 1; 00124 uint8_t *packet = new uint8_t[packetlen]; /* this is the UDP packet to send to the DNS */ 00125 if (packet == NULL) { 00126 return false; 00127 } 00128 00129 // Fill the header 00130 memset(packet, 0, packetlen); 00131 packet[1] = 1; // ID = 1 00132 packet[5] = 1; // QDCOUNT = 1 (contains one question) 00133 packet[2] = 1; // recursion requested 00134 00135 int c = 13; // point to NAME element in question section or request 00136 int cnt = 12; // points to the counter of 00137 packet[cnt] = 0; 00138 for (int i = 0 ; i < len ; i++) { 00139 if (hostname[i] != '.') { 00140 // Copy the character and increment the character counter 00141 packet[cnt]++; 00142 packet[c++] = hostname[i]; 00143 } else { 00144 // Finished with this part, so go to the next 00145 cnt = c++; 00146 packet[cnt] = 0; 00147 } 00148 } 00149 00150 // Terminate this domain name with a zero entry 00151 packet[c++] = 0; 00152 00153 // Set QTYPE 00154 packet[c++] = 0; 00155 packet[c++] = 1; 00156 // Set QCLASS 00157 packet[c++] = 0; 00158 packet[c++] = 1; 00159 00160 00161 if (socket->sendto(addr, packet, packetlen) < 0) { 00162 delete packet; 00163 return false; 00164 } 00165 delete packet; 00166 wait_ms(500); 00167 00168 packet = new uint8_t [1024]; 00169 00170 // Receive the answer from DNS 00171 int response_length = 0; 00172 response_length = socket->recvfrom(NULL, packet, 1024); 00173 00174 if (response_length > 0 ) { 00175 if (!resolve(packet, ipaddress)) { 00176 delete packet; 00177 return NSAPI_ERROR_DNS_FAILURE; 00178 } 00179 00180 // cleanup and return 00181 delete packet; 00182 return 0; 00183 } 00184 00185 delete packet; 00186 return NSAPI_ERROR_DNS_FAILURE; 00187 } 00188 00189 int32_t dnsQuery(NetworkStack *iface, const char *host, char *ip) 00190 { 00191 if (isIP(host)) { 00192 strcpy(ip, host); 00193 return 0; 00194 } 00195 00196 UDPSocket sock(iface); 00197 00198 for (unsigned i = 0; i < DNS_COUNT; i++) { 00199 return query(&sock, SocketAddress(DNS_IPS[0], 53), host, ip); 00200 } 00201 00202 return NSAPI_ERROR_DNS_FAILURE; 00203 } 00204 00205 int32_t dnsQuery(UDPSocket *socket, const char *host, char *ip) 00206 { 00207 if (isIP(host)) { 00208 strcpy(ip, host); 00209 return 0; 00210 } 00211 00212 for (unsigned i = 0; i < DNS_COUNT; i++) { 00213 return query(socket, SocketAddress(DNS_IPS[0], 53), host, ip); 00214 } 00215 00216 return NSAPI_ERROR_DNS_FAILURE; 00217 }
Generated on Tue Jul 12 2022 18:03:54 by 1.7.2