Skip to content

Commit 7fe0423

Browse files
author
Mika
committed
Added DHCPv6 vendor data generation for DNS queries
New library added for generating the vendor data in DHCPv6 Added support for storage of DNS queries in BBR
1 parent 639f9db commit 7fe0423

File tree

5 files changed

+193
-11
lines changed

5 files changed

+193
-11
lines changed

nanostack/ws_bbr_api.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,8 @@ int ws_bbr_radius_timing_validate(int8_t interface_id, bbr_radius_timing_t *timi
490490
*
491491
* This function can be called multiple times.
492492
* if domain name matches a existing entry address is updated.
493-
* If address and domain name is set to NULL entire list is cleared
493+
* If domain name is set to NULL entire list is cleared
494+
* if address is set to NULL the Domain name is removed from the list.
494495
*
495496
* \param interface_id Network interface ID.
496497
* \param address The address of the DNS query result.

source/6LoWPAN/ws/ws_bbr_api.c

Lines changed: 101 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "nsconfig.h"
2020
#include "ns_types.h"
2121
#include "ns_trace.h"
22+
#include "nsdynmemLIB.h"
2223
#include "net_interface.h"
2324
#include "socket_api.h"
2425
#include "eventOS_event.h"
@@ -41,6 +42,7 @@
4142
#include "6LoWPAN/ws/ws_pae_controller.h"
4243
#include "DHCPv6_Server/DHCPv6_server_service.h"
4344
#include "DHCPv6_client/dhcpv6_client_api.h"
45+
#include "libDHCPv6/libDHCPv6_vendordata.h"
4446
#include "libNET/src/net_dns_internal.h"
4547

4648

@@ -93,6 +95,17 @@ static rpl_dodag_conf_t rpl_conf = {
9395
.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL
9496
};
9597

98+
typedef struct dns_resolution {
99+
/** Resolved address for the domain*/
100+
uint8_t address[16];
101+
/** Domain name string */
102+
char *domain_name;
103+
} dns_resolution_t;
104+
105+
#define MAX_DNS_RESOLUTIONS 4
106+
107+
static dns_resolution_t pre_resolved_dns_queries[MAX_DNS_RESOLUTIONS] = {0};
108+
96109
static void ws_bbr_rpl_version_timer_start(protocol_interface_info_entry_t *cur, uint8_t version)
97110
{
98111
// Set the next timeout value for version update
@@ -368,7 +381,8 @@ static bool wisun_dhcp_address_add_cb(int8_t interfaceId, dhcp_address_cache_upd
368381
wisun_bbr_na_send(backbone_interface_id, address_info->allocatedAddress);
369382
return true;
370383
}
371-
static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *cur)
384+
385+
static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *cur, uint8_t *global_id)
372386
{
373387
//add DNS server information to DHCP server that is learned from the backbone interface.
374388
uint8_t dns_server_address[16];
@@ -381,9 +395,34 @@ static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *
381395
}
382396

383397
//TODO Generate vendor data in Wi-SUN network include the cached DNS query results in some sort of TLV format
384-
(void)dhcp_vendor_data_ptr;
385-
(void)dhcp_vendor_data_len;
386-
//DHCPv6_server_service_set_vendor_data(cur->id, dhcp_vendor_data_ptr, dhcp_vendor_data_len);
398+
int vendor_data_len = 0;
399+
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
400+
if (pre_resolved_dns_queries[n].domain_name != NULL) {
401+
vendor_data_len += net_dns_option_vendor_option_data_dns_query_length(pre_resolved_dns_queries[n].domain_name);
402+
}
403+
}
404+
if (vendor_data_len) {
405+
ns_dyn_mem_free(dhcp_vendor_data_ptr);
406+
dhcp_vendor_data_ptr = ns_dyn_mem_alloc(vendor_data_len);
407+
if (!dhcp_vendor_data_ptr) {
408+
tr_warn("Vendor info set fail");
409+
return;
410+
}
411+
dhcp_vendor_data_len = vendor_data_len;
412+
}
413+
if (dhcp_vendor_data_ptr) {
414+
// Write vendor data
415+
uint8_t *ptr = dhcp_vendor_data_ptr;
416+
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
417+
if (pre_resolved_dns_queries[n].domain_name != NULL) {
418+
ptr = net_dns_option_vendor_option_data_dns_query_write(ptr, pre_resolved_dns_queries[n].address, pre_resolved_dns_queries[n].domain_name);
419+
tr_info("set DNS query result for %s, addr: %s", pre_resolved_dns_queries[n].domain_name, tr_ipv6(pre_resolved_dns_queries[n].address));
420+
}
421+
}
422+
}
423+
424+
(void)global_id;
425+
//DHCPv6_server_service_set_vendor_data(cur->id, global_id, ARM_ENTERPRISE_NUMBER, dhcp_vendor_data_ptr, dhcp_vendor_data_len);
387426
}
388427

389428
static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8_t *global_id, uint32_t dhcp_address_lifetime)
@@ -406,7 +445,7 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8
406445
//SEt max value for not limiting address allocation
407446
DHCPv6_server_service_set_max_clients_accepts_count(cur->id, global_id, MAX_SUPPORTED_ADDRESS_LIST_SIZE);
408447

409-
ws_bbr_dhcp_server_dns_info_update(cur);
448+
ws_bbr_dhcp_server_dns_info_update(cur, global_id);
410449

411450
ws_dhcp_client_address_request(cur, global_id, ll);
412451
}
@@ -594,7 +633,7 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
594633
// Add also global prefix and route to RPL
595634
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, WS_ROUTE_LIFETIME, false);
596635
}
597-
ws_bbr_dhcp_server_dns_info_update(cur);
636+
ws_bbr_dhcp_server_dns_info_update(cur, current_global_prefix);
598637
}
599638
}
600639
void ws_bbr_pan_version_increase(protocol_interface_info_entry_t *cur)
@@ -1200,7 +1239,7 @@ int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16],
12001239
{
12011240
#ifdef HAVE_WS_BORDER_ROUTER
12021241
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
1203-
if (!cur || !address || !domain_name_ptr) {
1242+
if (!cur) {
12041243
return -1;
12051244
}
12061245

@@ -1210,10 +1249,62 @@ int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16],
12101249
*
12111250
* This is included in the vendor extension where the format is decided by the vendor
12121251
*/
1213-
// TODO search if entry exists replace if address is NULL delete the entry
1214-
// TODO This information should expire if not updated by client
12151252

1216-
ws_bbr_dhcp_server_dns_info_update(cur);
1253+
// Delete all entries
1254+
if (!domain_name_ptr) {
1255+
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
1256+
// Delete all entries
1257+
memset(pre_resolved_dns_queries[n].address, 0, 16);
1258+
ns_dyn_mem_free(pre_resolved_dns_queries[n].domain_name);
1259+
pre_resolved_dns_queries[n].domain_name = NULL;
1260+
}
1261+
goto update_information;
1262+
}
1263+
1264+
// Update existing entries or delete
1265+
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
1266+
if (pre_resolved_dns_queries[n].domain_name != NULL &&
1267+
strcasecmp(pre_resolved_dns_queries[n].domain_name, domain_name_ptr) == 0) {
1268+
// Matching query updated
1269+
if (address) {
1270+
// Update address
1271+
memcpy(pre_resolved_dns_queries[n].address, address, 16);
1272+
} else {
1273+
// delete entry
1274+
memset(pre_resolved_dns_queries[n].address, 0, 16);
1275+
ns_dyn_mem_free(pre_resolved_dns_queries[n].domain_name);
1276+
pre_resolved_dns_queries[n].domain_name = NULL;
1277+
}
1278+
goto update_information;
1279+
}
1280+
}
1281+
1282+
if (address && domain_name_ptr) {
1283+
// Store new entry to the list
1284+
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
1285+
if (pre_resolved_dns_queries[n].domain_name == NULL) {
1286+
// Free entry found
1287+
pre_resolved_dns_queries[n].domain_name = ns_dyn_mem_alloc(strlen(domain_name_ptr) + 1);
1288+
if (!pre_resolved_dns_queries[n].domain_name) {
1289+
// Out of memory
1290+
return -2;
1291+
}
1292+
memcpy(pre_resolved_dns_queries[n].address, address, 16);
1293+
strcpy(pre_resolved_dns_queries[n].domain_name, domain_name_ptr);
1294+
goto update_information;
1295+
}
1296+
}
1297+
// No room to store new field
1298+
return -3;
1299+
}
1300+
1301+
update_information:
1302+
if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) == 0) {
1303+
// Not in active state so changes are activated after start
1304+
return 0;
1305+
}
1306+
1307+
ws_bbr_dhcp_server_dns_info_update(cur, current_global_prefix);
12171308
return 0;
12181309
#else
12191310
(void) interface_id;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright (c) 2020, Arm Limited and affiliates.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "nsconfig.h"
19+
#include "ns_types.h"
20+
#include "ns_trace.h"
21+
#include <string.h>
22+
#include "common_functions.h"
23+
#include "libDHCPv6.h"
24+
#include "libDHCPv6_vendordata.h"
25+
26+
27+
28+
/* DHCPv6 vendor options to distribute ARM vendor data*/
29+
30+
uint16_t net_dns_option_vendor_option_data_dns_query_length(char *domain)
31+
{
32+
return 4 + 16 + strlen(domain) + 1;
33+
}
34+
35+
uint8_t *net_dns_option_vendor_option_data_dns_query_write(uint8_t *ptr, uint8_t *address, char *domain)
36+
{
37+
int domain_len = strlen(domain);
38+
int length = 16 + domain_len + 1;
39+
40+
ptr = common_write_16_bit(ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT, ptr);
41+
ptr = common_write_16_bit(length, ptr);
42+
memcpy(ptr, address, 16);
43+
ptr += 16;
44+
memcpy(ptr, domain, domain_len + 1);
45+
ptr += domain_len + 1;
46+
return ptr;
47+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2020, Arm Limited and affiliates.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#ifndef LIBDHCPV6_VENDOR_DATA_H_
19+
#define LIBDHCPV6_VENDOR_DATA_H_
20+
21+
22+
/*ARM enterprise number used to identify ARM generated Vendor data options*/
23+
#define ARM_ENTERPRISE_NUMBER 4128
24+
25+
/* ARM Defined vendor data option to distribute DNS query results through DHCP server
26+
* Format
27+
*
28+
* uint8_t address[16]
29+
* domain string nul terminated.
30+
*
31+
* multiple results must be in separated vendor option data fields
32+
* */
33+
#define ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT 297
34+
35+
/* DHCPv6 vendor options to distribute ARM vendor data*/
36+
37+
uint16_t net_dns_option_vendor_option_data_dns_query_length(char *domain);
38+
uint8_t *net_dns_option_vendor_option_data_dns_query_write(uint8_t *ptr, uint8_t *address, char *domain);
39+
40+
41+
42+
#endif /* LIBDHCPV6_VENDOR_DATA_H_ */

sources.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ SRCS += \
205205
source/DHCPv6_client/dhcpv6_client_service.c \
206206
source/libDHCPv6/dhcp_service_api.c \
207207
source/libDHCPv6/libDHCPv6.c \
208+
source/libDHCPv6/libDHCPv6_vendordata.c \
208209
source/libDHCPv6/libDHCPv6_server.c \
209210
source/Service_Libs/utils/ns_crc.c \
210211
source/Service_Libs/utils/isqrt.c \

0 commit comments

Comments
 (0)