Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2a8ff99

Browse filesBrowse files
committed
fix(dns): Fix IPv6-only network, by IPv6 preference if you have public address
Work around because AF_UNSPEC does not check available addresses when determining result. If you have a global scope IPv6 address, then first check for IPv6 DNS result; if you don't have an IPv6, or there is no IPv6 result, then check IPv4. This allows IPv6-only networks to connect to dual-stack destinations, as they will get the IPv6 address (rather than the unusable IPv4). It also means a dual-stack host to a dual-stack destination will preference IPv6. There is no effect if you are on an IPv4-only network, or it is an IPv4-only destination.
1 parent dcc3076 commit 2a8ff99
Copy full SHA for 2a8ff99

File tree

1 file changed

+50
-17
lines changed
Filter options

1 file changed

+50
-17
lines changed

‎libraries/Network/src/NetworkManager.cpp

Copy file name to clipboardExpand all lines: libraries/Network/src/NetworkManager.cpp
+50-17Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ NetworkManager::NetworkManager(){
1515

1616
}
1717

18+
NetworkInterface * getNetifByID(Network_Interface_ID id);
19+
1820
bool NetworkManager::begin(){
1921
static bool initialized = false;
2022
if(!initialized){
@@ -45,33 +47,66 @@ bool NetworkManager::begin(){
4547
*/
4648
int NetworkManager::hostByName(const char* aHostname, IPAddress& aResult)
4749
{
50+
static bool hasGlobalV6 = false;
4851
err_t err = ERR_OK;
52+
const char *servname = "0";
53+
struct addrinfo *res;
54+
aResult = static_cast<uint32_t>(0);
4955

50-
// This should generally check if we have a global address assigned to one of the interfaces.
51-
// 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.
52-
// That is of course, if 'preferV6' is not set to true
53-
static bool hasGlobalV6 = false;
56+
// First check if the host parses as a literal address
57+
if (aResult.fromString(aHostname)) {
58+
return 1;
59+
}
60+
61+
// **Workaround**
62+
// LWIP AF_UNSPEC always prefers IPv4 and doesn't check what network is
63+
// available. See https://github.com/espressif/esp-idf/issues/13255
64+
// Until that is fixed, as a work around if we have a global scope IPv6,
65+
// then we check IPv6 only first.
66+
67+
// This checks if we have a global address assigned to one of the interfaces.
68+
// If such address is assigned, then we trying to get V6 from DNS first.
5469
bool hasGlobalV6Now = false;//ToDo: implement this!
70+
for (int i = 0; i < ESP_NETIF_ID_MAX; ++i){
71+
NetworkInterface * iface = getNetifByID((Network_Interface_ID)i);
72+
if(iface != NULL && iface->hasGlobalIPv6()){
73+
hasGlobalV6Now = true;
74+
}
75+
if (hasGlobalV6Now){
76+
break;
77+
}
78+
}
79+
80+
// Clear DNS cache if the flag has changed
5581
if(hasGlobalV6 != hasGlobalV6Now){
5682
hasGlobalV6 = hasGlobalV6Now;
5783
dns_clear_cache();
5884
log_d("Clearing DNS cache");
5985
}
6086

61-
aResult = static_cast<uint32_t>(0);
87+
if (hasGlobalV6) {
88+
const struct addrinfo hints6 = {
89+
.ai_family = AF_INET6,
90+
.ai_socktype = SOCK_STREAM,
91+
};
92+
err = lwip_getaddrinfo(aHostname, servname, &hints6, &res);
6293

63-
// First check if the host parses as a literal address
64-
if (aResult.fromString(aHostname)) {
65-
return 1;
94+
if (err == ERR_OK)
95+
{
96+
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr;
97+
// As an array of u8_t
98+
aResult = IPAddress(IPv6, ipv6->sin6_addr.s6_addr);
99+
log_d("DNS found IPv6 first %s", aResult.toString().c_str());
100+
lwip_freeaddrinfo(res);
101+
return 1;
102+
}
66103
}
104+
// **End Workaround**
67105

68-
const char *servname = "0";
69-
struct addrinfo *res;
70-
struct addrinfo hints;
71-
memset(&hints, 0, sizeof(hints));
72-
hints.ai_family = AF_UNSPEC;
73-
hints.ai_socktype = SOCK_STREAM;
74-
106+
const struct addrinfo hints = {
107+
.ai_family = AF_UNSPEC,
108+
.ai_socktype = SOCK_STREAM,
109+
};
75110
err = lwip_getaddrinfo(aHostname, servname, &hints, &res);
76111
if (err == ERR_OK)
77112
{
@@ -131,8 +166,6 @@ bool NetworkManager::setHostname(const char * name)
131166
return true;
132167
}
133168

134-
NetworkInterface * getNetifByID(Network_Interface_ID id);
135-
136169
size_t NetworkManager::printTo(Print & out) const {
137170
size_t bytes = 0;
138171

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.