diff --git a/libraries/Network/src/NetworkEvents.cpp b/libraries/Network/src/NetworkEvents.cpp index 87508107a1a..5f24e23a894 100644 --- a/libraries/Network/src/NetworkEvents.cpp +++ b/libraries/Network/src/NetworkEvents.cpp @@ -55,7 +55,7 @@ NetworkEvents::~NetworkEvents(){ } } -static uint32_t _initial_bits = NET_DNS_IDLE_BIT; +static uint32_t _initial_bits = 0; bool NetworkEvents::initNetworkEvents(){ if(!_arduino_event_group){ diff --git a/libraries/Network/src/NetworkEvents.h b/libraries/Network/src/NetworkEvents.h index 788470002fd..eaee117d0fc 100644 --- a/libraries/Network/src/NetworkEvents.h +++ b/libraries/Network/src/NetworkEvents.h @@ -28,9 +28,6 @@ static const int WIFI_SCANNING_BIT = BIT0; static const int WIFI_SCAN_DONE_BIT= BIT1; #endif -static const int NET_DNS_IDLE_BIT = BIT2; -static const int NET_DNS_DONE_BIT = BIT3; - #define NET_HAS_IP6_GLOBAL_BIT 0 ESP_EVENT_DECLARE_BASE(ARDUINO_EVENTS); diff --git a/libraries/Network/src/NetworkInterface.cpp b/libraries/Network/src/NetworkInterface.cpp index e3d0a9e0070..1865246cf76 100644 --- a/libraries/Network/src/NetworkInterface.cpp +++ b/libraries/Network/src/NetworkInterface.cpp @@ -606,6 +606,35 @@ IPAddress NetworkInterface::dnsIP(uint8_t dns_no) const if(esp_netif_get_dns_info(_esp_netif, dns_no?ESP_NETIF_DNS_BACKUP:ESP_NETIF_DNS_MAIN, &d) != ESP_OK){ return IPAddress(); } + if (d.ip.type == ESP_IPADDR_TYPE_V6){ + // IPv6 from 4x uint32_t; byte order based on IPV62STR() in esp_netif_ip_addr.h + log_d("DNS got IPv6: " IPV6STR, IPV62STR(d.ip.u_addr.ip6)); + uint32_t addr0 esp_netif_htonl(d.ip.u_addr.ip6.addr[0]); + uint32_t addr1 esp_netif_htonl(d.ip.u_addr.ip6.addr[1]); + uint32_t addr2 esp_netif_htonl(d.ip.u_addr.ip6.addr[2]); + uint32_t addr3 esp_netif_htonl(d.ip.u_addr.ip6.addr[3]); + return IPAddress( + (uint8_t)(addr0 >> 24) & 0xFF, + (uint8_t)(addr0 >> 16) & 0xFF, + (uint8_t)(addr0 >> 8) & 0xFF, + (uint8_t)addr0 & 0xFF, + (uint8_t)(addr1 >> 24) & 0xFF, + (uint8_t)(addr1 >> 16) & 0xFF, + (uint8_t)(addr1 >> 8) & 0xFF, + (uint8_t)addr1 & 0xFF, + (uint8_t)(addr2 >> 24) & 0xFF, + (uint8_t)(addr2 >> 16) & 0xFF, + (uint8_t)(addr2 >> 8) & 0xFF, + (uint8_t)addr2 & 0xFF, + (uint8_t)(addr3 >> 24) & 0xFF, + (uint8_t)(addr3 >> 16) & 0xFF, + (uint8_t)(addr3 >> 8) & 0xFF, + (uint8_t)addr3 & 0xFF, + d.ip.u_addr.ip6.zone + ); + } + // IPv4 from single uint32_t + log_d("DNS IPv4: " IPSTR, IP2STR(&d.ip.u_addr.ip4)); return IPAddress(d.ip.u_addr.ip4.addr); } diff --git a/libraries/Network/src/NetworkManager.cpp b/libraries/Network/src/NetworkManager.cpp index 779b4bf050f..7aeab8901ec 100644 --- a/libraries/Network/src/NetworkManager.cpp +++ b/libraries/Network/src/NetworkManager.cpp @@ -5,11 +5,11 @@ */ #include "NetworkManager.h" #include "NetworkInterface.h" +#include "IPAddress.h" #include "esp_netif.h" -#include "lwip/ip_addr.h" #include "lwip/dns.h" -#include "esp32-hal-log.h" #include "esp_mac.h" +#include "netdb.h" NetworkManager::NetworkManager(){ @@ -36,43 +36,6 @@ bool NetworkManager::begin(){ return initialized; } -typedef struct gethostbynameParameters { - const char *hostname; - ip_addr_t addr; - uint8_t addr_type; - int result; -} gethostbynameParameters_t; - -/** - * DNS callback - * @param name - * @param ipaddr - * @param callback_arg - */ -static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg) -{ - gethostbynameParameters_t *parameters = static_cast(callback_arg); - if(ipaddr) { - if(parameters->result == 0){ - memcpy(&(parameters->addr), ipaddr, sizeof(ip_addr_t)); - parameters->result = 1; - } - } else { - parameters->result = -1; - } - Network.setStatusBits(NET_DNS_DONE_BIT); -} - -/** - * Callback to execute dns_gethostbyname in lwIP's TCP/IP context - * @param param Parameters for dns_gethostbyname call - */ -static esp_err_t wifi_gethostbyname_tcpip_ctx(void *param) -{ - gethostbynameParameters_t *parameters = static_cast(param); - return dns_gethostbyname_addrtype(parameters->hostname, ¶meters->addr, &wifi_dns_found_callback, parameters, parameters->addr_type); -} - /** * Resolve the given hostname to an IP address. * @param aHostname Name to be resolved @@ -80,10 +43,9 @@ static esp_err_t wifi_gethostbyname_tcpip_ctx(void *param) * @return 1 if aIPAddrString was successfully converted to an IP address, * else error code */ -int NetworkManager::hostByName(const char* aHostname, IPAddress& aResult, bool preferV6) +int NetworkManager::hostByName(const char* aHostname, IPAddress& aResult) { err_t err = ERR_OK; - gethostbynameParameters_t params; // This should generally check if we have a global address assigned to one of the interfaces. // If such address is not assigned, there is no point in trying to get V6 from DNS as we will not be able to reach it. @@ -97,32 +59,41 @@ int NetworkManager::hostByName(const char* aHostname, IPAddress& aResult, bool p } aResult = static_cast(0); - params.hostname = aHostname; - params.addr_type = (preferV6 || hasGlobalV6)?LWIP_DNS_ADDRTYPE_IPV6_IPV4:LWIP_DNS_ADDRTYPE_IPV4; - params.result = 0; - aResult.to_ip_addr_t(&(params.addr)); - - if (!aResult.fromString(aHostname)) { - Network.waitStatusBits(NET_DNS_IDLE_BIT, 16000); - Network.clearStatusBits(NET_DNS_IDLE_BIT | NET_DNS_DONE_BIT); - - err = esp_netif_tcpip_exec(wifi_gethostbyname_tcpip_ctx, ¶ms); - if (err == ERR_OK) { - aResult.from_ip_addr_t(&(params.addr)); - } else if (err == ERR_INPROGRESS) { - Network.waitStatusBits(NET_DNS_DONE_BIT, 15000); //real internal timeout in lwip library is 14[s] - Network.clearStatusBits(NET_DNS_DONE_BIT); - if (params.result == 1) { - aResult.from_ip_addr_t(&(params.addr)); - err = ERR_OK; - } - } - Network.setStatusBits(NET_DNS_IDLE_BIT); + + // First check if the host parses as a literal address + if (aResult.fromString(aHostname)) { + return 1; } - if (err == ERR_OK) { + + const char *servname = "0"; + struct addrinfo *res; + const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }; + err = lwip_getaddrinfo(aHostname, servname, &hints, &res); + if (err == ERR_OK) + { + if (res->ai_family == AF_INET6) + { + struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr; + // As an array of u8_t + aResult = IPAddress(IPv6, ipv6->sin6_addr.s6_addr); + log_d("DNS found IPv6 %s", aResult.toString().c_str()); + } + else + { + struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr; + // As a single u32_t + aResult = IPAddress(ipv4->sin_addr.s_addr); + log_d("DNS found IPv4 %s", aResult.toString().c_str()); + } + + lwip_freeaddrinfo(res); return 1; } - log_e("DNS Failed for '%s' with error '%d' and result '%d'", aHostname, err, params.result); + + log_e("DNS Failed for '%s' with error '%d'", aHostname, err); return err; } diff --git a/libraries/Network/src/NetworkManager.h b/libraries/Network/src/NetworkManager.h index 0202dd95aff..fd783d61a34 100644 --- a/libraries/Network/src/NetworkManager.h +++ b/libraries/Network/src/NetworkManager.h @@ -14,7 +14,7 @@ class NetworkManager : public NetworkEvents, public Printable { NetworkManager(); bool begin(); - int hostByName(const char *aHostname, IPAddress &aResult, bool preferV6=false); + int hostByName(const char *aHostname, IPAddress &aResult); uint8_t * macAddress(uint8_t * mac); String macAddress(); diff --git a/libraries/WiFi/src/WiFiGeneric.cpp b/libraries/WiFi/src/WiFiGeneric.cpp index cf1c2078730..68617935d4d 100644 --- a/libraries/WiFi/src/WiFiGeneric.cpp +++ b/libraries/WiFi/src/WiFiGeneric.cpp @@ -794,9 +794,9 @@ bool WiFiGenericClass::setDualAntennaConfig(uint8_t gpio_ant1, uint8_t gpio_ant2 /* * Deprecated Methods */ -int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult, bool preferV6) +int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult) { - return Network.hostByName(aHostname, aResult, preferV6); + return Network.hostByName(aHostname, aResult); } IPAddress WiFiGenericClass::calculateNetworkID(IPAddress ip, IPAddress subnet) { diff --git a/libraries/WiFi/src/WiFiGeneric.h b/libraries/WiFi/src/WiFiGeneric.h index 2bb73e6b6fb..aa61c935d5d 100644 --- a/libraries/WiFi/src/WiFiGeneric.h +++ b/libraries/WiFi/src/WiFiGeneric.h @@ -115,7 +115,7 @@ class WiFiGenericClass static void useStaticBuffers(bool bufferMode); static bool useStaticBuffers(); - static int hostByName(const char *aHostname, IPAddress &aResult, bool preferV6=false); + static int hostByName(const char *aHostname, IPAddress &aResult); static IPAddress calculateNetworkID(IPAddress ip, IPAddress subnet); static IPAddress calculateBroadcast(IPAddress ip, IPAddress subnet);