diff --git a/features/nanostack/sal-stack-nanostack/nanostack/ws_bbr_api.h b/features/nanostack/sal-stack-nanostack/nanostack/ws_bbr_api.h index bba584aec9..85c4fd3d59 100644 --- a/features/nanostack/sal-stack-nanostack/nanostack/ws_bbr_api.h +++ b/features/nanostack/sal-stack-nanostack/nanostack/ws_bbr_api.h @@ -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. diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api.c index ae4d377b60..eedd4ea623 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bbr_api.c @@ -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" @@ -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" @@ -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 @@ -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]; @@ -377,13 +391,37 @@ static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t * (void)cur; if (net_dns_server_get(backbone_interface_id, dns_server_address, &dns_search_list_ptr, &dns_search_list_len, 0) == 0) { /*Only supporting one DNS server address*/ - //DHCPv6_server_service_set_dns_server(cur->id, dns_server_address, dns_search_list_ptr, dns_search_list_len); + DHCPv6_server_service_set_dns_server(cur->id, global_id, dns_server_address, dns_search_list_ptr, dns_search_list_len); } //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)); + } + } + } + + 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) @@ -406,7 +444,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); } @@ -594,7 +632,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) @@ -1200,7 +1238,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; } @@ -1210,10 +1248,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; diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bootstrap.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bootstrap.c index a1a490709f..808acb7bf2 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bootstrap.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_bootstrap.c @@ -65,6 +65,7 @@ #include "platform/topo_trace.h" #include "dhcp_service_api.h" #include "libDHCPv6/libDHCPv6.h" +#include "libDHCPv6/libDHCPv6_vendordata.h" #include "DHCPv6_client/dhcpv6_client_api.h" #include "ws_management_api.h" #include "net_rpl.h" @@ -73,6 +74,7 @@ #include "6LoWPAN/ws/ws_eapol_pdu.h" #include "6LoWPAN/ws/ws_eapol_auth_relay.h" #include "6LoWPAN/ws/ws_eapol_relay.h" +#include "libNET/src/net_dns_internal.h" #define TRACE_GROUP "wsbs" @@ -872,6 +874,80 @@ static void ws_bootstrap_dhcp_neighbour_update_cb(int8_t interface_id, uint8_t l ws_bootstrap_mac_neighbor_short_time_set(cur, mac64, WS_NEIGHBOUR_DHCP_ENTRY_LIFETIME); } +static void ws_bootstrap_dhcp_info_notify_cb(int8_t interface, dhcp_option_notify_t *options, dhcp_server_notify_info_t *server_info) +{ + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface); + if (!cur) { + return; + } + uint8_t server_ll64[16]; + memcpy(server_ll64, ADDR_LINK_LOCAL_PREFIX, 8); + + if (server_info->duid_length == 8) { + memcpy(server_ll64 + 8, server_info->duid, 8); + } else { + server_ll64[8] = server_info->duid[0]; + server_ll64[9] = server_info->duid[1]; + server_ll64[10] = server_info->duid[2]; + server_ll64[11] = 0xff; + server_ll64[12] = 0xfe; + server_ll64[13] = server_info->duid[3]; + server_ll64[14] = server_info->duid[4]; + server_ll64[15] = server_info->duid[5]; + } + server_ll64[8] ^= 2; + + switch (options->option_type) { + case DHCPV6_OPTION_VENDOR_SPECIFIC_INFO: + if (options->option.vendor_spesific.enterprise_number != ARM_ENTERPRISE_NUMBER) { + break; + } + while (options->option.vendor_spesific.data_length) { + uint16_t option_type; + char *domain; + uint8_t *address; + uint16_t option_len; + option_len = net_dns_option_vendor_option_data_get_next(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &option_type); + tr_debug("DHCP vendor specific data type:%u length %d", option_type, option_len); + //tr_debug("DHCP vendor specific data %s", trace_array(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length)); + + if (option_len == 0) { + // Option fields were corrupted + break; + } + if (option_type == ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT) { + // Process ARM DNS query result + domain = NULL; + address = NULL; + if (net_dns_option_vendor_option_data_dns_query_read(options->option.vendor_spesific.data, options->option.vendor_spesific.data_length, &address, &domain) > 0 || + domain || address) { + // Valid ARM DNS query entry + net_dns_query_result_set(interface, address, domain, server_info->life_time); + } + } + + options->option.vendor_spesific.data_length -= option_len; + options->option.vendor_spesific.data += option_len; + } + break; + + case DHCPV6_OPTION_DNS_SERVERS: + while (options->option.generic.data_length) { + net_dns_server_address_set(interface, server_ll64, options->option.generic.data, server_info->life_time); + options->option.generic.data_length -= 16; + options->option.generic.data += 16; + } + break; + case DHCPV6_OPTION_DOMAIN_LIST: + net_dns_server_search_list_set(interface, server_ll64, options->option.generic.data, options->option.generic.data_length, server_info->life_time); + break; + default: + break; + } + +} + + static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) { int8_t ret_val = -1; @@ -923,6 +999,7 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) dhcp_service_link_local_rx_cb_set(cur->id, ws_bootstrap_dhcp_neighbour_update_cb); dhcp_client_configure(cur->id, true, true, true); //RENEW uses SOLICIT, Interface will use 1 instance for address get, IAID address hint is not used. dhcp_client_solicit_timeout_set(cur->id, WS_DHCP_SOLICIT_TIMEOUT, WS_DHCP_SOLICIT_MAX_RT, WS_DHCP_SOLICIT_MAX_RC); + dhcp_client_option_notification_cb_set(cur->id, ws_bootstrap_dhcp_info_notify_cb); ws_nud_table_reset(cur); @@ -1520,7 +1597,11 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry tr_info("Updated PAN configuration own:%d, heard:%d", cur->ws_info->pan_information.pan_version, pan_version); // restart PAN version timer - cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout; + //Check Here Do we have a selected Primary parent + if (!cur->ws_info->configuration_learned || cur->ws_info->rpl_state == RPL_EVENT_DAO_DONE) { + cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout; + } + cur->ws_info->pan_information.pan_version = pan_version; ws_pae_controller_gtk_hash_update(cur, gtkhash_ptr); diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_config.h b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_config.h index 26009e1bb0..589724fda8 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_config.h +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_config.h @@ -273,4 +273,11 @@ extern uint8_t DEVICE_MIN_SENS; #define RADIUS_CLIENT_RETRY_IMAX 30 // First retry maximum 3 seconds #define RADIUS_CLIENT_TIMER_EXPIRATIONS 3 // Number of retries is three +/* + * EAP-TLS fragment length + * + * Configures both EAP-TLS and the RADIUS client (Framed-MTU on RFC 2864) + */ +#define EAP_TLS_FRAGMENT_LEN_VALUE 600 // EAP-TLS fragment length + #endif /* WS_CONFIG_H_ */ diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_eapol_relay.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_eapol_relay.c index a5a83c3ec3..0bc7a5a472 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_eapol_relay.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_eapol_relay.c @@ -66,11 +66,14 @@ int8_t ws_eapol_relay_start(protocol_interface_info_entry_t *interface_ptr, uint return -1; } - if (ws_eapol_relay_get(interface_ptr)) { + eapol_relay_t *eapol_relay = ws_eapol_relay_get(interface_ptr); + + if (eapol_relay) { + memcpy(&eapol_relay->remote_addr.address, remote_addr, 16); return 0; } - eapol_relay_t *eapol_relay = ns_dyn_mem_alloc(sizeof(eapol_relay_t)); + eapol_relay = ns_dyn_mem_alloc(sizeof(eapol_relay_t)); if (!eapol_relay) { return -1; } diff --git a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_controller.c b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_controller.c index b11e91cb1b..e222d825da 100644 --- a/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_controller.c +++ b/features/nanostack/sal-stack-nanostack/source/6LoWPAN/ws/ws_pae_controller.c @@ -1221,7 +1221,8 @@ int8_t ws_pae_controller_radius_address_set(int8_t interface_id, const uint8_t * } if (ws_pae_auth_radius_address_set(controller->interface_ptr, radius_cfg->radius_addr) < 0) { - return -1; + // If not set here since authenticator not created, then set on authenticator initialization + return 0; } return 0; diff --git a/features/nanostack/sal-stack-nanostack/source/Common_Protocols/icmpv6.c b/features/nanostack/sal-stack-nanostack/source/Common_Protocols/icmpv6.c index 52b8754257..1f8beaf6a3 100644 --- a/features/nanostack/sal-stack-nanostack/source/Common_Protocols/icmpv6.c +++ b/features/nanostack/sal-stack-nanostack/source/Common_Protocols/icmpv6.c @@ -639,6 +639,21 @@ if_address_entry_t *icmpv6_slaac_address_add(protocol_interface_info_entry_t *cu } #ifdef HAVE_IPV6_ND + +static uint8_t icmpv6_dns_search_list_remove_pad(uint8_t *data_ptr, uint8_t length) +{ + while (length) { + + if (data_ptr[length - 2] && data_ptr[length - 1] == 0) { + break; + } else if (data_ptr[length - 2] == 0 && data_ptr[length - 1] == 0) { + length--; + } + } + + return length; +} + static buffer_t *icmpv6_ra_handler(buffer_t *buf) { protocol_interface_info_entry_t *cur; @@ -869,7 +884,8 @@ static buffer_t *icmpv6_ra_handler(buffer_t *buf) uint32_t dns_lifetime = common_read_32_bit(dptr + 2); // 2 x reserved uint8_t *dns_search_list = dptr + 6; uint8_t dns_search_list_len = length - 8; // Length includes type and length - + //Cut Padding + dns_search_list_len = icmpv6_dns_search_list_remove_pad(dns_search_list, dns_search_list_len); //tr_info("DNS Search List: %s Lifetime: %lu", trace_array(dns_search_list, dns_search_list_len), (unsigned long) dns_lifetime); // Add DNS server to DNS information storage. net_dns_server_search_list_set(cur->id, buf->src_sa.address, dns_search_list, dns_search_list_len, dns_lifetime); diff --git a/features/nanostack/sal-stack-nanostack/source/DHCPv6_Server/DHCPv6_Server_service.c b/features/nanostack/sal-stack-nanostack/source/DHCPv6_Server/DHCPv6_Server_service.c index a7755034a9..8784c634d2 100644 --- a/features/nanostack/sal-stack-nanostack/source/DHCPv6_Server/DHCPv6_Server_service.c +++ b/features/nanostack/sal-stack-nanostack/source/DHCPv6_Server/DHCPv6_Server_service.c @@ -115,12 +115,29 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r } response->responseLength = libdhcpv6_address_reply_message_len(replyPacket->clientDUID.duid_length, replyPacket->serverDUID.duid_length, 0, replyPacket->rapidCommit, address_allocated); + //Calculate DNS LIST and Vendor data lengths here + response->responseLength += libdhcpv6_dns_server_message_sizes(serverBase); + response->responseLength += libdhcpv6_vendor_data_message_sizes(serverBase); + response->responsePtr = ns_dyn_mem_temporary_alloc(response->responseLength); if (response->responsePtr) { + uint8_t *ptr = response->responsePtr; + //Write Generic data at beginning + ptr = libdhcpv6_header_write(ptr, DHCPV6_REPLY_TYPE, replyPacket->transaction_ID); + ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_SERVER_ID_OPTION, &replyPacket->serverDUID); //16 + ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_CLIENT_ID_OPTION, &replyPacket->clientDUID); //16 if (address_allocated) { - libdhcpv6_reply_message_write(response->responsePtr, replyPacket, &nonTemporalAddress, NULL); + ptr = libdhcpv6_identity_association_option_write(ptr, replyPacket->iaId, replyPacket->T0, replyPacket->T1, true); + ptr = libdhcpv6_ia_address_option_write(ptr, nonTemporalAddress.requestedAddress, nonTemporalAddress.preferredLifeTime, nonTemporalAddress.validLifeTime); + //Write DNS LIST and Vendor data here + ptr = libdhcpv6_dns_server_message_writes(serverBase, ptr); + ptr = libdhcpv6_vendor_data_message_writes(serverBase, ptr); } else { - libdhcpv6_reply_message_write(response->responsePtr, replyPacket, NULL, NULL); + ptr = libdhcpv6_identity_association_option_write_with_status(ptr, replyPacket->iaId, replyPacket->T0, replyPacket->T1, DHCPV6_STATUS_NO_ADDR_AVAILABLE_CODE); + } + + if (replyPacket->rapidCommit) { + ptr = libdhcpv6_rapid_commit_option_write(ptr); } return 0; } @@ -407,6 +424,71 @@ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t gu return 0; } + +int DHCPv6_server_service_set_dns_server(int8_t interface, uint8_t guaPrefix[static 16], uint8_t dns_server_address[static 16], uint8_t *dns_search_list_ptr, uint8_t dns_search_list_len) +{ + dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); + if (!serverInfo) { + return -1; + } + + dhcpv6_dns_server_data_t *dns_entry = libdhcpv6_dns_server_allocate(serverInfo, dns_server_address); + if (!dns_entry) { + return -1; + } + + if (dns_entry->search_list_length != dns_search_list_len) { + ns_dyn_mem_free(dns_entry->search_list); + dns_entry->search_list = NULL; + dns_entry->search_list_length = 0; + if (dns_search_list_len) { + dns_entry->search_list = ns_dyn_mem_alloc(dns_search_list_len); + if (dns_entry->search_list) { + dns_entry->search_list_length = dns_search_list_len; + } + } + } + + if (dns_entry->search_list_length) { + //Copy Search List to allocated buffer + memcpy(dns_entry->search_list, dns_search_list_ptr, dns_entry->search_list_length); + } + + return 0; +} + +int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, uint8_t *dhcp_vendor_data_ptr, uint8_t dhcp_vendor_data_len) +{ + dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix); + if (!serverInfo) { + return -1; + } + + dhcpv6_vendor_data_t *vendor_data_entry = libdhcpv6_vendor_data_allocate(serverInfo, enterprise_number); + + if (!vendor_data_entry) { + return -1; + } + + if (vendor_data_entry->vendor_data_length != dhcp_vendor_data_len) { + ns_dyn_mem_free(vendor_data_entry->vendor_data); + vendor_data_entry->vendor_data = NULL; + vendor_data_entry->vendor_data_length = 0; + if (dhcp_vendor_data_len) { + vendor_data_entry->vendor_data = ns_dyn_mem_alloc(dhcp_vendor_data_len); + if (vendor_data_entry->vendor_data) { + vendor_data_entry->vendor_data_length = dhcp_vendor_data_len; + } + } + } + + if (vendor_data_entry->vendor_data_length) { + //Copy Venfor Data to allocated buffer + memcpy(vendor_data_entry->vendor_data, dhcp_vendor_data_ptr, vendor_data_entry->vendor_data_length); + } + return 0; +} + #else int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType) diff --git a/features/nanostack/sal-stack-nanostack/source/DHCPv6_Server/DHCPv6_server_service.h b/features/nanostack/sal-stack-nanostack/source/DHCPv6_Server/DHCPv6_server_service.h index 8f8616f4f4..024a46acde 100644 --- a/features/nanostack/sal-stack-nanostack/source/DHCPv6_Server/DHCPv6_server_service.h +++ b/features/nanostack/sal-stack-nanostack/source/DHCPv6_Server/DHCPv6_server_service.h @@ -89,6 +89,11 @@ int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_ * /param validLifeTimne in seconds */ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t guaPrefix[static 16], uint32_t validLifeTimne); + +int DHCPv6_server_service_set_dns_server(int8_t interface, uint8_t guaPrefix[static 16], uint8_t dns_server_address[static 16], uint8_t *dns_search_list_ptr, uint8_t dns_search_list_len); + +int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, uint8_t *dhcp_vendor_data_ptr, uint8_t dhcp_vendor_data_len); + #else #define DHCPv6_server_service_delete(interface, guaPrefix, delete_gua_addresses) #endif diff --git a/features/nanostack/sal-stack-nanostack/source/DHCPv6_client/dhcpv6_client_api.h b/features/nanostack/sal-stack-nanostack/source/DHCPv6_client/dhcpv6_client_api.h index ccfc6c1ddf..57025e76ef 100644 --- a/features/nanostack/sal-stack-nanostack/source/DHCPv6_client/dhcpv6_client_api.h +++ b/features/nanostack/sal-stack-nanostack/source/DHCPv6_client/dhcpv6_client_api.h @@ -79,8 +79,48 @@ void dhcp_client_delete(int8_t interface); */ typedef void (dhcp_client_global_adress_cb)(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status); +typedef struct dhcp_server_notify_info { + uint16_t duid_type; + uint16_t duid_length; + uint32_t life_time; + uint8_t *duid; +} dhcp_server_notify_info_t; + + +typedef struct dhcp_gen_option { + uint16_t data_length; + uint8_t *data; +} dhcp_gen_option_t; + +typedef struct dhcp_vendor_spesific_option { + uint32_t enterprise_number; + uint16_t data_length; + uint8_t *data; +} dhcp_vendor_spesific_option_t; + +typedef struct dhcp_option_notify_s { + uint8_t option_type; + union { + dhcp_gen_option_t generic; + dhcp_vendor_spesific_option_t vendor_spesific; + } option; +} dhcp_option_notify_t; + +/* give dhcp Client server Optional options notication + * + * /param interface interface id + * /param option_type Type of option + * /param option_data data of options. + * /param option_length length of option. + * /param server_info info inclu DUID and Life-time for notify options + * + */ +typedef void (dhcp_client_options_notify_cb)(int8_t interface, dhcp_option_notify_t *options, dhcp_server_notify_info_t *server_info); + int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], dhcp_client_global_adress_cb *error_cb); +int dhcp_client_option_notification_cb_set(int8_t interface, dhcp_client_options_notify_cb *notify_cb); + /* Renew all leased adddresses might be used when short address changes * * /param interface interface where address is got diff --git a/features/nanostack/sal-stack-nanostack/source/DHCPv6_client/dhcpv6_client_service.c b/features/nanostack/sal-stack-nanostack/source/DHCPv6_client/dhcpv6_client_service.c index a8cecf6d8d..559b6ccf1d 100644 --- a/features/nanostack/sal-stack-nanostack/source/DHCPv6_client/dhcpv6_client_service.c +++ b/features/nanostack/sal-stack-nanostack/source/DHCPv6_client/dhcpv6_client_service.c @@ -33,6 +33,7 @@ typedef struct { dhcp_client_global_adress_cb *global_address_cb; + dhcp_client_options_notify_cb *option_information_cb; uint16_t service_instance; uint16_t relay_instance; uint16_t sol_timeout; @@ -152,6 +153,17 @@ void dhcp_client_solicit_timeout_set(int8_t interface, uint16_t timeout, uint16_ return; } +int dhcp_client_option_notification_cb_set(int8_t interface, dhcp_client_options_notify_cb *notify_cb) +{ + dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface); + if (!dhcp_client) { + return -1; + } + dhcp_client->option_information_cb = notify_cb; + return 0; + +} + void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16]) { dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface); @@ -215,6 +227,67 @@ void dhcpv6_client_send_error_cb(dhcpv6_client_server_data_t *srv_data_ptr) } +static void dhcp_vendor_information_notify(uint8_t *ptr, uint16_t data_len, dhcp_client_class_t *dhcp_client, dhcpv6_client_server_data_t *srv_data_ptr) +{ + if (!dhcp_client->option_information_cb) { + return; + } + + if (!srv_data_ptr->iaNontemporalAddress.validLifetime) { + return; //Valid Lifetime zero + } + + dhcp_option_notify_t dhcp_option; + + uint16_t type, length; + bool valid_optional_options; + + dhcp_server_notify_info_t server_info; + server_info.life_time = srv_data_ptr->iaNontemporalAddress.validLifetime; + server_info.duid = srv_data_ptr->serverDUID.duid + 2; // Skip the type + server_info.duid_type = srv_data_ptr->serverDUID.type; + server_info.duid_length = srv_data_ptr->serverDUID.duid_length - 2;// remove the type + + while (data_len >= 4) { + type = common_read_16_bit(ptr); + ptr += 2; + length = common_read_16_bit(ptr); + ptr += 2; + data_len -= 4; + if (data_len < length) { + return; + } + valid_optional_options = false; + //Accept only listed items below with validated lengths + if ((type == DHCPV6_OPTION_VENDOR_SPECIFIC_INFO || type == DHCPV6_OPTION_VENDOR_CLASS) && data_len >= 4) { + valid_optional_options = true; + //Parse enterprise number + dhcp_option.option.vendor_spesific.enterprise_number = common_read_32_bit(ptr); + ptr += 4; + data_len -= 4; + length -= 4; + dhcp_option.option.vendor_spesific.data = ptr; + dhcp_option.option.vendor_spesific.data_length = length; + + + } else if (type == DHCPV6_OPTION_DNS_SERVERS && (length >= 16 && ((length % 16) == 0))) { + valid_optional_options = true; + dhcp_option.option.generic.data = ptr; + dhcp_option.option.generic.data_length = length; + } else if (type == DHCPV6_OPTION_DOMAIN_LIST) { + valid_optional_options = true; + dhcp_option.option.generic.data = ptr; + dhcp_option.option.generic.data_length = length; + } + if (valid_optional_options) { + dhcp_option.option_type = type; + dhcp_client->option_information_cb(dhcp_client->interface, &dhcp_option, &server_info); + } + data_len -= length; + ptr += length; + } +} + /* solication responce received for either global address or routter id assignment */ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uint8_t *msg_ptr, uint16_t msg_len) { @@ -310,6 +383,10 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin if (dhcp_client->global_address_cb) { dhcp_client->global_address_cb(dhcp_client->interface, srv_data_ptr->server_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, status); } + + //Optional Options notify from Reply + dhcp_vendor_information_notify(msg_ptr, msg_len, dhcp_client, srv_data_ptr); + return RET_MSG_ACCEPTED; error_exit: dhcpv6_client_send_error_cb(srv_data_ptr); diff --git a/features/nanostack/sal-stack-nanostack/source/Security/kmp/kmp_socket_if.c b/features/nanostack/sal-stack-nanostack/source/Security/kmp/kmp_socket_if.c index cfecba64d8..6197e4304d 100644 --- a/features/nanostack/sal-stack-nanostack/source/Security/kmp/kmp_socket_if.c +++ b/features/nanostack/sal-stack-nanostack/source/Security/kmp/kmp_socket_if.c @@ -91,7 +91,7 @@ int8_t kmp_socket_if_register(kmp_service_t *service, uint8_t *instance_id, bool if (*instance_id == 0) { socket_if->instance_id = kmp_socket_if_instance_id++; if (socket_if->instance_id == 0) { - socket_if->instance_id++; + socket_if->instance_id = kmp_socket_if_instance_id++; } *instance_id = socket_if->instance_id; } diff --git a/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c b/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c index 5c2f5ee0e4..9592059724 100644 --- a/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c +++ b/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c @@ -201,8 +201,8 @@ static int8_t eap_tls_sec_prot_lib_ack_update(tls_data_t *tls) return false; } - if (tls->handled_len + TLS_FRAGMENT_LEN < tls->total_len) { - tls->handled_len += TLS_FRAGMENT_LEN; + if (tls->handled_len + EAP_TLS_FRAGMENT_LEN_VALUE < tls->total_len) { + tls->handled_len += EAP_TLS_FRAGMENT_LEN_VALUE; return false; } @@ -236,8 +236,8 @@ static uint8_t *eap_tls_sec_prot_lib_fragment_write(uint8_t *data, uint16_t tota data_begin[0] = *flags; } - if (total_len - handled_len > TLS_FRAGMENT_LEN) { - *message_len += TLS_FRAGMENT_LEN; + if (total_len - handled_len > EAP_TLS_FRAGMENT_LEN_VALUE) { + *message_len += EAP_TLS_FRAGMENT_LEN_VALUE; if (handled_len == 0) { data_begin -= 4; // length diff --git a/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.h b/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.h index 78be243eeb..6af3687869 100644 --- a/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.h +++ b/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.h @@ -54,7 +54,6 @@ typedef struct { uint16_t handled_len; /**< Handled length of the data buffer (e.g. acked by other end) */ } tls_data_t; -#define TLS_FRAGMENT_LEN 600 //EAP-TLS fragment length #define TLS_HEAD_LEN 5 //EAP-TLS flags and EAP-TLS length extern const uint8_t eap_msg_trace[4][10]; diff --git a/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c b/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c index 33c46eb8ae..7018d56c98 100644 --- a/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c +++ b/features/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c @@ -495,7 +495,7 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot) // On timeout if (sec_prot_result_timeout_check(&data->common)) { - // Do nothing for now + // Do nothing (trickle timer not running, so should not happen) return; } diff --git a/features/nanostack/sal-stack-nanostack/source/Security/protocols/radius_sec_prot/avp_helper.h b/features/nanostack/sal-stack-nanostack/source/Security/protocols/radius_sec_prot/avp_helper.h index 1fdd5bb54e..8687a112fa 100644 --- a/features/nanostack/sal-stack-nanostack/source/Security/protocols/radius_sec_prot/avp_helper.h +++ b/features/nanostack/sal-stack-nanostack/source/Security/protocols/radius_sec_prot/avp_helper.h @@ -46,8 +46,8 @@ // EUI-64 in ascii string: 00-11-..-77 #define STATION_ID_LEN 16 + 7 -// MTU value TBD -#define FRAMED_MTU 1400 +// MTU value is set by EAP-TLS fragment length +#define FRAMED_MTU EAP_TLS_FRAGMENT_LEN_VALUE #define NAS_PORT 1 diff --git a/features/nanostack/sal-stack-nanostack/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c b/features/nanostack/sal-stack-nanostack/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c index 986397f25f..a8dc175b7b 100644 --- a/features/nanostack/sal-stack-nanostack/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c +++ b/features/nanostack/sal-stack-nanostack/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c @@ -508,7 +508,9 @@ static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16 if (radius_client_sec_prot_ms_mppe_recv_key_pmk_decrypt(prot, recv_key, recv_key_len - AVP_FIXED_LEN, data->request_authenticator, data->new_pmk) >= 0) { data->new_pmk_set = true; +#ifdef EXTRA_DEBUG_INFO tr_info("RADIUS PMK: %s %s", tr_array(data->new_pmk, 16), tr_array(data->new_pmk + 16, 16)); +#endif } } } diff --git a/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.c b/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.c index 4af8669e75..78cb5154d5 100644 --- a/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.c +++ b/features/nanostack/sal-stack-nanostack/source/Service_Libs/fhss/fhss_ws.c @@ -859,13 +859,13 @@ static uint32_t fhss_ws_get_retry_period_callback(const fhss_api_t *api, uint8_t if (!fhss_structure) { return return_value; } - // We don't know the broadcast schedule, use large backoff with MAC retries + // We don't know the broadcast schedule, use randomised large backoff with MAC retries if (fhss_structure->ws->broadcast_timer_running == false) { - return 100000; + return (uint32_t) randLIB_get_random_in_range(20000, 45000); } // We don't know the TX/RX slots, use randomised large backoff with MAC retries if (fhss_structure->own_hop == 0xff) { - return ((uint32_t) randLIB_get_random_in_range(50, 150) * 1000); + return (uint32_t) randLIB_get_random_in_range(20000, 45000); } if (fhss_structure->ws->is_on_bc_channel == true) { return return_value; diff --git a/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6.c b/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6.c index 7b021aba39..722e41f46e 100644 --- a/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6.c +++ b/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6.c @@ -234,6 +234,10 @@ dhcpv6_client_server_data_t *libdhcpv6_nonTemporal_validate_class_pointer(void * return NULL; } +uint16_t libdhcpv6_vendor_option_size(uint16_t vendor_data_length) +{ + return vendor_data_length + 8; // ID Type 2, length 2 ,Enterpise number 4 +} uint16_t libdhcpv6_duid_option_size(uint16_t duidLength) { @@ -324,15 +328,6 @@ uint8_t *libdhcpv6_rapid_commit_option_write(uint8_t *ptr) return ptr; } -uint8_t *libdhcvp6_vendor_specific_option_write(uint8_t *ptr, uint8_t *data, uint16_t dataLength) -{ - ptr = common_write_16_bit(DHCPV6_OPTION_VENDOR_SPECIFIC_INFO, ptr); - ptr = common_write_16_bit(dataLength, ptr); - memcpy(ptr, data, dataLength); - ptr += dataLength; - return ptr; -} - uint8_t *libdhcvp6_request_option_write(uint8_t *ptr, uint8_t optionCnt, uint16_t *optionPtr) { uint16_t optionLength = libdhcvp6_request_option_size(optionCnt); @@ -840,31 +835,6 @@ uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv return ptr; } - -uint8_t *libdhcpv6_reply_message_write(uint8_t *ptr, dhcpv6_reply_packet_s *replyPacket, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcpv6_vendor_data_packet_s *vendorData) -{ - ptr = libdhcpv6_header_write(ptr, DHCPV6_REPLY_TYPE, replyPacket->transaction_ID); - ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_SERVER_ID_OPTION, &replyPacket->serverDUID); //16 - ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_CLIENT_ID_OPTION, &replyPacket->clientDUID); //16 - - if (nonTemporalAddress) { - ptr = libdhcpv6_identity_association_option_write(ptr, replyPacket->iaId, replyPacket->T0, replyPacket->T1, true); - ptr = libdhcpv6_ia_address_option_write(ptr, nonTemporalAddress->requestedAddress, nonTemporalAddress->preferredLifeTime, nonTemporalAddress->validLifeTime); - } else { - ptr = libdhcpv6_identity_association_option_write_with_status(ptr, replyPacket->iaId, replyPacket->T0, replyPacket->T1, DHCPV6_STATUS_NO_ADDR_AVAILABLE_CODE); - } - - if (vendorData) { - ptr = libdhcvp6_vendor_specific_option_write(ptr, vendorData->vendorData, vendorData->vendorDataLength); - } - - if (replyPacket->rapidCommit) { - ptr = libdhcpv6_rapid_commit_option_write(ptr); - } - - return ptr; -} - uint16_t libdhcpv6_solication_message_length(uint16_t clientDUIDLength, bool addressDefined, uint8_t requestOptionCount) { uint16_t length = 0; diff --git a/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6.h b/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6.h index c495a18fe4..dd2bd6309f 100644 --- a/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6.h +++ b/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6.h @@ -217,9 +217,13 @@ typedef struct dhcpv6_relay_msg { #define DHCPV6_OPTION_IA_PREFIX_DELEGATION_MIN_LENGTH 0x000c /** Identity Association END */ +#define DHCPV6_OPTION_VENDOR_CLASS 0x0010 #define DHCPV6_OPTION_VENDOR_SPECIFIC_INFO 0x0011 /** SEQUENCYID, RouterIDMask 32-bit*/ +#define DHCPV6_OPTION_DNS_SERVERS 0x0017 +#define DHCPV6_OPTION_DOMAIN_LIST 0x0018 + #define DHCPV6_STATUS_CODE_OPTION 0x000d #define DHCPV6_STATUS_CODE_OPTION_LEN 0x0002 #define DHCPV6_STATUS_NO_ADDR_AVAILABLE_CODE 0x0002 @@ -277,6 +281,7 @@ uint16_t libdhcpv6_duid_option_size(uint16_t duidLength); uint8_t libdhcpv6_duid_linktype_size(uint16_t linkType); uint16_t libdhcvp6_request_option_size(uint8_t optionCnt); uint16_t libdhcpv6_non_temporal_address_size(bool addressDefined); +uint16_t libdhcpv6_vendor_option_size(uint16_t vendor_data_length); uint16_t libdhcpv6_solication_message_length(uint16_t clientDUIDLength, bool addressDefined, uint8_t requestOptionCount); uint16_t libdhcpv6_address_request_message_len(uint16_t clientDUIDLength, uint16_t serverDUIDLength, uint8_t requstOptionCnt, bool add_address); @@ -287,7 +292,6 @@ uint16_t libdhcpv6_address_reply_message_len(uint16_t clientDUIDLength, uint16_t #endif uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv6_solication_base_packet_s *packet, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcp_duid_options_params_t *serverLink); -uint8_t *libdhcpv6_reply_message_write(uint8_t *ptr, dhcpv6_reply_packet_s *replyPacket, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcpv6_vendor_data_packet_s *vendorData); uint8_t *libdhcpv6_dhcp_relay_msg_write(uint8_t *ptr, uint8_t type, uint8_t hop_limit, uint8_t *peer_addres, uint8_t *link_address); uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t length); @@ -327,17 +331,6 @@ uint8_t *libdhcpv6_elapsed_time_option_write(uint8_t *ptr, uint16_t elapsedTime) */ uint8_t *libdhcpv6_rapid_commit_option_write(uint8_t *ptr); -/** - * This Function write dhcpv6 thread requested vendor spesific data - * - * \param ptr pointer where option will be writed - * \param data Vendor Data - * \param dataLength Vendor Data length - * - * return incremented pointer after write - */ -uint8_t *libdhcvp6_vendor_specific_option_write(uint8_t *ptr, uint8_t *data, uint16_t dataLength); - /** * This Function write dhcpv6 request option write * @@ -379,6 +372,6 @@ int libdhcpv6_solication_message_options_validate(uint8_t *ptr, uint16_t data_le int libdhcpv6_advertisment_message_option_validate(dhcp_duid_options_params_t *clientId, dhcp_duid_options_params_t *serverId, dhcp_ia_non_temporal_params_t *dhcp_ia_non_temporal_params, uint8_t *ptr, uint16_t data_length); bool libdhcpv6_rapid_commit_option_at_packet(uint8_t *ptr, uint16_t length); bool libdhcpv6_time_elapsed_option_at_packet(uint8_t *ptr, uint16_t length); -bool libdhcpv6_relay_msg_read(uint8_t *ptr, uint16_t length, dhcpv6_relay_msg_t *relay_msg); +bool libdhcpv6_relay_msg_read(uint8_t *ptr, uint16_t length, dhcpv6_relay_msg_t *relay_msg); #endif /* LIBDHCPV6_H_ */ diff --git a/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_server.c b/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_server.c index f3c0ccba8c..d324c81269 100644 --- a/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_server.c +++ b/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_server.c @@ -58,6 +58,8 @@ static dhcpv6_gua_server_entry_s *libdhcpv6_server_entry_allocate(void) entry->removeCb = NULL; entry->addCb = NULL; ns_list_init(&entry->allocatedAddressList); + ns_list_init(&entry->dnsServerList); + ns_list_init(&entry->vendorDataList); return entry; } @@ -338,6 +340,20 @@ void libdhcpv6_gua_server_free_by_prefix_and_interfaceid(uint8_t *prefix, int8_t ns_list_remove(&serverInfo->allocatedAddressList, cur); ns_dyn_mem_free(cur); } + + ns_list_foreach_safe(dhcpv6_dns_server_data_t, cur, &serverInfo->dnsServerList) { + //DNS Server Info Remove + ns_list_remove(&serverInfo->dnsServerList, cur); + ns_dyn_mem_free(cur->search_list); + ns_dyn_mem_free(cur); + } + + ns_list_foreach_safe(dhcpv6_vendor_data_t, cur, &serverInfo->vendorDataList) { + ns_list_remove(&serverInfo->vendorDataList, cur); + ns_dyn_mem_free(cur->vendor_data); + ns_dyn_mem_free(cur); + } + ns_list_remove(&dhcpv6_gua_server_list, serverInfo); ns_dyn_mem_free(serverInfo->serverDynamic_DUID); ns_dyn_mem_free(serverInfo); @@ -494,5 +510,119 @@ dhcpv6_allocated_address_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_ser return newEntry; } +dhcpv6_dns_server_data_t *libdhcpv6_dns_server_discover(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) +{ + ns_list_foreach(dhcpv6_dns_server_data_t, cur, &serverInfo->dnsServerList) { + if (memcmp(cur->server_address, address, 16) == 0) { + return cur; + } + } + return NULL; +} + +dhcpv6_dns_server_data_t *libdhcpv6_dns_server_allocate(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address) +{ + dhcpv6_dns_server_data_t *entry = libdhcpv6_dns_server_discover(serverInfo, address); + if (entry) { + return entry; + } + + entry = ns_dyn_mem_alloc(sizeof(dhcpv6_dns_server_data_t)); + if (!entry) { + return NULL; + } + ns_list_add_to_end(&serverInfo->dnsServerList, entry); + memcpy(entry->server_address, address, 16); + entry->search_list = NULL; + entry->search_list_length = 0; + return entry; +} + +dhcpv6_vendor_data_t *libdhcpv6_vendor_data_discover(dhcpv6_gua_server_entry_s *serverInfo, uint32_t enterprise_number) +{ + ns_list_foreach(dhcpv6_vendor_data_t, cur, &serverInfo->vendorDataList) { + if (cur->enterprise_number == enterprise_number) { + return cur; + } + } + return NULL; +} + +dhcpv6_vendor_data_t *libdhcpv6_vendor_data_allocate(dhcpv6_gua_server_entry_s *serverInfo, uint32_t enterprise_number) +{ + dhcpv6_vendor_data_t *entry = libdhcpv6_vendor_data_discover(serverInfo, enterprise_number); + + if (entry) { + return entry; + } + + entry = ns_dyn_mem_alloc(sizeof(dhcpv6_vendor_data_t)); + if (!entry) { + return NULL; + } + ns_list_add_to_end(&serverInfo->vendorDataList, entry); + entry->enterprise_number = enterprise_number; + entry->vendor_data = NULL; + entry->vendor_data_length = 0; + return entry; +} + + +uint16_t libdhcpv6_dns_server_message_sizes(dhcpv6_gua_server_entry_s *serverInfo) +{ + uint16_t message_size = 0; + ns_list_foreach(dhcpv6_dns_server_data_t, cur, &serverInfo->dnsServerList) { + message_size += 4 + 16; //Type Length + address // + //Search List part + message_size += 4 + cur->search_list_length; //Type Length + search_list_length + } + return message_size; +} + +uint16_t libdhcpv6_vendor_data_message_sizes(dhcpv6_gua_server_entry_s *serverInfo) +{ + uint16_t message_size = 0; + ns_list_foreach(dhcpv6_vendor_data_t, cur, &serverInfo->vendorDataList) { + message_size += 4 + 4 + cur->vendor_data_length; //Type + Length + enterprise + vendor_data_length + } + return message_size; +} + +uint8_t *libdhcpv6_dns_server_message_writes(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *ptr) +{ + ns_list_foreach(dhcpv6_dns_server_data_t, cur, &serverInfo->dnsServerList) { + //Write first DNS Server info + ptr = common_write_16_bit(DHCPV6_OPTION_DNS_SERVERS, ptr); + ptr = common_write_16_bit(16, ptr); //Length + memcpy(ptr, cur->server_address, 16); + ptr += 16; + + ptr = common_write_16_bit(DHCPV6_OPTION_DOMAIN_LIST, ptr); + ptr = common_write_16_bit(cur->search_list_length, ptr); //Length + if (cur->search_list_length) { + memcpy(ptr, cur->search_list, cur->search_list_length); + ptr += cur->search_list_length; + } + } + return ptr; +} + +uint8_t *libdhcpv6_vendor_data_message_writes(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *ptr) +{ + ns_list_foreach(dhcpv6_vendor_data_t, cur, &serverInfo->vendorDataList) { + + uint16_t length = cur->vendor_data_length + 4; + ptr = common_write_16_bit(DHCPV6_OPTION_VENDOR_SPECIFIC_INFO, ptr); + ptr = common_write_16_bit(length, ptr); //Length + ptr = common_write_32_bit(cur->enterprise_number, ptr); + if (cur->vendor_data_length) { + memcpy(ptr, cur->vendor_data, cur->vendor_data_length); + ptr += cur->vendor_data_length; + } + } + return ptr; +} + + #endif diff --git a/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_server.h b/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_server.h index 3b4c0643e2..3ea3e5f2ab 100644 --- a/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_server.h +++ b/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_server.h @@ -45,6 +45,20 @@ typedef struct dhcpv6_allocated_address_entry_s { ns_list_link_t link; /*!< List link entry */ } dhcpv6_allocated_address_entry_t; +typedef struct dhcpv6_dns_server_data_s { + uint8_t server_address[16]; + uint8_t *search_list; + uint8_t search_list_length; + ns_list_link_t link; /*!< List link entry */ +} dhcpv6_dns_server_data_t; + +typedef struct dhcpv6_vendor_data_s { + uint32_t enterprise_number; + uint8_t *vendor_data; + uint8_t vendor_data_length; + ns_list_link_t link; /*!< List link entry */ +} dhcpv6_vendor_data_t; + typedef struct dhcpv6_allocated_address_s { uint8_t nonTemporalAddress[16]; @@ -58,6 +72,8 @@ typedef struct dhcpv6_allocated_address_s { } dhcpv6_allocated_address_t; typedef NS_LIST_HEAD(dhcpv6_allocated_address_entry_t, link) dhcpv6_allocated_address_list_t; +typedef NS_LIST_HEAD(dhcpv6_dns_server_data_t, link) dhcpv6_dns_server_list_t; +typedef NS_LIST_HEAD(dhcpv6_vendor_data_t, link) dhcpv6_vendor_data_list_t; typedef struct dhcp_address_cache_update { uint8_t *allocatedAddress; @@ -84,6 +100,8 @@ typedef struct dhcpv6_gua_server_entry_s { dhcp_address_prefer_remove_cb *removeCb; dhcp_address_add_notify_cb *addCb; dhcpv6_allocated_address_list_t allocatedAddressList; + dhcpv6_dns_server_list_t dnsServerList; + dhcpv6_vendor_data_list_t vendorDataList; dhcpv6_allocated_address_t tempAddressEntry; ns_list_link_t link; /*!< List link entry */ } dhcpv6_gua_server_entry_s; @@ -99,6 +117,14 @@ dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_interfaceid(i dhcpv6_gua_server_entry_s *libdhcpv6_server_data_get_by_prefix_and_socketinstance(uint16_t socketInstance, uint8_t *prefixPtr); dhcpv6_allocated_address_t *libdhcpv6_address_allocated_list_scan(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *euid64, uint16_t linkType, uint32_t iaID, uint32_t T0, uint32_t T1, bool allocateNew); void libdhcpv6_allocated_address_write(uint8_t *ptr, dhcpv6_allocated_address_entry_t *address, dhcpv6_gua_server_entry_s *serverInfo); +dhcpv6_dns_server_data_t *libdhcpv6_dns_server_discover(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); +dhcpv6_dns_server_data_t *libdhcpv6_dns_server_allocate(dhcpv6_gua_server_entry_s *serverInfo, const uint8_t *address); +dhcpv6_vendor_data_t *libdhcpv6_vendor_data_discover(dhcpv6_gua_server_entry_s *serverInfo, uint32_t enterprise_number); +dhcpv6_vendor_data_t *libdhcpv6_vendor_data_allocate(dhcpv6_gua_server_entry_s *serverInfo, uint32_t enterprise_number); +uint16_t libdhcpv6_dns_server_message_sizes(dhcpv6_gua_server_entry_s *serverInfo); +uint16_t libdhcpv6_vendor_data_message_sizes(dhcpv6_gua_server_entry_s *serverInfo); +uint8_t *libdhcpv6_dns_server_message_writes(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *ptr); +uint8_t *libdhcpv6_vendor_data_message_writes(dhcpv6_gua_server_entry_s *serverInfo, uint8_t *ptr); #else #define libdhcpv6_gua_server_list_empty() true #define libdhcpv6_server_data_get_by_prefix_and_interfaceid(interfaceId, prefixPtr) NULL diff --git a/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_vendordata.c b/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_vendordata.c new file mode 100644 index 0000000000..2854517d5e --- /dev/null +++ b/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_vendordata.c @@ -0,0 +1,100 @@ +/* + * 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 +#include "common_functions.h" +#include "libDHCPv6.h" +#include "libDHCPv6_vendordata.h" + +#define TRACE_GROUP "vend" + + +/* 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; +} + +uint16_t net_dns_option_vendor_option_data_get_next(uint8_t *ptr, uint16_t length, uint16_t *type) +{ + uint16_t option_len; + + if (length < 4) { + // Corrupted + return 0; + } + if (type) { + *type = common_read_16_bit(ptr); + } + + option_len = common_read_16_bit(ptr + 2); + if (option_len + 4 > length) { + // Corrupted + return 0; + } + + return option_len + 4; +} + +uint16_t net_dns_option_vendor_option_data_dns_query_read(uint8_t *ptr, uint16_t length, uint8_t **address, char **domain) +{ + uint16_t option_len; + option_len = common_read_16_bit(ptr + 2); + + if (length < 4 + 16 + 1) { + // Corrupted as there is no room for all fields + return 0; + } + if (option_len < 17) { + // Corrupted as not enough room in field + return 0; + } + if (*(ptr + 4 + option_len - 1) != 0) { + // Not nul terminated string for domain + return 0; + } + + if (common_read_16_bit(ptr) != ARM_DHCP_VENDOR_DATA_DNS_QUERY_RESULT) { + return 0; + } + + if (address) { + *address = ptr + 4; + } + if (domain) { + *domain = (char *)(ptr + 4 + 16); + } + return option_len; +} diff --git a/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_vendordata.h b/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_vendordata.h new file mode 100644 index 0000000000..1a1ef44f7f --- /dev/null +++ b/features/nanostack/sal-stack-nanostack/source/libDHCPv6/libDHCPv6_vendordata.h @@ -0,0 +1,44 @@ +/* + * 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); + +uint16_t net_dns_option_vendor_option_data_get_next(uint8_t *ptr, uint16_t length, uint16_t *type); +uint16_t net_dns_option_vendor_option_data_dns_query_read(uint8_t *ptr, uint16_t length, uint8_t **address, char **domain); + + +#endif /* LIBDHCPV6_VENDOR_DATA_H_ */ diff --git a/features/nanostack/sal-stack-nanostack/source/libNET/src/net_dns.c b/features/nanostack/sal-stack-nanostack/source/libNET/src/net_dns.c index ef71f382fe..b7c7c3eec5 100644 --- a/features/nanostack/sal-stack-nanostack/source/libNET/src/net_dns.c +++ b/features/nanostack/sal-stack-nanostack/source/libNET/src/net_dns.c @@ -115,7 +115,7 @@ int8_t net_dns_server_address_set(int8_t interface_id, const uint8_t address[16] } info_ptr->lifetime = lifetime; memcpy(info_ptr->dns_server_address, dns_server_address, 16); - tr_info("DNS Server: %s Lifetime: %lu", trace_ipv6(info_ptr->dns_server_address), (unsigned long) info_ptr->lifetime); + tr_info("DNS Server: %s from: %s Lifetime: %lu", trace_ipv6(info_ptr->dns_server_address), trace_ipv6(info_ptr->address), (unsigned long) info_ptr->lifetime); return 0; } @@ -234,7 +234,7 @@ static dns_query_t *dns_query_result_create(int8_t interface_id, const char *dom } this->interface_id = interface_id; strcpy(this->domain_str, domain_str); - tr_debug("Create DNS query entry for %s", this->domain_str); + //tr_debug("Create DNS query entry for %s", this->domain_str); ns_list_add_to_start(&dns_query_list, this); return this; } diff --git a/features/nanostack/sal-stack-nanostack/sources.mk b/features/nanostack/sal-stack-nanostack/sources.mk index 8db71ba294..2d895e803a 100644 --- a/features/nanostack/sal-stack-nanostack/sources.mk +++ b/features/nanostack/sal-stack-nanostack/sources.mk @@ -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 \