DnsQuery for NetworkSocketAPI
Fork of DnsQuery by
Diff: DnsQuery.cpp
- Revision:
- 10:0fe2c42a0261
- Parent:
- 9:16e5208cc4ef
- Child:
- 12:e23ef3dab4b9
--- a/DnsQuery.cpp Sun Feb 28 11:23:59 2016 -0600 +++ b/DnsQuery.cpp Sun Feb 28 22:07:29 2016 -0600 @@ -37,57 +37,129 @@ #endif - -DnsQuery::DnsQuery(UDPSocket *sock,const char* hostname, char* ipaddress) -{ - socket = sock; - this->getHostByName(hostname, ipaddress); -} - -bool DnsQuery::getHostByName(const char* hostname, char* resolvedIp) -{ - if (isIP(hostname)) { - strcpy(resolvedIp, hostname); - return true; - } +#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" +}; - const char * dnsIPs[] = { - "8.8.8.8", - "209.244.0.3", - "84.200.69.80", - "8.26.56.26", - "208.67.222.222" - }; - for(int i = 0; i<5; i++){ - _dnsip = dnsIPs[i]; - if(this->getIP(hostname, resolvedIp)){ - return true; - } - - } - return false; - -} - -bool DnsQuery::isIP(const char* hostname) const +static bool isIP(const char *host) { int i; - for (i = 0; hostname[i]; i++) { - if (!(hostname[i] >= '0' && hostname[i] <= '9') && hostname[i] != '.') { + for (i = 0; host[i]; i++) { + if (!(host[i] >= '0' && host[i] <= '9') && host[i] != '.') { return false; } } - // Ending with '.' garuntees hostname - if (i > 0 && hostname[i-1] == '.') { + // Ending with '.' garuntees host + if (i > 0 && host[i-1] == '.') { return false; } return true; } -bool DnsQuery::getIP(const char* hostname, char* ipaddress) + +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 { + c+= n; // skip this segment, not interested in string domain names + } + } + + 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]; + + INFO("Record of TYPE=%d and CLASS=%d detected !", TYPE, CLASS); + 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; + } else { + } + 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]; + + INFO("Resolving response : ID = %d, QR = %d, Opcode = %d, RCODE = %d", ID, QR, Opcode, RCODE); + if ((ID != 1) || (QR != 1) || (Opcode != 0) || (RCODE != 0)) { + ERR("Received non matching response from DNS !"); + 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; +} + + +int32_t dnsQuery(NetworkInterface *iface, const char *host, char *ip) +{ + if (isIP(host)) { + strcpy(ip, host); + return 0; + } + + UDPSocket sock(iface); + int32_t err; + + for (unsigned i = 0; i < DNS_COUNT; i++) { + err = sock.open(DNS_IPS[0], 53); + if (err < 0) { + return err; + } + + err = dnsQuery(&sock, host, ip); + if (err >= 0) { + return sock.close(); + } else if (err != NS_ERROR_DNS_FAILURE) { + sock.close(); + return err; + } + } + + sock.close(); + return NS_ERROR_DNS_FAILURE; +} + +int32_t dnsQuery(UDPSocket *socket, const char *hostname, char *ipaddress) { INFO("%s", hostname); int len = 0; @@ -132,11 +204,8 @@ // Set QCLASS packet[c++] = 0; packet[c++] = 1; - - - // Ready to send to DNS - socket->open(_dnsip, 53); + INFO("Sending packet of length %d",packetlen); /* for( int i = 0 ; i < c ; i++) { @@ -162,85 +231,20 @@ */ if (response_length > 0 ) { if (!resolve(packet, ipaddress)) { - socket->close(); delete packet; ERR("NO IP FOUND\n"); - return false; + return NS_ERROR_DNS_FAILURE; } // cleanup and return delete packet; - socket->close(); - return true; + return 0; } else { ERR("SocketRecvFrom returned %d !", response_length); } - socket->close(); delete packet; ERR("NO IP FOUND\n"); - return false; + return NS_ERROR_DNS_FAILURE; } -bool DnsQuery::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]; - - INFO("Resolving response : ID = %d, QR = %d, Opcode = %d, RCODE = %d", ID, QR, Opcode, RCODE); - if ((ID != 1) || (QR != 1) || (Opcode != 0) || (RCODE != 0)) { - ERR("Received non matching response from DNS !"); - 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; -} - -bool DnsQuery::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 { - c+= n; // skip this segment, not interested in string domain names - } - } - - 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]; - - INFO("Record of TYPE=%d and CLASS=%d detected !", TYPE, CLASS); - 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; - } else { - } - c+= RDLENGTH; - - return false; -}