diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 5f2bb733e8..fcb45c61d2 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -1260,10 +1260,9 @@ menu "LWIP" choice LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE prompt "Netconn external resolve Hook" - default LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT if OPENTHREAD_DNS64_CLIENT - default LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE if !OPENTHREAD_DNS64_CLIENT + default LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE help - Enables custom DNS resolve hook. + Enables custom DNS resolve hook (without callback). Setting this to "default" provides weak implementation stub that could be overwritten in application code. Setting this to "custom" provides hook's declaration @@ -1278,6 +1277,30 @@ menu "LWIP" endchoice + config LWIP_HOOK_DNS_EXTERNAL_RESOLVE_SELECT_CUSTOM + bool + default n + help + This hidden option helps configure the DNS external resolve + hook for external components like OpenThread. It ensures that + `LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM` is selected without directly + adding a dependency in the choice construct. + + choice LWIP_HOOK_DNS_EXTERNAL_RESOLVE + prompt "DNS external resolve Hook" + default LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM if LWIP_HOOK_DNS_EXTERNAL_RESOLVE_SELECT_CUSTOM + help + Enables custom DNS resolve hook (with callback). + Setting this to "custom" provides hook's declaration + only and expects the application to implement it. + + config LWIP_HOOK_DNS_EXT_RESOLVE_NONE + bool "No hook declared" + config LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM + bool "Custom implementation" + + endchoice + choice LWIP_HOOK_IP6_INPUT prompt "IPv6 packet input" depends on LWIP_IPV6 diff --git a/components/lwip/lwip b/components/lwip/lwip index bced058f73..0606eed9d8 160000 --- a/components/lwip/lwip +++ b/components/lwip/lwip @@ -1 +1 @@ -Subproject commit bced058f737eaabea1aa193f3c365ee78ff555f3 +Subproject commit 0606eed9d8b98a797514fdf6eabb4daf1c8c8cd9 diff --git a/components/lwip/port/include/lwip_default_hooks.h b/components/lwip/port/include/lwip_default_hooks.h index bdc54064a9..86d33368d4 100644 --- a/components/lwip/port/include/lwip_default_hooks.h +++ b/components/lwip/port/include/lwip_default_hooks.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,7 @@ #include "lwip/ip_addr.h" #include "lwip/arch.h" #include "lwip/err.h" +#include "lwip/dns.h" #include "lwip/pbuf.h" #include "netif/dhcp_state.h" @@ -55,6 +56,14 @@ int lwip_hook_netconn_external_resolve(const char *name, ip_addr_t *addr, u8_t a #define LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE lwip_hook_netconn_external_resolve #endif /* CONFIG_LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE... */ +#if defined(CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM) +int 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); + +#define LWIP_HOOK_DNS_EXTERNAL_RESOLVE lwip_hook_dns_external_resolve +#endif /* CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM */ + + #if defined(CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM) || defined(CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT) int lwip_hook_ip6_input(struct pbuf *p, struct netif *inp); diff --git a/components/lwip/test_apps/README.md b/components/lwip/test_apps/README.md index 3a502b1f86..bf47d80ec6 100644 --- a/components/lwip/test_apps/README.md +++ b/components/lwip/test_apps/README.md @@ -1,2 +1,2 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index 0b90b78b01..160084fbcb 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -299,6 +299,7 @@ menu "OpenThread" config OPENTHREAD_DNS64_CLIENT bool "Use dns64 client" depends on OPENTHREAD_ENABLED && LWIP_IPV4 + select LWIP_HOOK_DNS_EXTERNAL_RESOLVE_SELECT_CUSTOM default n help Select this option to acquire NAT64 address from dns servers. diff --git a/components/openthread/src/esp_openthread_dns64.c b/components/openthread/src/esp_openthread_dns64.c index 0f3a0124a9..79faa1ad92 100644 --- a/components/openthread/src/esp_openthread_dns64.c +++ b/components/openthread/src/esp_openthread_dns64.c @@ -1,26 +1,40 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "esp_openthread_dns64.h" +#include "esp_openthread_lock.h" #include "esp_openthread_state.h" #include "esp_check.h" #include "esp_event.h" #include "esp_log.h" -#include "openthread/instance.h" -#include "openthread/netdata.h" #include "lwip_default_hooks.h" #include "lwip/api.h" +#include "lwip/def.h" #include "lwip/dns.h" +#include "lwip/opt.h" +#include "openthread/instance.h" +#include "openthread/netdata.h" #define TAG "OT_DNS64" + +typedef struct dns_resolve_entry { + char name[DNS_MAX_NAME_LENGTH]; + dns_found_callback found; + void *callback_arg; + bool is_using; +} dns_resolve_entry_t; + +static dns_resolve_entry_t s_dns_resolve_entry[DNS_TABLE_SIZE]; + esp_err_t esp_openthread_dns64_client_init(void) { dns_setserver(OPENTHREAD_DNS_SERVER_INDEX, NULL); + memset(s_dns_resolve_entry, 0, sizeof(s_dns_resolve_entry)); return ESP_OK; } @@ -41,11 +55,13 @@ esp_err_t esp_openthread_get_nat64_prefix(ip6_addr_t *nat64_prefix) otExternalRouteConfig route; memset(&route, 0, sizeof(route)); + esp_openthread_task_switching_lock_acquire(portMAX_DELAY); while (otNetDataGetNextRoute(instance, &iter, &route) == OT_ERROR_NONE) { if (route.mNat64) { break; } } + esp_openthread_task_switching_lock_release(); if (route.mNat64) { memcpy(nat64_prefix->addr, route.mPrefix.mPrefix.mFields.m8, sizeof(nat64_prefix->addr)); @@ -55,9 +71,39 @@ esp_err_t esp_openthread_get_nat64_prefix(ip6_addr_t *nat64_prefix) } } -int lwip_hook_netconn_external_resolve(const char *name, ip_addr_t *addr, u8_t addrtype, err_t *err) +static void dns_found_handler(const char *name, const ip_addr_t *ipaddr, void *callback_arg) { - if (addrtype == NETCONN_DNS_IPV4) { + dns_resolve_entry_t *resolve_entry = (dns_resolve_entry_t *)callback_arg; + if (resolve_entry && resolve_entry->found) { + if (lwip_strnicmp(name, resolve_entry->name, sizeof(resolve_entry->name)) == 0) { + ip_addr_t ipaddr_copy = *ipaddr; + ip6_addr_t nat64_prefix; + if (ipaddr_copy.type == IPADDR_TYPE_V4 && esp_openthread_get_nat64_prefix(&nat64_prefix) == ESP_OK) { + ipaddr_copy.type = IPADDR_TYPE_V6; + memcpy(ipaddr_copy.u_addr.ip6.addr, nat64_prefix.addr, sizeof(nat64_prefix.addr)); + ipaddr_copy.u_addr.ip6.addr[3] = ipaddr->u_addr.ip4.addr; + ipaddr_copy.u_addr.ip6.zone = IP6_NO_ZONE; + } + resolve_entry->found(name, &ipaddr_copy, resolve_entry->callback_arg); + } + resolve_entry->is_using = false; + } +} + +static dns_resolve_entry_t *find_free_dns_resolve_entry(void) +{ + for (uint8_t i = 0; i < DNS_TABLE_SIZE; ++i) { + if (s_dns_resolve_entry[i].is_using == false) { + return &s_dns_resolve_entry[i]; + } + } + return NULL; +} + +int 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) +{ + if (addrtype == LWIP_DNS_ADDRTYPE_IPV4) { return 0; } @@ -67,17 +113,32 @@ int lwip_hook_netconn_external_resolve(const char *name, ip_addr_t *addr, u8_t a *err = ERR_ABRT; return 1; } - - *err = netconn_gethostbyname_addrtype(name, addr, NETCONN_DNS_IPV4); - if (*err != ERR_OK) { + dns_resolve_entry_t *entry = find_free_dns_resolve_entry(); + if (!entry) { + ESP_LOGE(TAG, "Cannot find free dns resolve entry"); + *err = ERR_MEM; return 1; } - if (addr->type == IPADDR_TYPE_V4) { - ip4_addr_t addr_copy = addr->u_addr.ip4; - addr->type = IPADDR_TYPE_V6; - memcpy(addr->u_addr.ip6.addr, nat64_prefix.addr, sizeof(nat64_prefix.addr)); - addr->u_addr.ip6.addr[3] = addr_copy.addr; - addr->u_addr.ip6.zone = IP6_NO_ZONE; + + strncpy(entry->name, name, strnlen(name, sizeof(entry->name) - 1)); + entry->name[strnlen(name, sizeof(entry->name) - 1)] = 0; + entry->found = found; + entry->callback_arg = callback_arg; + entry->is_using = true; + + *err = dns_gethostbyname_addrtype(name, addr, dns_found_handler, entry, LWIP_DNS_ADDRTYPE_IPV4); + if (*err != ERR_INPROGRESS) { + // If dns query is not enqueued, mark the entry not being used. + entry->is_using = false; + } + if (*err == ERR_OK) { + if (addr->type == IPADDR_TYPE_V4) { + ip4_addr_t addr_copy = addr->u_addr.ip4; + addr->type = IPADDR_TYPE_V6; + memcpy(addr->u_addr.ip6.addr, nat64_prefix.addr, sizeof(nat64_prefix.addr)); + addr->u_addr.ip6.addr[3] = addr_copy.addr; + addr->u_addr.ip6.zone = IP6_NO_ZONE; + } } return 1; }