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