Merge branch 'feat/thread_dns_ext_resolve' into 'master'

feat(openthread): Replace netconn external resolve hook with dns external hook

See merge request espressif/esp-idf!33344
This commit is contained in:
Shu Chen 2024-09-13 15:45:25 +08:00
commit 4d4062a2b8
3 changed files with 89 additions and 19 deletions

View File

@ -1311,10 +1311,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
@ -1329,11 +1328,20 @@ 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_NONE
default LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM if LWIP_HOOK_DNS_EXTERNAL_RESOLVE_SELECT_CUSTOM
help
Enables custom DNS resolve hook.
Enables custom DNS resolve hook (with callback).
Setting this to "custom" provides hook's declaration
only and expects the application to implement it.

View File

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

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
*/
#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;
}