Skip to content

Commit ed73a48

Browse files
authored
Merge pull request #13733 from artokin/enable_nanostack_dNS_cache_usage-master
Enable Nanostack DNS cache usage
2 parents 00aee87 + 8598064 commit ed73a48

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed

connectivity/nanostack/include/nanostack-interface/Nanostack.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,58 @@ class Nanostack : public OnboardNetworkStack, private mbed::NonCopyable<Nanostac
5959
/** @copydoc NetworkStack::get_ip_address */
6060
nsapi_error_t get_ip_address(SocketAddress *sockAddr) override;
6161

62+
/** Translate a hostname to an IP address with specific version using network interface name.
63+
*
64+
* The hostname may be either a domain name or an IP address. If the
65+
* hostname is an IP address, no network transactions will be performed.
66+
*
67+
* Method first checks Nanostack DNS query result cache. If match is found, then the result is returned immediately.
68+
* Otherwise method calls DNS resolver to find a match.
69+
*
70+
* @param host Hostname to resolve.
71+
* @param address Pointer to a SocketAddress to store the result.
72+
* @param version IP version of address to resolve, NSAPI_UNSPEC indicates
73+
* version is chosen by the stack (defaults to NSAPI_UNSPEC).
74+
* @param interface_name Network interface name
75+
* @return NSAPI_ERROR_OK on success, negative error code on failure.
76+
*/
77+
virtual nsapi_error_t gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version, const char *interface_name);
78+
79+
/** Translate a hostname to an IP address (asynchronous) using network interface name.
80+
*
81+
* The hostname may be either a domain name or a dotted IP address. If the
82+
* hostname is an IP address, no network transactions will be performed.
83+
*
84+
* Method first checks Nanostack DNS query result cache. If match is found, then the result is returned immediately.
85+
*
86+
* Call is non-blocking. Result of the DNS operation is returned by the callback.
87+
* If this function returns failure, callback will not be called. In case result
88+
* is success (IP address was found from DNS cache), callback will be called
89+
* before function returns.
90+
*
91+
* @param host Hostname to resolve.
92+
* @param callback Callback that is called for result.
93+
* @param version IP version of address to resolve, NSAPI_UNSPEC indicates
94+
* version is chosen by the stack (defaults to NSAPI_UNSPEC).
95+
* @param interface_name Network interface name
96+
* @return 0 on immediate success,
97+
* negative error code on immediate failure or
98+
* a positive unique id that represents the hostname translation operation
99+
* and can be passed to cancel.
100+
*/
101+
virtual nsapi_value_or_error_t gethostbyname_async(const char *name, hostbyname_cb_t callback, nsapi_version_t version, const char *interface_name);
102+
103+
/** Get a domain name server from a list of servers to query
104+
*
105+
* Returns a DNS server address for a index. DNS servers are queried from Nanostack DNS cache.
106+
* If returns error no more DNS servers to read.
107+
*
108+
* @param index Index of the DNS server, starts from zero
109+
* @param address Destination for the host address
110+
* @return 0 on success, negative error code on failure
111+
*/
112+
virtual nsapi_error_t get_dns_server(int index, SocketAddress *address, const char *interface_name);
113+
62114
/** Opens a socket
63115
*
64116
* Creates a network socket and stores it in the specified handle.

connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,19 @@ class WisunBorderRouter {
307307
* */
308308
mesh_error_t validate_radius_timing(ws_br_radius_timing_t *timing);
309309

310+
/**
311+
* \brief Set DNS query result to Nanostack cache.
312+
*
313+
* Function sets DNS query result to Nanostack cache to get distributed to the devices in the Wi-SUN network.
314+
* Function must be called for a running Wi-SUN Border Router instance.
315+
*
316+
* \param address resolved address of domain_name.
317+
* \param domain_name name of the domain. Must be non-NULL.
318+
* \return MESH_ERROR_NONE on success.
319+
* \return error value in case of failure.
320+
* */
321+
mesh_error_t set_dns_query_result(SocketAddress *address, char *domain_name);
322+
310323
private:
311324
mesh_error_t configure();
312325
mesh_error_t apply_configuration(int8_t mesh_if_id);

connectivity/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,3 +452,20 @@ mesh_error_t WisunBorderRouter::validate_radius_timing(ws_br_radius_timing_t *ti
452452

453453
return MESH_ERROR_NONE;
454454
}
455+
456+
mesh_error_t WisunBorderRouter::set_dns_query_result(SocketAddress *address, char *domain_name)
457+
{
458+
if (!domain_name || !address) {
459+
return MESH_ERROR_PARAM;
460+
}
461+
462+
if (_mesh_if_id < 0) {
463+
return MESH_ERROR_STATE;
464+
}
465+
466+
if (ws_bbr_dns_query_result_set(_mesh_if_id, (const uint8_t *)address->get_ip_bytes(), domain_name) >= 0) {
467+
return MESH_ERROR_NONE;
468+
}
469+
470+
return MESH_ERROR_UNKNOWN;
471+
}

connectivity/nanostack/source/Nanostack.cpp

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,22 @@
3030
#include "mesh_system.h" // from inside mbed-mesh-api
3131
#include "socket_api.h"
3232
#include "net_interface.h"
33+
#include "nsapi_dns.h"
3334

3435
// Uncomment to enable trace
3536
//#define HAVE_DEBUG
3637
#include "ns_trace.h"
3738
#define TRACE_GROUP "nsif"
3839

40+
//#define NSIF_DEEP_TRACE
41+
#ifdef NSIF_DEEP_TRACE
42+
#define TRACE_DEEP tr_debug
43+
#else
44+
#define TRACE_DEEP(...)
45+
#endif
46+
47+
#define NANOSTACK_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
48+
3949
#define NS_INTERFACE_SOCKETS_MAX 16 //same as NanoStack SOCKET_MAX
4050

4151
#define MALLOC ns_dyn_mem_alloc
@@ -150,6 +160,51 @@ static int8_t find_interface_by_address(const uint8_t target_addr[16])
150160
return -1;
151161
}
152162

163+
static int8_t nanostack_interface_id_parse(const char *interface_name)
164+
{
165+
int namelen;
166+
int8_t interface_id = -1;
167+
168+
TRACE_DEEP("nanostack_interface_id_parse() %s", interface_name ? interface_name : "null");
169+
170+
if (!interface_name) {
171+
return -1;
172+
}
173+
174+
// parse interface ID from the interface_name
175+
namelen = strlen(interface_name);
176+
if (namelen < 4 || namelen > 5) {
177+
return -1;
178+
}
179+
180+
if ((strncmp("MES", interface_name, 3) == 0) && NANOSTACK_ISDIGIT(interface_name[3])) {
181+
interface_id = atoi(&interface_name[3]);
182+
}
183+
184+
TRACE_DEEP("parsed interfaceID = %d", interface_id);
185+
return interface_id;
186+
}
187+
188+
static int nanostack_dns_query_result_check(const char *domain_name, SocketAddress *address, const char *interface_name)
189+
{
190+
uint8_t dns_query_addr[16] = {0};
191+
int8_t interface_id, ns_query_result;
192+
193+
interface_id = nanostack_interface_id_parse(interface_name);
194+
195+
ns_query_result = arm_net_dns_query_result_get(interface_id, dns_query_addr, (char *)domain_name);
196+
197+
TRACE_DEEP("nanostack_dns_query_result_check(): interface_id=%d, ret=%d, resolved %s to %s",
198+
interface_id, ns_query_result, domain_name, trace_ipv6(dns_query_addr));
199+
200+
if (ns_query_result == 0) {
201+
address->set_ip_bytes(dns_query_addr, NSAPI_IPv6);
202+
return 0;
203+
}
204+
205+
return -1;
206+
}
207+
153208
void *NanostackSocket::operator new (std::size_t sz)
154209
{
155210
return MALLOC(sz);
@@ -532,6 +587,84 @@ nsapi_error_t Nanostack::get_ip_address(SocketAddress *sockAddr)
532587
return NSAPI_ERROR_NO_ADDRESS;
533588
}
534589

590+
nsapi_error_t Nanostack::gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version, const char *interface_name)
591+
{
592+
if (name[0] == '\0') {
593+
return NSAPI_ERROR_PARAMETER;
594+
}
595+
// check for simple ip addresses
596+
if (address->set_ip_address(name)) {
597+
if (version != NSAPI_UNSPEC && address->get_ip_version() != version) {
598+
return NSAPI_ERROR_DNS_FAILURE;
599+
}
600+
return NSAPI_ERROR_OK;
601+
}
602+
603+
// Nanostack is IPv6 stack
604+
if (version == NSAPI_UNSPEC) {
605+
version = NSAPI_IPv6;
606+
}
607+
608+
// try nanostack DNS cache, if not found then fallback to dns query
609+
if (nanostack_dns_query_result_check(name, address, interface_name) == 0) {
610+
return NSAPI_ERROR_OK;
611+
}
612+
613+
return nsapi_dns_query(this, name, address, interface_name, version);
614+
}
615+
616+
nsapi_value_or_error_t Nanostack::gethostbyname_async(const char *name, hostbyname_cb_t callback, nsapi_version_t version, const char *interface_name)
617+
{
618+
SocketAddress address;
619+
620+
if (name[0] == '\0') {
621+
return NSAPI_ERROR_PARAMETER;
622+
}
623+
624+
// check for simple ip addresses
625+
if (address.set_ip_address(name)) {
626+
if (version != NSAPI_UNSPEC && address.get_ip_version() != version) {
627+
return NSAPI_ERROR_DNS_FAILURE;
628+
}
629+
callback(NSAPI_ERROR_OK, &address);
630+
return NSAPI_ERROR_OK;
631+
}
632+
633+
// Nanostack is IPv6 stack
634+
if (version == NSAPI_UNSPEC) {
635+
version = NSAPI_IPv6;
636+
}
637+
638+
// try nanostack DNS cache, if not found then fallback to dns query
639+
if (nanostack_dns_query_result_check(name, &address, interface_name) == 0) {
640+
// hit found, return result immediately
641+
callback(NSAPI_ERROR_OK, &address);
642+
return NSAPI_ERROR_OK;
643+
}
644+
645+
call_in_callback_cb_t call_in_cb = get_call_in_callback();
646+
return nsapi_dns_query_async(this, name, callback, call_in_cb, interface_name, version);
647+
}
648+
649+
nsapi_error_t Nanostack::get_dns_server(int index, SocketAddress *address, const char *interface_name)
650+
{
651+
uint8_t dns_srv_address[16];
652+
int8_t interface_id;
653+
int8_t ret;
654+
655+
interface_id = nanostack_interface_id_parse(interface_name);
656+
657+
ret = arm_net_dns_server_get(interface_id, dns_srv_address, NULL, 0, index);
658+
659+
if (ret == 0) {
660+
address->set_ip_bytes(dns_srv_address, NSAPI_IPv6);
661+
TRACE_DEEP("get_dns_server(), index=%d, ret=%d, address=%s", index, ret, trace_ipv6((uint8_t *)address->get_ip_bytes()));
662+
return NSAPI_ERROR_OK;
663+
}
664+
665+
return NSAPI_ERROR_NO_ADDRESS;
666+
}
667+
535668
nsapi_error_t Nanostack::socket_open(void **handle, nsapi_protocol_t protocol)
536669
{
537670
// Validate parameters

0 commit comments

Comments
 (0)