Skip to content

Commit 3323f36

Browse files
author
Mika
committed
Add support for Ethernet RA dns configuration
Add interface to include default route to RA messages Add interface to include DNS server address in RA Messages Add interface to include DNS search list in RA messages Add parsing of DNS information from RA
1 parent d8e7d40 commit 3323f36

File tree

8 files changed

+282
-1
lines changed

8 files changed

+282
-1
lines changed

nanostack/net_ipv6_api.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,50 @@ int8_t arm_nwk_ipv6_opaque_iid_key(const void *secret_key, uint8_t key_len);
131131
*/
132132
int8_t arm_nwk_ipv6_opaque_iid_enable(int8_t interface_id, bool enable);
133133

134+
/**
135+
* \brief Enable/disable default route in Router advertisements
136+
*
137+
* Enable or disable RFC 4861 Default router configuration in router advertisements.
138+
* This makes the device a default router in the interface.
139+
*
140+
* \param interface_id Interface ID.
141+
* \param enable True to enable.
142+
* \return 0 enabled/disabled OK.
143+
* \return <0 failed (for example invalid interface ID).
144+
*
145+
*/
146+
int8_t arm_nwk_ipv6_default_route_enable(int8_t interface_id, bool enable);
147+
148+
/**
149+
* \brief add Recursive DNS Server Option information to Router advertisements
150+
*
151+
* Add Recursive DNS Server Option from RFC 8106 to router advertisements.
152+
* This makes it possible to configure DNS server address to other devices connected to the interface.
153+
*
154+
* \param interface_id Interface ID.
155+
* \param address 16 byte array for IPv6 address.
156+
* \param lifetime advertised lifetime of the entry. 0 to delete address.
157+
* \return 0 DNS server option option successful.
158+
* \return <0 failed (for example invalid interface ID).
159+
*
160+
*/
161+
int8_t arm_nwk_ipv6_dns_server_add(int8_t interface_id, uint8_t *address, uint32_t lifetime);
162+
163+
/**
164+
* \brief add DNS Search List Option information to Router advertisements
165+
*
166+
* Add DNS Search List Option from RFC 8106 to router advertisements.
167+
* This makes it possible to configure DNS search list to other devices connected to the interface.
168+
*
169+
* \param interface_id Interface ID.
170+
* \param data byte array encoded following https://tools.ietf.org/html/rfc1035#section-3.1.
171+
* \param data_len Length of the byte array
172+
* \param lifetime advertised lifetime of the entry. 0 to delete address.
173+
* \return 0 DNS server option option successful.
174+
* \return <0 failed (for example invalid interface ID).
175+
*
176+
*/
177+
int8_t arm_nwk_ipv6_dns_search_list_add(int8_t interface_id, uint8_t *data, uint16_t data_len, uint32_t lifetime);
178+
179+
134180
#endif /* NET_IPV6_API_H_ */

source/Common_Protocols/icmpv6.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,40 @@ static buffer_t *icmpv6_ra_handler(buffer_t *buf)
859859
} else {
860860
ipv6_route_delete(prefix_ptr, prefix_length, cur->id, buf->src_sa.address, ROUTE_RADV);
861861
}
862+
} else if (type == ICMPV6_OPT_DNS_SEARCH_LIST) {
863+
864+
if (length < 8) {
865+
tr_warn("Invalid RA DNS search list opt corrupt");
866+
goto next_option; // invalid not accepted
867+
}
868+
uint32_t dns_lifetime = common_read_32_bit(dptr + 2); // 2 x reserved
869+
uint8_t *dns_search_list = dptr + 6;
870+
uint8_t dns_search_list_len = length - 8; // Length includes type and length
871+
872+
tr_info("DNS Search List: %s Lifetime: %lu", trace_array(dns_search_list, dns_search_list_len), (unsigned long) dns_lifetime);
873+
// TODO Add DNS server to DNS information storage.
874+
// dns_search_list_storage(cur, buf->src_sa.address, dns_search_list, dns_search_list_len, dns_lifetime);
875+
(void)dns_search_list;
876+
(void)dns_search_list_len;
877+
(void)dns_lifetime;
878+
879+
} else if (type == ICMPV6_OPT_RECURSIVE_DNS_SERVER) {
880+
uint8_t dns_length = length / 8;
881+
882+
if (dns_length < 3) {
883+
tr_warn("Invalid RA DNS server opt corrupt");
884+
goto next_option; // invalid not accepted
885+
}
886+
uint8_t dns_count = (dns_length - 1) / 2;
887+
uint32_t dns_lifetime = common_read_32_bit(dptr + 2); // 2 x reserved
888+
for (int n = 0; n < dns_count; n++) {
889+
uint8_t *dns_srv_addr = dptr + 6 + n * 16;
890+
tr_info("DNS Server: %s Lifetime: %lu", trace_ipv6(dns_srv_addr), (unsigned long) dns_lifetime);
891+
// TODO Add DNS server to DNS information storage.
892+
// dns_server_storage(cur, buf->src_sa.address, dns_srv_addr, dns_lifetime);
893+
(void)dns_srv_addr;
894+
(void)dns_lifetime;
895+
}
862896
} else if (type == ICMPV6_OPT_6LOWPAN_CONTEXT) {
863897
nd_ra_process_lowpan_context_option(cur, dptr - 2);
864898
}

source/Common_Protocols/icmpv6.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@
7777
#define ICMPV6_OPT_REDIRECTED_HDR 4
7878
#define ICMPV6_OPT_MTU 5
7979
#define ICMPV6_OPT_ROUTE_INFO 24
80+
#define ICMPV6_OPT_RECURSIVE_DNS_SERVER 25
81+
#define ICMPV6_OPT_DNS_SEARCH_LIST 31
8082
#define ICMPV6_OPT_ADDR_REGISTRATION 33
8183
#define ICMPV6_OPT_6LOWPAN_CONTEXT 34
8284
#define ICMPV6_OPT_AUTHORITATIVE_BORDER_RTR 35

source/ipv6_stack/protocol_ipv6.c

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ typedef struct ipv6_interface_route_on_link_t {
5757
ns_list_link_t link;
5858
} ipv6_interface_route_on_link_t;
5959

60+
typedef struct ipv6_interface_dns_server_on_link_t {
61+
uint8_t addr[16]; /*!< DNS Server IPv6 address */
62+
ns_list_link_t link;
63+
} ipv6_interface_dns_server_on_link_t;
64+
6065
#define WB_UPDATE_PERIOD_SECONDS 23
6166

6267
#define ROUTER_SOL_MAX_COUNTER 4
@@ -77,6 +82,14 @@ static NS_LIST_DEFINE(prefix_on_link, ipv6_interface_prefix_on_link_t, link);
7782
static NS_LIST_DEFINE(route_on_link, ipv6_interface_route_on_link_t, link);
7883
static prefix_list_t ipv6_prefixs = NS_LIST_INIT(ipv6_prefixs);
7984

85+
86+
/*Router advertisement daemon configurations*/
87+
static uint16_t radv_default_route_lifetime = 0;
88+
static NS_LIST_DEFINE(dns_server_list, ipv6_interface_dns_server_on_link_t, link);
89+
90+
static uint16_t dns_search_list_len = 0;
91+
static uint8_t *dns_search_list_ptr = NULL;
92+
8093
bool tunnel_in_use = false;
8194

8295
static void ethernet_data_conf_cb(const eth_mac_api_t *api, const eth_data_conf_t *data)
@@ -426,6 +439,73 @@ void ipv6_stack_route_advert_update(uint8_t *address, uint8_t prefixLength, uint
426439
}
427440
}
428441

442+
void ipv6_stack_route_advert_default_route(struct protocol_interface_info_entry *cur, bool enable)
443+
{
444+
if (enable) {
445+
radv_default_route_lifetime = icmpv6_radv_max_rtr_adv_interval(cur) * 2 / 10;
446+
} else {
447+
radv_default_route_lifetime = 0;
448+
}
449+
}
450+
451+
int8_t ipv6_stack_route_advert_dns_server_add(uint8_t *address)
452+
{
453+
454+
if (!address) {
455+
return -1;
456+
}
457+
458+
ns_list_foreach(ipv6_interface_dns_server_on_link_t, cur_server, &dns_server_list) {
459+
if (memcmp(cur_server->addr, address, 16) == 0) {
460+
return 0;
461+
}
462+
}
463+
ipv6_interface_dns_server_on_link_t *new_entry = ns_dyn_mem_alloc(sizeof(ipv6_interface_dns_server_on_link_t));
464+
if (!new_entry) {
465+
return -1;
466+
}
467+
memcpy(new_entry->addr, address, 16);
468+
ns_list_add_to_end(&dns_server_list, new_entry);
469+
return 0;
470+
}
471+
472+
void ipv6_stack_route_advert_dns_server_delete(uint8_t *address)
473+
{
474+
/* If Address is NULL everything is cleared.
475+
* */
476+
ns_list_foreach_safe(ipv6_interface_dns_server_on_link_t, cur_server, &dns_server_list) {
477+
if (!address || memcmp(cur_server->addr, address, 16) == 0) {
478+
ns_list_remove(&dns_server_list, cur_server);
479+
ns_dyn_mem_free(cur_server);
480+
}
481+
}
482+
}
483+
484+
int8_t ipv6_stack_route_advert_dns_search_list_add(uint8_t *data, uint16_t data_len, uint32_t lifetime)
485+
{
486+
487+
if (dns_search_list_ptr) {
488+
ns_dyn_mem_free(dns_search_list_ptr);
489+
dns_search_list_ptr = NULL;
490+
dns_search_list_len = 0;
491+
}
492+
493+
// Check if this is delete operation
494+
if (lifetime == 0 || data_len == 0 || data == NULL) {
495+
return 0;
496+
}
497+
498+
dns_search_list_len = ((data_len / 8) + 1) * 8; //Should have padding to 8 bytes
499+
dns_search_list_ptr = ns_dyn_mem_alloc(dns_search_list_len);
500+
if (!dns_search_list_ptr) {
501+
return -1;
502+
}
503+
504+
memset(dns_search_list_ptr, 0, dns_search_list_len);
505+
memcpy(dns_search_list_ptr, data, data_len);
506+
return 0;
507+
}
508+
429509
void ipv6_prefix_on_link_update(uint8_t *address)
430510
{
431511
protocol_interface_info_entry_t *cur = nwk_interface_get_ipv6_ptr();
@@ -630,6 +710,7 @@ int8_t ipv6_interface_down(protocol_interface_info_entry_t *cur)
630710
icmpv6_prefix_list_free(&ipv6_prefixs);
631711
ipv6_prefix_online_list_free();
632712
ipv6_rote_advert_list_free();
713+
ipv6_stack_route_advert_dns_server_delete(NULL);
633714
neighbor_cache_flush(&cur->neigh_cache);
634715
ipv6_route_table_remove_interface(cur->id);
635716
protocol_core_interface_info_reset(cur);
@@ -661,6 +742,12 @@ void ipv6_nd_ra_advert(protocol_interface_info_entry_t *cur, const uint8_t *dest
661742
uint16_t length = 12 + 8 + 16;
662743
length += 32 * ns_list_count(&ipv6_prefixs);
663744
length += 32 * ns_list_count(&prefix_on_link);
745+
if (ns_list_count(&dns_server_list)) {
746+
length += 8 + 16 * ns_list_count(&dns_server_list);
747+
}
748+
if (dns_search_list_len) {
749+
length += 8 + dns_search_list_len;
750+
}
664751

665752
ns_list_foreach(ipv6_interface_route_on_link_t, tmp_route, &route_on_link) {
666753
if (tmp_route->prefix_len < 65) {
@@ -680,7 +767,7 @@ void ipv6_nd_ra_advert(protocol_interface_info_entry_t *cur, const uint8_t *dest
680767
*ptr++ = cur->adv_cur_hop_limit;
681768
*ptr++ = cur->rtr_adv_flags;
682769
//Do not advertise default route: set Router Lifetime to 0
683-
ptr = common_write_16_bit(0, ptr);
770+
ptr = common_write_16_bit(radv_default_route_lifetime, ptr);
684771
ptr = common_write_32_bit(cur->adv_reachable_time, ptr);
685772
ptr = common_write_32_bit(cur->adv_retrans_timer, ptr);
686773

@@ -749,6 +836,34 @@ void ipv6_nd_ra_advert(protocol_interface_info_entry_t *cur, const uint8_t *dest
749836
}
750837
}
751838

839+
if (ns_list_count(&dns_server_list)) {
840+
*ptr++ = ICMPV6_OPT_RECURSIVE_DNS_SERVER;
841+
*ptr++ = 1 + 2 * ns_list_count(&dns_server_list); // length is multiples of 8
842+
*ptr++ = 0; // Reserved
843+
*ptr++ = 0; // Reserved
844+
/* RFC8106 The value of Lifetime SHOULD by default be at least 3 * MaxRtrAdvInterval
845+
*
846+
* Lifetimes are short so we dont support removing entries by setting the lifetime 0
847+
* Lifetime is also for all entries so no maintenance is possible
848+
*/
849+
ptr = common_write_32_bit(icmpv6_radv_max_rtr_adv_interval(cur) * 3 / 10, ptr);
850+
851+
ns_list_foreach_safe(ipv6_interface_dns_server_on_link_t, dns, &dns_server_list) {
852+
memcpy(ptr, dns->addr, 16);
853+
ptr += 16;
854+
}
855+
}
856+
857+
if (dns_search_list_ptr && dns_search_list_len > 0) {
858+
*ptr++ = ICMPV6_OPT_DNS_SEARCH_LIST;
859+
*ptr++ = 1 + dns_search_list_len / 8; // length is multiples of 8
860+
*ptr++ = 0; // Reserved
861+
*ptr++ = 0; // Reserved
862+
ptr = common_write_32_bit(icmpv6_radv_max_rtr_adv_interval(cur) * 3 / 10, ptr);
863+
memcpy(ptr, dns_search_list_ptr, dns_search_list_len);
864+
ptr += dns_search_list_len;
865+
}
866+
752867
buffer_data_end_set(buf, ptr);
753868
memcpy(buf->dst_sa.address, dest, 16);
754869
/* Source must be LL address (even if non-LL dest) */

source/ipv6_stack/protocol_ipv6.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ void ipv6_nd_ra_advert(struct protocol_interface_info_entry *cur, const uint8_t
6666
void ipv6_interface_slaac_handler(struct protocol_interface_info_entry *cur, const uint8_t *slaacPrefix, uint8_t prefixLen, uint32_t validLifeTime, uint32_t preferredLifeTime);
6767
void ipv6_stack_route_advert_update(uint8_t *address, uint8_t prefixLength, uint8_t routePrefer);
6868
void ipv6_stack_route_advert_remove(uint8_t *address, uint8_t prefixLength);
69+
void ipv6_stack_route_advert_default_route(struct protocol_interface_info_entry *cur, bool enable);
70+
int8_t ipv6_stack_route_advert_dns_server_add(uint8_t *address);
71+
void ipv6_stack_route_advert_dns_server_delete(uint8_t *address);
72+
int8_t ipv6_stack_route_advert_dns_search_list_add(uint8_t *data, uint16_t data_len, uint32_t lifetime);
6973
void ipv6_prefix_on_link_update(uint8_t *address);
7074
void ipv6_prefix_on_link_remove(uint8_t *address);
7175
int8_t ipv6_interface_accept_ra(int8_t interface_id, net_ipv6_accept_ra_e accept_ra);
@@ -77,6 +81,10 @@ int8_t ipv6_interface_accept_ra(int8_t interface_id, net_ipv6_accept_ra_e accept
7781
#define ipv6_nd_ra_advert(cur, dest) ((void)0)
7882
#define ipv6_interface_sitelocal_clone(buf) ((void)0)
7983
#define ipv6_stack_route_advert_remove(address, prefixLength) ((void)0)
84+
#define ipv6_stack_route_advert_default_route(cur,enable)
85+
#define ipv6_stack_route_advert_dns_server_add(address)
86+
#define ipv6_stack_route_advert_dns_server_delete(address)
87+
#define ipv6_stack_route_advert_dns_search_list_add(data, data_len, lifetime)
8088
#define ipv6_prefix_on_link_update(address) ((void)0)
8189
#define ipv6_prefix_on_link_remove(address) ((void)0)
8290
#define ipv6_stack_route_advert_update(address, prefixLength, routePrefer) ((void)0)

source/libNET/src/net_ipv6.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "Common_Protocols/ipv6_flow.h"
2626
#include "Common_Protocols/ipv6_fragmentation.h"
2727
#include "NWK_INTERFACE/Include/protocol.h"
28+
#include "ipv6_stack/protocol_ipv6.h"
2829

2930
#include "net_ipv6_api.h"
3031

@@ -73,3 +74,59 @@ int8_t arm_nwk_ipv6_opaque_iid_enable(int8_t interface_id, bool enable)
7374
cur->opaque_slaac_iids = enable;
7475
return 0;
7576
}
77+
78+
int8_t arm_nwk_ipv6_default_route_enable(int8_t interface_id, bool enable)
79+
{
80+
#ifdef HAVE_ETHERNET
81+
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
82+
if (!cur) {
83+
return -1;
84+
}
85+
86+
ipv6_stack_route_advert_default_route(cur, enable);
87+
return 0;
88+
#else
89+
(void)interface_id;
90+
(void)enable;
91+
return -1;
92+
#endif
93+
}
94+
95+
int8_t arm_nwk_ipv6_dns_server_add(int8_t interface_id, uint8_t *address, uint32_t lifetime)
96+
{
97+
#ifdef HAVE_ETHERNET
98+
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
99+
if (!cur) {
100+
return -1;
101+
}
102+
if (lifetime == 0) {
103+
ipv6_stack_route_advert_dns_server_delete(address);
104+
} else {
105+
return ipv6_stack_route_advert_dns_server_add(address);
106+
}
107+
108+
return 0;
109+
#else
110+
(void)interface_id;
111+
(void)address;
112+
(void)lifetime;
113+
return -1;
114+
#endif
115+
}
116+
117+
int8_t arm_nwk_ipv6_dns_search_list_add(int8_t interface_id, uint8_t *data, uint16_t data_len, uint32_t lifetime)
118+
{
119+
#ifdef HAVE_ETHERNET
120+
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
121+
if (!cur) {
122+
return -1;
123+
}
124+
return ipv6_stack_route_advert_dns_search_list_add(data, data_len, lifetime);
125+
#else
126+
(void)interface_id;
127+
(void)data;
128+
(void)data_len;
129+
(void)lifetime;
130+
return -1;
131+
#endif
132+
}

test/nanostack/unittest/libNET/net_ipv6/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ TEST_SRC_FILES = \
1313
../../stub/protocol_core_stub.c \
1414
../../stub/ipv6_fragmentation_stub.c \
1515
../../stub/ipv6_flow_stub.c \
16+
../../stub/protocol_ipv6_stub.c \
1617
../../stub/ipv6_routing_table_stub.c \
1718
../../stub/address_stub.c \
1819

test/nanostack/unittest/stub/protocol_ipv6_stub.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,24 @@ void ipv6_stack_route_advert_update(uint8_t *address, uint8_t prefixLength, uint
108108
{
109109
}
110110

111+
void ipv6_stack_route_advert_default_route(struct protocol_interface_info_entry *cur, bool enable)
112+
{
113+
}
114+
115+
int8_t ipv6_stack_route_advert_dns_server_add(uint8_t *address)
116+
{
117+
return 0;
118+
}
119+
120+
void ipv6_stack_route_advert_dns_server_delete(uint8_t *address)
121+
{
122+
}
123+
124+
int8_t ipv6_stack_route_advert_dns_search_list_add(uint8_t *data, uint16_t data_len, uint32_t lifetime)
125+
{
126+
return 0;
127+
}
128+
111129
void ipv6_prefix_on_link_update(uint8_t *address)
112130
{
113131

0 commit comments

Comments
 (0)