Skip to content

Commit

Permalink
Added DHCPv6 vendor data generation for DNS queries
Browse files Browse the repository at this point in the history
New library added for generating the vendor data in DHCPv6

Added support for storage of DNS queries in BBR
  • Loading branch information
Mika committed Sep 2, 2020
1 parent 639f9db commit 7fe0423
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 11 deletions.
3 changes: 2 additions & 1 deletion nanostack/ws_bbr_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,8 @@ int ws_bbr_radius_timing_validate(int8_t interface_id, bbr_radius_timing_t *timi
*
* This function can be called multiple times.
* if domain name matches a existing entry address is updated.
* If address and domain name is set to NULL entire list is cleared
* If domain name is set to NULL entire list is cleared
* if address is set to NULL the Domain name is removed from the list.
*
* \param interface_id Network interface ID.
* \param address The address of the DNS query result.
Expand Down
111 changes: 101 additions & 10 deletions source/6LoWPAN/ws/ws_bbr_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "nsconfig.h"
#include "ns_types.h"
#include "ns_trace.h"
#include "nsdynmemLIB.h"
#include "net_interface.h"
#include "socket_api.h"
#include "eventOS_event.h"
Expand All @@ -41,6 +42,7 @@
#include "6LoWPAN/ws/ws_pae_controller.h"
#include "DHCPv6_Server/DHCPv6_server_service.h"
#include "DHCPv6_client/dhcpv6_client_api.h"
#include "libDHCPv6/libDHCPv6_vendordata.h"
#include "libNET/src/net_dns_internal.h"


Expand Down Expand Up @@ -93,6 +95,17 @@ static rpl_dodag_conf_t rpl_conf = {
.dio_redundancy_constant = WS_RPL_DIO_REDUNDANCY_SMALL
};

typedef struct dns_resolution {
/** Resolved address for the domain*/
uint8_t address[16];
/** Domain name string */
char *domain_name;
} dns_resolution_t;

#define MAX_DNS_RESOLUTIONS 4

static dns_resolution_t pre_resolved_dns_queries[MAX_DNS_RESOLUTIONS] = {0};

static void ws_bbr_rpl_version_timer_start(protocol_interface_info_entry_t *cur, uint8_t version)
{
// Set the next timeout value for version update
Expand Down Expand Up @@ -368,7 +381,8 @@ static bool wisun_dhcp_address_add_cb(int8_t interfaceId, dhcp_address_cache_upd
wisun_bbr_na_send(backbone_interface_id, address_info->allocatedAddress);
return true;
}
static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *cur)

static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *cur, uint8_t *global_id)
{
//add DNS server information to DHCP server that is learned from the backbone interface.
uint8_t dns_server_address[16];
Expand All @@ -381,9 +395,34 @@ static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *
}

//TODO Generate vendor data in Wi-SUN network include the cached DNS query results in some sort of TLV format
(void)dhcp_vendor_data_ptr;
(void)dhcp_vendor_data_len;
//DHCPv6_server_service_set_vendor_data(cur->id, dhcp_vendor_data_ptr, dhcp_vendor_data_len);
int vendor_data_len = 0;
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
if (pre_resolved_dns_queries[n].domain_name != NULL) {
vendor_data_len += net_dns_option_vendor_option_data_dns_query_length(pre_resolved_dns_queries[n].domain_name);
}
}
if (vendor_data_len) {
ns_dyn_mem_free(dhcp_vendor_data_ptr);
dhcp_vendor_data_ptr = ns_dyn_mem_alloc(vendor_data_len);
if (!dhcp_vendor_data_ptr) {
tr_warn("Vendor info set fail");
return;
}
dhcp_vendor_data_len = vendor_data_len;
}
if (dhcp_vendor_data_ptr) {
// Write vendor data
uint8_t *ptr = dhcp_vendor_data_ptr;
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
if (pre_resolved_dns_queries[n].domain_name != NULL) {
ptr = net_dns_option_vendor_option_data_dns_query_write(ptr, pre_resolved_dns_queries[n].address, pre_resolved_dns_queries[n].domain_name);
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));
}
}
}

(void)global_id;
//DHCPv6_server_service_set_vendor_data(cur->id, global_id, ARM_ENTERPRISE_NUMBER, dhcp_vendor_data_ptr, dhcp_vendor_data_len);
}

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

ws_bbr_dhcp_server_dns_info_update(cur);
ws_bbr_dhcp_server_dns_info_update(cur, global_id);

ws_dhcp_client_address_request(cur, global_id, ll);
}
Expand Down Expand Up @@ -594,7 +633,7 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
// Add also global prefix and route to RPL
rpl_control_update_dodag_route(protocol_6lowpan_rpl_root_dodag, current_global_prefix, 64, 0, WS_ROUTE_LIFETIME, false);
}
ws_bbr_dhcp_server_dns_info_update(cur);
ws_bbr_dhcp_server_dns_info_update(cur, current_global_prefix);
}
}
void ws_bbr_pan_version_increase(protocol_interface_info_entry_t *cur)
Expand Down Expand Up @@ -1200,7 +1239,7 @@ int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16],
{
#ifdef HAVE_WS_BORDER_ROUTER
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
if (!cur || !address || !domain_name_ptr) {
if (!cur) {
return -1;
}

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

ws_bbr_dhcp_server_dns_info_update(cur);
// Delete all entries
if (!domain_name_ptr) {
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
// Delete all entries
memset(pre_resolved_dns_queries[n].address, 0, 16);
ns_dyn_mem_free(pre_resolved_dns_queries[n].domain_name);
pre_resolved_dns_queries[n].domain_name = NULL;
}
goto update_information;
}

// Update existing entries or delete
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
if (pre_resolved_dns_queries[n].domain_name != NULL &&
strcasecmp(pre_resolved_dns_queries[n].domain_name, domain_name_ptr) == 0) {
// Matching query updated
if (address) {
// Update address
memcpy(pre_resolved_dns_queries[n].address, address, 16);
} else {
// delete entry
memset(pre_resolved_dns_queries[n].address, 0, 16);
ns_dyn_mem_free(pre_resolved_dns_queries[n].domain_name);
pre_resolved_dns_queries[n].domain_name = NULL;
}
goto update_information;
}
}

if (address && domain_name_ptr) {
// Store new entry to the list
for (int n = 0; n < MAX_DNS_RESOLUTIONS; n++) {
if (pre_resolved_dns_queries[n].domain_name == NULL) {
// Free entry found
pre_resolved_dns_queries[n].domain_name = ns_dyn_mem_alloc(strlen(domain_name_ptr) + 1);
if (!pre_resolved_dns_queries[n].domain_name) {
// Out of memory
return -2;
}
memcpy(pre_resolved_dns_queries[n].address, address, 16);
strcpy(pre_resolved_dns_queries[n].domain_name, domain_name_ptr);
goto update_information;
}
}
// No room to store new field
return -3;
}

update_information:
if (memcmp(current_global_prefix, ADDR_UNSPECIFIED, 8) == 0) {
// Not in active state so changes are activated after start
return 0;
}

ws_bbr_dhcp_server_dns_info_update(cur, current_global_prefix);
return 0;
#else
(void) interface_id;
Expand Down
47 changes: 47 additions & 0 deletions source/libDHCPv6/libDHCPv6_vendordata.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2020, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.
*/

#include "nsconfig.h"
#include "ns_types.h"
#include "ns_trace.h"
#include <string.h>
#include "common_functions.h"
#include "libDHCPv6.h"
#include "libDHCPv6_vendordata.h"



/* DHCPv6 vendor options to distribute ARM vendor data*/

uint16_t net_dns_option_vendor_option_data_dns_query_length(char *domain)
{
return 4 + 16 + strlen(domain) + 1;
}

uint8_t *net_dns_option_vendor_option_data_dns_query_write(uint8_t *ptr, uint8_t *address, char *domain)
{
int domain_len = strlen(domain);
int length = 16 + domain_len + 1;

ptr = common_write_16_bit(ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT, ptr);
ptr = common_write_16_bit(length, ptr);
memcpy(ptr, address, 16);
ptr += 16;
memcpy(ptr, domain, domain_len + 1);
ptr += domain_len + 1;
return ptr;
}
42 changes: 42 additions & 0 deletions source/libDHCPv6/libDHCPv6_vendordata.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2020, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.
*/

#ifndef LIBDHCPV6_VENDOR_DATA_H_
#define LIBDHCPV6_VENDOR_DATA_H_


/*ARM enterprise number used to identify ARM generated Vendor data options*/
#define ARM_ENTERPRISE_NUMBER 4128

/* ARM Defined vendor data option to distribute DNS query results through DHCP server
* Format
*
* uint8_t address[16]
* domain string nul terminated.
*
* multiple results must be in separated vendor option data fields
* */
#define ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT 297

/* DHCPv6 vendor options to distribute ARM vendor data*/

uint16_t net_dns_option_vendor_option_data_dns_query_length(char *domain);
uint8_t *net_dns_option_vendor_option_data_dns_query_write(uint8_t *ptr, uint8_t *address, char *domain);



#endif /* LIBDHCPV6_VENDOR_DATA_H_ */
1 change: 1 addition & 0 deletions sources.mk
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ SRCS += \
source/DHCPv6_client/dhcpv6_client_service.c \
source/libDHCPv6/dhcp_service_api.c \
source/libDHCPv6/libDHCPv6.c \
source/libDHCPv6/libDHCPv6_vendordata.c \
source/libDHCPv6/libDHCPv6_server.c \
source/Service_Libs/utils/ns_crc.c \
source/Service_Libs/utils/isqrt.c \
Expand Down

0 comments on commit 7fe0423

Please sign in to comment.