@@ -47,55 +47,90 @@ int NetworkManager::hostByName(const char* aHostname, IPAddress& aResult, bool p
47
47
{
48
48
// IDEA: Rename to getAddressInfo() ?
49
49
50
- err_t err = ERR_OK;
51
-
52
- // This should generally check if we have a global address assigned to one of the interfaces.
53
- // 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.
54
- // That is of course, if 'preferV6' is not set to true
50
+ err_t err = -1 ;
51
+ const char *servname = " 0" ;
52
+ struct addrinfo *res;
55
53
static bool hasGlobalV6 = false ;
56
- bool hasGlobalV6Now = false ;// ToDo: implement this!
54
+
55
+ aResult = static_cast <uint32_t >(0 );
56
+
57
+ // First check if the host parses as a literal address
58
+ if (aResult.fromString (aHostname)) {
59
+ return 1 ;
60
+ }
61
+
62
+ // **Workaround**
63
+ // LWIP AF_UNSPEC always prefers IPv4 and doesn't check what network is
64
+ // available. See https://github.com/espressif/esp-idf/issues/13255
65
+ // Until that is fixed, as a work around if we have a global scope IPv6,
66
+ // then we check IPv6 only first.
67
+
68
+ // Iterate over active interfaces, and find if we have any global scope IPv6
69
+ bool hasGlobalV6Now = false ;
70
+ esp_netif_t *netif = NULL ;
71
+ while ((netif = esp_netif_next_unsafe (netif)) != NULL ) {
72
+ esp_ip6_addr_t ip6[CONFIG_LWIP_IPV6_NUM_ADDRESSES];
73
+ int ip6_addrs = esp_netif_get_all_ip6 (netif, ip6);
74
+ for (int j = 0 ; j < ip6_addrs; ++j) {
75
+ // Both global and unique local addresses have global scope.
76
+ // ULA assumes either private DNS or NAT66 (same assumption as IPv4 private address ranges).
77
+ esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type (&(ip6[j]));
78
+ if (ipv6_type == ESP_IP6_ADDR_IS_GLOBAL || ipv6_type == ESP_IP6_ADDR_IS_UNIQUE_LOCAL) {
79
+ hasGlobalV6Now = true ;
80
+ break ;
81
+ }
82
+ }
83
+ if (hasGlobalV6Now) break ;
84
+ }
85
+
86
+ // Clear DNS cache if the flag has changed
57
87
if (hasGlobalV6 != hasGlobalV6Now){
58
88
hasGlobalV6 = hasGlobalV6Now;
59
89
dns_clear_cache ();
60
90
log_d (" Clearing DNS cache" );
61
91
}
62
92
63
- aResult = static_cast <uint32_t >(0 );
64
-
65
- // First check if the host parses as a literal address
66
- if (!aResult.fromString (aHostname)) {
67
- const char *servname = " 0" ;
68
- struct addrinfo *res;
69
- const struct addrinfo hints = {
70
- .ai_family = AF_UNSPEC,
93
+ if (hasGlobalV6) {
94
+ const struct addrinfo hints6 = {
95
+ .ai_family = AF_INET6,
71
96
.ai_socktype = SOCK_STREAM,
72
97
};
73
- err = lwip_getaddrinfo (aHostname, servname, &hints, &res);
74
- if (err == 0 )
75
- {
76
- if (res->ai_family == AF_INET6)
77
- {
78
- struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr ;
79
- // As an array of u8_t
80
- aResult = IPAddress (IPv6, ipv6->sin6_addr .s6_addr );
81
- log_d (" DNS found IPv6 %s" , aResult.toString ().c_str ());
82
- }
83
- else if (res->ai_family == AF_INET)
84
- {
85
- struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr ;
86
- // As a single u32_t
87
- aResult = IPAddress (ipv4->sin_addr .s_addr );
88
- log_d (" DNS found IPv4 %s" , aResult.toString ().c_str ());
89
- }
90
- else
91
- {
92
- err = -1 ;
93
- }
98
+ err = lwip_getaddrinfo (aHostname, servname, &hints6, &res);
94
99
100
+ if (err == ERR_OK)
101
+ {
102
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr ;
103
+ // As an array of u8_t
104
+ aResult = IPAddress (IPv6, ipv6->sin6_addr .s6_addr );
105
+ log_d (" DNS found first IPv6 %s" , aResult.toString ().c_str ());
95
106
lwip_freeaddrinfo (res);
107
+ return 1 ;
96
108
}
97
109
}
98
- if (err == ERR_OK) {
110
+ // **End Workaround**
111
+
112
+ const struct addrinfo hints = {
113
+ .ai_family = AF_UNSPEC,
114
+ .ai_socktype = SOCK_STREAM,
115
+ };
116
+ err = lwip_getaddrinfo (aHostname, servname, &hints, &res);
117
+ if (err == ERR_OK)
118
+ {
119
+ if (res->ai_family == AF_INET6)
120
+ {
121
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr ;
122
+ // As an array of u8_t
123
+ aResult = IPAddress (IPv6, ipv6->sin6_addr .s6_addr );
124
+ log_d (" DNS found any IPv6 %s" , aResult.toString ().c_str ());
125
+ }
126
+ else
127
+ {
128
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr ;
129
+ // As a single u32_t
130
+ aResult = IPAddress (ipv4->sin_addr .s_addr );
131
+ log_d (" DNS found any IPv4 %s" , aResult.toString ().c_str ());
132
+ }
133
+ lwip_freeaddrinfo (res);
99
134
return 1 ;
100
135
}
101
136
log_e (" DNS Failed for '%s' with error '%d'" , aHostname, err);
0 commit comments