Skip to content

Commit 7ffd232

Browse files
committed
feat(example/protocols): Add DNS fuction to check IPv6 first if relevant
If we have an IPv6 global scope address (on any interface), then check IPv6 first, and if that fails fall back to IPv4. Global scope includes ULA (if ULA is configured, similar to private address ranges, DNS is expected). If we don't have a global IPv6, then only check IPv4.
1 parent be06a6f commit 7ffd232

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

examples/common_components/protocol_examples_common/connect.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "freertos/event_groups.h"
1919
#include "lwip/err.h"
2020
#include "lwip/sys.h"
21+
#include "lwip/netdb.h"
2122

2223
static const char *TAG = "example_common";
2324

@@ -136,3 +137,46 @@ esp_err_t example_disconnect(void)
136137
#endif
137138
return ESP_OK;
138139
}
140+
141+
esp_err_t example_getaddrinfo(const char *nodename, const char *servname, struct addrinfo **res)
142+
{
143+
#if CONFIG_EXAMPLE_CONNECT_IPV6
144+
// Iterate over active interfaces, and find if we have any global scope IPv6
145+
bool has_global_scope_ipv6 = false;
146+
esp_netif_t *netif = NULL;
147+
while ((netif = esp_netif_next_unsafe(netif)) != NULL) {
148+
esp_ip6_addr_t ip6[MAX_IP6_ADDRS_PER_NETIF];
149+
int ip6_addrs = esp_netif_get_all_ip6(netif, ip6);
150+
for (int j = 0; j < ip6_addrs; ++j) {
151+
// Both global and unique local addresses have global scope.
152+
// ULA assumes either private DNS or NAT66 (same assumpation as IPv4 private address ranges).
153+
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&(ip6[j]));
154+
if (ipv6_type == ESP_IP6_ADDR_IS_GLOBAL || ipv6_type == ESP_IP6_ADDR_IS_UNIQUE_LOCAL) {
155+
has_global_scope_ipv6 = true;
156+
break;
157+
}
158+
}
159+
if (has_global_scope_ipv6) break;
160+
}
161+
162+
if (has_global_scope_ipv6) {
163+
const struct addrinfo hints6 = {
164+
.ai_family = AF_INET6,
165+
.ai_socktype = SOCK_STREAM,
166+
};
167+
ESP_LOGI(TAG, "IPv6 DNS lookup");
168+
int err6 = getaddrinfo(nodename, servname, &hints6, res);
169+
if(err6 == 0) return err6;
170+
ESP_LOGI(TAG, "- IPv6 DNS lookup failed, trying IPv4 lookup");
171+
}
172+
#endif
173+
174+
const struct addrinfo hints4 = {
175+
.ai_family = AF_INET,
176+
.ai_socktype = SOCK_STREAM,
177+
};
178+
ESP_LOGI(TAG, "IPv4 DNS lookup");
179+
int err4 = getaddrinfo(nodename, servname, &hints4, res);
180+
181+
return err4;
182+
}

examples/common_components/protocol_examples_common/include/protocol_examples_common.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "esp_eth.h"
1818
#endif
1919
#endif // !CONFIG_IDF_TARGET_LINUX
20+
#include "lwip/netdb.h"
2021

2122
#ifdef __cplusplus
2223
extern "C" {
@@ -77,6 +78,14 @@ esp_err_t example_disconnect(void);
7778
*/
7879
esp_err_t example_configure_stdin_stdout(void);
7980

81+
/**
82+
* @brief Resolve best destination address based on available source addresses
83+
*
84+
* If a global IPv6 address is available, this tries to get an IPv6 address,
85+
* otherwise it falls back to IPv4.
86+
*/
87+
esp_err_t example_getaddrinfo(const char *nodename, const char *servname, struct addrinfo **res);
88+
8089
/**
8190
* @brief Returns esp-netif pointer created by example_connect() described by
8291
* the supplied desc field

0 commit comments

Comments
 (0)