From 905856a0543efd9ead764afe20bac21ddd9dff83 Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Mon, 30 May 2022 15:53:11 +0800 Subject: [PATCH] openthread: add NAT64 and DNS64 support * Add required configs and headers for NAT64 and DNS64 * Add hook for DNS name resolution * Add NAT64 and DNS64 example commands --- components/lwip/Kconfig | 3 +- components/openthread/CMakeLists.txt | 3 +- components/openthread/Kconfig | 7 +++ .../openthread/include/esp_openthread.h | 20 +++--- .../openthread/include/esp_openthread_dns64.h | 43 +++++++++++++ .../openthread/include/esp_openthread_types.h | 9 +-- components/openthread/lib | 2 +- .../openthread-core-esp32x-ftd-config.h | 10 +++ .../openthread/src/esp_openthread_dns64.c | 63 +++++++++++++++++++ examples/openthread/README_nat64.md | 48 ++++++++++++++ examples/openthread/ot_br/main/esp_ot_br.c | 10 +-- examples/openthread/ot_cli/sdkconfig.defaults | 4 ++ tools/ci/check_copyright_ignore.txt | 1 - 13 files changed, 196 insertions(+), 27 deletions(-) create mode 100644 components/openthread/include/esp_openthread_dns64.h create mode 100644 components/openthread/src/esp_openthread_dns64.c create mode 100644 examples/openthread/README_nat64.md diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 2e5987bede..b0dfd2d979 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -965,7 +965,8 @@ menu "LWIP" choice LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE prompt "Netconn external resolve Hook" - default LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE + default LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT if OPENTHREAD_DNS64_CLIENT + default LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE if !OPENTHREAD_DNS64_CLIENT help Enables custom DNS resolve hook. Setting this to "default" provides weak implementation diff --git a/components/openthread/CMakeLists.txt b/components/openthread/CMakeLists.txt index e35d02730f..d29b6bd6e4 100644 --- a/components/openthread/CMakeLists.txt +++ b/components/openthread/CMakeLists.txt @@ -33,6 +33,7 @@ if(CONFIG_OPENTHREAD_ENABLED) if(CONFIG_OPENTHREAD_FTD OR CONFIG_OPENTHREAD_MTD) list(APPEND src_dirs + "src" "openthread/examples/apps/cli" "openthread/src/core/backbone_router" "openthread/src/core/coap" @@ -141,7 +142,7 @@ idf_component_register(SRC_DIRS "${src_dirs}" EXCLUDE_SRCS "${exclude_srcs}" INCLUDE_DIRS "${public_include_dirs}" PRIV_INCLUDE_DIRS "${private_include_dirs}" - REQUIRES mbedtls ieee802154 console lwip) + REQUIRES esp_event mbedtls ieee802154 console lwip) if(CONFIG_OPENTHREAD_ENABLED) if(CONFIG_OPENTHREAD_RADIO) diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index 461b090cc8..e6e962be94 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -98,4 +98,11 @@ menu "OpenThread" default 65 range 50 100 + config OPENTHREAD_DNS64_CLIENT + bool "Use dns64 client" + depends on OPENTHREAD_ENABLED + default n + help + Select this option to acquire NAT64 address from dns servers. + endmenu diff --git a/components/openthread/include/esp_openthread.h b/components/openthread/include/esp_openthread.h index a29b3efa36..f98f193d5c 100644 --- a/components/openthread/include/esp_openthread.h +++ b/components/openthread/include/esp_openthread.h @@ -1,16 +1,8 @@ -// Copyright 2021 Espressif Systems (Shanghai) CO LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -18,6 +10,7 @@ #include "esp_openthread_types.h" #include "openthread/error.h" #include "openthread/instance.h" +#include "lwip/ip_addr.h" #ifdef __cplusplus extern "C" { @@ -72,6 +65,7 @@ esp_err_t esp_openthread_deinit(void); */ otInstance *esp_openthread_get_instance(void); + #ifdef __cplusplus } // end of extern "C" #endif diff --git a/components/openthread/include/esp_openthread_dns64.h b/components/openthread/include/esp_openthread_dns64.h new file mode 100644 index 0000000000..fafa7b4af2 --- /dev/null +++ b/components/openthread/include/esp_openthread_dns64.h @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_openthread.h" +#include "lwip/netdb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief This function acquires the NAT64 prefix in the Thread network. + * + * @param[out] nat64_prefix The NAT64 prefix output. + * + * @return + * - ESP_OK on success + * - ESP_ERR_NOT_FOUND if NAT64 prefix available + * + */ +esp_err_t esp_openthread_get_nat64_prefix(ip6_addr_t *nat64_prefix); + + +/** + * @brief The alternative function for gethostbyname and adds the NAT64 prefix. + * + */ +struct hostent *esp_openthread_gethostbyname_dns64(const char *name); + +/** + * @brief The alternative function for getaddrinfo and adds the NAT64 prefix. + * + */ +int esp_openthread_getaddrinfo_dns64(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res); + +#ifdef __cplusplus +} +#endif diff --git a/components/openthread/include/esp_openthread_types.h b/components/openthread/include/esp_openthread_types.h index 47caed0f23..9c22a06edc 100644 --- a/components/openthread/include/esp_openthread_types.h +++ b/components/openthread/include/esp_openthread_types.h @@ -21,8 +21,7 @@ extern "C" { * @brief OpenThread event declarations * */ -typedef enum -{ +typedef enum { OPENTHREAD_EVENT_START, /*!< OpenThread stack start */ OPENTHREAD_EVENT_STOP, /*!< OpenThread stack stop */ OPENTHREAD_EVENT_IF_UP, /*!< OpenThread network interface up */ @@ -69,8 +68,7 @@ typedef struct { * @brief The radio mode of OpenThread. * */ -typedef enum -{ +typedef enum { RADIO_MODE_NATIVE = 0x0, /*!< Use the native 15.4 radio */ RADIO_MODE_UART_RCP = 0x1, /*!< UART connection to a 15.4 capable radio co-processor (RCP) */ RADIO_MODE_SPI_RCP = 0x2, /*!< SPI connection to a 15.4 capable radio co-processor (RCP) */ @@ -80,8 +78,7 @@ typedef enum * @brief How OpenThread connects to the host. * */ -typedef enum -{ +typedef enum { HOST_CONNECTION_MODE_NONE = 0x0, /*!< Disable host connection */ HOST_CONNECTION_MODE_CLI_UART = 0x1, /*!< CLI UART connection to the host */ HOST_CONNECTION_MODE_RCP_UART = 0x2, /*!< RCP UART connection to the host */ diff --git a/components/openthread/lib b/components/openthread/lib index 9fabccb43c..af1ac2b377 160000 --- a/components/openthread/lib +++ b/components/openthread/lib @@ -1 +1 @@ -Subproject commit 9fabccb43c2318d45d7d893902a614d94d0f2e2a +Subproject commit af1ac2b3770335db96702bcb06ca793a1425dc86 diff --git a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h index a6b41853ad..49be86e632 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -149,6 +149,16 @@ #define OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE 1 #endif +/** + * @def OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE + * + * Define to 1 to enable Border Routing NAT64 support. + * + */ +#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE +#define OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE 1 +#endif + /** * @def OPENTHREAD_CONFIG_ECDSA_ENABLE * diff --git a/components/openthread/src/esp_openthread_dns64.c b/components/openthread/src/esp_openthread_dns64.c new file mode 100644 index 0000000000..ed767234fa --- /dev/null +++ b/components/openthread/src/esp_openthread_dns64.c @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_openthread_dns64.h" + +#include "esp_log.h" +#include "openthread/instance.h" +#include "openthread/netdata.h" +#include "lwip_default_hooks.h" +#include "lwip/api.h" + +#define TAG "OT_DNS64" + +esp_err_t esp_openthread_get_nat64_prefix(ip6_addr_t *nat64_prefix) +{ + otNetworkDataIterator iter = OT_NETWORK_DATA_ITERATOR_INIT; + otInstance *instance = esp_openthread_get_instance(); + otExternalRouteConfig route; + + memset(&route, 0, sizeof(route)); + while (otNetDataGetNextRoute(instance, &iter, &route) == OT_ERROR_NONE) { + if (route.mNat64) { + break; + } + } + + if (route.mNat64) { + memcpy(nat64_prefix->addr, route.mPrefix.mPrefix.mFields.m8, sizeof(nat64_prefix->addr)); + return ESP_OK; + } else { + return ESP_ERR_NOT_FOUND; + } +} + +int lwip_hook_netconn_external_resolve(const char *name, ip_addr_t *addr, u8_t addrtype, err_t *err) +{ + if (addrtype == NETCONN_DNS_IPV4) { + return 0; + } + + ip6_addr_t nat64_prefix; + if (esp_openthread_get_nat64_prefix(&nat64_prefix) != ESP_OK) { + ESP_LOGE(TAG, "Cannot find NAT64 prefix\n"); + *err = ERR_ABRT; + return 1; + } + + *err = netconn_gethostbyname_addrtype(name, addr, NETCONN_DNS_IPV4); + if (*err != ERR_OK) { + 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; + } + return 1; +} diff --git a/examples/openthread/README_nat64.md b/examples/openthread/README_nat64.md new file mode 100644 index 0000000000..0f30a8db95 --- /dev/null +++ b/examples/openthread/README_nat64.md @@ -0,0 +1,48 @@ +# Visiting the Internet on the Thread network with NAT64 + +The Espressif Thread border router supports NAT64 which allows Thread devices to visit the IPv4 Internet. + +## Building the Thread border router with NAT64 + +The Thread border router supports NAT64 by default. After the Wi-Fi and the Thread network is launched, we can fetch the NAT64 prefix: + +``` +> br nat64prefix +fd97:83ad:debc:2:0:0::/96 +Done +``` + +This prefix will be used for translating the IPv4 addresses. + +## Visiting IPv4 UDP servers + +Build and run the OpenThread cli example with the default configuration and join the Thread network formed by the border router. +On the local machine, setup a basic UDP echo server. The destination UDP address will be the hexadecimal IPv4 address added to the NAT64 prefix. +Say the host has address 192.168.1.2 and the NAT64 prefix is fd97:83ad:debc:2:0:0::/96, the destination address will be fd97:83ad:debc:2:0:0:c0a8:0102. + +``` +> udp send fd97:83ad:debc:2:0:0:c0a8:0102 4388 hello + +Done +> 5 bytes from fd97:83ad:debc:2:0:0:c0a8:102 4388 hello +``` + +## Visiting IPv4 HTTP servers + +For visiting HTTP servers with domain names, we need to first set the DNS server: + +``` +> dns64server 8.8.8.8 +Done +``` + +Now we can curl the HTTP server + +``` +> curl http://www.google.com + +Done +> I (33809) HTTP_CLIENT: Body received in fetch header state, 0x3fca4025, 111 + ... +// Other HTTP response to follow +``` diff --git a/examples/openthread/ot_br/main/esp_ot_br.c b/examples/openthread/ot_br/main/esp_ot_br.c index 73a0f835c8..348c0510d0 100644 --- a/examples/openthread/ot_br/main/esp_ot_br.c +++ b/examples/openthread/ot_br/main/esp_ot_br.c @@ -10,7 +10,7 @@ * Unless required by applicable law or agreed to in writing, this * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. -*/ + */ #include #include @@ -28,7 +28,10 @@ #include "esp_openthread_lock.h" #include "esp_openthread_netif_glue.h" #include "esp_openthread_types.h" +#include "esp_ot_cli_extension.h" #include "esp_ot_config.h" +#include "esp_ot_wifi_cmd.h" +#include "esp_vfs_dev.h" #include "esp_vfs_eventfd.h" #include "esp_wifi.h" #include "mdns.h" @@ -51,8 +54,6 @@ #include "openthread/logging.h" #include "openthread/tasklet.h" #include "openthread/thread_ftd.h" -#include "esp_ot_wifi_cmd.h" -#include "esp_ot_cli_extension.h" #define TAG "esp_ot_br" @@ -166,7 +167,7 @@ static void ot_task_worker(void *aContext) }; esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); - esp_netif_t *openthread_netif = esp_netif_new(&cfg); + esp_netif_t *openthread_netif = esp_netif_new(&cfg); assert(openthread_netif != NULL); // Initialize the OpenThread stack @@ -211,6 +212,7 @@ void app_main(void) ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); + #if CONFIG_OPENTHREAD_BR_AUTO_START ESP_ERROR_CHECK(example_connect()); ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); diff --git a/examples/openthread/ot_cli/sdkconfig.defaults b/examples/openthread/ot_cli/sdkconfig.defaults index f7807d740a..98d7110895 100644 --- a/examples/openthread/ot_cli/sdkconfig.defaults +++ b/examples/openthread/ot_cli/sdkconfig.defaults @@ -5,6 +5,8 @@ CONFIG_IDF_TARGET="esp32h2" CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y # end of libsodium +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=2048 + # # Partition Table # @@ -33,6 +35,8 @@ CONFIG_MBEDTLS_ECJPAKE_C=y # CONFIG_OPENTHREAD_ENABLED=y CONFIG_OPENTHREAD_BORDER_ROUTER=n +CONFIG_OPENTHREAD_SRP_CLIENT=y +CONFIG_OPENTHREAD_DNS64_CLIENT=y # end of OpenThread # diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 631ba90633..369e714e54 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -949,7 +949,6 @@ components/nvs_flash/test_nvs_host/test_nvs_handle.cpp components/nvs_flash/test_nvs_host/test_nvs_initialization.cpp components/nvs_flash/test_nvs_host/test_nvs_partition.cpp components/nvs_flash/test_nvs_host/test_nvs_storage.cpp -components/openthread/include/esp_openthread.h components/openthread/include/esp_openthread_lock.h components/protocomm/include/transports/protocomm_console.h components/protocomm/include/transports/protocomm_httpd.h