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 01d7efb

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 0a47f34 commit 01d7efb
Copy full SHA for 01d7efb

File tree

1 file changed

+51
-18
lines changed
Filter options

1 file changed

+51
-18
lines changed

‎libraries/Network/src/NetworkManager.cpp

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

1515
}
1616

17+
NetworkInterface * getNetifByID(Network_Interface_ID id);
18+
1719
bool NetworkManager::begin(){
1820
static bool initialized = false;
1921
if(!initialized){
@@ -44,33 +46,66 @@ bool NetworkManager::begin(){
4446
*/
4547
int NetworkManager::hostByName(const char* aHostname, IPAddress& aResult)
4648
{
49+
static bool hasGlobalV6 = false;
4750
err_t err = ERR_OK;
51+
const char *servname = "0";
52+
struct addrinfo *res;
53+
aResult = static_cast<uint32_t>(0);
4854

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

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

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

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

133-
NetworkInterface * getNetifByID(Network_Interface_ID id);
134-
135168
bool NetworkManager::setDefaultInterface(NetworkInterface & ifc)
136169
{
137170
return ifc.setDefault();

0 commit comments

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