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"
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+
96109static 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 ];
@@ -377,13 +391,37 @@ static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *
377391 (void )cur ;
378392 if (net_dns_server_get (backbone_interface_id , dns_server_address , & dns_search_list_ptr , & dns_search_list_len , 0 ) == 0 ) {
379393 /*Only supporting one DNS server address*/
380- // DHCPv6_server_service_set_dns_server(cur->id, dns_server_address, dns_search_list_ptr, dns_search_list_len);
394+ DHCPv6_server_service_set_dns_server (cur -> id , global_id , dns_server_address , dns_search_list_ptr , dns_search_list_len );
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+ DHCPv6_server_service_set_vendor_data (cur -> id , global_id , ARM_ENTERPRISE_NUMBER , dhcp_vendor_data_ptr , dhcp_vendor_data_len );
387425}
388426
389427static void ws_bbr_dhcp_server_start (protocol_interface_info_entry_t * cur , uint8_t * global_id , uint32_t dhcp_address_lifetime )
@@ -406,7 +444,7 @@ static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8
406444 //SEt max value for not limiting address allocation
407445 DHCPv6_server_service_set_max_clients_accepts_count (cur -> id , global_id , MAX_SUPPORTED_ADDRESS_LIST_SIZE );
408446
409- ws_bbr_dhcp_server_dns_info_update (cur );
447+ ws_bbr_dhcp_server_dns_info_update (cur , global_id );
410448
411449 ws_dhcp_client_address_request (cur , global_id , ll );
412450}
@@ -594,7 +632,7 @@ static void ws_bbr_rpl_status_check(protocol_interface_info_entry_t *cur)
594632 // Add also global prefix and route to RPL
595633 rpl_control_update_dodag_route (protocol_6lowpan_rpl_root_dodag , current_global_prefix , 64 , 0 , WS_ROUTE_LIFETIME , false);
596634 }
597- ws_bbr_dhcp_server_dns_info_update (cur );
635+ ws_bbr_dhcp_server_dns_info_update (cur , current_global_prefix );
598636 }
599637}
600638void ws_bbr_pan_version_increase (protocol_interface_info_entry_t * cur )
@@ -1200,7 +1238,7 @@ int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16],
12001238{
12011239#ifdef HAVE_WS_BORDER_ROUTER
12021240 protocol_interface_info_entry_t * cur = protocol_stack_interface_info_get_by_id (interface_id );
1203- if (!cur || ! address || ! domain_name_ptr ) {
1241+ if (!cur ) {
12041242 return -1 ;
12051243 }
12061244
@@ -1210,10 +1248,62 @@ int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16],
12101248 *
12111249 * This is included in the vendor extension where the format is decided by the vendor
12121250 */
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
12151251
1216- ws_bbr_dhcp_server_dns_info_update (cur );
1252+ // Delete all entries
1253+ if (!domain_name_ptr ) {
1254+ for (int n = 0 ; n < MAX_DNS_RESOLUTIONS ; n ++ ) {
1255+ // Delete all entries
1256+ memset (pre_resolved_dns_queries [n ].address , 0 , 16 );
1257+ ns_dyn_mem_free (pre_resolved_dns_queries [n ].domain_name );
1258+ pre_resolved_dns_queries [n ].domain_name = NULL ;
1259+ }
1260+ goto update_information ;
1261+ }
1262+
1263+ // Update existing entries or delete
1264+ for (int n = 0 ; n < MAX_DNS_RESOLUTIONS ; n ++ ) {
1265+ if (pre_resolved_dns_queries [n ].domain_name != NULL &&
1266+ strcasecmp (pre_resolved_dns_queries [n ].domain_name , domain_name_ptr ) == 0 ) {
1267+ // Matching query updated
1268+ if (address ) {
1269+ // Update address
1270+ memcpy (pre_resolved_dns_queries [n ].address , address , 16 );
1271+ } else {
1272+ // delete entry
1273+ memset (pre_resolved_dns_queries [n ].address , 0 , 16 );
1274+ ns_dyn_mem_free (pre_resolved_dns_queries [n ].domain_name );
1275+ pre_resolved_dns_queries [n ].domain_name = NULL ;
1276+ }
1277+ goto update_information ;
1278+ }
1279+ }
1280+
1281+ if (address && domain_name_ptr ) {
1282+ // Store new entry to the list
1283+ for (int n = 0 ; n < MAX_DNS_RESOLUTIONS ; n ++ ) {
1284+ if (pre_resolved_dns_queries [n ].domain_name == NULL ) {
1285+ // Free entry found
1286+ pre_resolved_dns_queries [n ].domain_name = ns_dyn_mem_alloc (strlen (domain_name_ptr ) + 1 );
1287+ if (!pre_resolved_dns_queries [n ].domain_name ) {
1288+ // Out of memory
1289+ return -2 ;
1290+ }
1291+ memcpy (pre_resolved_dns_queries [n ].address , address , 16 );
1292+ strcpy (pre_resolved_dns_queries [n ].domain_name , domain_name_ptr );
1293+ goto update_information ;
1294+ }
1295+ }
1296+ // No room to store new field
1297+ return -3 ;
1298+ }
1299+
1300+ update_information :
1301+ if (memcmp (current_global_prefix , ADDR_UNSPECIFIED , 8 ) == 0 ) {
1302+ // Not in active state so changes are activated after start
1303+ return 0 ;
1304+ }
1305+
1306+ ws_bbr_dhcp_server_dns_info_update (cur , current_global_prefix );
12171307 return 0 ;
12181308#else
12191309 (void ) interface_id ;
0 commit comments