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

This commit is contained in:
WanqQixiang 2024-08-14 10:52:54 +08:00 committed by Wang Qixiang
parent a0e954b941
commit f62628d334
3 changed files with 89 additions and 19 deletions

View File

@ -1295,10 +1295,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
@ -1313,11 +1312,20 @@ 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 choice LWIP_HOOK_DNS_EXTERNAL_RESOLVE
prompt "DNS external resolve Hook" 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 help
Enables custom DNS resolve hook. Enables custom DNS resolve hook (with callback).
Setting this to "custom" provides hook's declaration Setting this to "custom" provides hook's declaration
only and expects the application to implement it. only and expects the application to implement it.

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;
} }