Compare commits

...
Author SHA1 Message Date
J. Nick Koston a4bbea04b9 Merge remote-tracking branch 'origin/dev' into openthread-dns64-ipv6-literal
# Conflicts:
#	esphome/components/openthread/openthread_esp.cpp
2026-10-13 09:59:12 -10:00
J. Nick Koston e2fe0ce715 Merge remote-tracking branch 'upstream/dev' into HEAD 2026-09-17 08:47:58 -05:00
J. Nick Koston 5c7285e936 Merge remote-tracking branch 'upstream/dev' into HEAD 2026-09-16 09:30:17 -05:00
J. Nick Koston 38a61a8081 [openthread] Drop --undefined so the DNS client is only linked when used 2026-09-13 20:17:48 -05:00
J. Nick Koston 31dc228d05 [openthread] Silence clang-tidy naming checks on the linker wrap symbols 2026-09-13 20:11:52 -05:00
J. Nick Koston 5e57387667 [openthread] Resolve IPv6 literal addresses when the DNS64 client is enabled
ESP-IDF's DNS64 lwIP hook runs before lwIP's literal address check and
retries every lookup as IPv4, so an IPv6 literal such as an MQTT broker
address never resolves. Wrap the hook and let lwIP handle IPv6 literals.
2026-09-13 20:06:16 -05:00
2 changed files with 22 additions and 0 deletions
@@ -160,6 +160,8 @@ def set_sdkconfig_options(config: ConfigType) -> None:
)
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_DNS64_CLIENT", True)
# The DNS64 hook breaks IPv6 literal lookups; see openthread_esp.cpp.
cg.add_build_flag("-Wl,--wrap=lwip_hook_dns_external_resolve")
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_SRP_CLIENT", True)
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_SRP_CLIENT_MAX_SERVICES", 5)
@@ -15,6 +15,10 @@
#include "esp_netif.h"
#include "esp_openthread_netif_glue.h"
#include "esp_vfs_eventfd.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "lwip/dns.h"
#include "lwip/ip_addr.h"
#include "nvs_flash.h"
ESPHOME_LOG_TAG(TAG, "openthread");
@@ -180,4 +184,20 @@ InstanceLock::~InstanceLock() {
}
} // namespace esphome::openthread
// ESP-IDF's DNS64 hook runs before lwIP's literal address check and retries every lookup as IPv4,
// so an IPv6 literal never resolves. Let lwIP handle those; linked with --wrap from __init__.py.
// NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming)
extern "C" {
int __real_lwip_hook_dns_external_resolve(const char *name, ip_addr_t *addr, dns_found_callback found,
void *callback_arg, u8_t addrtype, err_t *err);
int __wrap_lwip_hook_dns_external_resolve(const char *name, ip_addr_t *addr, dns_found_callback found,
void *callback_arg, u8_t addrtype, err_t *err) {
ip_addr_t literal;
if (ipaddr_aton(name, &literal) && IP_IS_V6_VAL(literal))
return 0;
return __real_lwip_hook_dns_external_resolve(name, addr, found, callback_arg, addrtype, err);
}
} // extern "C"
// NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming)
#endif