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
This commit is contained in:
Jiacheng Guo 2022-05-30 15:53:11 +08:00
parent 4ae9f7a488
commit 905856a054
13 changed files with 196 additions and 27 deletions

View File

@ -965,7 +965,8 @@ 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_NONE default LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT if OPENTHREAD_DNS64_CLIENT
default LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE if !OPENTHREAD_DNS64_CLIENT
help help
Enables custom DNS resolve hook. Enables custom DNS resolve hook.
Setting this to "default" provides weak implementation Setting this to "default" provides weak implementation

View File

@ -33,6 +33,7 @@ if(CONFIG_OPENTHREAD_ENABLED)
if(CONFIG_OPENTHREAD_FTD OR CONFIG_OPENTHREAD_MTD) if(CONFIG_OPENTHREAD_FTD OR CONFIG_OPENTHREAD_MTD)
list(APPEND src_dirs list(APPEND src_dirs
"src"
"openthread/examples/apps/cli" "openthread/examples/apps/cli"
"openthread/src/core/backbone_router" "openthread/src/core/backbone_router"
"openthread/src/core/coap" "openthread/src/core/coap"
@ -141,7 +142,7 @@ idf_component_register(SRC_DIRS "${src_dirs}"
EXCLUDE_SRCS "${exclude_srcs}" EXCLUDE_SRCS "${exclude_srcs}"
INCLUDE_DIRS "${public_include_dirs}" INCLUDE_DIRS "${public_include_dirs}"
PRIV_INCLUDE_DIRS "${private_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_ENABLED)
if(CONFIG_OPENTHREAD_RADIO) if(CONFIG_OPENTHREAD_RADIO)

View File

@ -98,4 +98,11 @@ menu "OpenThread"
default 65 default 65
range 50 100 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 endmenu

View File

@ -1,16 +1,8 @@
// Copyright 2021 Espressif Systems (Shanghai) CO LTD /*
// * SPDX-FileCopyrightText: 2021-2022 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. * SPDX-License-Identifier: Apache-2.0
// 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
#pragma once #pragma once
@ -18,6 +10,7 @@
#include "esp_openthread_types.h" #include "esp_openthread_types.h"
#include "openthread/error.h" #include "openthread/error.h"
#include "openthread/instance.h" #include "openthread/instance.h"
#include "lwip/ip_addr.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -72,6 +65,7 @@ esp_err_t esp_openthread_deinit(void);
*/ */
otInstance *esp_openthread_get_instance(void); otInstance *esp_openthread_get_instance(void);
#ifdef __cplusplus #ifdef __cplusplus
} // end of extern "C" } // end of extern "C"
#endif #endif

View File

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

View File

@ -21,8 +21,7 @@ extern "C" {
* @brief OpenThread event declarations * @brief OpenThread event declarations
* *
*/ */
typedef enum typedef enum {
{
OPENTHREAD_EVENT_START, /*!< OpenThread stack start */ OPENTHREAD_EVENT_START, /*!< OpenThread stack start */
OPENTHREAD_EVENT_STOP, /*!< OpenThread stack stop */ OPENTHREAD_EVENT_STOP, /*!< OpenThread stack stop */
OPENTHREAD_EVENT_IF_UP, /*!< OpenThread network interface up */ OPENTHREAD_EVENT_IF_UP, /*!< OpenThread network interface up */
@ -69,8 +68,7 @@ typedef struct {
* @brief The radio mode of OpenThread. * @brief The radio mode of OpenThread.
* *
*/ */
typedef enum typedef enum {
{
RADIO_MODE_NATIVE = 0x0, /*!< Use the native 15.4 radio */ 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_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) */ 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. * @brief How OpenThread connects to the host.
* *
*/ */
typedef enum typedef enum {
{
HOST_CONNECTION_MODE_NONE = 0x0, /*!< Disable host connection */ HOST_CONNECTION_MODE_NONE = 0x0, /*!< Disable host connection */
HOST_CONNECTION_MODE_CLI_UART = 0x1, /*!< CLI UART connection to the host */ HOST_CONNECTION_MODE_CLI_UART = 0x1, /*!< CLI UART connection to the host */
HOST_CONNECTION_MODE_RCP_UART = 0x2, /*!< RCP UART connection to the host */ HOST_CONNECTION_MODE_RCP_UART = 0x2, /*!< RCP UART connection to the host */

@ -1 +1 @@
Subproject commit 9fabccb43c2318d45d7d893902a614d94d0f2e2a Subproject commit af1ac2b3770335db96702bcb06ca793a1425dc86

View File

@ -149,6 +149,16 @@
#define OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE 1 #define OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE 1
#endif #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 * @def OPENTHREAD_CONFIG_ECDSA_ENABLE
* *

View File

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

View File

@ -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
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="zh-HK"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"> ...
// Other HTTP response to follow
```

View File

@ -10,7 +10,7 @@
* Unless required by applicable law or agreed to in writing, this * Unless required by applicable law or agreed to in writing, this
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. * CONDITIONS OF ANY KIND, either express or implied.
*/ */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -28,7 +28,10 @@
#include "esp_openthread_lock.h" #include "esp_openthread_lock.h"
#include "esp_openthread_netif_glue.h" #include "esp_openthread_netif_glue.h"
#include "esp_openthread_types.h" #include "esp_openthread_types.h"
#include "esp_ot_cli_extension.h"
#include "esp_ot_config.h" #include "esp_ot_config.h"
#include "esp_ot_wifi_cmd.h"
#include "esp_vfs_dev.h"
#include "esp_vfs_eventfd.h" #include "esp_vfs_eventfd.h"
#include "esp_wifi.h" #include "esp_wifi.h"
#include "mdns.h" #include "mdns.h"
@ -51,8 +54,6 @@
#include "openthread/logging.h" #include "openthread/logging.h"
#include "openthread/tasklet.h" #include "openthread/tasklet.h"
#include "openthread/thread_ftd.h" #include "openthread/thread_ftd.h"
#include "esp_ot_wifi_cmd.h"
#include "esp_ot_cli_extension.h"
#define TAG "esp_ot_br" #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_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); assert(openthread_netif != NULL);
// Initialize the OpenThread stack // Initialize the OpenThread stack
@ -211,6 +212,7 @@ void app_main(void)
ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_event_loop_create_default());
#if CONFIG_OPENTHREAD_BR_AUTO_START #if CONFIG_OPENTHREAD_BR_AUTO_START
ESP_ERROR_CHECK(example_connect()); ESP_ERROR_CHECK(example_connect());
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));

View File

@ -5,6 +5,8 @@ CONFIG_IDF_TARGET="esp32h2"
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
# end of libsodium # end of libsodium
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=2048
# #
# Partition Table # Partition Table
# #
@ -33,6 +35,8 @@ CONFIG_MBEDTLS_ECJPAKE_C=y
# #
CONFIG_OPENTHREAD_ENABLED=y CONFIG_OPENTHREAD_ENABLED=y
CONFIG_OPENTHREAD_BORDER_ROUTER=n CONFIG_OPENTHREAD_BORDER_ROUTER=n
CONFIG_OPENTHREAD_SRP_CLIENT=y
CONFIG_OPENTHREAD_DNS64_CLIENT=y
# end of OpenThread # end of OpenThread
# #

View File

@ -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_initialization.cpp
components/nvs_flash/test_nvs_host/test_nvs_partition.cpp components/nvs_flash/test_nvs_host/test_nvs_partition.cpp
components/nvs_flash/test_nvs_host/test_nvs_storage.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/openthread/include/esp_openthread_lock.h
components/protocomm/include/transports/protocomm_console.h components/protocomm/include/transports/protocomm_console.h
components/protocomm/include/transports/protocomm_httpd.h components/protocomm/include/transports/protocomm_httpd.h