Merge branch 'feat/lwip_dns_external_resolve_hook_v5_3' into 'release/v5.3'

feat(lwip): Add DNS external hook in TCPIP context and replace netconn external resolve hook with dns external hook for OpenThread (v5.3)

See merge request espressif/esp-idf!33512
This commit is contained in:
Shu Chen 2024-09-20 14:18:01 +08:00
commit ae4b955a0c
6 changed files with 115 additions and 21 deletions

View File

@ -1260,10 +1260,9 @@ menu "LWIP"
choice LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE choice LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE
prompt "Netconn external resolve Hook" prompt "Netconn external resolve Hook"
default LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT if OPENTHREAD_DNS64_CLIENT default LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE
default LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE if !OPENTHREAD_DNS64_CLIENT
help help
Enables custom DNS resolve hook. Enables custom DNS resolve hook (without callback).
Setting this to "default" provides weak implementation Setting this to "default" provides weak implementation
stub that could be overwritten in application code. stub that could be overwritten in application code.
Setting this to "custom" provides hook's declaration Setting this to "custom" provides hook's declaration
@ -1278,6 +1277,30 @@ menu "LWIP"
endchoice 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 choice LWIP_HOOK_IP6_INPUT
prompt "IPv6 packet input" prompt "IPv6 packet input"
depends on LWIP_IPV6 depends on LWIP_IPV6

@ -1 +1 @@
Subproject commit bced058f737eaabea1aa193f3c365ee78ff555f3 Subproject commit 0606eed9d8b98a797514fdf6eabb4daf1c8c8cd9

View File

@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -9,6 +9,7 @@
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "lwip/arch.h" #include "lwip/arch.h"
#include "lwip/err.h" #include "lwip/err.h"
#include "lwip/dns.h"
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "netif/dhcp_state.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 #define LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE lwip_hook_netconn_external_resolve
#endif /* CONFIG_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) #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); int lwip_hook_ip6_input(struct pbuf *p, struct netif *inp);

View File

@ -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 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | | ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -299,6 +299,7 @@ menu "OpenThread"
config OPENTHREAD_DNS64_CLIENT config OPENTHREAD_DNS64_CLIENT
bool "Use dns64 client" bool "Use dns64 client"
depends on OPENTHREAD_ENABLED && LWIP_IPV4 depends on OPENTHREAD_ENABLED && LWIP_IPV4
select LWIP_HOOK_DNS_EXTERNAL_RESOLVE_SELECT_CUSTOM
default n default n
help help
Select this option to acquire NAT64 address from dns servers. Select this option to acquire NAT64 address from dns servers.

View File

@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
#include "esp_openthread_dns64.h" #include "esp_openthread_dns64.h"
#include "esp_openthread_lock.h"
#include "esp_openthread_state.h" #include "esp_openthread_state.h"
#include "esp_check.h" #include "esp_check.h"
#include "esp_event.h" #include "esp_event.h"
#include "esp_log.h" #include "esp_log.h"
#include "openthread/instance.h"
#include "openthread/netdata.h"
#include "lwip_default_hooks.h" #include "lwip_default_hooks.h"
#include "lwip/api.h" #include "lwip/api.h"
#include "lwip/def.h"
#include "lwip/dns.h" #include "lwip/dns.h"
#include "lwip/opt.h"
#include "openthread/instance.h"
#include "openthread/netdata.h"
#define TAG "OT_DNS64" #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) esp_err_t esp_openthread_dns64_client_init(void)
{ {
dns_setserver(OPENTHREAD_DNS_SERVER_INDEX, NULL); dns_setserver(OPENTHREAD_DNS_SERVER_INDEX, NULL);
memset(s_dns_resolve_entry, 0, sizeof(s_dns_resolve_entry));
return ESP_OK; return ESP_OK;
} }
@ -41,11 +55,13 @@ esp_err_t esp_openthread_get_nat64_prefix(ip6_addr_t *nat64_prefix)
otExternalRouteConfig route; otExternalRouteConfig route;
memset(&route, 0, sizeof(route)); memset(&route, 0, sizeof(route));
esp_openthread_task_switching_lock_acquire(portMAX_DELAY);
while (otNetDataGetNextRoute(instance, &iter, &route) == OT_ERROR_NONE) { while (otNetDataGetNextRoute(instance, &iter, &route) == OT_ERROR_NONE) {
if (route.mNat64) { if (route.mNat64) {
break; break;
} }
} }
esp_openthread_task_switching_lock_release();
if (route.mNat64) { if (route.mNat64) {
memcpy(nat64_prefix->addr, route.mPrefix.mPrefix.mFields.m8, sizeof(nat64_prefix->addr)); 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; 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; *err = ERR_ABRT;
return 1; return 1;
} }
dns_resolve_entry_t *entry = find_free_dns_resolve_entry();
*err = netconn_gethostbyname_addrtype(name, addr, NETCONN_DNS_IPV4); if (!entry) {
if (*err != ERR_OK) { ESP_LOGE(TAG, "Cannot find free dns resolve entry");
*err = ERR_MEM;
return 1; return 1;
} }
if (addr->type == IPADDR_TYPE_V4) {
ip4_addr_t addr_copy = addr->u_addr.ip4; strncpy(entry->name, name, strnlen(name, sizeof(entry->name) - 1));
addr->type = IPADDR_TYPE_V6; entry->name[strnlen(name, sizeof(entry->name) - 1)] = 0;
memcpy(addr->u_addr.ip6.addr, nat64_prefix.addr, sizeof(nat64_prefix.addr)); entry->found = found;
addr->u_addr.ip6.addr[3] = addr_copy.addr; entry->callback_arg = callback_arg;
addr->u_addr.ip6.zone = IP6_NO_ZONE; 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; return 1;
} }