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.
Fork of DnsQuery by
DnsQuery.cpp@18:2cb1fffed50c, 2016-04-19 (annotated)
- Committer:
- Christopher Haster
- Date:
- Tue Apr 19 18:29:55 2016 -0500
- Revision:
- 18:2cb1fffed50c
- Parent:
- 17:18a6b52be896
- Child:
- 19:4c6f4b6036e6
Matched changes to NSAPI
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| Christopher Haster |
18:2cb1fffed50c | 1 | /* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de) |
| Christopher Haster |
18:2cb1fffed50c | 2 | * |
| Christopher Haster |
18:2cb1fffed50c | 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
| Christopher Haster |
18:2cb1fffed50c | 4 | * and associated documentation files (the "Software"), to deal in the Software without restriction, |
| Christopher Haster |
18:2cb1fffed50c | 5 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, |
| Christopher Haster |
18:2cb1fffed50c | 6 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
| Christopher Haster |
18:2cb1fffed50c | 7 | * furnished to do so, subject to the following conditions: |
| Christopher Haster |
18:2cb1fffed50c | 8 | * |
| Christopher Haster |
18:2cb1fffed50c | 9 | * The above copyright notice and this permission notice shall be included in all copies or |
| Christopher Haster |
18:2cb1fffed50c | 10 | * substantial portions of the Software. |
| Christopher Haster |
18:2cb1fffed50c | 11 | * |
| Christopher Haster |
18:2cb1fffed50c | 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING |
| Christopher Haster |
18:2cb1fffed50c | 13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| Christopher Haster |
18:2cb1fffed50c | 14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
| Christopher Haster |
18:2cb1fffed50c | 15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| Christopher Haster |
18:2cb1fffed50c | 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| Christopher Haster |
18:2cb1fffed50c | 17 | */ |
| Christopher Haster |
18:2cb1fffed50c | 18 | #include "DnsQuery.h" |
| Christopher Haster |
18:2cb1fffed50c | 19 | #include <stdio.h> |
| Christopher Haster |
18:2cb1fffed50c | 20 | #include <string.h> |
| Christopher Haster |
18:2cb1fffed50c | 21 | |
| Christopher Haster |
18:2cb1fffed50c | 22 | |
| Christopher Haster |
18:2cb1fffed50c | 23 | #define DNS_COUNT (sizeof DNS_IPS / sizeof DNS_IPS[0]) |
| Christopher Haster |
18:2cb1fffed50c | 24 | const char *DNS_IPS[] = { |
| Christopher Haster |
18:2cb1fffed50c | 25 | "8.8.8.8", |
| Christopher Haster |
18:2cb1fffed50c | 26 | "209.244.0.3", |
| Christopher Haster |
18:2cb1fffed50c | 27 | "84.200.69.80", |
| Christopher Haster |
18:2cb1fffed50c | 28 | "8.26.56.26", |
| Christopher Haster |
18:2cb1fffed50c | 29 | "208.67.222.222" |
| Christopher Haster |
18:2cb1fffed50c | 30 | }; |
| Christopher Haster |
18:2cb1fffed50c | 31 | |
| Christopher Haster |
18:2cb1fffed50c | 32 | static bool isIP(const char *host) |
| Christopher Haster |
18:2cb1fffed50c | 33 | { |
| Christopher Haster |
18:2cb1fffed50c | 34 | int i; |
| Christopher Haster |
18:2cb1fffed50c | 35 | |
| Christopher Haster |
18:2cb1fffed50c | 36 | for (i = 0; host[i]; i++) { |
| Christopher Haster |
18:2cb1fffed50c | 37 | if (!(host[i] >= '0' && host[i] <= '9') && host[i] != '.') { |
| Christopher Haster |
18:2cb1fffed50c | 38 | return false; |
| Christopher Haster |
18:2cb1fffed50c | 39 | } |
| Christopher Haster |
18:2cb1fffed50c | 40 | } |
| Christopher Haster |
18:2cb1fffed50c | 41 | |
| Christopher Haster |
18:2cb1fffed50c | 42 | // Ending with '.' garuntees host |
| Christopher Haster |
18:2cb1fffed50c | 43 | if (i > 0 && host[i-1] == '.') { |
| Christopher Haster |
18:2cb1fffed50c | 44 | return false; |
| Christopher Haster |
18:2cb1fffed50c | 45 | } |
| Christopher Haster |
18:2cb1fffed50c | 46 | |
| Christopher Haster |
18:2cb1fffed50c | 47 | return true; |
| Christopher Haster |
18:2cb1fffed50c | 48 | } |
| Christopher Haster |
18:2cb1fffed50c | 49 | |
| Christopher Haster |
18:2cb1fffed50c | 50 | |
| Christopher Haster |
18:2cb1fffed50c | 51 | static bool parseRR(uint8_t *resp, int &c, char *adr) |
| Christopher Haster |
18:2cb1fffed50c | 52 | { |
| Christopher Haster |
18:2cb1fffed50c | 53 | int n = 0; |
| Christopher Haster |
18:2cb1fffed50c | 54 | while((n=resp[c++]) != 0) { |
| Christopher Haster |
18:2cb1fffed50c | 55 | if ((n & 0xc0) != 0) { |
| Christopher Haster |
18:2cb1fffed50c | 56 | // This is a link |
| Christopher Haster |
18:2cb1fffed50c | 57 | c++; |
| Christopher Haster |
18:2cb1fffed50c | 58 | break; |
| Christopher Haster |
18:2cb1fffed50c | 59 | } else { |
| Christopher Haster |
18:2cb1fffed50c | 60 | // skip this segment, not interested in string domain names |
| Christopher Haster |
18:2cb1fffed50c | 61 | c+= n; |
| Christopher Haster |
18:2cb1fffed50c | 62 | } |
| Christopher Haster |
18:2cb1fffed50c | 63 | } |
| Christopher Haster |
18:2cb1fffed50c | 64 | |
| Christopher Haster |
18:2cb1fffed50c | 65 | int TYPE = (((int)resp[c])<<8) + resp[c+1]; |
| Christopher Haster |
18:2cb1fffed50c | 66 | int CLASS = (((int)resp[c+2])<<8) + resp[c+3]; |
| Christopher Haster |
18:2cb1fffed50c | 67 | int RDLENGTH = (((int)resp[c+8])<<8) + resp[c+9]; |
| Christopher Haster |
18:2cb1fffed50c | 68 | |
| Christopher Haster |
18:2cb1fffed50c | 69 | c+= 10; |
| Christopher Haster |
18:2cb1fffed50c | 70 | if ((CLASS == 1) && (TYPE == 1)) { |
| Christopher Haster |
18:2cb1fffed50c | 71 | sprintf(adr,"%d.%d.%d.%d", resp[c], resp[c+1], resp[c+2], resp[c+3]); |
| Christopher Haster |
18:2cb1fffed50c | 72 | c+= RDLENGTH; |
| Christopher Haster |
18:2cb1fffed50c | 73 | return true; |
| Christopher Haster |
18:2cb1fffed50c | 74 | } |
| Christopher Haster |
18:2cb1fffed50c | 75 | c+= RDLENGTH; |
| Christopher Haster |
18:2cb1fffed50c | 76 | |
| Christopher Haster |
18:2cb1fffed50c | 77 | return false; |
| Christopher Haster |
18:2cb1fffed50c | 78 | } |
| Christopher Haster |
18:2cb1fffed50c | 79 | |
| Christopher Haster |
18:2cb1fffed50c | 80 | |
| Christopher Haster |
18:2cb1fffed50c | 81 | static bool resolve(unsigned char *resp, char *ipaddress) |
| Christopher Haster |
18:2cb1fffed50c | 82 | { |
| Christopher Haster |
18:2cb1fffed50c | 83 | |
| Christopher Haster |
18:2cb1fffed50c | 84 | int ID = (((int)resp[0]) <<8) + resp[1]; |
| Christopher Haster |
18:2cb1fffed50c | 85 | int QR = resp[2] >>7; |
| Christopher Haster |
18:2cb1fffed50c | 86 | int Opcode = (resp[2]>>3) & 0x0F; |
| Christopher Haster |
18:2cb1fffed50c | 87 | int RCODE = (resp[3] & 0x0F); |
| Christopher Haster |
18:2cb1fffed50c | 88 | int ANCOUNT = (((int)resp[6])<<8)+ resp[7]; |
| Christopher Haster |
18:2cb1fffed50c | 89 | |
| Christopher Haster |
18:2cb1fffed50c | 90 | if ((ID != 1) || (QR != 1) || (Opcode != 0) || (RCODE != 0)) { |
| Christopher Haster |
18:2cb1fffed50c | 91 | return false; |
| Christopher Haster |
18:2cb1fffed50c | 92 | } |
| Christopher Haster |
18:2cb1fffed50c | 93 | |
| Christopher Haster |
18:2cb1fffed50c | 94 | int c = 12; |
| Christopher Haster |
18:2cb1fffed50c | 95 | int d; |
| Christopher Haster |
18:2cb1fffed50c | 96 | // Skip domain question |
| Christopher Haster |
18:2cb1fffed50c | 97 | while( (d=resp[c++]) != 0) { |
| Christopher Haster |
18:2cb1fffed50c | 98 | c+=d; |
| Christopher Haster |
18:2cb1fffed50c | 99 | } |
| Christopher Haster |
18:2cb1fffed50c | 100 | c+= 4; // skip QTYPE and QCLASS |
| Christopher Haster |
18:2cb1fffed50c | 101 | |
| Christopher Haster |
18:2cb1fffed50c | 102 | // Here comes the resource record |
| Christopher Haster |
18:2cb1fffed50c | 103 | for (int ans = 0 ; ans < ANCOUNT; ans++) { |
| Christopher Haster |
18:2cb1fffed50c | 104 | if (parseRR(resp, c, ipaddress)) { |
| Christopher Haster |
18:2cb1fffed50c | 105 | return true; |
| Christopher Haster |
18:2cb1fffed50c | 106 | } |
| Christopher Haster |
18:2cb1fffed50c | 107 | } |
| Christopher Haster |
18:2cb1fffed50c | 108 | |
| Christopher Haster |
18:2cb1fffed50c | 109 | return false; |
| Christopher Haster |
18:2cb1fffed50c | 110 | } |
| Christopher Haster |
18:2cb1fffed50c | 111 | |
| Christopher Haster |
18:2cb1fffed50c | 112 | static int32_t query(UDPSocket *socket, const SocketAddress &addr, const char *hostname, char *ipaddress) |
| Christopher Haster |
18:2cb1fffed50c | 113 | { |
| Christopher Haster |
18:2cb1fffed50c | 114 | int len = 0; |
| Christopher Haster |
18:2cb1fffed50c | 115 | if (hostname == NULL) { |
| Christopher Haster |
18:2cb1fffed50c | 116 | return false; |
| Christopher Haster |
18:2cb1fffed50c | 117 | } |
| Christopher Haster |
18:2cb1fffed50c | 118 | len = strlen(hostname); |
| Christopher Haster |
18:2cb1fffed50c | 119 | if ((len > 128) || (len == 0)) { |
| Christopher Haster |
18:2cb1fffed50c | 120 | return false; |
| Christopher Haster |
18:2cb1fffed50c | 121 | } |
| Christopher Haster |
18:2cb1fffed50c | 122 | |
| Christopher Haster |
18:2cb1fffed50c | 123 | int packetlen = /* size of HEADER structure */ 12 + /* size of QUESTION Structure */5 + len + 1; |
| Christopher Haster |
18:2cb1fffed50c | 124 | uint8_t *packet = new uint8_t[packetlen]; /* this is the UDP packet to send to the DNS */ |
| Christopher Haster |
18:2cb1fffed50c | 125 | if (packet == NULL) { |
| Christopher Haster |
18:2cb1fffed50c | 126 | return false; |
| Christopher Haster |
18:2cb1fffed50c | 127 | } |
| Christopher Haster |
18:2cb1fffed50c | 128 | |
| Christopher Haster |
18:2cb1fffed50c | 129 | // Fill the header |
| Christopher Haster |
18:2cb1fffed50c | 130 | memset(packet, 0, packetlen); |
| Christopher Haster |
18:2cb1fffed50c | 131 | packet[1] = 1; // ID = 1 |
| Christopher Haster |
18:2cb1fffed50c | 132 | packet[5] = 1; // QDCOUNT = 1 (contains one question) |
| Christopher Haster |
18:2cb1fffed50c | 133 | packet[2] = 1; // recursion requested |
| Christopher Haster |
18:2cb1fffed50c | 134 | |
| Christopher Haster |
18:2cb1fffed50c | 135 | int c = 13; // point to NAME element in question section or request |
| Christopher Haster |
18:2cb1fffed50c | 136 | int cnt = 12; // points to the counter of |
| Christopher Haster |
18:2cb1fffed50c | 137 | packet[cnt] = 0; |
| Christopher Haster |
18:2cb1fffed50c | 138 | for (int i = 0 ; i < len ; i++) { |
| Christopher Haster |
18:2cb1fffed50c | 139 | if (hostname[i] != '.') { |
| Christopher Haster |
18:2cb1fffed50c | 140 | // Copy the character and increment the character counter |
| Christopher Haster |
18:2cb1fffed50c | 141 | packet[cnt]++; |
| Christopher Haster |
18:2cb1fffed50c | 142 | packet[c++] = hostname[i]; |
| Christopher Haster |
18:2cb1fffed50c | 143 | } else { |
| Christopher Haster |
18:2cb1fffed50c | 144 | // Finished with this part, so go to the next |
| Christopher Haster |
18:2cb1fffed50c | 145 | cnt = c++; |
| Christopher Haster |
18:2cb1fffed50c | 146 | packet[cnt] = 0; |
| Christopher Haster |
18:2cb1fffed50c | 147 | } |
| Christopher Haster |
18:2cb1fffed50c | 148 | } |
| Christopher Haster |
18:2cb1fffed50c | 149 | |
| Christopher Haster |
18:2cb1fffed50c | 150 | // Terminate this domain name with a zero entry |
| Christopher Haster |
18:2cb1fffed50c | 151 | packet[c++] = 0; |
| Christopher Haster |
18:2cb1fffed50c | 152 | |
| Christopher Haster |
18:2cb1fffed50c | 153 | // Set QTYPE |
| Christopher Haster |
18:2cb1fffed50c | 154 | packet[c++] = 0; |
| Christopher Haster |
18:2cb1fffed50c | 155 | packet[c++] = 1; |
| Christopher Haster |
18:2cb1fffed50c | 156 | // Set QCLASS |
| Christopher Haster |
18:2cb1fffed50c | 157 | packet[c++] = 0; |
| Christopher Haster |
18:2cb1fffed50c | 158 | packet[c++] = 1; |
| Christopher Haster |
18:2cb1fffed50c | 159 | |
| Christopher Haster |
18:2cb1fffed50c | 160 | |
| Christopher Haster |
18:2cb1fffed50c | 161 | if (socket->sendto(addr, packet, packetlen) < 0) { |
| Christopher Haster |
18:2cb1fffed50c | 162 | delete packet; |
| Christopher Haster |
18:2cb1fffed50c | 163 | return false; |
| Christopher Haster |
18:2cb1fffed50c | 164 | } |
| Christopher Haster |
18:2cb1fffed50c | 165 | delete packet; |
| Christopher Haster |
18:2cb1fffed50c | 166 | |
| Christopher Haster |
18:2cb1fffed50c | 167 | packet = new uint8_t [1024]; |
| Christopher Haster |
18:2cb1fffed50c | 168 | |
| Christopher Haster |
18:2cb1fffed50c | 169 | // Receive the answer from DNS |
| Christopher Haster |
18:2cb1fffed50c | 170 | int response_length = 0; |
| Christopher Haster |
18:2cb1fffed50c | 171 | response_length = socket->recvfrom(NULL, packet, 1024); |
| Christopher Haster |
18:2cb1fffed50c | 172 | |
| Christopher Haster |
18:2cb1fffed50c | 173 | if (response_length > 0 ) { |
| Christopher Haster |
18:2cb1fffed50c | 174 | if (!resolve(packet, ipaddress)) { |
| Christopher Haster |
18:2cb1fffed50c | 175 | delete packet; |
| Christopher Haster |
18:2cb1fffed50c | 176 | return NSAPI_ERROR_DNS_FAILURE; |
| Christopher Haster |
18:2cb1fffed50c | 177 | } |
| Christopher Haster |
18:2cb1fffed50c | 178 | |
| Christopher Haster |
18:2cb1fffed50c | 179 | // cleanup and return |
| Christopher Haster |
18:2cb1fffed50c | 180 | delete packet; |
| Christopher Haster |
18:2cb1fffed50c | 181 | return 0; |
| Christopher Haster |
18:2cb1fffed50c | 182 | } |
| Christopher Haster |
18:2cb1fffed50c | 183 | |
| Christopher Haster |
18:2cb1fffed50c | 184 | delete packet; |
| Christopher Haster |
18:2cb1fffed50c | 185 | return NSAPI_ERROR_DNS_FAILURE; |
| Christopher Haster |
18:2cb1fffed50c | 186 | } |
| Christopher Haster |
18:2cb1fffed50c | 187 | |
| Christopher Haster |
18:2cb1fffed50c | 188 | int32_t dnsQuery(NetworkStack *iface, const char *host, char *ip) |
| Christopher Haster |
18:2cb1fffed50c | 189 | { |
| Christopher Haster |
18:2cb1fffed50c | 190 | if (isIP(host)) { |
| Christopher Haster |
18:2cb1fffed50c | 191 | strcpy(ip, host); |
| Christopher Haster |
18:2cb1fffed50c | 192 | return 0; |
| Christopher Haster |
18:2cb1fffed50c | 193 | } |
| Christopher Haster |
18:2cb1fffed50c | 194 | |
| Christopher Haster |
18:2cb1fffed50c | 195 | UDPSocket sock(iface); |
| Christopher Haster |
18:2cb1fffed50c | 196 | |
| Christopher Haster |
18:2cb1fffed50c | 197 | for (unsigned i = 0; i < DNS_COUNT; i++) { |
| Christopher Haster |
18:2cb1fffed50c | 198 | return query(&sock, SocketAddress(DNS_IPS[0], 53), host, ip); |
| Christopher Haster |
18:2cb1fffed50c | 199 | } |
| Christopher Haster |
18:2cb1fffed50c | 200 | |
| Christopher Haster |
18:2cb1fffed50c | 201 | return NSAPI_ERROR_DNS_FAILURE; |
| Christopher Haster |
18:2cb1fffed50c | 202 | } |
| Christopher Haster |
18:2cb1fffed50c | 203 | |
| Christopher Haster |
18:2cb1fffed50c | 204 | int32_t dnsQuery(UDPSocket *socket, const char *host, char *ip) |
| Christopher Haster |
18:2cb1fffed50c | 205 | { |
| Christopher Haster |
18:2cb1fffed50c | 206 | if (isIP(host)) { |
| Christopher Haster |
18:2cb1fffed50c | 207 | strcpy(ip, host); |
| Christopher Haster |
18:2cb1fffed50c | 208 | return 0; |
| Christopher Haster |
18:2cb1fffed50c | 209 | } |
| Christopher Haster |
18:2cb1fffed50c | 210 | |
| Christopher Haster |
18:2cb1fffed50c | 211 | for (unsigned i = 0; i < DNS_COUNT; i++) { |
| Christopher Haster |
18:2cb1fffed50c | 212 | return query(socket, SocketAddress(DNS_IPS[0], 53), host, ip); |
| Christopher Haster |
18:2cb1fffed50c | 213 | } |
| Christopher Haster |
18:2cb1fffed50c | 214 | |
| Christopher Haster |
18:2cb1fffed50c | 215 | return NSAPI_ERROR_DNS_FAILURE; |
| Christopher Haster |
18:2cb1fffed50c | 216 | } |
