From 00ebd657841cae76f0ade85204a76c15e3cde052 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Fri, 28 Aug 2020 15:12:51 +0300 Subject: [PATCH 1/6] Mesh: Enable Nanostack DNS cache usage Inherit methods gethostbyname, gethostbyname_async and get_dns_server to Nanostack class. Methods will try to find DNS server address or DNS query results from Nanostack DNS cache. --- .../include/nanostack-interface/Nanostack.h | 52 ++++++++ connectivity/nanostack/source/Nanostack.cpp | 120 ++++++++++++++++++ 2 files changed, 172 insertions(+) diff --git a/connectivity/nanostack/include/nanostack-interface/Nanostack.h b/connectivity/nanostack/include/nanostack-interface/Nanostack.h index 232c836ff1b..c322ef75a5b 100644 --- a/connectivity/nanostack/include/nanostack-interface/Nanostack.h +++ b/connectivity/nanostack/include/nanostack-interface/Nanostack.h @@ -59,6 +59,58 @@ class Nanostack : public OnboardNetworkStack, private mbed::NonCopyableset_ip_bytes(dns_query_addr, NSAPI_IPv6); + return 0; + } + + return -1; +} + void *NanostackSocket::operator new (std::size_t sz) { return MALLOC(sz); @@ -532,6 +584,74 @@ nsapi_error_t Nanostack::get_ip_address(SocketAddress *sockAddr) return NSAPI_ERROR_NO_ADDRESS; } +nsapi_error_t Nanostack::gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version, const char *interface_name) +{ + if (name[0] == '\0') { + return NSAPI_ERROR_PARAMETER; + } + // check for simple ip addresses + if (address->set_ip_address(name)) { + if (version != NSAPI_UNSPEC && address->get_ip_version() != version) { + return NSAPI_ERROR_DNS_FAILURE; + } + return NSAPI_ERROR_OK; + } + + // try nanostack DNS cache, if not found then fallback to dns query + if (nanostack_dns_query_result_check(name, address, interface_name) == 0) { + return 0; + } + + return nsapi_dns_query(this, name, address, interface_name, version); +} + +nsapi_value_or_error_t Nanostack::gethostbyname_async(const char *name, hostbyname_cb_t callback, nsapi_version_t version, const char *interface_name) +{ + SocketAddress address; + + if (name[0] == '\0') { + return NSAPI_ERROR_PARAMETER; + } + + // check for simple ip addresses + if (address.set_ip_address(name)) { + if (version != NSAPI_UNSPEC && address.get_ip_version() != version) { + return NSAPI_ERROR_DNS_FAILURE; + } + callback(NSAPI_ERROR_OK, &address); + return NSAPI_ERROR_OK; + } + + // try nanostack DNS cache, if not found then fallback to dns query + if (nanostack_dns_query_result_check(name, &address, interface_name) == 0) { + // hit found, return result immediately + callback(NSAPI_ERROR_OK, &address); + return NSAPI_ERROR_OK; + } + + call_in_callback_cb_t call_in_cb = get_call_in_callback(); + return nsapi_dns_query_async(this, name, callback, call_in_cb, interface_name, version); +} + +nsapi_error_t Nanostack::get_dns_server(int index, SocketAddress *address, const char *interface_name) +{ + uint8_t dns_srv_address[16]; + int8_t interface_id; + int8_t ret; + + interface_id = nanostack_interface_id_parse(interface_name); + + ret = arm_net_dns_server_get(interface_id, dns_srv_address, NULL, 0, index); + + if (ret == 0) { + address->set_ip_bytes(dns_srv_address, NSAPI_IPv6); + TRACE_DEEP("get_dns_server(), index=%d, ret=%d, address=%s", index, ret, trace_ipv6((uint8_t*)address->get_ip_bytes())); + return NSAPI_ERROR_OK; + } + + return NSAPI_ERROR_NO_ADDRESS; +} + nsapi_error_t Nanostack::socket_open(void **handle, nsapi_protocol_t protocol) { // Validate parameters From 2e790b5ff19ec5ef803d9a8b955e57aa4c1304a1 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 31 Aug 2020 10:53:48 +0300 Subject: [PATCH 2/6] Review corrections -Check address version NSAPI_UNSPEC -Disable traces -More specific interface ID parsing -Harmonize return values --- connectivity/nanostack/source/Nanostack.cpp | 27 +++++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/connectivity/nanostack/source/Nanostack.cpp b/connectivity/nanostack/source/Nanostack.cpp index 38f276936e3..1b08ffa8959 100644 --- a/connectivity/nanostack/source/Nanostack.cpp +++ b/connectivity/nanostack/source/Nanostack.cpp @@ -37,11 +37,11 @@ #include "ns_trace.h" #define TRACE_GROUP "nsif" -#define NSIF_DEEP_TRACE +//#define NSIF_DEEP_TRACE #ifdef NSIF_DEEP_TRACE #define TRACE_DEEP tr_debug #else -#define TRACE_DEP(...) +#define TRACE_DEEP(...) #endif #define NS_INTERFACE_SOCKETS_MAX 16 //same as NanoStack SOCKET_MAX @@ -160,6 +160,7 @@ static int8_t find_interface_by_address(const uint8_t target_addr[16]) static int8_t nanostack_interface_id_parse(const char* interface_name) { + int namelen; int8_t interface_id = -1; TRACE_DEEP("nanostack_interface_id_parse() %s", interface_name ? interface_name : "null"); @@ -169,20 +170,20 @@ static int8_t nanostack_interface_id_parse(const char* interface_name) } // parse interface ID from the interface_name - if (strlen(interface_name) < 4) { + namelen = strlen(interface_name); + if (namelen < 4 || namelen > 5) { return -1; } - interface_id = atoi(&interface_name[3]); - if (interface_id < 0) { - return -1; + if ((strncmp("MES", interface_name, 3) == 0) && isdigit(interface_name[3])) { + interface_id = atoi(&interface_name[3]); } TRACE_DEEP("parsed interfaceID = %d", interface_id); return interface_id; } -static int8_t nanostack_dns_query_result_check(const char *domain_name, SocketAddress *address, const char *interface_name) +static int nanostack_dns_query_result_check(const char *domain_name, SocketAddress *address, const char *interface_name) { uint8_t dns_query_addr[16] = {0}; int8_t interface_id, ns_query_result; @@ -597,9 +598,14 @@ nsapi_error_t Nanostack::gethostbyname(const char *name, SocketAddress *address, return NSAPI_ERROR_OK; } + // Nanostack is IPv6 stack + if (version == NSAPI_UNSPEC) { + version = NSAPI_IPv6; + } + // try nanostack DNS cache, if not found then fallback to dns query if (nanostack_dns_query_result_check(name, address, interface_name) == 0) { - return 0; + return NSAPI_ERROR_OK; } return nsapi_dns_query(this, name, address, interface_name, version); @@ -622,6 +628,11 @@ nsapi_value_or_error_t Nanostack::gethostbyname_async(const char *name, hostbyna return NSAPI_ERROR_OK; } + // Nanostack is IPv6 stack + if (version == NSAPI_UNSPEC) { + version = NSAPI_IPv6; + } + // try nanostack DNS cache, if not found then fallback to dns query if (nanostack_dns_query_result_check(name, &address, interface_name) == 0) { // hit found, return result immediately From da8f3bebcacda431d3fd9596146453de95ef2ef8 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 31 Aug 2020 11:52:01 +0300 Subject: [PATCH 3/6] Follow Mbed OS coding style --- connectivity/nanostack/source/Nanostack.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/connectivity/nanostack/source/Nanostack.cpp b/connectivity/nanostack/source/Nanostack.cpp index 1b08ffa8959..b9f04da697f 100644 --- a/connectivity/nanostack/source/Nanostack.cpp +++ b/connectivity/nanostack/source/Nanostack.cpp @@ -158,7 +158,7 @@ static int8_t find_interface_by_address(const uint8_t target_addr[16]) return -1; } -static int8_t nanostack_interface_id_parse(const char* interface_name) +static int8_t nanostack_interface_id_parse(const char *interface_name) { int namelen; int8_t interface_id = -1; @@ -190,10 +190,10 @@ static int nanostack_dns_query_result_check(const char *domain_name, SocketAddre interface_id = nanostack_interface_id_parse(interface_name); - ns_query_result = arm_net_dns_query_result_get(interface_id, dns_query_addr, (char*)domain_name); + ns_query_result = arm_net_dns_query_result_get(interface_id, dns_query_addr, (char *)domain_name); TRACE_DEEP("nanostack_dns_query_result_check(): interface_id=%d, ret=%d, resolved %s to %s", - interface_id, ns_query_result, domain_name, trace_ipv6(dns_query_addr)); + interface_id, ns_query_result, domain_name, trace_ipv6(dns_query_addr)); if (ns_query_result == 0) { address->set_ip_bytes(dns_query_addr, NSAPI_IPv6); @@ -656,7 +656,7 @@ nsapi_error_t Nanostack::get_dns_server(int index, SocketAddress *address, const if (ret == 0) { address->set_ip_bytes(dns_srv_address, NSAPI_IPv6); - TRACE_DEEP("get_dns_server(), index=%d, ret=%d, address=%s", index, ret, trace_ipv6((uint8_t*)address->get_ip_bytes())); + TRACE_DEEP("get_dns_server(), index=%d, ret=%d, address=%s", index, ret, trace_ipv6((uint8_t *)address->get_ip_bytes())); return NSAPI_ERROR_OK; } From d02561e5e9201e6026a21dc2872aa3eb202c3269 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 31 Aug 2020 14:36:33 +0300 Subject: [PATCH 4/6] Update WisunBorderRouter class Add set_dns_query_result to WisunBorderRouter. --- .../mbed-mesh-api/WisunBorderRouter.h | 13 +++++++++++++ .../mbed-mesh-api/source/WisunBorderRouter.cpp | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h b/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h index 22b2c01a60b..b8ab1d0cd18 100644 --- a/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h +++ b/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h @@ -307,6 +307,19 @@ class WisunBorderRouter { * */ mesh_error_t validate_radius_timing(ws_br_radius_timing_t *timing); + /** + * \brief Set DNS query result to Nanostack cache. + * + * Function sets DNS query result to Nanostack cache to get distributed to the devices in the Wi-SUN network. + * Function must be called for a running Wi-SUN Border Router instance. + * + * \param address resolved address of domain_name. + * \param domain_name name of the domain. Must be non-NULL. + * \return MESH_ERROR_NONE on success. + * \return error value in case of failure. + * */ + mesh_error_t set_dns_query_result(SocketAddress *address, char *domain_name); + private: mesh_error_t configure(); mesh_error_t apply_configuration(int8_t mesh_if_id); diff --git a/connectivity/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp b/connectivity/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp index a633ed7c7a2..557f58eb296 100644 --- a/connectivity/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp +++ b/connectivity/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp @@ -452,3 +452,20 @@ mesh_error_t WisunBorderRouter::validate_radius_timing(ws_br_radius_timing_t *ti return MESH_ERROR_NONE; } + +mesh_error_t WisunBorderRouter::set_dns_query_result(SocketAddress *address, char *domain_name) +{ + if (!domain_name || !address) { + return MESH_ERROR_PARAM; + } + + if (_mesh_if_id < 0) { + return MESH_ERROR_STATE; + } + + if (ws_bbr_dns_query_result_set(_mesh_if_id, (const uint8_t *)address->get_ip_bytes(), domain_name) >= 0 ) { + return MESH_ERROR_NONE; + } + + return MESH_ERROR_UNKNOWN; +} From a53233da08573b88501a9f0a0a4c8f598165a4cd Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 31 Aug 2020 16:36:13 +0300 Subject: [PATCH 5/6] Follow Mbed OS coding style --- .../nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connectivity/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp b/connectivity/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp index 557f58eb296..941e577a63a 100644 --- a/connectivity/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp +++ b/connectivity/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp @@ -463,7 +463,7 @@ mesh_error_t WisunBorderRouter::set_dns_query_result(SocketAddress *address, cha return MESH_ERROR_STATE; } - if (ws_bbr_dns_query_result_set(_mesh_if_id, (const uint8_t *)address->get_ip_bytes(), domain_name) >= 0 ) { + if (ws_bbr_dns_query_result_set(_mesh_if_id, (const uint8_t *)address->get_ip_bytes(), domain_name) >= 0) { return MESH_ERROR_NONE; } From 859806477424f5f6167596a975ec4e19c532cf73 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Wed, 2 Sep 2020 15:15:45 +0300 Subject: [PATCH 6/6] Use macro for isdigit --- connectivity/nanostack/source/Nanostack.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/connectivity/nanostack/source/Nanostack.cpp b/connectivity/nanostack/source/Nanostack.cpp index b9f04da697f..bc37fbfc599 100644 --- a/connectivity/nanostack/source/Nanostack.cpp +++ b/connectivity/nanostack/source/Nanostack.cpp @@ -44,6 +44,8 @@ #define TRACE_DEEP(...) #endif +#define NANOSTACK_ISDIGIT(c) ((c) >= '0' && (c) <= '9') + #define NS_INTERFACE_SOCKETS_MAX 16 //same as NanoStack SOCKET_MAX #define MALLOC ns_dyn_mem_alloc @@ -175,7 +177,7 @@ static int8_t nanostack_interface_id_parse(const char *interface_name) return -1; } - if ((strncmp("MES", interface_name, 3) == 0) && isdigit(interface_name[3])) { + if ((strncmp("MES", interface_name, 3) == 0) && NANOSTACK_ISDIGIT(interface_name[3])) { interface_id = atoi(&interface_name[3]); }