Library to resolve text URLs to IP addresses (IPv4)

Dependents:   NetworkSocketAPI NetworkSocketAPI Nucleo-AWS-IoT-mbed

Files at this revision

API Documentation at this revision

Comitter:
Christopher Haster
Date:
Tue Apr 19 18:29:55 2016 -0500
Parent:
17:18a6b52be896
Commit message:
Matched changes to NSAPI

Changed in this revision

DnsQuery.cpp Show annotated file Show diff for this revision Revisions of this file
DnsQuery.h Show annotated file Show diff for this revision Revisions of this file
--- a/DnsQuery.cpp	Tue Apr 05 23:39:38 2016 +0000
+++ b/DnsQuery.cpp	Tue Apr 19 18:29:55 2016 -0500
@@ -1,216 +1,216 @@
-/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
- * and associated documentation files (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge, publish, distribute,
- * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or
- * substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
- * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "DnsQuery.h"
-#include <stdio.h>
-#include <string.h>
-
-
-#define DNS_COUNT (sizeof DNS_IPS / sizeof DNS_IPS[0])
-const char *DNS_IPS[] = {
-    "8.8.8.8",
-    "209.244.0.3",
-    "84.200.69.80",
-    "8.26.56.26",
-    "208.67.222.222"
-};
-
-static bool isIP(const char *host)
-{
-    int i;
-
-    for (i = 0; host[i]; i++) {
-        if (!(host[i] >= '0' && host[i] <= '9') && host[i] != '.') {
-            return false;
-        }
-    }
-
-    // Ending with '.' garuntees host
-    if (i > 0 && host[i-1] == '.') {
-        return false;
-    }
-
-    return true;
-}
-
-
-static bool parseRR(uint8_t *resp, int &c, char *adr)
-{
-    int n = 0;
-    while((n=resp[c++]) != 0) {
-        if ((n & 0xc0) != 0) {
-            //  This is a link
-            c++;
-            break;
-        } else {
-            //  skip this segment, not interested in string domain names
-            c+= n;
-        }
-    }
-
-    int TYPE = (((int)resp[c])<<8) + resp[c+1];
-    int CLASS = (((int)resp[c+2])<<8) + resp[c+3];
-    int RDLENGTH = (((int)resp[c+8])<<8) + resp[c+9];
-
-    c+= 10;
-    if ((CLASS == 1) && (TYPE == 1)) {
-        sprintf(adr,"%d.%d.%d.%d", resp[c], resp[c+1], resp[c+2], resp[c+3]);
-        c+= RDLENGTH;
-        return true;
-    }
-    c+= RDLENGTH;
-
-    return false;
-}
-
-
-static bool resolve(unsigned char *resp, char *ipaddress)
-{
-
-    int ID = (((int)resp[0]) <<8) + resp[1];
-    int QR = resp[2] >>7;
-    int Opcode = (resp[2]>>3) & 0x0F;
-    int RCODE = (resp[3] & 0x0F);
-    int ANCOUNT = (((int)resp[6])<<8)+ resp[7];
-
-    if ((ID != 1) || (QR != 1) || (Opcode != 0) || (RCODE != 0)) {
-        return false;
-    }
-
-    int c = 12;
-    int d;
-    //  Skip domain question
-    while(  (d=resp[c++]) != 0) {
-        c+=d;
-    }
-    c+= 4; //   skip QTYPE and QCLASS
-
-    //  Here comes the resource record
-    for (int ans = 0 ; ans < ANCOUNT; ans++) {
-        if (parseRR(resp, c, ipaddress)) {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-static int32_t query(UDPSocket *socket, const SocketAddress &addr, const char *hostname, char *ipaddress)
-{
-    int len = 0;
-    if (hostname == NULL) {
-        return false;
-    }
-    len = strlen(hostname);
-    if ((len > 128) || (len == 0)) {
-        return false;
-    }
-
-    int packetlen = /* size of HEADER structure */ 12 + /* size of QUESTION Structure */5 + len + 1;
-    uint8_t *packet = new uint8_t[packetlen]; /* this is the UDP packet to send to the DNS */
-    if (packet == NULL) {
-        return false;
-    }
-
-    //  Fill the header
-    memset(packet, 0, packetlen);
-    packet[1] = 1;      //  ID = 1
-    packet[5] = 1;      // QDCOUNT = 1 (contains one question)
-    packet[2] = 1;      // recursion requested
-
-    int c = 13;         //  point to NAME element in question section or request
-    int cnt = 12;       //  points to the counter of
-    packet[cnt] = 0;
-    for (int i = 0 ; i < len ; i++) {
-        if (hostname[i] != '.') {
-            //  Copy the character and increment the character counter
-            packet[cnt]++;
-            packet[c++] = hostname[i];
-        } else {
-            //  Finished with this part, so go to the next
-            cnt = c++;
-            packet[cnt] = 0;
-        }
-    }
-
-    //  Terminate this domain name with a zero entry
-    packet[c++] = 0;
-
-    //  Set QTYPE
-    packet[c++] = 0;
-    packet[c++] = 1;
-    //  Set QCLASS
-    packet[c++] = 0;
-    packet[c++] = 1;
-
-
-    if (socket->sendto(addr, packet, packetlen) < 0) {
-        delete packet;
-        return false;
-    }
-    delete packet;
-
-    packet = new uint8_t [1024];
-
-    //  Receive the answer from DNS
-    int response_length = 0;
-    response_length = socket->recvfrom(NULL, packet, 1024);
-
-    if (response_length > 0 ) {
-        if (!resolve(packet, ipaddress)) {
-            delete packet;
-            return NSAPI_ERROR_DNS_FAILURE;
-        }
-        
-        //  cleanup and return
-        delete packet;
-        return 0;
-    }
-    
-    delete packet;
-    return NSAPI_ERROR_DNS_FAILURE;
-}
-
-int32_t dnsQuery(NetworkInterface *iface, const char *host, char *ip)
-{
-    if (isIP(host)) {
-        strcpy(ip, host);
-        return 0;
-    }
-
-    UDPSocket sock(iface);
-
-    for (unsigned i = 0; i < DNS_COUNT; i++) {
-        return query(&sock, SocketAddress(DNS_IPS[0], 53), host, ip);
-    }
-
-    return NSAPI_ERROR_DNS_FAILURE;
-}
-
-int32_t dnsQuery(UDPSocket *socket, const char *host, char *ip)
-{
-    if (isIP(host)) {
-        strcpy(ip, host);
-        return 0;
-    }
-
-    for (unsigned i = 0; i < DNS_COUNT; i++) {
-        return query(socket, SocketAddress(DNS_IPS[0], 53), host, ip);
-    }
-
-    return NSAPI_ERROR_DNS_FAILURE;
-}
+/* Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "DnsQuery.h"
+#include <stdio.h>
+#include <string.h>
+
+
+#define DNS_COUNT (sizeof DNS_IPS / sizeof DNS_IPS[0])
+const char *DNS_IPS[] = {
+    "8.8.8.8",
+    "209.244.0.3",
+    "84.200.69.80",
+    "8.26.56.26",
+    "208.67.222.222"
+};
+
+static bool isIP(const char *host)
+{
+    int i;
+
+    for (i = 0; host[i]; i++) {
+        if (!(host[i] >= '0' && host[i] <= '9') && host[i] != '.') {
+            return false;
+        }
+    }
+
+    // Ending with '.' garuntees host
+    if (i > 0 && host[i-1] == '.') {
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool parseRR(uint8_t *resp, int &c, char *adr)
+{
+    int n = 0;
+    while((n=resp[c++]) != 0) {
+        if ((n & 0xc0) != 0) {
+            //  This is a link
+            c++;
+            break;
+        } else {
+            //  skip this segment, not interested in string domain names
+            c+= n;
+        }
+    }
+
+    int TYPE = (((int)resp[c])<<8) + resp[c+1];
+    int CLASS = (((int)resp[c+2])<<8) + resp[c+3];
+    int RDLENGTH = (((int)resp[c+8])<<8) + resp[c+9];
+
+    c+= 10;
+    if ((CLASS == 1) && (TYPE == 1)) {
+        sprintf(adr,"%d.%d.%d.%d", resp[c], resp[c+1], resp[c+2], resp[c+3]);
+        c+= RDLENGTH;
+        return true;
+    }
+    c+= RDLENGTH;
+
+    return false;
+}
+
+
+static bool resolve(unsigned char *resp, char *ipaddress)
+{
+
+    int ID = (((int)resp[0]) <<8) + resp[1];
+    int QR = resp[2] >>7;
+    int Opcode = (resp[2]>>3) & 0x0F;
+    int RCODE = (resp[3] & 0x0F);
+    int ANCOUNT = (((int)resp[6])<<8)+ resp[7];
+
+    if ((ID != 1) || (QR != 1) || (Opcode != 0) || (RCODE != 0)) {
+        return false;
+    }
+
+    int c = 12;
+    int d;
+    //  Skip domain question
+    while(  (d=resp[c++]) != 0) {
+        c+=d;
+    }
+    c+= 4; //   skip QTYPE and QCLASS
+
+    //  Here comes the resource record
+    for (int ans = 0 ; ans < ANCOUNT; ans++) {
+        if (parseRR(resp, c, ipaddress)) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+static int32_t query(UDPSocket *socket, const SocketAddress &addr, const char *hostname, char *ipaddress)
+{
+    int len = 0;
+    if (hostname == NULL) {
+        return false;
+    }
+    len = strlen(hostname);
+    if ((len > 128) || (len == 0)) {
+        return false;
+    }
+
+    int packetlen = /* size of HEADER structure */ 12 + /* size of QUESTION Structure */5 + len + 1;
+    uint8_t *packet = new uint8_t[packetlen]; /* this is the UDP packet to send to the DNS */
+    if (packet == NULL) {
+        return false;
+    }
+
+    //  Fill the header
+    memset(packet, 0, packetlen);
+    packet[1] = 1;      //  ID = 1
+    packet[5] = 1;      // QDCOUNT = 1 (contains one question)
+    packet[2] = 1;      // recursion requested
+
+    int c = 13;         //  point to NAME element in question section or request
+    int cnt = 12;       //  points to the counter of
+    packet[cnt] = 0;
+    for (int i = 0 ; i < len ; i++) {
+        if (hostname[i] != '.') {
+            //  Copy the character and increment the character counter
+            packet[cnt]++;
+            packet[c++] = hostname[i];
+        } else {
+            //  Finished with this part, so go to the next
+            cnt = c++;
+            packet[cnt] = 0;
+        }
+    }
+
+    //  Terminate this domain name with a zero entry
+    packet[c++] = 0;
+
+    //  Set QTYPE
+    packet[c++] = 0;
+    packet[c++] = 1;
+    //  Set QCLASS
+    packet[c++] = 0;
+    packet[c++] = 1;
+
+
+    if (socket->sendto(addr, packet, packetlen) < 0) {
+        delete packet;
+        return false;
+    }
+    delete packet;
+
+    packet = new uint8_t [1024];
+
+    //  Receive the answer from DNS
+    int response_length = 0;
+    response_length = socket->recvfrom(NULL, packet, 1024);
+
+    if (response_length > 0 ) {
+        if (!resolve(packet, ipaddress)) {
+            delete packet;
+            return NSAPI_ERROR_DNS_FAILURE;
+        }
+        
+        //  cleanup and return
+        delete packet;
+        return 0;
+    }
+    
+    delete packet;
+    return NSAPI_ERROR_DNS_FAILURE;
+}
+
+int32_t dnsQuery(NetworkStack *iface, const char *host, char *ip)
+{
+    if (isIP(host)) {
+        strcpy(ip, host);
+        return 0;
+    }
+
+    UDPSocket sock(iface);
+
+    for (unsigned i = 0; i < DNS_COUNT; i++) {
+        return query(&sock, SocketAddress(DNS_IPS[0], 53), host, ip);
+    }
+
+    return NSAPI_ERROR_DNS_FAILURE;
+}
+
+int32_t dnsQuery(UDPSocket *socket, const char *host, char *ip)
+{
+    if (isIP(host)) {
+        strcpy(ip, host);
+        return 0;
+    }
+
+    for (unsigned i = 0; i < DNS_COUNT; i++) {
+        return query(socket, SocketAddress(DNS_IPS[0], 53), host, ip);
+    }
+
+    return NSAPI_ERROR_DNS_FAILURE;
+}
--- a/DnsQuery.h	Tue Apr 05 23:39:38 2016 +0000
+++ b/DnsQuery.h	Tue Apr 19 18:29:55 2016 -0500
@@ -1,41 +1,41 @@
-/* 
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
- * and associated documentation files (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge, publish, distribute,
- * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or
- * substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
- * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#ifndef __DNSQUERY_H__
-#define __DNSQUERY_H__
-
-#include "NetworkInterface.h"
-#include "UDPSocket.h"
-
-
-/** Function dnsQuery implements the functionality to query a domain name 
-  * server for an IP-Address of a given hostname.
-  * @param iface : Network interface to use for DNS resolution.
-  * @param sock : Previously opened socket to use for DNS resolution.
-  * @param hostname : The hostname of interest as a string.
-  *     Format must be without http:// or www. IE google.com, mbed.org, etc.
-  *     If a standard IP Address is passed, it will be copied into ip unmodified.
-  * @param ipaddress : A reference to a IPADDRESS_t object which will receive 
-  *     the resolved IP Address of the host in question.
-  * @returns 0 on succes, NS_DNS_FAILURE if host is not found,
-  *     or a negative value for other errors.
-  */
-int32_t dnsQuery(NetworkInterface *iface, const char *host, char *ip);
-int32_t dnsQuery(UDPSocket *sock, const char *host, char *ip);
-
-
-#endif // __DNSQUERY_H__
+/* 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __DNSQUERY_H__
+#define __DNSQUERY_H__
+
+#include "NetworkStack.h"
+#include "UDPSocket.h"
+
+
+/** Function dnsQuery implements the functionality to query a domain name 
+  * server for an IP-Address of a given hostname.
+  * @param iface : Network interface to use for DNS resolution.
+  * @param sock : Previously opened socket to use for DNS resolution.
+  * @param hostname : The hostname of interest as a string.
+  *     Format must be without http:// or www. IE google.com, mbed.org, etc.
+  *     If a standard IP Address is passed, it will be copied into ip unmodified.
+  * @param ipaddress : A reference to a IPADDRESS_t object which will receive 
+  *     the resolved IP Address of the host in question.
+  * @returns 0 on succes, NS_DNS_FAILURE if host is not found,
+  *     or a negative value for other errors.
+  */
+int32_t dnsQuery(NetworkStack *iface, const char *host, char *ip);
+int32_t dnsQuery(UDPSocket *sock, const char *host, char *ip);
+
+
+#endif // __DNSQUERY_H__