From 9a4e8a5964c54f2a983ffd4c13755176d4f9df52 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 7 Sep 2020 14:38:36 +0300 Subject: [PATCH] Squashed 'connectivity/nanostack/sal-stack-nanostack/' changes from 48609aeded..d879e6db87 d879e6db87 Merge branch 'release_internal' into release_external eef9246079 Fixed network border router timeout recovery and EAPOL relay address fix bac7ca6852 Changed RADIUS MTU and small fixes a9f8b756e1 Addeed support for DHCP vendor data d8f00036f5 DHCPv6 functionality update 7fe04231ed Added DHCPv6 vendor data generation for DNS queries 639f9dbfb2 FHSS: Changed retry backoffs when no BC schedule or TX slots (#2440) 91acececbd Remove test files 6568bc1790 Merge branch 'release_internal' into release_external 4192cc8974 Added configuration for RADIUS retry timer (#2438) 684b714415 Added support for retries and multiple sockets to RADIUS client (#2426) 89e0ae0904 WS: Restart auto CCA threshold after discovery (#2435) dbb09b171d MAC/WS: Min possible Tack to 1ms and CCA interval to 2ms (#2434) 43b2ae27a2 Cca threshold test (#2436) 28108e1f38 Added device min sensitivity setting and stack information 7060c70cde Cca threshold test (#2432) 640be71e31 WS: temporarily set default CCA threshold to -80 (#2431) 0a472aefb2 WS: Calculate UFSI drift and trace (#2430) 61d3db8882 Create APIs for DNS cache results 587add577c MAC: Validate TX time (#2429) a1bfed4846 Added typecast when computing max_timout from drift (#2428) 089fb3b8fe Neighbour temporary entry update and Enhanced ACK tx update 70244f60e5 Wi-sun parameter and debug trace update 5752eae833 Created validate TX time handler (#2423) 022d61fb65 Wi-sun Neighbour table update and DHCP new callback 857b41fc0a Merge pull request #2421 from ARMmbed/update_from_mbed_os 1a9dd13f6d (via Mbed-OS)WS Management API missing include 4318f37d4c Calculate drift in critical state (#2419) 01a1909c94 FHSS WS: Do not use drift compensation with unpredictable linux timer (#2418) git-subtree-dir: connectivity/nanostack/sal-stack-nanostack git-subtree-split: d879e6db8791115ce435d8804238ba38d43e78f8 --- nanostack/dhcp_service_api.h | 20 ++ nanostack/mlme.h | 1 - nanostack/net_interface.h | 68 ++++ nanostack/ws_bbr_api.h | 85 ++++- nanostack/ws_management_api.h | 27 ++ source/6LoWPAN/MAC/mac_helper.c | 15 - source/6LoWPAN/MAC/mac_helper.h | 2 - source/6LoWPAN/ws/ws_bbr_api.c | 175 ++++++++++ source/6LoWPAN/ws/ws_bootstrap.c | 169 ++++++++- source/6LoWPAN/ws/ws_bootstrap.h | 8 +- source/6LoWPAN/ws/ws_common.c | 14 +- source/6LoWPAN/ws/ws_common.h | 3 + source/6LoWPAN/ws/ws_common_defines.h | 5 +- source/6LoWPAN/ws/ws_config.h | 21 +- source/6LoWPAN/ws/ws_eapol_relay.c | 7 +- source/6LoWPAN/ws/ws_empty_functions.c | 9 + source/6LoWPAN/ws/ws_llc_data_service.c | 28 +- source/6LoWPAN/ws/ws_management_api.c | 14 + source/6LoWPAN/ws/ws_neighbor_class.c | 47 ++- source/6LoWPAN/ws/ws_neighbor_class.h | 4 +- source/6LoWPAN/ws/ws_pae_auth.c | 36 +- source/6LoWPAN/ws/ws_pae_controller.c | 219 ++++++++---- source/6LoWPAN/ws/ws_pae_controller.h | 37 ++ source/6LoWPAN/ws/ws_pae_lib.c | 60 ++++ source/6LoWPAN/ws/ws_pae_lib.h | 65 ++++ source/Common_Protocols/icmpv6.c | 36 +- source/DHCPv6_Server/DHCPv6_Server_service.c | 86 ++++- source/DHCPv6_Server/DHCPv6_server_service.h | 5 + source/DHCPv6_client/dhcpv6_client_api.h | 40 +++ source/DHCPv6_client/dhcpv6_client_service.c | 77 ++++ source/MAC/IEEE802_15_4/mac_defines.h | 1 - source/MAC/IEEE802_15_4/mac_mcps_sap.c | 16 +- source/MAC/IEEE802_15_4/mac_mlme.c | 42 +-- source/MAC/IEEE802_15_4/mac_pd_sap.c | 64 ++-- source/NWK_INTERFACE/protocol_core.c | 3 + source/Security/kmp/kmp_api.c | 90 ++++- source/Security/kmp/kmp_api.h | 76 +++- source/Security/kmp/kmp_eapol_pdu_if.c | 14 +- source/Security/kmp/kmp_socket_if.c | 91 +++-- .../eap_tls_sec_prot/eap_tls_sec_prot_lib.c | 10 +- .../eap_tls_sec_prot/eap_tls_sec_prot_lib.h | 1 - .../radius_eap_tls_sec_prot.c | 156 ++++++--- .../protocols/radius_sec_prot/avp_helper.h | 4 +- .../radius_sec_prot/radius_client_sec_prot.c | 254 ++++++++++++-- source/Security/protocols/sec_prot.h | 97 +++++ source/Security/protocols/sec_prot_cfg.h | 5 +- source/Service_Libs/fhss/fhss_ws.c | 13 +- source/libDHCPv6/dhcp_service_api.c | 67 ++++ source/libDHCPv6/libDHCPv6.c | 38 +- source/libDHCPv6/libDHCPv6.h | 19 +- source/libDHCPv6/libDHCPv6_server.c | 130 +++++++ source/libDHCPv6/libDHCPv6_server.h | 26 ++ source/libDHCPv6/libDHCPv6_vendordata.c | 100 ++++++ source/libDHCPv6/libDHCPv6_vendordata.h | 44 +++ source/libNET/src/net_dns.c | 330 ++++++++++++++++++ source/libNET/src/net_dns_internal.h | 47 +++ source/libNET/src/ns_net.c | 20 +- sources.mk | 2 + 58 files changed, 2721 insertions(+), 422 deletions(-) create mode 100644 source/libDHCPv6/libDHCPv6_vendordata.c create mode 100644 source/libDHCPv6/libDHCPv6_vendordata.h create mode 100644 source/libNET/src/net_dns.c create mode 100644 source/libNET/src/net_dns_internal.h diff --git a/nanostack/dhcp_service_api.h b/nanostack/dhcp_service_api.h index e4759a59515..1a3be195aa1 100644 --- a/nanostack/dhcp_service_api.h +++ b/nanostack/dhcp_service_api.h @@ -109,6 +109,15 @@ typedef int (dhcp_service_receive_req_cb)(uint16_t instance_id, uint32_t msg_tr_ typedef int (dhcp_service_receive_resp_cb)(uint16_t instance_id, void *ptr, uint8_t msg_name, uint8_t *msg_ptr, uint16_t msg_len); +/** + * \brief Neighbour table update callback this is called for DHCP relay and server link local responses. + * + * \param interface interface where address is got + * \param ll_addr Link local which neighbour must be guarantee. + * + */ +typedef void (dhcp_relay_neighbour_cb)(int8_t interface, uint8_t ll_addr[static 16]); + /** * \brief Initialize a new DHCP service instance. @@ -235,5 +244,16 @@ void dhcp_service_req_remove_all(void *msg_class_ptr); */ bool dhcp_service_timer_tick(uint16_t ticks); +/** + * \brief Register callback which is called when Relay or server RX direct message. + * + * \param interface_id Interface id for registed callback. + * \param notify_cb callback pointer + * + * \return 0, if everything went fine. + * \return -1, if error occurred. + */ +int dhcp_service_link_local_rx_cb_set(int8_t interface_id, dhcp_relay_neighbour_cb *notify_cb); + #endif //DHCP_SERVICE_API_H_ diff --git a/nanostack/mlme.h b/nanostack/mlme.h index ee6a244172f..859457d1611 100644 --- a/nanostack/mlme.h +++ b/nanostack/mlme.h @@ -267,7 +267,6 @@ typedef enum { macEdfeForceStop = 0xf2, /*< Use this command for Data wait timeout at LLC: Mac stop Edfe session data wait and enable normal FHSS mode */ macSetDataWhitening = 0xf3, /*< Enable or disable data whitening, boolean true for enable, false for disable */ macCCAThresholdStart = 0xf4, /*< Start automatic CCA threshold */ - macDevicePendingAckTrig = 0xf5, /*< Trig Pending ACK for Accepted Data packet for temporary neighbour */ mac802_15_4Mode = 0xf6, /*= 0 success + * + */ +int ws_bbr_radius_timing_set(int8_t interface_id, bbr_radius_timing_t *timing); + +/** + * Get RADIUS timing information + * + * Function sets RADIUS timing information from Border Router. + * + * \param interface_id Network interface ID. + * \param timing Timing information + * + * \return < 0 failure + * \return >= 0 success + * + */ +int ws_bbr_radius_timing_get(int8_t interface_id, bbr_radius_timing_t *timing); + +/** + * Validate RADIUS timing information + * + * Function validates RADIUS timing information. + * + * \param interface_id Network interface ID. + * \param timing Timing information + * + * \return < 0 failure + * \return >= 0 success + * + */ +int ws_bbr_radius_timing_validate(int8_t interface_id, bbr_radius_timing_t *timing); + +/** + * \brief A function to set DNS query results to border router + * + * Border router distributes these query results in DHCP Solicit responses to + * all the devices joining to the Wi-SUN mesh network. + * + * Border router keeps these forever, but if application does not update these in regular interval + * The address might stop working. So periodic keep alive is required. + * + * These cached query results will become available in the Wi-SUN interface. + * + * This function can be called multiple times. + * if domain name matches a existing entry address is updated. + * 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. + * \param domain_name_ptr Domain name matching the address + * + * \return < 0 failure + * \return >= 0 success + */ +int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16], char *domain_name_ptr); + #endif /* WS_BBR_API_H_ */ diff --git a/nanostack/ws_management_api.h b/nanostack/ws_management_api.h index 8d155595cdb..a5feb762874 100644 --- a/nanostack/ws_management_api.h +++ b/nanostack/ws_management_api.h @@ -30,6 +30,7 @@ #include "ns_types.h" #include "net_interface.h" /* Declaration for channel_list_s. */ +#include "fhss_config.h" #ifdef __cplusplus extern "C" { @@ -112,6 +113,8 @@ typedef struct ws_stack_info { uint8_t rsl_out; /** parent RSSI in measured RSSI value calculated using EWMA specified by Wi-SUN from range of -174 (0) to +80 (254) dBm.*/ uint8_t rsl_in; + /** Device RF minimum sensitivity configuration. lowest level of radio signal strength packet heard. Range of -174 (0) to +80 (254) dBm*/ + uint8_t device_min_sens; /** ETX To border router */ uint16_t routing_cost; /** Network PAN ID */ @@ -614,6 +617,30 @@ int ws_stack_info_get( int8_t interface_id, ws_stack_info_t *info_ptr); +/** + * Set minimum RF sensitivity acceptable for the parent selection + * + * Set radio signal minimum sensitivity level acceptable for parent selection. + * Range of -174 (0) to +80 (254) dBm. + * + * If device_min_sens is set to 0 then automatic adjustment is done by the stack. + * + * Setting a value that is not suitable for Radio might prevent the device joining to the network. + * + * NOTE: Currently lower EAPOL parents are accepted if there is no parents higher than + * DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERESIS + * NOTE: Currently not using this value to limit parents as it is only RECOMENDED in specification. + * + * \param interface_id Network interface ID. + * \param device_min_sens value used in the parent selections. + * + * \return 0 Success. + * \return <0 Failure. + */ +int ws_device_min_sens_set( + int8_t interface_id, + uint8_t device_min_sens); + #ifdef __cplusplus } #endif diff --git a/source/6LoWPAN/MAC/mac_helper.c b/source/6LoWPAN/MAC/mac_helper.c index ab5961f5f2a..86fc64ebde5 100644 --- a/source/6LoWPAN/MAC/mac_helper.c +++ b/source/6LoWPAN/MAC/mac_helper.c @@ -947,21 +947,6 @@ void mac_helper_devicetable_direct_set(struct mac_api_s *mac_api, const mlme_dev mac_api->mlme_req(mac_api, MLME_SET, &set_req); } -void mac_helper_devicetable_ack_trig(const mlme_device_descriptor_t *device_desc, protocol_interface_info_entry_t *cur) -{ - if (!cur->mac_api) { - return; - } - - mlme_set_t set_req; - set_req.attr = macDevicePendingAckTrig; - set_req.attr_index = 0; - set_req.value_pointer = (void *)device_desc; - set_req.value_size = sizeof(mlme_device_descriptor_t); - cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_req); -} - - int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_set) { protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); diff --git a/source/6LoWPAN/MAC/mac_helper.h b/source/6LoWPAN/MAC/mac_helper.h index 8c9c651cd1f..fd1eb19d868 100644 --- a/source/6LoWPAN/MAC/mac_helper.h +++ b/source/6LoWPAN/MAC/mac_helper.h @@ -128,8 +128,6 @@ void mac_helper_devicetable_set(const mlme_device_descriptor_t *device_dec, stru void mac_helper_devicetable_direct_set(struct mac_api_s *mac_api, const mlme_device_descriptor_t *device_desc, uint8_t attribute_index); -void mac_helper_devicetable_ack_trig(const mlme_device_descriptor_t *device_desc, struct protocol_interface_info_entry *cur); - int8_t mac_helper_mac_mlme_max_retry_set(int8_t interface_id, uint8_t mac_retry_set); int8_t mac_helper_mac_device_description_pan_id_update(int8_t interface_id, uint16_t pan_id); diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index 878c431f512..eedd4ea6236 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/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,9 @@ #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" + #include "ws_bbr_api.h" @@ -73,6 +77,9 @@ static uint8_t current_global_prefix[16] = {0}; // DHCP requires 16 bytes prefix static uint32_t bbr_delay_timer = BBR_CHECK_INTERVAL; // initial delay. static uint32_t global_prefix_unavailable_timer = 0; // initial delay. +static uint8_t *dhcp_vendor_data_ptr = NULL; +static uint8_t dhcp_vendor_data_len = 0; + static rpl_dodag_conf_t rpl_conf = { // Lifetime values .default_lifetime = 120, @@ -88,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 @@ -364,6 +382,48 @@ static bool wisun_dhcp_address_add_cb(int8_t interfaceId, dhcp_address_cache_upd return true; } +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]; + uint8_t *dns_search_list_ptr = NULL; + uint8_t dns_search_list_len = 0; + (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, 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 + 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) { uint8_t ll[16]; @@ -384,6 +444,8 @@ 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, global_id); + ws_dhcp_client_address_request(cur, global_id, ll); } static void ws_bbr_dhcp_server_stop(protocol_interface_info_entry_t *cur, uint8_t *global_id) @@ -570,6 +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, current_global_prefix); } } void ws_bbr_pan_version_increase(protocol_interface_info_entry_t *cur) @@ -1137,3 +1200,115 @@ int ws_bbr_radius_shared_secret_get(int8_t interface_id, uint16_t *shared_secret return -1; #endif } + +int ws_bbr_radius_timing_set(int8_t interface_id, bbr_radius_timing_t *timing) +{ +#ifdef HAVE_WS_BORDER_ROUTER + return ws_pae_controller_radius_timing_set(interface_id, timing); +#else + (void) interface_id; + (void) timing; + return -1; +#endif +} + +int ws_bbr_radius_timing_get(int8_t interface_id, bbr_radius_timing_t *timing) +{ +#ifdef HAVE_WS_BORDER_ROUTER + return ws_pae_controller_radius_timing_get(interface_id, timing); +#else + (void) interface_id; + (void) timing; + return -1; +#endif +} + +int ws_bbr_radius_timing_validate(int8_t interface_id, bbr_radius_timing_t *timing) +{ +#ifdef HAVE_WS_BORDER_ROUTER + return ws_pae_controller_radius_timing_validate(interface_id, timing); +#else + (void) interface_id; + (void) timing; + return -1; +#endif +} + +int ws_bbr_dns_query_result_set(int8_t interface_id, const uint8_t address[16], char *domain_name_ptr) +{ +#ifdef HAVE_WS_BORDER_ROUTER + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + if (!cur) { + return -1; + } + + /* This information is only stored to the DHCPv6 server where it is distributed to the network + * + * Border router stores a list of these entries and includes a function to parse and generate the vendor data output + * + * This is included in the vendor extension where the format is decided by the vendor + */ + + // 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; + (void) address; + (void) domain_name_ptr; + return -1; +#endif +} diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 6bd10d5aa61..808acb7bf2c 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -63,7 +63,9 @@ #include "Service_Libs/nd_proxy/nd_proxy.h" #include "Service_Libs/blacklist/blacklist.h" #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" @@ -72,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" @@ -136,14 +139,37 @@ mac_neighbor_table_entry_t *ws_bootstrap_mac_neighbor_add(struct protocol_interf } // TODO only call these for new neighbour mlme_device_descriptor_t device_desc; - neighbor->lifetime = WS_NEIGHBOR_LINK_TIMEOUT; - neighbor->link_lifetime = WS_NEIGHBOR_LINK_TIMEOUT; - tr_debug("Added new neighbor %s : index:%u", trace_array(src64, 8), neighbor->index); + neighbor->lifetime = WS_NEIGHBOUR_TEMPORARY_ENTRY_LIFETIME; + neighbor->link_lifetime = WS_NEIGHBOUR_TEMPORARY_ENTRY_LIFETIME; mac_helper_device_description_write(interface, &device_desc, neighbor->mac64, neighbor->mac16, 0, false); mac_helper_devicetable_set(&device_desc, interface, neighbor->index, interface->mac_parameters->mac_default_key_index, true); + return neighbor; } +void ws_bootstrap_neighbor_set_stable(struct protocol_interface_info_entry *interface, const uint8_t *src64) +{ + mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(interface), src64, MAC_ADDR_MODE_64_BIT); + + if (neighbor && neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { + neighbor->lifetime = WS_NEIGHBOR_LINK_TIMEOUT; + neighbor->link_lifetime = WS_NEIGHBOR_LINK_TIMEOUT; + tr_info("Added new neighbor %s : index:%u", trace_array(src64, 8), neighbor->index); + } +} + +void ws_bootstrap_mac_neighbor_short_time_set(struct protocol_interface_info_entry *interface, const uint8_t *src64, uint32_t valid_time) +{ + mac_neighbor_table_entry_t *neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(interface), src64, MAC_ADDR_MODE_64_BIT); + + if (neighbor && neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { + //mlme_device_descriptor_t device_desc; + neighbor->lifetime = valid_time; + neighbor->link_lifetime = valid_time; + tr_debug("Set short response neighbor %s : index:%u", trace_array(src64, 8), neighbor->index); + } +} + static void ws_bootstrap_neighbor_delete(struct protocol_interface_info_entry *interface, mac_neighbor_table_entry_t *entry_ptr) { mac_helper_devicetable_remove(interface->mac_api, entry_ptr->index, entry_ptr->mac64); @@ -161,6 +187,7 @@ static void ws_bootstap_eapol_neigh_entry_allocate(struct protocol_interface_inf if (!mac_entry) { return; } + ws_bootstrap_neighbor_set_stable(interface, mac_64); mac_entry->lifetime = 0xffffffff; mac_entry->link_lifetime = 0xffffffff; ws_neighbor_class_entry_t *ws_neigh = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, mac_entry->index); @@ -170,14 +197,6 @@ static void ws_bootstap_eapol_neigh_entry_allocate(struct protocol_interface_inf interface->ws_info->eapol_tx_index = mac_entry->index; } -void ws_bootstrap_eapol_rx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64) -{ - mlme_device_descriptor_t device_desc; - - mac_helper_device_description_write(interface, &device_desc, src64, 0xffff, 0, false); - mac_helper_devicetable_ack_trig(&device_desc, interface); -} - ws_neighbor_class_entry_t *ws_bootstrap_eapol_tx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64) { mlme_device_descriptor_t device_desc; @@ -838,6 +857,97 @@ bool ws_bootstrap_nd_ns_transmit(protocol_interface_info_entry_t *cur, ipv6_neig return true; } +static void ws_bootstrap_dhcp_neighbour_update_cb(int8_t interface_id, uint8_t ll_addr[static 16]) +{ + if (memcmp(ll_addr, ADDR_LINK_LOCAL_PREFIX, 8)) { + return; + } + + protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); + if (!cur) { + return; + } + + uint8_t mac64[8]; + memcpy(mac64, ll_addr + 8, 8); + mac64[0] ^= 2; + 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; @@ -886,8 +996,10 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur) cur->if_ns_transmit = ws_bootstrap_nd_ns_transmit; dhcp_client_init(cur->id, DHCPV6_DUID_HARDWARE_IEEE_802_NETWORKS_TYPE); + 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); @@ -1434,12 +1546,13 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry if (!neighbour_pointer_valid) { return; } + ws_bootstrap_neighbor_set_stable(cur, data->SrcAddr); } if (neighbour_pointer_valid) { etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64); //Update Neighbor Broadcast and Unicast Parameters - ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp); + ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp, (uint8_t *) data->SrcAddr); ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule); ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor_info.ws_neighbor, &ws_bt_ie, data->timestamp); ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie); @@ -1484,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); @@ -1523,7 +1640,7 @@ static void ws_bootstrap_pan_config_solicit_analyse(struct protocol_interface_in llc_neighbour_req_t neighbor_info; if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) { etx_lqi_dbm_update(cur->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64); - ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp); + ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp, (uint8_t *) data->SrcAddr); ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us, &cur->ws_info->hopping_schdule); } @@ -1603,6 +1720,10 @@ bool ws_bootstrap_validate_channel_function(ws_us_ie_t *ws_us, ws_bs_ie_t *ws_bs static void ws_bootstrap_asynch_ind(struct protocol_interface_info_entry *cur, const struct mcps_data_ind_s *data, const struct mcps_data_ie_list *ie_ext, uint8_t message_type) { + // Store weakest heard packet RSSI + if (cur->ws_info->weakest_received_rssi > data->signal_dbm) { + cur->ws_info->weakest_received_rssi = data->signal_dbm; + } if (data->SrcAddrMode != MAC_ADDR_MODE_64_BIT) { // Not from long address @@ -1691,7 +1812,7 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent { uint8_t ll_target[16]; - if (mac_neighbor_info(interface)->neighbour_list_size <= mac_neighbor_info(interface)->list_total_size - WS_NON_CHILD_NEIGHBOUR_COUNT) { + if (mac_neighbor_info(interface)->neighbour_list_size <= mac_neighbor_info(interface)->list_total_size - ws_common_temporary_entry_size(mac_neighbor_info(interface)->list_total_size)) { // Enough neighbor entries return; } @@ -1707,6 +1828,10 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent continue; } + if (cur->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { + continue; + } + if (cur->link_role == PRIORITY_PARENT_NEIGHBOUR) { //This is our primary parent we cannot delete continue; @@ -1834,7 +1959,7 @@ static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&cur->ws_info->neighbor_storage, entry_ptr->index); etx_storage_t *etx_entry = etx_storage_entry_get(cur->id, entry_ptr->index); - if (!entry_ptr->trusted_device || !ws_neighbor || !etx_entry || ws_neighbor->negative_aro_send) { + if (!entry_ptr->trusted_device || !ws_neighbor || !etx_entry || ws_neighbor->negative_aro_send || entry_ptr->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { return false; } @@ -2515,6 +2640,7 @@ static bool ws_rpl_new_parent_callback(uint8_t *ll_parent_address, void *handle, bool create_ok = ws_bootstrap_neighbor_info_request(cur, entry->mac64, &neigh_buffer, true); if (create_ok) { ws_neighbor_class_entry_t *ws_neigh = neigh_buffer.ws_neighbor; + ws_bootstrap_neighbor_set_stable(cur, entry->mac64); //Copy fhss temporary data *ws_neigh = entry->neigh_info_list; //ETX Create here @@ -2613,6 +2739,7 @@ static void ws_bootstrap_start_discovery(protocol_interface_info_entry_t *cur) cur->nwk_nd_re_scan_count = 0; cur->ws_info->configuration_learned = false; cur->ws_info->pan_timeout_timer = 0; + cur->ws_info->weakest_received_rssi = 0; // Clear learned neighbours ws_bootstrap_neighbor_list_clean(cur); @@ -3226,8 +3353,8 @@ static int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, pa ns_list_add_to_end(&cur->ws_info->parent_list_free, parent_ptr); return -1; } - - ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &parent_ptr->ws_utt, parent_ptr->timestamp); + ws_bootstrap_neighbor_set_stable(cur, parent_ptr->addr); + ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &parent_ptr->ws_utt, parent_ptr->timestamp, parent_ptr->addr); ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &parent_ptr->ws_us, &cur->ws_info->hopping_schdule); return 0; } @@ -3374,6 +3501,11 @@ void ws_bootstrap_state_machine(protocol_interface_info_entry_t *cur) cur->ws_info->trickle_pcs_running = false; cur->ws_info->trickle_pc_consistency_block_period = 0; ws_fhss_configure(cur, false); + int8_t new_default = cur->ws_info->weakest_received_rssi - 1; + if ((new_default < CCA_DEFAULT_DBM) && (new_default >= CCA_LOW_LIMIT) && (new_default <= CCA_HIGH_LIMIT)) { + // Restart automatic CCA threshold using weakest received RSSI as new default + mac_helper_start_auto_cca_threshold(cur->id, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->weakest_received_rssi - 1, CCA_HIGH_LIMIT, CCA_LOW_LIMIT); + } ws_bootstrap_start_authentication(cur); break; case ER_RPL_SCAN: @@ -3535,6 +3667,7 @@ int ws_bootstrap_get_info(protocol_interface_info_entry_t *cur, struct ws_stack_ info_ptr->rsl_out = ws_neighbour->rsl_out; info_ptr->routing_cost = ws_neighbour->routing_cost; } + info_ptr->device_min_sens = DEVICE_MIN_SENS; if (ws_bootstrap_state_discovery(cur)) { info_ptr->join_state = 1; } else if (ws_bootstrap_state_authenticate(cur)) { diff --git a/source/6LoWPAN/ws/ws_bootstrap.h b/source/6LoWPAN/ws/ws_bootstrap.h index d936c23ce6a..7be0655ca3c 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.h +++ b/source/6LoWPAN/ws/ws_bootstrap.h @@ -86,14 +86,16 @@ bool ws_bootstrap_validate_channel_plan(struct ws_us_ie *ws_us, struct protocol_ bool ws_bootstrap_validate_channel_function(struct ws_us_ie *ws_us, struct ws_bs_ie *ws_bs); -void ws_bootstrap_eapol_rx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64); - struct ws_neighbor_class_entry *ws_bootstrap_eapol_tx_temporary_set(struct protocol_interface_info_entry *interface, const uint8_t *src64); void ws_bootstrap_eapol_tx_temporary_clear(struct protocol_interface_info_entry *interface); +void ws_bootstrap_neighbor_set_stable(struct protocol_interface_info_entry *interface, const uint8_t *src64); + int ws_bootstrap_get_info(protocol_interface_info_entry_t *cur, struct ws_stack_info *info_ptr); +void ws_bootstrap_mac_neighbor_short_time_set(struct protocol_interface_info_entry *interface, const uint8_t *src64, uint32_t valid_time); + #else #define ws_bootstrap_init(interface_id, bootstrap_mode) (-1) @@ -101,10 +103,12 @@ int ws_bootstrap_get_info(protocol_interface_info_entry_t *cur, struct ws_stack_ #define ws_bootstrap_restart(cur) #define ws_bootstrap_neighbor_remove(cur, ll_address) #define ws_bootstrap_aro_failure(cur, ll_address) +#define ws_bootstrap_neighbor_set_stable(interface, src64) #define ws_bootstrap_primary_parent_update(interface, neighbor) #define ws_bootstrap_secondary_parent_update(interface) #define ws_bootstrap_get_info(cur, info_ptr) + #endif //HAVE_WS #endif /* WS_BOOTSTRAP_H_ */ diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index 841ce15dab8..b1d734a77a2 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -379,12 +379,21 @@ void ws_common_neighbor_remove(protocol_interface_info_entry_t *cur, const uint8 ws_bootstrap_neighbor_remove(cur, ll_address); } - +uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size) +{ + if (mac_table_size >= 128) { + return (WS_RPL_CANDIDATE_PARENT_COUNT + WS_LARGE_TEMPORARY_NEIGHBOUR_ENTRIES); + } else if (mac_table_size >= 64) { + return (WS_RPL_CANDIDATE_PARENT_COUNT + WS_MEDIUM_TEMPORARY_NEIGHBOUR_ENTRIES); + } else { + return (WS_RPL_CANDIDATE_PARENT_COUNT + WS_SMALL_TEMPORARY_NEIGHBOUR_ENTRIES); + } +} uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *interface, const uint8_t *eui64) { uint8_t child_count = 0; - uint8_t max_child_count = mac_neighbor_info(interface)->list_total_size - WS_NON_CHILD_NEIGHBOUR_COUNT; + uint8_t max_child_count = mac_neighbor_info(interface)->list_total_size - ws_common_temporary_entry_size(mac_neighbor_info(interface)->list_total_size); // Test API to limit child count if (test_max_child_count_override != 0xffff) { @@ -422,6 +431,7 @@ uint8_t ws_common_allow_child_registration(protocol_interface_info_entry_t *inte tr_warn("Child registration not allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size); return ARO_FULL; } + ws_bootstrap_neighbor_set_stable(interface, eui64); tr_info("Child registration allowed %d/%d, max:%d", child_count, max_child_count, mac_neighbor_info(interface)->list_total_size); return ARO_SUCCESS; } diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 4dadf81b365..96a425c1308 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -83,6 +83,8 @@ typedef struct ws_info_s { uint8_t rpl_state; // state from rpl_event_t uint8_t pas_requests; // Amount of PAN solicits sent uint8_t eapol_tx_index; + uint8_t device_min_sens; // Device min sensitivity set by the application + int8_t weakest_received_rssi; // Weakest received signal (dBm) parent_info_t parent_info[WS_PARENT_LIST_SIZE]; parent_info_list_t parent_list_free; parent_info_list_t parent_list_reserved; @@ -155,6 +157,7 @@ void ws_common_primary_parent_update(protocol_interface_info_entry_t *interface, void ws_common_secondary_parent_update(protocol_interface_info_entry_t *interface); +uint8_t ws_common_temporary_entry_size(uint8_t mac_table_size); #define ws_info(cur) ((cur)->ws_info) #else #define ws_info(cur) ((ws_info_t *) NULL) diff --git a/source/6LoWPAN/ws/ws_common_defines.h b/source/6LoWPAN/ws/ws_common_defines.h index f6f5e5cca84..58f570f8715 100644 --- a/source/6LoWPAN/ws/ws_common_defines.h +++ b/source/6LoWPAN/ws/ws_common_defines.h @@ -240,6 +240,9 @@ typedef struct ws_bs_ie { #define WS_FAN_VERSION_1_0 1 #define WS_NEIGHBOR_LINK_TIMEOUT 2200 + +#define WS_NEIGHBOUR_TEMPORARY_ENTRY_LIFETIME 5 +#define WS_NEIGHBOUR_DHCP_ENTRY_LIFETIME 60 #define WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_LARGE 520 #define WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT_SMALL 260 #define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2 @@ -342,7 +345,7 @@ typedef struct ws_bs_ie { // With FHSS we need to check CCA twice on TX channel #define WS_NUMBER_OF_CSMA_PERIODS 2 // Interval between two CCA checks -#define WS_CSMA_MULTI_CCA_INTERVAL 1000 +#define WS_CSMA_MULTI_CCA_INTERVAL 2000 /* Default FHSS timing information * diff --git a/source/6LoWPAN/ws/ws_config.h b/source/6LoWPAN/ws/ws_config.h index 62a338ea0d0..589724fda8a 100644 --- a/source/6LoWPAN/ws/ws_config.h +++ b/source/6LoWPAN/ws/ws_config.h @@ -153,9 +153,10 @@ extern uint8_t DEVICE_MIN_SENS; * Amount of ND reply entries left * rest are used as child count, but is related to neighbour table size */ -#define WS_RPL_CANDIDATE_PARENT_COUNT 3 // Largest possible value -#define WS_TEMPORARY_NEIGHBOUR_ENTRIES 7 -#define WS_NON_CHILD_NEIGHBOUR_COUNT (WS_RPL_CANDIDATE_PARENT_COUNT + WS_TEMPORARY_NEIGHBOUR_ENTRIES) +#define WS_RPL_CANDIDATE_PARENT_COUNT 3 +#define WS_SMALL_TEMPORARY_NEIGHBOUR_ENTRIES 7 +#define WS_MEDIUM_TEMPORARY_NEIGHBOUR_ENTRIES 12 +#define WS_LARGE_TEMPORARY_NEIGHBOUR_ENTRIES 22 /* * Neighbour blacklist timers @@ -265,4 +266,18 @@ extern uint8_t DEVICE_MIN_SENS; // How many times sending of initial EAPOL-key is retried #define DEFAULT_INITIAL_KEY_RETRY_COUNT 2 +/* + * RADIUS client retry timer defaults + */ +#define RADIUS_CLIENT_RETRY_IMIN 20 // First retry minimum 1 seconds +#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/source/6LoWPAN/ws/ws_eapol_relay.c b/source/6LoWPAN/ws/ws_eapol_relay.c index a5a83c3ec3e..0bc7a5a472e 100644 --- a/source/6LoWPAN/ws/ws_eapol_relay.c +++ b/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/source/6LoWPAN/ws/ws_empty_functions.c b/source/6LoWPAN/ws/ws_empty_functions.c index bc3d4ec2e39..942eb00e404 100644 --- a/source/6LoWPAN/ws/ws_empty_functions.c +++ b/source/6LoWPAN/ws/ws_empty_functions.c @@ -413,4 +413,13 @@ int ws_stack_info_get(int8_t interface_id, ws_stack_info_t *info_ptr) return -1; } +int ws_device_min_sens_set( + int8_t interface_id, + uint8_t device_min_sens) +{ + (void) interface_id; + (void) device_min_sens; + return -1; +} + #endif // no HAVE_WS diff --git a/source/6LoWPAN/ws/ws_llc_data_service.c b/source/6LoWPAN/ws/ws_llc_data_service.c index c9ffe9c1d40..d20f9980c9e 100644 --- a/source/6LoWPAN/ws/ws_llc_data_service.c +++ b/source/6LoWPAN/ws/ws_llc_data_service.c @@ -100,7 +100,7 @@ typedef struct { typedef NS_LIST_HEAD(llc_message_t, link) llc_message_list_t; #define MAX_NEIGH_TEMPORARY_MULTICAST_SIZE 5 -#define MAX_NEIGH_TEMPORRY_EAPOL_SIZE 30 +#define MAX_NEIGH_TEMPORRY_EAPOL_SIZE 20 #define MAX_NEIGH_TEMPORAY_LIST_SIZE (MAX_NEIGH_TEMPORARY_MULTICAST_SIZE + MAX_NEIGH_TEMPORRY_EAPOL_SIZE) typedef struct { @@ -465,10 +465,16 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t * } } //ETX update + llc_neighbour_req_t neighbor_info; + neighbor_info.ws_neighbor = NULL; + neighbor_info.neighbor = NULL; if (message->ack_requested && messsage_type == WS_FT_DATA) { - llc_neighbour_req_t neighbor_info; + bool success = false; + if (message->dst_address_type == MAC_ADDR_MODE_64_BIT) { + base->ws_neighbor_info_request_cb(interface, message->dst_address, &neighbor_info, false); + } switch (data->status) { case MLME_SUCCESS: case MLME_TX_NO_ACK: @@ -477,7 +483,7 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t * success = true; } - if (message->dst_address_type == MAC_ADDR_MODE_64_BIT && base->ws_neighbor_info_request_cb(interface, message->dst_address, &neighbor_info, false)) { + if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime == WS_NEIGHBOR_LINK_TIMEOUT) { etx_transm_attempts_update(interface->id, 1 + data->tx_retries, success, neighbor_info.neighbor->index, neighbor_info.neighbor->mac64); //TODO discover RSL from Enchanced ACK Header IE elements ws_utt_ie_t ws_utt; @@ -487,7 +493,7 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t * neighbor_info.neighbor->lifetime = neighbor_info.neighbor->link_lifetime; } - ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp); + ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp, neighbor_info.neighbor->mac64); } int8_t rsl; @@ -500,6 +506,7 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t * default: break; } + } //Free message llc_message_free(message, base); @@ -529,6 +536,12 @@ static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t * ns_list_remove(&base->temp_entries->llc_eap_pending_list, message); ws_llc_mpx_eapol_send(base, message); } + } else { + if (neighbor_info.ws_neighbor && neighbor_info.neighbor && neighbor_info.neighbor->link_lifetime != WS_NEIGHBOR_LINK_TIMEOUT) { + //Remove temp neighbour + tr_debug("Remove Temp Entry by TX confirm"); + mac_neighbor_table_neighbor_remove(mac_neighbor_info(interface), neighbor_info.neighbor); + } } return; @@ -689,7 +702,7 @@ static void ws_llc_data_indication_cb(const mac_api_t *api, const mcps_data_ind_ return; } - ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp); + ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp, (uint8_t *) data->SrcAddr); if (us_ie_inline) { ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &us_ie, &interface->ws_info->hopping_schdule); } @@ -711,7 +724,8 @@ static void ws_llc_data_indication_cb(const mac_api_t *api, const mcps_data_ind_ neighbor_info.ws_neighbor->unicast_data_rx = true; } - // Calculate RSL for all UDATA packages heard + // Calculate RSL for all UDATA packets heard + ws_neighbor_class_rf_sensitivity_calculate(interface->ws_info->device_min_sens, data->signal_dbm); ws_neighbor_class_rsl_in_calculate(neighbor_info.ws_neighbor, data->signal_dbm); if (neighbor_info.neighbor) { @@ -795,7 +809,7 @@ static void ws_llc_eapol_indication_cb(const mac_api_t *api, const mcps_data_ind temp_entry->signal_dbm = data->signal_dbm; } uint8_t auth_eui64[8]; - ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp); + ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp, (uint8_t *) data->SrcAddr); if (us_ie_inline) { ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &us_ie, &interface->ws_info->hopping_schdule); } diff --git a/source/6LoWPAN/ws/ws_management_api.c b/source/6LoWPAN/ws/ws_management_api.c index a3246435582..5215f2c8d9c 100644 --- a/source/6LoWPAN/ws/ws_management_api.c +++ b/source/6LoWPAN/ws/ws_management_api.c @@ -741,4 +741,18 @@ int ws_stack_info_get(int8_t interface_id, ws_stack_info_t *info_ptr) return ws_bootstrap_get_info(cur, info_ptr); } +int ws_device_min_sens_set( + int8_t interface_id, + uint8_t device_min_sens) +{ + protocol_interface_info_entry_t *cur; + cur = protocol_stack_interface_info_get_by_id(interface_id); + if (!cur || !ws_info(cur)) { + return -1; + } + DEVICE_MIN_SENS = device_min_sens; + ws_info(cur)->device_min_sens = device_min_sens; + return 0; +} + #endif // HAVE_WS diff --git a/source/6LoWPAN/ws/ws_neighbor_class.c b/source/6LoWPAN/ws/ws_neighbor_class.c index eedb016240d..4cafc622a7a 100644 --- a/source/6LoWPAN/ws/ws_neighbor_class.c +++ b/source/6LoWPAN/ws/ws_neighbor_class.c @@ -89,8 +89,44 @@ void ws_neighbor_class_entry_remove(ws_neighbor_class_t *class_data, uint8_t att } } -void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp) +#ifdef FEA_TRACE_SUPPORT +static int own_ceil(float value) { + int ivalue = (int)value; + if (value == (float)ivalue) { + return ivalue; + } + return ivalue + 1; +} + +static void ws_neighbor_calculate_ufsi_drift(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp, uint8_t address[8]) +{ + if (ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp && ws_neighbor->fhss_data.uc_timing_info.ufsi) { + uint32_t seq_length = 0x10000; + if (ws_neighbor->fhss_data.uc_timing_info.unicast_channel_function == WS_TR51CF) { + seq_length = ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels; + } + // Convert 24-bit UFSI to real time before drift calculation + uint32_t time_since_seq_start_prev_ms = own_ceil((float)((uint64_t)ws_neighbor->fhss_data.uc_timing_info.ufsi * seq_length * ws_neighbor->fhss_data.uc_timing_info.unicast_dwell_interval) / 0x1000000); + uint32_t time_since_seq_start_cur_ms = own_ceil((float)((uint64_t)ws_utt->ufsi * seq_length * ws_neighbor->fhss_data.uc_timing_info.unicast_dwell_interval) / 0x1000000); + uint32_t time_since_last_ufsi_us = timestamp - ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp; + uint32_t ufsi_diff_ms = time_since_seq_start_cur_ms - time_since_seq_start_prev_ms; + int32_t ufsi_drift_ms = (int32_t)(time_since_last_ufsi_us / 1000 - ufsi_diff_ms); + // Only trace if there is significant error + if (ufsi_drift_ms < -5 || ufsi_drift_ms > 5) { + tr_debug("UFSI updated: %s, drift: %"PRIi32"ms in %"PRIu32" seconds", trace_array(address, 8), ufsi_drift_ms, time_since_last_ufsi_us / 1000000); + } + } +} +#endif + +void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp, uint8_t address[8]) +{ +#ifdef FEA_TRACE_SUPPORT + ws_neighbor_calculate_ufsi_drift(ws_neighbor, ws_utt, timestamp, address); +#else + (void) address; +#endif ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp = timestamp; ws_neighbor->fhss_data.uc_timing_info.ufsi = ws_utt->ufsi; } @@ -245,8 +281,13 @@ void ws_neighbor_class_neighbor_broadcast_schedule_set(ws_neighbor_class_entry_t ws_neighbor->fhss_data.bc_timing_info.broadcast_schedule_id = ws_bs_ie->broadcast_schedule_identifier; } -void ws_neighbor_class_rf_sensitivity_calculate(uint8_t rsl_heard) +void ws_neighbor_class_rf_sensitivity_calculate(uint8_t dev_min_sens_config, int8_t dbm_heard) { + if (dev_min_sens_config != 0) { + // Automatic mode disabled + return; + } + uint8_t rsl_heard = ws_neighbor_class_rsl_from_dbm_calculate(dbm_heard); if (DEVICE_MIN_SENS > rsl_heard) { // We are hearing packet with lower than min_sens dynamically learn the sensitivity DEVICE_MIN_SENS = rsl_heard; @@ -285,8 +326,6 @@ static void ws_neighbor_class_parent_set_analyze(ws_neighbor_class_entry_t *ws_n void ws_neighbor_class_rsl_in_calculate(ws_neighbor_class_entry_t *ws_neighbor, int8_t dbm_heard) { uint8_t rsl = ws_neighbor_class_rsl_from_dbm_calculate(dbm_heard); - // Calculate minimum sensitivity from heard packets. - ws_neighbor_class_rf_sensitivity_calculate(rsl); if (ws_neighbor->rsl_in == RSL_UNITITIALIZED) { ws_neighbor->rsl_in = rsl << WS_RSL_SCALING; } diff --git a/source/6LoWPAN/ws/ws_neighbor_class.h b/source/6LoWPAN/ws/ws_neighbor_class.h index e1ebf048232..aa63fa181f8 100644 --- a/source/6LoWPAN/ws/ws_neighbor_class.h +++ b/source/6LoWPAN/ws/ws_neighbor_class.h @@ -106,7 +106,7 @@ void ws_neighbor_class_entry_remove(ws_neighbor_class_t *class_data, uint8_t att * \param timestamp timestamp for received data * */ -void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp); +void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp, uint8_t address[8]); /** * ws_neighbor_class_neighbor_unicast_schedule_set a function for update neighbor unicast shedule information @@ -146,7 +146,7 @@ void ws_neighbor_class_neighbor_broadcast_schedule_set(ws_neighbor_class_entry_t * \param rsl_heard; rsl_heard heard from Radio * */ -void ws_neighbor_class_rf_sensitivity_calculate(uint8_t rsl_heard); +void ws_neighbor_class_rf_sensitivity_calculate(uint8_t dev_min_sens_config, int8_t dbm_heard); /** * ws_neighbor_class_rsl_from_dbm_calculate diff --git a/source/6LoWPAN/ws/ws_pae_auth.c b/source/6LoWPAN/ws/ws_pae_auth.c index b435270c771..448127abb78 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.c +++ b/source/6LoWPAN/ws/ws_pae_auth.c @@ -94,6 +94,7 @@ typedef struct { ws_pae_auth_nw_info_updated *nw_info_updated; /**< Security keys network info updated callback */ ws_pae_auth_ip_addr_get *ip_addr_get; /**< IP address get callback */ supp_list_t active_supp_list; /**< List of active supplicants */ + shared_comp_list_t shared_comp_list; /**< Shared component list */ arm_event_storage_t *timer; /**< Timer */ sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */ const sec_prot_certs_t *certs; /**< Certificates */ @@ -121,6 +122,8 @@ static int8_t ws_pae_auth_timer_if_start(kmp_service_t *service, kmp_api_t *kmp) static int8_t ws_pae_auth_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp); static int8_t ws_pae_auth_timer_start(pae_auth_t *pae_auth); static int8_t ws_pae_auth_timer_stop(pae_auth_t *pae_auth); +static int8_t ws_pae_auth_shared_comp_add(kmp_service_t *service, kmp_shared_comp_t *data); +static int8_t ws_pae_auth_shared_comp_remove(kmp_service_t *service, kmp_shared_comp_t *data); static bool ws_pae_auth_timer_running(pae_auth_t *pae_auth); static void ws_pae_auth_kmp_service_addr_get(kmp_service_t *service, kmp_api_t *kmp, kmp_addr_t *local_addr, kmp_addr_t *remote_addr); static void ws_pae_auth_kmp_service_ip_addr_get(kmp_service_t *service, kmp_api_t *kmp, uint8_t *address); @@ -156,6 +159,7 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot pae_auth->pan_id = 0xffff; pae_auth->interface_ptr = interface_ptr; ws_pae_lib_supp_list_init(&pae_auth->active_supp_list); + ws_pae_lib_shared_comp_list_init(&pae_auth->shared_comp_list); pae_auth->timer = NULL; pae_auth->hash_set = NULL; @@ -192,6 +196,10 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot goto error; } + if (kmp_service_shared_comp_if_register(pae_auth->kmp_service, ws_pae_auth_shared_comp_add, ws_pae_auth_shared_comp_remove)) { + goto error; + } + if (auth_key_sec_prot_register(pae_auth->kmp_service) < 0) { goto error; } @@ -594,6 +602,8 @@ static void ws_pae_auth_free(pae_auth_t *pae_auth) return; } + ws_pae_lib_shared_comp_list_free(&pae_auth->shared_comp_list); + ws_pae_lib_supp_list_delete(&pae_auth->active_supp_list); kmp_socket_if_unregister(pae_auth->kmp_service); @@ -741,6 +751,8 @@ void ws_pae_auth_slow_timer(uint16_t seconds) } ws_pae_lib_supp_list_slow_timer_update(&pae_auth->active_supp_list, seconds); + + ws_pae_lib_shared_comp_list_timeout(&pae_auth->shared_comp_list, seconds); } // Update key storage timer @@ -837,6 +849,26 @@ static int8_t ws_pae_auth_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp) return 0; } +static int8_t ws_pae_auth_shared_comp_add(kmp_service_t *service, kmp_shared_comp_t *data) +{ + pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service); + if (!pae_auth) { + return -1; + } + + return ws_pae_lib_shared_comp_list_add(&pae_auth->shared_comp_list, data); +} + +static int8_t ws_pae_auth_shared_comp_remove(kmp_service_t *service, kmp_shared_comp_t *data) +{ + pae_auth_t *pae_auth = ws_pae_auth_by_kmp_service_get(service); + if (!pae_auth) { + return -1; + } + + return ws_pae_lib_shared_comp_list_remove(&pae_auth->shared_comp_list, data); +} + static int8_t ws_pae_auth_timer_start(pae_auth_t *pae_auth) { pae_auth->timer_running = true; @@ -948,7 +980,7 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, uint8_t m kmp_type_e kmp_type_to_search = type; // If radius is enabled, route EAP-TLS to radius EAP-TLS - if (pae_auth->sec_cfg->radius_cfg.radius_addr_set && type == IEEE_802_1X_MKA) { + if (pae_auth->sec_cfg->radius_cfg != NULL && pae_auth->sec_cfg->radius_cfg->radius_addr_set && type == IEEE_802_1X_MKA) { kmp_type_to_search = RADIUS_IEEE_802_1X_MKA; } @@ -1118,7 +1150,7 @@ static kmp_type_e ws_pae_auth_next_protocol_get(pae_auth_t *pae_auth, supp_entry if (sec_keys->pmk_mismatch) { sec_keys->ptk_mismatch = true; // start EAP-TLS towards supplicant - if (pae_auth->sec_cfg->radius_cfg.radius_addr_set) { + if (pae_auth->sec_cfg->radius_cfg != NULL && pae_auth->sec_cfg->radius_cfg->radius_addr_set) { next_type = RADIUS_IEEE_802_1X_MKA; } else { next_type = IEEE_802_1X_MKA; diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index 80b72e5231c..e222d825da2 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -24,6 +24,7 @@ #include "fhss_config.h" #include "ns_address.h" #include "ws_management_api.h" +#include "ws_bbr_api.h" #include "Service_Libs/utils/ns_file.h" #include "NWK_INTERFACE/Include/protocol.h" #include "6LoWPAN/ws/ws_config.h" @@ -106,6 +107,7 @@ typedef struct { } pae_controller_t; typedef struct { + sec_radius_cfg_t *radius_cfg; /**< Radius configuration settings */ uint16_t node_limit; /**< Max number of stored supplicants */ bool node_limit_set : 1; /**< Node limit set */ bool ext_cert_valid_enabled : 1; /**< Extended certificate validation enabled */ @@ -146,13 +148,12 @@ static const char *NW_INFO_FILE = NW_INFO_FILE_NAME; static NS_LIST_DEFINE(pae_controller_list, pae_controller_t, link); pae_controller_config_t pae_controller_config = { + .radius_cfg = NULL, .node_limit = 0, .node_limit_set = false, .ext_cert_valid_enabled = false }; -sec_radius_cfg_t *pae_controller_radius_settings; - int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface_ptr) { pae_controller_t *controller = ws_pae_controller_get(interface_ptr); @@ -217,16 +218,16 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in return -1; } - if (pae_controller_radius_settings) { - // If either address or password is set, both must be set - if (controller->sec_cfg.radius_cfg.radius_addr_set || controller->sec_cfg.radius_cfg.radius_shared_secret_len > 0) { - if (!controller->sec_cfg.radius_cfg.radius_addr_set) { + // If either radius address or password is set, both must be set + if (controller->sec_cfg.radius_cfg != NULL) { + if (controller->sec_cfg.radius_cfg->radius_addr_set || controller->sec_cfg.radius_cfg->radius_shared_secret_len > 0) { + if (!controller->sec_cfg.radius_cfg->radius_addr_set) { return -1; } - if (controller->sec_cfg.radius_cfg.radius_shared_secret_len == 0) { + if (controller->sec_cfg.radius_cfg->radius_shared_secret_len == 0) { return -1; } - if (ws_pae_auth_radius_address_set(interface_ptr, controller->sec_cfg.radius_cfg.radius_addr) < 0) { + if (ws_pae_auth_radius_address_set(interface_ptr, controller->sec_cfg.radius_cfg->radius_addr) < 0) { return -1; } } @@ -704,9 +705,7 @@ int8_t ws_pae_controller_configure(protocol_interface_info_entry_t *interface_pt ws_pae_timers_settings_init(&controller->sec_cfg.timer_cfg, sec_timer_cfg); } - if (pae_controller_radius_settings) { - controller->sec_cfg.radius_cfg = *pae_controller_radius_settings; - } + controller->sec_cfg.radius_cfg = pae_controller_config.radius_cfg; return 0; } @@ -1171,36 +1170,59 @@ int8_t ws_pae_controller_certificate_revocation_list_remove(const arm_cert_revoc return ret; } +sec_radius_cfg_t *ws_pae_controller_radius_config_get(void) +{ + if (pae_controller_config.radius_cfg != NULL) { + return pae_controller_config.radius_cfg; + } + + pae_controller_config.radius_cfg = ns_dyn_mem_alloc(sizeof(sec_radius_cfg_t)); + if (pae_controller_config.radius_cfg == NULL) { + return NULL; + } + + pae_controller_config.radius_cfg->radius_retry_trickle_params.Imin = RADIUS_CLIENT_RETRY_IMIN; + pae_controller_config.radius_cfg->radius_retry_trickle_params.Imax = RADIUS_CLIENT_RETRY_IMAX; + pae_controller_config.radius_cfg->radius_retry_trickle_params.k = 0; + pae_controller_config.radius_cfg->radius_retry_trickle_params.TimerExpirations = RADIUS_CLIENT_TIMER_EXPIRATIONS; + + pae_controller_config.radius_cfg->radius_addr_set = false; + pae_controller_config.radius_cfg->radius_shared_secret_len = 0; + pae_controller_config.radius_cfg->radius_shared_secret = NULL; + + return pae_controller_config.radius_cfg; +} + int8_t ws_pae_controller_radius_address_set(int8_t interface_id, const uint8_t *address) { - pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id); + sec_radius_cfg_t *radius_cfg = ws_pae_controller_radius_config_get(); + if (radius_cfg == NULL) { + return -1; + } - // If remote address is not set, clear radius information - if (!address) { - if (pae_controller_radius_settings != NULL) { - pae_controller_radius_settings->radius_addr_set = false; - } - if (controller) { - ws_pae_controller_configure(controller->interface_ptr, NULL, NULL); - } + if (address != NULL) { + memcpy(radius_cfg->radius_addr, address, 16); + radius_cfg->radius_addr_set = true; + } else { + radius_cfg->radius_addr_set = false; + } + + pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id); + if (!controller) { return 0; } - if (pae_controller_radius_settings == NULL) { - pae_controller_radius_settings = ns_dyn_mem_alloc(sizeof(sec_radius_cfg_t)); - if (!pae_controller_radius_settings) { - return -1; - } - memset(pae_controller_radius_settings, 0, sizeof(sec_radius_cfg_t)); + if (ws_pae_controller_configure(controller->interface_ptr, NULL, NULL) < 0) { + return -1; } - memcpy(pae_controller_radius_settings->radius_addr, address, 16); - pae_controller_radius_settings->radius_addr_set = true; - if (controller) { - ws_pae_controller_configure(controller->interface_ptr, NULL, NULL); - if (ws_pae_auth_radius_address_set(controller->interface_ptr, controller->sec_cfg.radius_cfg.radius_addr) < 0) { - return -1; - } + if (!radius_cfg->radius_addr_set) { + return 0; + } + + if (ws_pae_auth_radius_address_set(controller->interface_ptr, radius_cfg->radius_addr) < 0) { + // If not set here since authenticator not created, then set on authenticator initialization + return 0; } return 0; @@ -1214,54 +1236,84 @@ int8_t ws_pae_controller_radius_address_get(int8_t interface_id, uint8_t *addres return -1; } - if (pae_controller_radius_settings == NULL || !pae_controller_radius_settings->radius_addr_set) { + sec_radius_cfg_t *radius_cfg = ws_pae_controller_radius_config_get(); + if (radius_cfg == NULL) { + return -1; + } + + if (!radius_cfg->radius_addr_set) { return -1; } - memcpy(address, pae_controller_radius_settings->radius_addr, 16); + memcpy(address, radius_cfg->radius_addr, 16); + return 0; } int8_t ws_pae_controller_radius_shared_secret_set(int8_t interface_id, const uint16_t shared_secret_len, const uint8_t *shared_secret) { + sec_radius_cfg_t *radius_cfg = ws_pae_controller_radius_config_get(); + if (radius_cfg == NULL) { + return -1; + } + + radius_cfg->radius_shared_secret = shared_secret; + radius_cfg->radius_shared_secret_len = shared_secret_len; + pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id); + if (controller) { + ws_pae_controller_configure(controller->interface_ptr, NULL, NULL); + } - // If shared secret is not set, clear radius information - if (shared_secret_len == 0 || !shared_secret) { - if (pae_controller_radius_settings != NULL) { - memset(pae_controller_radius_settings->radius_shared_secret, 0, pae_controller_radius_settings->radius_shared_secret_len); - pae_controller_radius_settings->radius_shared_secret_len = 0; - } - if (controller) { - ws_pae_controller_configure(controller->interface_ptr, NULL, NULL); - } - return 0; + return 0; +} + +int8_t ws_pae_controller_radius_shared_secret_get(int8_t interface_id, uint16_t *shared_secret_len, uint8_t *shared_secret) +{ + (void) interface_id; + + if (shared_secret_len == NULL) { + return -1; + } + + sec_radius_cfg_t *radius_cfg = ws_pae_controller_radius_config_get(); + if (radius_cfg == NULL) { + return -1; } - if (pae_controller_radius_settings == NULL) { - pae_controller_radius_settings = ns_dyn_mem_alloc(sizeof(sec_radius_cfg_t)); - if (!pae_controller_radius_settings) { - return -1; + uint16_t length = radius_cfg->radius_shared_secret_len; + if (shared_secret != NULL) { + if (length > *shared_secret_len) { + length = *shared_secret_len; + } + if (length > 0 && radius_cfg->radius_shared_secret != NULL) { + memcpy(shared_secret, radius_cfg->radius_shared_secret, length); } - memset(pae_controller_radius_settings, 0, sizeof(sec_radius_cfg_t)); } - if (pae_controller_radius_settings->radius_shared_secret != NULL && - pae_controller_radius_settings->radius_shared_secret_len != shared_secret_len) { - ns_dyn_mem_free(pae_controller_radius_settings->radius_shared_secret); - pae_controller_radius_settings->radius_shared_secret = NULL; + *shared_secret_len = length; + + return 0; +} + +int8_t ws_pae_controller_radius_timing_set(int8_t interface_id, bbr_radius_timing_t *timing) +{ + (void) interface_id; + + if (timing == NULL) { + return -1; } - if (pae_controller_radius_settings->radius_shared_secret == NULL) { - pae_controller_radius_settings->radius_shared_secret = ns_dyn_mem_alloc(shared_secret_len); - if (pae_controller_radius_settings->radius_shared_secret == NULL) { - return -1; - } + sec_radius_cfg_t *radius_cfg = ws_pae_controller_radius_config_get(); + if (radius_cfg == NULL) { + return -1; } - memcpy(pae_controller_radius_settings->radius_shared_secret, shared_secret, shared_secret_len); - pae_controller_radius_settings->radius_shared_secret_len = shared_secret_len; + radius_cfg->radius_retry_trickle_params.Imin = timing->radius_retry_imin; + radius_cfg->radius_retry_trickle_params.Imax = timing->radius_retry_imax; + radius_cfg->radius_retry_trickle_params.TimerExpirations = timing->radius_retry_count; + pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id); if (controller) { ws_pae_controller_configure(controller->interface_ptr, NULL, NULL); } @@ -1269,28 +1321,45 @@ int8_t ws_pae_controller_radius_shared_secret_set(int8_t interface_id, const uin return 0; } -int8_t ws_pae_controller_radius_shared_secret_get(int8_t interface_id, uint16_t *shared_secret_len, uint8_t *shared_secret) +int8_t ws_pae_controller_radius_timing_get(int8_t interface_id, bbr_radius_timing_t *timing) { (void) interface_id; - if (shared_secret_len == NULL) { + if (timing == NULL) { return -1; } - uint16_t length = 0; - if (pae_controller_radius_settings != NULL) { - length = pae_controller_radius_settings->radius_shared_secret_len; - if (shared_secret != NULL) { - if (length > *shared_secret_len) { - length = *shared_secret_len; - } - if (length > 0 && pae_controller_radius_settings->radius_shared_secret != NULL) { - memcpy(shared_secret, pae_controller_radius_settings->radius_shared_secret, length); - } - } + if (pae_controller_config.radius_cfg == NULL) { + timing->radius_retry_imin = RADIUS_CLIENT_RETRY_IMIN; + timing->radius_retry_imax = RADIUS_CLIENT_RETRY_IMAX; + timing->radius_retry_count = RADIUS_CLIENT_TIMER_EXPIRATIONS; + return 0; } - *shared_secret_len = length; + sec_radius_cfg_t *radius_cfg = ws_pae_controller_radius_config_get(); + if (radius_cfg == NULL) { + return -1; + } + + timing->radius_retry_imin = radius_cfg->radius_retry_trickle_params.Imin; + timing->radius_retry_imax = radius_cfg->radius_retry_trickle_params.Imax; + timing->radius_retry_count = radius_cfg->radius_retry_trickle_params.TimerExpirations; + + return 0; +} + +int8_t ws_pae_controller_radius_timing_validate(int8_t interface_id, bbr_radius_timing_t *timing) +{ + (void) interface_id; + + if (timing == NULL) { + return -1; + } + + if (timing->radius_retry_imin == 0 || timing->radius_retry_imax == 0 || + timing->radius_retry_imin > timing->radius_retry_imax) { + return -1; + } return 0; } diff --git a/source/6LoWPAN/ws/ws_pae_controller.h b/source/6LoWPAN/ws/ws_pae_controller.h index 93c3abdd34e..2b619ccf922 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.h +++ b/source/6LoWPAN/ws/ws_pae_controller.h @@ -30,6 +30,7 @@ typedef enum { struct nvm_tlv_entry; struct ws_sec_timer_cfg_s; struct ws_sec_prot_cfg_s; +struct bbr_radius_timing; /** * ws_pae_controller_set_target sets EAPOL target for PAE supplicant @@ -282,6 +283,42 @@ int8_t ws_pae_controller_radius_shared_secret_set(int8_t interface_id, const uin */ int8_t ws_pae_controller_radius_shared_secret_get(int8_t interface_id, uint16_t *shared_secret_len, uint8_t *shared_secret); +/** + * ws_pae_controller_radius_timing_set set radius timing information + * + * \param interface_id interface identifier + * \param timing timing information + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_controller_radius_timing_set(int8_t interface_id, struct bbr_radius_timing *timing); + +/** + * ws_pae_controller_radius_timing_get get radius timing information + * + * \param interface_id interface identifier + * \param timing timing information + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_controller_radius_timing_get(int8_t interface_id, struct bbr_radius_timing *timing); + +/** + * ws_pae_controller_radius_timing_validate validate radius timing information + * + * \param interface_id interface identifier + * \param timing timing information + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_controller_radius_timing_validate(int8_t interface_id, struct bbr_radius_timing *timing); + /** * ws_pae_controller_nw_info_set set network information * diff --git a/source/6LoWPAN/ws/ws_pae_lib.c b/source/6LoWPAN/ws/ws_pae_lib.c index 52ceaaba6a2..3f9ab10b37f 100644 --- a/source/6LoWPAN/ws/ws_pae_lib.c +++ b/source/6LoWPAN/ws/ws_pae_lib.c @@ -448,4 +448,64 @@ supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list) return retry_supp; } +int8_t ws_pae_lib_shared_comp_list_init(shared_comp_list_t *comp_list) +{ + ns_list_init(comp_list); + return 0; +} + +int8_t ws_pae_lib_shared_comp_list_free(shared_comp_list_t *comp_list) +{ + ns_list_foreach_safe(shared_comp_entry_t, entry, comp_list) { + if (entry->data->delete) { + entry->data->delete (); + } + ns_list_remove(comp_list, entry); + ns_dyn_mem_free(entry); + } + return 0; +} + +int8_t ws_pae_lib_shared_comp_list_add(shared_comp_list_t *comp_list, kmp_shared_comp_t *data) +{ + ns_list_foreach(shared_comp_entry_t, entry, comp_list) { + if (entry->data == data) { + return -1; + } + } + + shared_comp_entry_t *entry = ns_dyn_mem_alloc(sizeof(shared_comp_entry_t)); + if (!entry) { + return -1; + } + entry->data = data; + ns_list_add_to_end(comp_list, entry); + + return 0; +} + +int8_t ws_pae_lib_shared_comp_list_remove(shared_comp_list_t *comp_list, kmp_shared_comp_t *data) +{ + ns_list_foreach(shared_comp_entry_t, entry, comp_list) { + if (entry->data == data) { + ns_list_remove(comp_list, entry); + ns_dyn_mem_free(entry); + return 0; + } + } + + return 0; +} + +int8_t ws_pae_lib_shared_comp_list_timeout(shared_comp_list_t *comp_list, uint16_t ticks) +{ + ns_list_foreach(shared_comp_entry_t, entry, comp_list) { + if (entry->data->timeout) { + entry->data->timeout(ticks); + } + } + + return 0; +} + #endif /* HAVE_WS */ diff --git a/source/6LoWPAN/ws/ws_pae_lib.h b/source/6LoWPAN/ws/ws_pae_lib.h index 5058e3e3640..dc9a0b67b56 100644 --- a/source/6LoWPAN/ws/ws_pae_lib.h +++ b/source/6LoWPAN/ws/ws_pae_lib.h @@ -45,6 +45,13 @@ typedef struct supp_entry_s { typedef NS_LIST_HEAD(supp_entry_t, link) supp_list_t; +typedef struct { + kmp_shared_comp_t *data; /**< KMP shared component data */ + ns_list_link_t link; /**< Link */ +} shared_comp_entry_t; + +typedef NS_LIST_HEAD(shared_comp_entry_t, link) shared_comp_list_t; + /** * ws_pae_lib_kmp_list_init initializes KMP list * @@ -388,4 +395,62 @@ kmp_api_t *ws_pae_lib_supp_list_kmp_receive_check(supp_list_t *supp_list, const */ supp_entry_t *ws_pae_lib_supp_list_entry_retry_timer_get(supp_list_t *supp_list); +/** + * ws_pae_lib_shared_comp_list_init init shared component list + * + * \param comp_list component list + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_lib_shared_comp_list_init(shared_comp_list_t *comp_list); + +/** + * ws_pae_lib_shared_comp_list_free free shared component list + * + * \param comp_list component list + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_lib_shared_comp_list_free(shared_comp_list_t *comp_list); + +/** + * ws_pae_lib_shared_comp_list_add add to shared component list + * + * \param comp_list component list + * \param data shared component + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_lib_shared_comp_list_add(shared_comp_list_t *comp_list, kmp_shared_comp_t *data); + +/** + * ws_pae_lib_shared_comp_list_remove remove from shared component list + * + * \param comp_list component list + * \param data shared component + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_lib_shared_comp_list_remove(shared_comp_list_t *comp_list, kmp_shared_comp_t *data); + +/** + * ws_pae_lib_shared_comp_list_timeout timeout to shared component list + * + * \param comp_list component list + * \param ticks elapsed time in seconds + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_lib_shared_comp_list_timeout(shared_comp_list_t *comp_list, uint16_t ticks); + #endif /* WS_PAE_AUTH_H_ */ diff --git a/source/Common_Protocols/icmpv6.c b/source/Common_Protocols/icmpv6.c index 7433f2640b6..1f8beaf6a32 100644 --- a/source/Common_Protocols/icmpv6.c +++ b/source/Common_Protocols/icmpv6.c @@ -46,6 +46,7 @@ #include "6LoWPAN/Bootstraps/protocol_6lowpan.h" #include "6LoWPAN/ws/ws_common_defines.h" #include "6LoWPAN/ws/ws_common.h" +#include "libNET/src/net_dns_internal.h" #define TRACE_GROUP "icmp" @@ -638,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; @@ -868,13 +884,11 @@ 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 - - tr_info("DNS Search List: %s Lifetime: %lu", trace_array(dns_search_list, dns_search_list_len), (unsigned long) dns_lifetime); - // TODO Add DNS server to DNS information storage. - // dns_search_list_storage(cur, buf->src_sa.address, dns_search_list, dns_search_list_len, dns_lifetime); - (void)dns_search_list; - (void)dns_search_list_len; - (void)dns_lifetime; + //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); } else if (type == ICMPV6_OPT_RECURSIVE_DNS_SERVER) { uint8_t dns_length = length / 8; @@ -887,11 +901,9 @@ static buffer_t *icmpv6_ra_handler(buffer_t *buf) uint32_t dns_lifetime = common_read_32_bit(dptr + 2); // 2 x reserved for (int n = 0; n < dns_count; n++) { uint8_t *dns_srv_addr = dptr + 6 + n * 16; - tr_info("DNS Server: %s Lifetime: %lu", trace_ipv6(dns_srv_addr), (unsigned long) dns_lifetime); - // TODO Add DNS server to DNS information storage. - // dns_server_storage(cur, buf->src_sa.address, dns_srv_addr, dns_lifetime); - (void)dns_srv_addr; - (void)dns_lifetime; + //tr_info("DNS Server: %s Lifetime: %lu", trace_ipv6(dns_srv_addr), (unsigned long) dns_lifetime); + // Add DNS server to DNS information storage. + net_dns_server_address_set(cur->id, buf->src_sa.address, dns_srv_addr, dns_lifetime); } } else if (type == ICMPV6_OPT_6LOWPAN_CONTEXT) { nd_ra_process_lowpan_context_option(cur, dptr - 2); diff --git a/source/DHCPv6_Server/DHCPv6_Server_service.c b/source/DHCPv6_Server/DHCPv6_Server_service.c index a7755034a9d..8784c634d25 100644 --- a/source/DHCPv6_Server/DHCPv6_Server_service.c +++ b/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/source/DHCPv6_Server/DHCPv6_server_service.h b/source/DHCPv6_Server/DHCPv6_server_service.h index 8f8616f4f41..024a46acdec 100644 --- a/source/DHCPv6_Server/DHCPv6_server_service.h +++ b/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/source/DHCPv6_client/dhcpv6_client_api.h b/source/DHCPv6_client/dhcpv6_client_api.h index ccfc6c1ddf8..57025e76efd 100644 --- a/source/DHCPv6_client/dhcpv6_client_api.h +++ b/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/source/DHCPv6_client/dhcpv6_client_service.c b/source/DHCPv6_client/dhcpv6_client_service.c index a8cecf6d8d2..559b6ccf1d2 100644 --- a/source/DHCPv6_client/dhcpv6_client_service.c +++ b/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/source/MAC/IEEE802_15_4/mac_defines.h b/source/MAC/IEEE802_15_4/mac_defines.h index 5052ad5d4ea..26f51cd520c 100644 --- a/source/MAC/IEEE802_15_4/mac_defines.h +++ b/source/MAC/IEEE802_15_4/mac_defines.h @@ -204,7 +204,6 @@ typedef struct protocol_interface_rf_mac_setup { bool macBroadcastDisabled: 1; bool scan_active: 1; bool rf_csma_extension_supported: 1; - bool ack_tx_possible: 1; uint16_t mac_short_address; uint16_t pan_id; uint8_t mac64[8]; diff --git a/source/MAC/IEEE802_15_4/mac_mcps_sap.c b/source/MAC/IEEE802_15_4/mac_mcps_sap.c index 22b8061c881..2a814d3fd0e 100644 --- a/source/MAC/IEEE802_15_4/mac_mcps_sap.c +++ b/source/MAC/IEEE802_15_4/mac_mcps_sap.c @@ -1883,6 +1883,9 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in //Remember to update security counter here! key_desc = mac_frame_security_key_get(rf_ptr, buffer); if (!key_desc) { +#ifdef __linux__ + tr_debug("Drop a ACK missing key desc"); +#endif buffer->status = MLME_UNAVAILABLE_KEY; return -2; } @@ -1890,6 +1893,9 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in buffer->aux_header.frameCounter = mac_sec_mib_key_outgoing_frame_counter_get(rf_ptr, key_desc); } if (!mac_frame_security_parameters_init(&ccm_ptr, rf_ptr, buffer, key_desc)) { +#ifdef __linux__ + tr_debug("Drop a ACK ignored by security init"); +#endif return -2; } if (init_build) { @@ -1921,6 +1927,9 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in mac_sec_mib_key_outgoing_frame_counter_decrement(rf_ptr, key_desc); ccm_free(&ccm_ptr); } +#ifdef __linux__ + tr_debug("Drop a ACK send by frame too long %u", frame_length); +#endif return -1; } @@ -1932,7 +1941,7 @@ int8_t mcps_generic_ack_build(protocol_interface_rf_mac_setup_s *rf_ptr, bool in tx_buf->ack_len = frame_length; uint8_t *mhr_start = ptr; - buffer->tx_time = mac_mcps_sap_get_phy_timestamp(rf_ptr) + 300; //Send 300 us later + buffer->tx_time = mac_mcps_sap_get_phy_timestamp(rf_ptr) + 1000; // 1ms delay before Ack ptr = mac_generic_packet_write(rf_ptr, ptr, buffer); @@ -2092,6 +2101,11 @@ static int8_t mcps_pd_data_cca_trig(protocol_interface_rf_mac_setup_s *rf_ptr, m if (rf_ptr->active_pd_data_request) { mac_csma_backoff_start(rf_ptr); } +#ifdef __linux__ + if (buffer->fcf_dsn.frametype == MAC_FRAME_ACK) { + tr_debug("Drop ACK by CCA request"); + } +#endif platform_exit_critical(); return -1; } diff --git a/source/MAC/IEEE802_15_4/mac_mlme.c b/source/MAC/IEEE802_15_4/mac_mlme.c index e1e2e4d3438..8229e29f3f3 100644 --- a/source/MAC/IEEE802_15_4/mac_mlme.c +++ b/source/MAC/IEEE802_15_4/mac_mlme.c @@ -673,50 +673,13 @@ static int8_t mac_mlme_set_ack_wait_duration(protocol_interface_rf_mac_setup_s * return 0; } -static void mac_mlme_trig_pending_ack(protocol_interface_rf_mac_setup_s *rf_mac_setup, mlme_device_descriptor_t *device_ptr) -{ - platform_enter_critical(); - if (rf_mac_setup->mac_ack_tx_active && !rf_mac_setup->ack_tx_possible && - device_ptr->PANId == rf_mac_setup->enhanced_ack_buffer.DstPANId) { - - //Compare address for pending neigbour add - if (rf_mac_setup->enhanced_ack_buffer.fcf_dsn.DstAddrMode == MAC_ADDR_MODE_16_BIT) { - uint16_t short_id = common_read_16_bit(rf_mac_setup->enhanced_ack_buffer.DstAddr); - if (short_id == device_ptr->ShortAddress) { - rf_mac_setup->ack_tx_possible = true; - } - } else if (rf_mac_setup->enhanced_ack_buffer.fcf_dsn.DstAddrMode == MAC_ADDR_MODE_64_BIT) { - if (memcmp(device_ptr->ExtAddress, rf_mac_setup->enhanced_ack_buffer.DstAddr, 8) == 0) { - rf_mac_setup->ack_tx_possible = true; - } - } - } - platform_exit_critical(); -} - static int8_t mac_mlme_device_description_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req) { if (set_req->value_size != sizeof(mlme_device_descriptor_t)) { return -1; } - if (mac_sec_mib_device_description_set(set_req->attr_index, (mlme_device_descriptor_t *) set_req->value_pointer, rf_mac_setup) != 0) { - return -1; - } - - mac_mlme_trig_pending_ack(rf_mac_setup, (mlme_device_descriptor_t *) set_req->value_pointer); - return 0; -} - -static int8_t mac_mlme_device_pending_ack_trig(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req) -{ - - if (set_req->value_size != sizeof(mlme_device_descriptor_t)) { - return -1; - } - mac_mlme_trig_pending_ack(rf_mac_setup, (mlme_device_descriptor_t *) set_req->value_pointer); - - return 0; + return mac_sec_mib_device_description_set(set_req->attr_index, (mlme_device_descriptor_t *) set_req->value_pointer, rf_mac_setup); } static int8_t mac_mlme_key_description_set(protocol_interface_rf_mac_setup_s *rf_mac_setup, const mlme_set_t *set_req) @@ -795,8 +758,6 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m return mac_mlme_set_ack_wait_duration(rf_mac_setup, set_req); case macDeviceTable: return mac_mlme_device_description_set(rf_mac_setup, set_req); - case macDevicePendingAckTrig: - return mac_mlme_device_pending_ack_trig(rf_mac_setup, set_req); case macKeyTable: return mac_mlme_key_description_set(rf_mac_setup, set_req); case macDefaultKeySource: @@ -1659,6 +1620,7 @@ int8_t mac_mlme_rf_channel_change(protocol_interface_rf_mac_setup_s *rf_mac_setu if (new_channel == rf_mac_setup->mac_channel) { return 0; } + platform_enter_critical(); if (rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CHANNEL, &new_channel) == 0) { rf_mac_setup->mac_channel = new_channel; diff --git a/source/MAC/IEEE802_15_4/mac_pd_sap.c b/source/MAC/IEEE802_15_4/mac_pd_sap.c index 799205ceb0e..6b36a7f7d69 100644 --- a/source/MAC/IEEE802_15_4/mac_pd_sap.c +++ b/source/MAC/IEEE802_15_4/mac_pd_sap.c @@ -453,37 +453,18 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r if (status == PHY_LINK_CCA_PREPARE) { - if (rf_ptr->mac_ack_tx_active) { - //Accept direct non crypted acks and crypted only if neighbor is at list - if (rf_ptr->ack_tx_possible) { -#ifdef TIMING_TOOL_TRACES - tr_info("%u TX_start %u", mac_mcps_sap_get_phy_timestamp(rf_ptr), rf_ptr->mac_channel); -#endif - return PHY_TX_ALLOWED; - } - - //Compare time to started time - if (mac_mcps_sap_get_phy_timestamp(rf_ptr) - rf_ptr->enhanced_ack_handler_timestamp > ENHANCED_ACK_NEIGHBOUR_POLL_MAX_TIME_US || mcps_generic_ack_build(rf_ptr, false) != 0) { - mac_data_ack_tx_finish(rf_ptr); - } - - return PHY_TX_NOT_ALLOWED; - } - if (rf_ptr->mac_edfe_tx_active) { - return PHY_TX_ALLOWED; + if (rf_ptr->mac_ack_tx_active || rf_ptr->mac_edfe_tx_active) { + goto VALIDATE_TX_TIME; } if (mac_data_asynch_channel_switch(rf_ptr, rf_ptr->active_pd_data_request)) { -#ifdef TIMING_TOOL_TRACES - tr_info("%u TX_start %u", mac_mcps_sap_get_phy_timestamp(rf_ptr), rf_ptr->mac_channel); -#endif rf_ptr->active_pd_data_request->initial_tx_channel = rf_ptr->mac_channel; int8_t channel_cca_threshold = mac_cca_thr_get_dbm(rf_ptr, rf_ptr->mac_channel); if (CCA_FAILED_DBM != channel_cca_threshold) { rf_ptr->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CHANNEL_CCA_THRESHOLD, (uint8_t *)&channel_cca_threshold); } - return PHY_TX_ALLOWED; + goto VALIDATE_TX_TIME; } if (rf_ptr->fhss_api) { @@ -525,10 +506,19 @@ static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *r return PHY_RESTART_CSMA; } } +VALIDATE_TX_TIME: + if (rf_ptr->active_pd_data_request && rf_ptr->active_pd_data_request->tx_time && !rf_ptr->mac_ack_tx_active && !rf_ptr->mac_edfe_tx_active) { + int32_t tx_time_error_us = mac_mcps_sap_get_phy_timestamp(rf_ptr) - rf_ptr->active_pd_data_request->tx_time; + // Positive error means that TX is too late. Do not allow transmit if transmission is delayed over 5ms + if (tx_time_error_us > 5000) { + mac_sap_cca_fail_cb(rf_ptr, 0xffff); + return PHY_TX_NOT_ALLOWED; + } + } #ifdef TIMING_TOOL_TRACES tr_info("%u TX_start %u", mac_mcps_sap_get_phy_timestamp(rf_ptr), rf_ptr->mac_channel); #endif - return 0; + return PHY_TX_ALLOWED; } if (rf_ptr->mac_ack_tx_active) { @@ -851,6 +841,9 @@ static int8_t mac_pd_sap_generate_ack(protocol_interface_rf_mac_setup_s *rf_ptr, return 0; } if (rf_ptr->mac_ack_tx_active) { +#ifdef __linux__ + tr_debug("Drop a New ack by pending request"); +#endif return -1; } @@ -863,18 +856,6 @@ static int8_t mac_pd_sap_generate_ack(protocol_interface_rf_mac_setup_s *rf_ptr, return -1; } - - if (rf_ptr->enhanced_ack_buffer.fcf_dsn.securityEnabled == 0 || rf_ptr->enhanced_ack_buffer.aux_header.securityLevel == 0) { - //Unsecured data will be acked immediately - rf_ptr->ack_tx_possible = true; - } else { - if (mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode, rf_ptr->enhanced_ack_buffer.DstPANId)) { - rf_ptr->ack_tx_possible = true; - } else { - rf_ptr->ack_tx_possible = false; - } - } - return mcps_generic_ack_build(rf_ptr, true); } @@ -909,11 +890,17 @@ static mac_pre_parsed_frame_t *mac_pd_sap_allocate_receive_buffer(protocol_inter if (fcf_read->frametype != FC_ACK_FRAME) { if (!ns_monitor_packet_allocation_allowed()) { // stack can not handle new packets for routing +#ifdef __linux__ + tr_debug("Packet ingress drop buffer allocation"); +#endif return NULL; } } mac_pre_parsed_frame_t *buffer = mcps_sap_pre_parsed_frame_buffer_get(pd_data_ind->data_ptr, pd_data_ind->data_len); if (!buffer) { +#ifdef __linux__ + tr_debug("macPD buffer allocate fail %u", pd_data_ind->data_len); +#endif return NULL; } //Copy Pre Parsed values @@ -1004,6 +991,9 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message) arm_pd_sap_generic_ind_t *pd_data_ind = &(message->message.generic_data_ind); mac_pre_parsed_frame_t *buffer = NULL; if (pd_data_ind->data_len == 0) { +#ifdef TIMING_TOOL_TRACES + tr_info("Collission at RF?"); +#endif goto ERROR_HANDLER; } @@ -1027,9 +1017,13 @@ int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message) goto ERROR_HANDLER; } if (!mac_pd_sap_rx_filter(pd_data_ind->data_ptr, &fcf_read, rf_ptr->mac_frame_filters, rf_ptr->mac64, rf_ptr->mac_short_address, rf_ptr->pan_id)) { + pd_data_ind->data_len = 0; // Do not update RX drop in that case goto ERROR_HANDLER; } if (mac_pd_sap_generate_ack(rf_ptr, &fcf_read, pd_data_ind)) { +#ifdef __linux__ + tr_debug("Drop a Data by ignored ACK generation"); +#endif goto ERROR_HANDLER; } if (buffer) { diff --git a/source/NWK_INTERFACE/protocol_core.c b/source/NWK_INTERFACE/protocol_core.c index 279bc7f0df6..168293a4b78 100644 --- a/source/NWK_INTERFACE/protocol_core.c +++ b/source/NWK_INTERFACE/protocol_core.c @@ -83,6 +83,7 @@ #include "Service_Libs/load_balance/load_balance_api.h" #include "Service_Libs/pan_blacklist/pan_blacklist_api.h" #include "Service_Libs/etx/etx.h" +#include "libNET/src/net_dns_internal.h" #include "mac_api.h" #include "ethernet_mac_api.h" @@ -304,6 +305,8 @@ void core_timer_event_handle(uint16_t ticksUpdate) ipv6_destination_cache_timer(seconds); ipv6_frag_timer(seconds); cipv6_frag_timer(seconds); + net_dns_timer_seconds(seconds); + #ifdef HAVE_WS ws_pae_controller_slow_timer(seconds); #endif diff --git a/source/Security/kmp/kmp_api.c b/source/Security/kmp/kmp_api.c index e175d9a851f..19be4a7f7a3 100644 --- a/source/Security/kmp/kmp_api.c +++ b/source/Security/kmp/kmp_api.c @@ -64,6 +64,7 @@ typedef NS_LIST_HEAD(kmp_sec_prot_entry_t, link) kmp_sec_prot_list_t; typedef struct { uint8_t instance_id; /**< Message interface instance identifier */ uint8_t header_size; /**< Message interface header size */ + uint8_t number_of_conn; /**< Message interface number of connections */ kmp_service_msg_if_send *send; /**< Message interface callback to send KMP frames */ ns_list_link_t link; /**< Link */ } kmp_msg_if_entry_t; @@ -71,17 +72,19 @@ typedef struct { typedef NS_LIST_HEAD(kmp_msg_if_entry_t, link) kmp_msg_if_list_t; struct kmp_service_s { - kmp_sec_prot_list_t sec_prot_list; /**< Security protocols list */ - kmp_msg_if_list_t msg_if_list; /**< Message interface list */ - kmp_service_incoming_ind *incoming_ind; /**< Callback to application to indicate incoming KMP frame */ - kmp_service_tx_status_ind *tx_status_ind; /**< Callback to application to indicate TX status */ - kmp_service_addr_get *addr_get; /**< Callback to get addresses related to KMP */ - kmp_service_ip_addr_get *ip_addr_get; /**< Callback to get IP addresses related to KMP */ - kmp_service_api_get *api_get; /**< Callback to get KMP API from a service */ - kmp_service_timer_if_start *timer_start; /**< Callback to start timer */ - kmp_service_timer_if_stop *timer_stop; /**< Callback to stop timer */ - kmp_service_event_if_event_send *event_send; /**< Callback to send event */ - ns_list_link_t link; /**< Link */ + kmp_sec_prot_list_t sec_prot_list; /**< Security protocols list */ + kmp_msg_if_list_t msg_if_list; /**< Message interface list */ + kmp_service_incoming_ind *incoming_ind; /**< Callback to application to indicate incoming KMP frame */ + kmp_service_tx_status_ind *tx_status_ind; /**< Callback to application to indicate TX status */ + kmp_service_addr_get *addr_get; /**< Callback to get addresses related to KMP */ + kmp_service_ip_addr_get *ip_addr_get; /**< Callback to get IP addresses related to KMP */ + kmp_service_api_get *api_get; /**< Callback to get KMP API from a service */ + kmp_service_timer_if_start *timer_start; /**< Callback to start timer */ + kmp_service_timer_if_stop *timer_stop; /**< Callback to stop timer */ + kmp_service_event_if_event_send *event_send; /**< Callback to send event */ + kmp_service_shared_comp_add *shared_comp_add; /**< Callback to shared component add */ + kmp_service_shared_comp_remove *shared_comp_remove; /**< Callback to shared component remove */ + ns_list_link_t link; /**< Link */ }; typedef struct { @@ -100,8 +103,11 @@ static void kmp_api_sec_prot_create_indication(sec_prot_t *prot); static void kmp_api_sec_prot_finished_indication(sec_prot_t *prot, sec_prot_result_e result, sec_prot_keys_t *sec_keys); static void kmp_api_sec_prot_finished(sec_prot_t *prot); static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size); +static int8_t kmp_sec_prot_conn_send(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number, uint8_t flags); static void kmp_sec_prot_timer_start(sec_prot_t *prot); static void kmp_sec_prot_timer_stop(sec_prot_t *prot); +static int8_t kmp_sec_prot_shared_comp_add(sec_prot_t *prot, shared_comp_data_t *data); +static int8_t kmp_sec_prot_shared_comp_remove(sec_prot_t *prot, shared_comp_data_t *data); static void kmp_sec_prot_state_machine_call(sec_prot_t *prot); static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64); static void kmp_sec_prot_ip_addr_get(sec_prot_t *prot, uint8_t *address); @@ -157,13 +163,17 @@ kmp_api_t *kmp_api_create(kmp_service_t *service, kmp_type_e type, uint8_t msg_i kmp->sec_prot.header_size = msg_if_entry->header_size; kmp->sec_prot.receive_peer_hdr_size = msg_if_entry->header_size; + kmp->sec_prot.number_of_conn = msg_if_entry->number_of_conn; kmp->sec_prot.create_conf = kmp_api_sec_prot_create_confirm; kmp->sec_prot.create_ind = kmp_api_sec_prot_create_indication; kmp->sec_prot.finished_ind = kmp_api_sec_prot_finished_indication; kmp->sec_prot.finished = kmp_api_sec_prot_finished; kmp->sec_prot.send = kmp_sec_prot_send; + kmp->sec_prot.conn_send = kmp_sec_prot_conn_send; kmp->sec_prot.timer_start = kmp_sec_prot_timer_start; kmp->sec_prot.timer_stop = kmp_sec_prot_timer_stop; + kmp->sec_prot.shared_comp_add = kmp_sec_prot_shared_comp_add; + kmp->sec_prot.shared_comp_remove = kmp_sec_prot_shared_comp_remove; kmp->sec_prot.state_machine_call = kmp_sec_prot_state_machine_call; kmp->sec_prot.addr_get = kmp_sec_prot_eui64_addr_get; kmp->sec_prot.ip_addr_get = kmp_sec_prot_ip_addr_get; @@ -237,6 +247,11 @@ static void kmp_api_sec_prot_finished(sec_prot_t *prot) } static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size) +{ + return kmp_sec_prot_conn_send(prot, pdu, size, 0, 0); +} + +static int8_t kmp_sec_prot_conn_send(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number, uint8_t flags) { kmp_api_t *kmp = kmp_api_get_from_prot(prot); @@ -256,7 +271,7 @@ static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size) int8_t result = -1; if (msg_if_entry->send) { - result = msg_if_entry->send(kmp->service, prot->msg_if_instance_id, kmp_id, kmp->addr, pdu, size, kmp->instance_identifier); + result = msg_if_entry->send(kmp->service, prot->msg_if_instance_id, kmp_id, kmp->addr, pdu, size, kmp->instance_identifier, conn_number, flags); } if (result < 0) { @@ -269,6 +284,7 @@ static int8_t kmp_sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size) static void kmp_sec_prot_timer_start(sec_prot_t *prot) { kmp_api_t *kmp = kmp_api_get_from_prot(prot); + kmp->timer_start_pending = false; if (kmp->service->timer_start(kmp->service, kmp) < 0) { kmp->timer_start_pending = true; @@ -278,10 +294,33 @@ static void kmp_sec_prot_timer_start(sec_prot_t *prot) static void kmp_sec_prot_timer_stop(sec_prot_t *prot) { kmp_api_t *kmp = kmp_api_get_from_prot(prot); + kmp->service->timer_stop(kmp->service, kmp); kmp->timer_start_pending = false; } +static int8_t kmp_sec_prot_shared_comp_add(sec_prot_t *prot, shared_comp_data_t *data) +{ + kmp_api_t *kmp = kmp_api_get_from_prot(prot); + + if (kmp->service->shared_comp_add == NULL) { + return -1; + } + kmp->service->shared_comp_add(kmp->service, (kmp_shared_comp_t *) data); + return 0; +} + +static int8_t kmp_sec_prot_shared_comp_remove(sec_prot_t *prot, shared_comp_data_t *data) +{ + kmp_api_t *kmp = kmp_api_get_from_prot(prot); + + if (kmp->service->shared_comp_add == NULL) { + return -1; + } + kmp->service->shared_comp_remove(kmp->service, (kmp_shared_comp_t *) data); + return 0; +} + static void kmp_sec_prot_eui64_addr_get(sec_prot_t *prot, uint8_t *local_eui64, uint8_t *remote_eui64) { kmp_api_t *kmp = kmp_api_get_from_prot(prot); @@ -444,6 +483,8 @@ kmp_service_t *kmp_service_create(void) service->tx_status_ind = 0; service->addr_get = 0; service->api_get = 0; + service->shared_comp_add = NULL; + service->shared_comp_remove = NULL; ns_list_add_to_start(&kmp_service_list, service); @@ -496,7 +537,7 @@ int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind return 0; } -int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id, kmp_service_msg_if_send *send, uint8_t header_size) +int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id, kmp_service_msg_if_send *send, uint8_t header_size, uint8_t number_of_conn) { if (!service) { return -1; @@ -533,11 +574,12 @@ int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id, entry->instance_id = instance_id; entry->send = send; entry->header_size = header_size; + entry->number_of_conn = number_of_conn; return 0; } -int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size) +int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t connection_num) { if (!service) { return -1; @@ -553,7 +595,14 @@ int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, k return -1; } - int8_t ret = kmp->sec_prot.receive(&kmp->sec_prot, pdu, size); + int8_t ret = -1; + if (kmp->sec_prot.receive != NULL) { + ret = kmp->sec_prot.receive(&kmp->sec_prot, pdu, size); + } + if (kmp->sec_prot.conn_receive != NULL) { + ret = kmp->sec_prot.conn_receive(&kmp->sec_prot, pdu, size, connection_num); + } + return ret; } @@ -642,6 +691,17 @@ int8_t kmp_service_timer_if_register(kmp_service_t *service, kmp_service_timer_i return 0; } +int8_t kmp_service_shared_comp_if_register(kmp_service_t *service, kmp_service_shared_comp_add add, kmp_service_shared_comp_remove remove) +{ + if (!service) { + return -1; + } + + service->shared_comp_add = add; + service->shared_comp_remove = remove; + return 0; +} + void kmp_service_event_if_event(kmp_service_t *service, void *data) { (void) service; diff --git a/source/Security/kmp/kmp_api.h b/source/Security/kmp/kmp_api.h index f51a1405886..fa945eb4805 100644 --- a/source/Security/kmp/kmp_api.h +++ b/source/Security/kmp/kmp_api.h @@ -59,6 +59,9 @@ typedef enum { KMP_TX_ERR_UNSPEC = -2, // Other reason } kmp_tx_status_e; +// On message interface send, do not deallocate pdu buffer +#define MSG_IF_SEND_FLAG_NO_DEALLOC 0x01 + typedef void kmp_sec_keys_t; typedef struct sec_prot_s sec_prot_t; typedef struct kmp_api_s kmp_api_t; @@ -367,12 +370,13 @@ int8_t kmp_service_cb_register(kmp_service_t *service, kmp_service_incoming_ind * \param addr address * \param pdu pdu * \param size pdu size + * \param conn_number connection number (0 for default) * * \return < 0 failure * \return >= 0 success * */ -int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size); +int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t conn_number); /** * kmp_service_msg_if_send send a message @@ -384,12 +388,14 @@ int8_t kmp_service_msg_if_receive(kmp_service_t *service, uint8_t instance_id, k * \param pdu pdu * \param size pdu size * \param tx_identifier TX identifier + * \param conn_number connection number (0 for default) + * \param flags flags * * \return < 0 failure * \return >= 0 success * */ -typedef int8_t kmp_service_msg_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier); +typedef int8_t kmp_service_msg_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e type, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier, uint8_t conn_number, uint8_t flags); /** * kmp_service_msg_if_register registers message interface @@ -398,12 +404,13 @@ typedef int8_t kmp_service_msg_if_send(kmp_service_t *service, uint8_t instance_ * \param instance_id message interface instance identifier * \param send KMP PDU send callback * \param header_size header size + * \param number_of_conn number of connections * * \return < 0 failure * \return >= 0 success * */ -int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id, kmp_service_msg_if_send *send, uint8_t header_size); +int8_t kmp_service_msg_if_register(kmp_service_t *service, uint8_t instance_id, kmp_service_msg_if_send *send, uint8_t header_size, uint8_t number_of_conn); /** * kmp_service_tx_status tx status indication @@ -467,6 +474,7 @@ int8_t kmp_service_sec_protocol_unregister(kmp_service_t *service, kmp_type_e ty * kmp_service_timer_if_timeout timer timeout * * \param service KMP instance + * \param ticks Ticks * */ void kmp_service_timer_if_timeout(kmp_api_t *kmp, uint16_t ticks); @@ -508,6 +516,68 @@ typedef int8_t kmp_service_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp) */ int8_t kmp_service_timer_if_register(kmp_service_t *service, kmp_service_timer_if_start start, kmp_service_timer_if_stop stop); +/** + * kmp_service_shared_comp_timer_timeout shared component timer timeout + * + * \param ticks timer ticks + * + * \return < 0 failure + * \return >= 0 success + * + */ +typedef int8_t kmp_service_shared_comp_timer_timeout(uint16_t ticks); + +/** + * kmp_service_shared_comp_delete shared component delete + * + * \return < 0 failure + * \return >= 0 success + * + */ +typedef int8_t kmp_service_shared_comp_delete(void); + +typedef struct { + kmp_service_shared_comp_timer_timeout *timeout; + kmp_service_shared_comp_delete *delete; +} kmp_shared_comp_t; + +/** + * kmp_service_shared_comp_add add shared component + * + * \param service KMP service + * \param data shared component data + * + * \return < 0 failure + * \return >= 0 success + * + */ +typedef int8_t kmp_service_shared_comp_add(kmp_service_t *service, kmp_shared_comp_t *data); + +/** + * kmp_service_shared_comp_remove remove shared component + * + * \param service KMP service + * \param data shared component data + * + * \return < 0 failure + * \return >= 0 success + * + */ +typedef int8_t kmp_service_shared_comp_remove(kmp_service_t *service, kmp_shared_comp_t *data); + +/** + * kmp_service_shared_comp_if_register register a continuous timer interface to KMP service + * + * \param service KMP service + * \param add shared component + * \param remove remove shared component + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t kmp_service_shared_comp_if_register(kmp_service_t *service, kmp_service_shared_comp_add add, kmp_service_shared_comp_remove remove); + /** * kmp_service_event_if_event event callback * diff --git a/source/Security/kmp/kmp_eapol_pdu_if.c b/source/Security/kmp/kmp_eapol_pdu_if.c index f12bc517b97..afcae84571b 100644 --- a/source/Security/kmp/kmp_eapol_pdu_if.c +++ b/source/Security/kmp/kmp_eapol_pdu_if.c @@ -49,7 +49,7 @@ typedef struct { static NS_LIST_DEFINE(kmp_eapol_pdu_if_list, kmp_eapol_pdu_if_t, link); -static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier); +static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier, uint8_t conn_number, uint8_t flags); static int8_t kmp_eapol_pdu_if_tx_status(protocol_interface_info_entry_t *interface_ptr, eapol_pdu_tx_status_e tx_status, uint8_t tx_identifier); int8_t kmp_eapol_pdu_if_register(kmp_service_t *service, protocol_interface_info_entry_t *interface_ptr) @@ -72,7 +72,7 @@ int8_t kmp_eapol_pdu_if_register(kmp_service_t *service, protocol_interface_info eapol_pdu_if->kmp_service = service; eapol_pdu_if->interface_ptr = interface_ptr; - if (kmp_service_msg_if_register(service, 0, kmp_eapol_pdu_if_send, EAPOL_PDU_IF_HEADER_SIZE) < 0) { + if (kmp_service_msg_if_register(service, 0, kmp_eapol_pdu_if_send, EAPOL_PDU_IF_HEADER_SIZE, 0) < 0) { ns_dyn_mem_free(eapol_pdu_if); return -1; } @@ -92,17 +92,19 @@ int8_t kmp_eapol_pdu_if_unregister(kmp_service_t *service) if (entry->kmp_service == service) { ns_list_remove(&kmp_eapol_pdu_if_list, entry); ns_dyn_mem_free(entry); - kmp_service_msg_if_register(service, 0, NULL, 0); + kmp_service_msg_if_register(service, 0, NULL, 0, 0); } } return 0; } -static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier) +static int8_t kmp_eapol_pdu_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier, uint8_t conn_number, uint8_t flags) { (void) instance_id; // Only one instance of eapol interface possible + (void) conn_number; // Only one connection of eapol interface possible - if (!service || !addr || !pdu) { + // No flags supported + if (!service || !addr || !pdu || flags) { return -1; } @@ -159,7 +161,7 @@ int8_t kmp_eapol_pdu_if_receive(protocol_interface_info_entry_t *interface_ptr, return -1; } - int8_t ret = kmp_service_msg_if_receive(service, 0, type, &addr, data_pdu, data_pdu_size); + int8_t ret = kmp_service_msg_if_receive(service, 0, type, &addr, data_pdu, data_pdu_size, 0); return ret; } diff --git a/source/Security/kmp/kmp_socket_if.c b/source/Security/kmp/kmp_socket_if.c index 66c78b10392..6197e4304d2 100644 --- a/source/Security/kmp/kmp_socket_if.c +++ b/source/Security/kmp/kmp_socket_if.c @@ -39,19 +39,20 @@ #define TRACE_GROUP "kmsi" -#define SOCKET_IF_HEADER_SIZE 27 +#define SOCKET_IF_HEADER_SIZE 27 +#define INSTANCE_SOCKETS_NUMBER 3 typedef struct { kmp_service_t *kmp_service; /**< KMP service */ uint8_t instance_id; /**< Instance identifier */ bool relay; /**< Interface is relay interface */ ns_address_t remote_addr; /**< Remote address */ - int8_t socket_id; /**< Socket ID */ - bool socket_id_set; /**< Socket ID is set */ + int8_t socket_id[INSTANCE_SOCKETS_NUMBER]; /**< Socket ID */ + unsigned socket_id_in_use : 4; /**< Socket ID is in use */ ns_list_link_t link; /**< Link */ } kmp_socket_if_t; -static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier); +static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier, uint8_t connection_num, uint8_t flags); static void kmp_socket_if_socket_cb(void *ptr); static NS_LIST_DEFINE(kmp_socket_if_list, kmp_socket_if_t, link); @@ -78,7 +79,10 @@ int8_t kmp_socket_if_register(kmp_service_t *service, uint8_t *instance_id, bool return -1; } memset(socket_if, 0, sizeof(kmp_socket_if_t)); - socket_if->socket_id = -1; + for (uint8_t socket_num = 0; socket_num < INSTANCE_SOCKETS_NUMBER; socket_num++) { + socket_if->socket_id[socket_num] = -1; + } + socket_if->socket_id_in_use = 1; new_socket_if_allocated = true; } @@ -87,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; } @@ -104,14 +108,19 @@ int8_t kmp_socket_if_register(kmp_service_t *service, uint8_t *instance_id, bool memcpy(&socket_if->remote_addr.address, remote_addr, 16); socket_if->remote_addr.identifier = remote_port; - if (socket_if->socket_id < 0 || address_changed) { - if (socket_if->socket_id >= 0) { - socket_close(socket_if->socket_id); - } - socket_if->socket_id = socket_open(IPV6_NH_UDP, local_port, &kmp_socket_if_socket_cb); - if (socket_if->socket_id < 0) { - ns_dyn_mem_free(socket_if); - return -1; + for (uint8_t socket_num = 0; socket_num < INSTANCE_SOCKETS_NUMBER; socket_num++) { + if (socket_if->socket_id_in_use & (1 << socket_num)) { + + if ((socket_if->socket_id[socket_num] < 1) || address_changed) { + if (socket_if->socket_id[socket_num] >= 0) { + socket_close(socket_if->socket_id[socket_num]); + } + socket_if->socket_id[socket_num] = socket_open(IPV6_NH_UDP, local_port, &kmp_socket_if_socket_cb); + if (socket_if->socket_id[socket_num] < 0) { + ns_dyn_mem_free(socket_if); + return -1; + } + } } } @@ -120,7 +129,12 @@ int8_t kmp_socket_if_register(kmp_service_t *service, uint8_t *instance_id, bool header_size = SOCKET_IF_HEADER_SIZE; } - if (kmp_service_msg_if_register(service, *instance_id, kmp_socket_if_send, header_size) < 0) { + if (kmp_service_msg_if_register(service, *instance_id, kmp_socket_if_send, header_size, INSTANCE_SOCKETS_NUMBER) < 0) { + for (uint8_t socket_num = 0; socket_num < INSTANCE_SOCKETS_NUMBER; socket_num++) { + if (socket_if->socket_id[socket_num] >= 0) { + socket_close(socket_if->socket_id[socket_num]); + } + } ns_dyn_mem_free(socket_if); return -1; } @@ -141,15 +155,19 @@ int8_t kmp_socket_if_unregister(kmp_service_t *service) ns_list_foreach_safe(kmp_socket_if_t, entry, &kmp_socket_if_list) { if (entry->kmp_service == service) { ns_list_remove(&kmp_socket_if_list, entry); - socket_close(entry->socket_id); - kmp_service_msg_if_register(service, entry->instance_id, NULL, 0); + for (uint8_t socket_num = 0; socket_num < INSTANCE_SOCKETS_NUMBER; socket_num++) { + if (entry->socket_id[socket_num] >= 0) { + socket_close(entry->socket_id[socket_num]); + } + } + kmp_service_msg_if_register(service, entry->instance_id, NULL, 0, 0); ns_dyn_mem_free(entry); } } return 0; } -static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier) +static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, kmp_type_e kmp_id, const kmp_addr_t *addr, void *pdu, uint16_t size, uint8_t tx_identifier, uint8_t connection_num, uint8_t flags) { (void) tx_identifier; @@ -157,6 +175,10 @@ static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, km return -1; } + if (connection_num >= INSTANCE_SOCKETS_NUMBER) { + return -1; + } + kmp_socket_if_t *socket_if = NULL; ns_list_foreach(kmp_socket_if_t, entry, &kmp_socket_if_list) { @@ -181,7 +203,26 @@ static int8_t kmp_socket_if_send(kmp_service_t *service, uint8_t instance_id, km *ptr = kmp_id; } - socket_sendto(socket_if->socket_id, &socket_if->remote_addr, pdu, size); + int8_t socket_id = -1; + if ((socket_if->socket_id_in_use & (1 << connection_num)) && socket_if->socket_id[connection_num] >= 0) { + socket_id = socket_if->socket_id[connection_num]; + } else { + if (socket_if->socket_id[connection_num] < 0) { + socket_if->socket_id[connection_num] = socket_open(IPV6_NH_UDP, 0, &kmp_socket_if_socket_cb); + } + if (socket_if->socket_id[connection_num] < 0) { + return -1; + } + socket_if->socket_id_in_use |= (1 << connection_num); + } + + socket_sendto(socket_id, &socket_if->remote_addr, pdu, size); + + // Deallocate unless flags deny it + if (flags & MSG_IF_SEND_FLAG_NO_DEALLOC) { + return 0; + } + ns_dyn_mem_free(pdu); return 0; @@ -196,11 +237,15 @@ static void kmp_socket_if_socket_cb(void *ptr) } kmp_socket_if_t *socket_if = NULL; + uint8_t connection_num = 0; ns_list_foreach(kmp_socket_if_t, entry, &kmp_socket_if_list) { - if (entry->socket_id == cb_data->socket_id) { - socket_if = entry; - break; + for (uint8_t socket_num = 0; socket_num < INSTANCE_SOCKETS_NUMBER; socket_num++) { + if (entry->socket_id[socket_num] == cb_data->socket_id) { + socket_if = entry; + connection_num = socket_num; + break; + } } } @@ -237,7 +282,7 @@ static void kmp_socket_if_socket_cb(void *ptr) cb_data->d_len -= SOCKET_IF_HEADER_SIZE; } - kmp_service_msg_if_receive(socket_if->kmp_service, socket_if->instance_id, type, &addr, data_ptr, cb_data->d_len); + kmp_service_msg_if_receive(socket_if->kmp_service, socket_if->instance_id, type, &addr, data_ptr, cb_data->d_len, connection_num); ns_dyn_mem_free(pdu); } diff --git a/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c b/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c index 1513f99cb0f..9592059724d 100644 --- a/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c +++ b/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.c @@ -177,7 +177,7 @@ uint8_t *eap_tls_sec_prot_lib_message_build(uint8_t eap_code, uint8_t eap_type, uint8_t *data_ptr = NULL; // Write EAP-TLS data (from EAP-TLS flags field onward) - if (tls_send->data) { + if (tls_send != NULL && tls_send->data) { data_ptr = eap_tls_sec_prot_lib_fragment_write(tls_send->data + TLS_HEAD_LEN, tls_send->total_len, tls_send->handled_len, &eap_len, flags); } @@ -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/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.h b/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.h index 285e617d643..6af3687869c 100644 --- a/source/Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.h +++ b/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 1100 //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/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c b/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c index 2c85d85378d..7018d56c98a 100644 --- a/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c +++ b/source/Security/protocols/eap_tls_sec_prot/radius_eap_tls_sec_prot.c @@ -65,20 +65,23 @@ typedef enum { // How many times initial EAPOL-key is accepted on wait for identity response state #define INITIAL_EAPOL_KEY_MAX_COUNT 2 +// How long to wait RADIUS client to proceed with handshake (RADIUS server to answer) +#define RADIUS_EAP_TLS_CLIENT_TIMEOUT 60 * 10 // 60 seconds + typedef struct { - sec_prot_common_t common; /**< Common data */ - sec_prot_t *radius_client_prot; /**< RADIUS client security protocol */ - sec_prot_receive *radius_client_send; /**< RADIUS client security protocol send (receive from peer) */ - eapol_pdu_t recv_eapol_pdu; /**< Received EAPOL PDU */ - tls_data_t tls_send; /**< EAP-TLS send buffer */ - uint16_t recv_eap_msg_len; /**< Received EAP message length */ - uint8_t *recv_eap_msg; /**< Received EAP message */ - uint16_t burst_filt_timer; /**< Burst filter timer */ - uint8_t eap_id_seq; /**< EAP sequence */ - uint8_t recv_eap_id_seq; /**< Last received EAP sequence */ - uint8_t eap_code; /**< Received EAP code */ - uint8_t eap_type; /**< Received EAP type */ - uint8_t init_key_cnt; /**< How many time initial EAPOL-key has been received */ + sec_prot_common_t common; /**< Common data */ + sec_prot_t *radius_client_prot; /**< RADIUS client security protocol */ + sec_prot_receive *radius_client_send; /**< RADIUS client security protocol send (receive from peer) */ + sec_prot_delete *radius_client_deleted; /**< RADIUS client security protocol peer deleted (notify to peer that radius EAP-TLS deleted) */ + eapol_pdu_t recv_eapol_pdu; /**< Received EAPOL PDU */ + uint16_t recv_eap_msg_len; /**< Received EAP message length */ + uint8_t *recv_eap_msg; /**< Received EAP message */ + uint16_t burst_filt_timer; /**< Burst filter timer */ + uint8_t eap_id_seq; /**< EAP sequence */ + uint8_t recv_eap_id_seq; /**< Last received EAP sequence */ + uint8_t eap_code; /**< Received EAP code */ + uint8_t eap_type; /**< Received EAP type */ + uint8_t init_key_cnt; /**< How many time initial EAPOL-key has been received */ } radius_eap_tls_sec_prot_int_t; static uint16_t radius_eap_tls_sec_prot_size(void); @@ -88,15 +91,18 @@ static void radius_eap_tls_sec_prot_create_request(sec_prot_t *prot, sec_prot_ke static void radius_eap_tls_sec_prot_delete(sec_prot_t *prot); static int8_t radius_eap_tls_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size); static int8_t radius_eap_tls_sec_prot_radius_client_receive(sec_prot_t *radius_client, void *pdu, uint16_t size); +static void radius_eap_tls_sec_prot_eap_tls_msg_free(sec_prot_t *prot); static int8_t radius_eap_tls_sec_prot_radius_eap_message_forward(sec_prot_t *prot, uint8_t *eap_code); +static int8_t radius_eap_tls_sec_prot_radius_eap_message_retry(sec_prot_t *prot); static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot); static int8_t radius_eap_tls_sec_prot_message_handle(sec_prot_t *prot, uint8_t *data_ptr, uint16_t *length); -static int8_t radius_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type, uint8_t tls_state); +static int8_t radius_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type); static void radius_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks); static int8_t radius_eap_tls_sec_prot_init_radius_client(sec_prot_t *prot); +static void radius_eap_tls_sec_prot_radius_client_deleted(sec_prot_t *prot); static void radius_eap_tls_sec_prot_seq_id_update(sec_prot_t *prot); @@ -126,6 +132,7 @@ static int8_t radius_eap_tls_sec_prot_init(sec_prot_t *prot) prot->create_resp = 0; prot->receive = radius_eap_tls_sec_prot_receive; prot->receive_peer = radius_eap_tls_sec_prot_radius_client_receive; + prot->peer_deleted = radius_eap_tls_sec_prot_radius_client_deleted; prot->delete = radius_eap_tls_sec_prot_delete; prot->state_machine = radius_eap_tls_sec_prot_state_machine; prot->timer_timeout = radius_eap_tls_sec_prot_timer_timeout; @@ -142,7 +149,6 @@ static int8_t radius_eap_tls_sec_prot_init(sec_prot_t *prot) data->recv_eap_id_seq = 0; data->eap_code = 0; data->eap_type = 0; - eap_tls_sec_prot_lib_message_init(&data->tls_send); data->init_key_cnt = 0; return 0; } @@ -150,7 +156,10 @@ static int8_t radius_eap_tls_sec_prot_init(sec_prot_t *prot) static void radius_eap_tls_sec_prot_delete(sec_prot_t *prot) { radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot); - eap_tls_sec_prot_lib_message_free(&data->tls_send); + + if (data->recv_eap_msg != NULL) { + ns_dyn_mem_free(data->recv_eap_msg); + } } static void radius_eap_tls_sec_prot_create_request(sec_prot_t *prot, sec_prot_keys_t *sec_keys) @@ -242,30 +251,13 @@ static int8_t radius_eap_tls_sec_prot_message_handle(sec_prot_t *prot, uint8_t * return EAP_TLS_MSG_CONTINUE; } -static int8_t radius_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type, uint8_t tls_state) +static int8_t radius_eap_tls_sec_prot_message_send(sec_prot_t *prot, uint8_t eap_code, uint8_t eap_type) { radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot); uint8_t flags = 0xff; - // EAP-TLS flags field is always present during TLS exchange - if (tls_state == EAP_TLS_EXCHANGE_ONGOING) { - flags = 0x00; - } - - if (eap_code == EAP_REQ) { - if (eap_type == EAP_TLS && tls_state == EAP_TLS_EXCHANGE_START) { - eap_tls_sec_prot_lib_message_allocate(&data->tls_send, TLS_HEAD_LEN, 0); - flags = EAP_TLS_START; - } - } else if (eap_code == EAP_SUCCESS || eap_code == EAP_FAILURE) { - // Send Success and Failure with same identifier as received in EAP Response - data->eap_id_seq = data->recv_eap_id_seq; - } else { - return -1; - } - uint16_t eapol_pdu_size; - uint8_t *eapol_decoded_data = eap_tls_sec_prot_lib_message_build(eap_code, eap_type, &flags, data->eap_id_seq, prot->header_size, &data->tls_send, &eapol_pdu_size); + uint8_t *eapol_decoded_data = eap_tls_sec_prot_lib_message_build(eap_code, eap_type, &flags, data->eap_id_seq, prot->header_size, NULL, &eapol_pdu_size); if (!eapol_decoded_data) { return -1; } @@ -327,7 +319,23 @@ static int8_t radius_eap_tls_sec_prot_radius_eap_message_forward(sec_prot_t *pro eap_type == EAP_IDENTITY ? "IDENTITY" : "TLS", data->eap_id_seq, flags, eapol_pdu_size, trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); - if (prot->send(prot, data->recv_eap_msg, eapol_pdu_size + prot->header_size) < 0) { + if (prot->conn_send(prot, data->recv_eap_msg, eapol_pdu_size + prot->header_size, 0, SEC_PROT_SEND_FLAG_NO_DEALLOC) < 0) { + return -1; + } + data->recv_eap_msg_len = eapol_pdu_size + prot->header_size; + + return 0; +} + +static int8_t radius_eap_tls_sec_prot_radius_eap_message_retry(sec_prot_t *prot) +{ + radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot); + + if (data->recv_eap_msg == NULL || data->recv_eap_msg_len == 0) { + return -1; + } + + if (prot->conn_send(prot, data->recv_eap_msg, data->recv_eap_msg_len, 0, SEC_PROT_SEND_FLAG_NO_DEALLOC) < 0) { return -1; } @@ -357,6 +365,10 @@ static int8_t radius_eap_tls_sec_prot_radius_client_receive(sec_prot_t *radius_c radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot); + if (data->recv_eap_msg != NULL) { + ns_dyn_mem_free(data->recv_eap_msg); + } + data->recv_eap_msg_len = size; data->recv_eap_msg = pdu; @@ -365,6 +377,18 @@ static int8_t radius_eap_tls_sec_prot_radius_client_receive(sec_prot_t *radius_c return 0; } +static void radius_eap_tls_sec_prot_eap_tls_msg_free(sec_prot_t *prot) +{ + radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot); + + if (data->recv_eap_msg != NULL) { + ns_dyn_mem_free(data->recv_eap_msg); + } + + data->recv_eap_msg = NULL; + data->recv_eap_msg_len = 0; +} + static int8_t radius_eap_tls_sec_prot_init_radius_client(sec_prot_t *prot) { radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot); @@ -377,10 +401,22 @@ static int8_t radius_eap_tls_sec_prot_init_radius_client(sec_prot_t *prot) return -1; } data->radius_client_send = data->radius_client_prot->receive_peer; + data->radius_client_deleted = data->radius_client_prot->peer_deleted; return 0; } +static void radius_eap_tls_sec_prot_radius_client_deleted(sec_prot_t *prot) +{ + radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot); + + tr_debug("EAP-TLS: client deleted"); + + data->radius_client_prot = NULL; + data->radius_client_send = NULL; + data->radius_client_deleted = NULL; +} + static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot) { radius_eap_tls_sec_prot_int_t *data = eap_tls_sec_prot_get(prot); @@ -390,14 +426,14 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot) // EAP-TLS authenticator state machine switch (sec_prot_state_get(&data->common)) { case EAP_TLS_STATE_INIT: - tr_info("EAP-TLS init"); + tr_info("EAP-TLS: init"); sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_CREATE_REQ); prot->timer_start(prot); break; // Wait KMP-CREATE.request case EAP_TLS_STATE_CREATE_REQ: - tr_info("EAP-TLS start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + tr_info("EAP-TLS: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); // Set default timeout for the total maximum length of the negotiation sec_prot_default_timeout_set(&data->common); @@ -409,7 +445,7 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot) radius_eap_tls_sec_prot_seq_id_update(prot); // Sends EAP request, Identity - radius_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE); + radius_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY); // Start trickle timer to re-send if no response sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params); @@ -423,7 +459,7 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot) // On timeout if (sec_prot_result_timeout_check(&data->common)) { // Re-sends EAP request, Identity - radius_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE); + radius_eap_tls_sec_prot_message_send(prot, EAP_REQ, EAP_IDENTITY); return; } @@ -432,13 +468,22 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot) return; } - tr_info("EAP-TLS EAP response id, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + tr_info("EAP-TLS: EAP response id, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); if (radius_eap_tls_sec_prot_init_radius_client(prot) < 0) { tr_error("EAP-TLS: radius client init failed"); return; } + // Free EAP request buffer since answer received and retries not needed + radius_eap_tls_sec_prot_eap_tls_msg_free(prot); + + // Stop trickle timer, radius client will continue + sec_prot_timer_trickle_stop(&data->common); + + // Set timeout to wait for RADIUS client to continue + data->common.ticks = RADIUS_EAP_TLS_CLIENT_TIMEOUT; + // Send to radius client data->radius_client_send(data->radius_client_prot, (void *) &data->recv_eapol_pdu, length); @@ -450,11 +495,11 @@ 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; } - tr_info("EAP-TLS EAP request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + tr_info("EAP-TLS: EAP request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); uint8_t eap_code; if (radius_eap_tls_sec_prot_radius_eap_message_forward(prot, &eap_code) < 0) { @@ -470,6 +515,9 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot) sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_FINISH); } + // Start trickle timer to re-send if no response + sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params); + sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_EAP_RESPONSE); break; @@ -478,17 +526,29 @@ 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 + tr_debug("EAP-TLS: retry EAP request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + if (radius_eap_tls_sec_prot_radius_eap_message_retry(prot) < 0) { + tr_error("EAP-TLS: retry msg send error"); + } return; } - tr_info("EAP-TLS EAP response, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + tr_info("EAP-TLS: EAP response, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); // Handle EAP response if (radius_eap_tls_sec_prot_message_handle(prot, data_ptr, &length) != EAP_TLS_MSG_CONTINUE) { return; } + // Free EAP request buffer since answer received and retries not needed + radius_eap_tls_sec_prot_eap_tls_msg_free(prot); + + // Stop trickle timer, radius client will continue + sec_prot_timer_trickle_stop(&data->common); + + // Set timeout to wait for RADIUS client to continue + data->common.ticks = RADIUS_EAP_TLS_CLIENT_TIMEOUT; + // Send to radius client data->radius_client_send(data->radius_client_prot, (void *) &data->recv_eapol_pdu, length); @@ -507,6 +567,12 @@ static void radius_eap_tls_sec_prot_state_machine(sec_prot_t *prot) case EAP_TLS_STATE_FINISHED: { uint8_t *remote_eui_64 = sec_prot_remote_eui_64_addr_get(prot); tr_info("EAP-TLS finished, eui-64: %s", remote_eui_64 ? trace_array(sec_prot_remote_eui_64_addr_get(prot), 8) : "not set"); + + // Indicate to radius client peer protocol that radius EAP-TLS has been deleted + if (data->radius_client_deleted) { + data->radius_client_deleted(data->radius_client_prot); + } + prot->timer_stop(prot); prot->finished(prot); break; diff --git a/source/Security/protocols/radius_sec_prot/avp_helper.h b/source/Security/protocols/radius_sec_prot/avp_helper.h index 1fdd5bb54e3..8687a112fa4 100644 --- a/source/Security/protocols/radius_sec_prot/avp_helper.h +++ b/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/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c b/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c index a181cf0dd3c..a8dc175b7b8 100644 --- a/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c +++ b/source/Security/protocols/radius_sec_prot/radius_client_sec_prot.c @@ -75,12 +75,17 @@ typedef enum { #define MS_MPPE_RECV_KEY_SALT_LEN 2 #define MS_MPPE_RECV_KEY_BLOCK_LEN 16 +#define RADIUS_CONN_NUMBER 3 +#define RADIUS_ID_RANGE_SIZE 10 +#define RADIUS_ID_RANGE_NUM (255 / RADIUS_ID_RANGE_SIZE) - 1 + typedef struct radius_client_sec_prot_lib_int_s radius_client_sec_prot_lib_int_t; typedef struct { sec_prot_common_t common; /**< Common data */ sec_prot_t *radius_eap_tls_prot; /**< Radius EAP-TLS security protocol */ sec_prot_receive *radius_eap_tls_send; /**< Radius EAP-TLS security protocol send (receive from peer) */ + sec_prot_delete *radius_eap_tls_deleted; /**< Radius EAP-TLS security protocol peer deleted (notify to peer that radius client deleted) */ uint8_t radius_eap_tls_header_size; /**< Radius EAP-TLS header size */ uint8_t new_pmk[PMK_LEN]; /**< New Pair Wise Master Key */ uint16_t recv_eap_msg_len; /**< Received EAP message length */ @@ -91,34 +96,46 @@ typedef struct { uint8_t *identity; /**< Supplicant EAP identity */ uint8_t radius_code; /**< Radius code that was received */ uint8_t radius_identifier; /**< Radius identifier that was last sent */ + uint8_t radius_id_conn_num; /**< Radius identifier connection number (socket instance) */ + uint8_t radius_id_range; /**< Radius identifier range */ uint8_t request_authenticator[16]; /**< Radius request authenticator that was last sent */ uint8_t state_len; /**< Radius state length that was last received */ uint8_t *state; /**< Radius state that was last received */ uint8_t remote_eui_64_hash[8]; /**< Remote EUI-64 hash used for calling station id */ bool remote_eui_64_hash_set : 1; /**< Remote EUI-64 hash used for calling station id set */ bool new_pmk_set : 1; /**< New Pair Wise Master Key set */ + bool radius_id_range_set : 1; /**< Radius identifier start value set */ } radius_client_sec_prot_int_t; typedef struct { - uint8_t radius_client_identifier; /**< Radius client identifier */ + uint8_t radius_identifier_timer[RADIUS_CONN_NUMBER][RADIUS_ID_RANGE_NUM]; + shared_comp_data_t comp_data; /**< Shared component data (timer, delete) */ uint8_t local_eui64_hash[8]; /**< Local EUI-64 hash used for called stations id */ uint8_t hash_random[16]; /**< Random used to generate local and remote EUI-64 hashes */ bool local_eui64_hash_set : 1; /**< Local EUI-64 hash used for called stations id set */ bool hash_random_set : 1; /**< Random used to generate local and remote EUI-64 hashes set */ + bool radius_id_timer_running : 1; /**> Radius identifier timer running */ } radius_client_sec_prot_shared_t; static uint16_t radius_client_sec_prot_size(void); static int8_t radius_client_sec_prot_init(sec_prot_t *prot); +static int8_t radius_client_sec_prot_shared_data_timeout(uint16_t ticks); +static void radius_identifier_timer_value_set(uint8_t conn_num, uint8_t id_range, uint8_t value); +static int8_t radius_client_sec_prot_shared_data_delete(void); +static void radius_identifier_timer_value_set(uint8_t conn_num, uint8_t id_range, uint8_t value); static void radius_client_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result); static void radius_client_sec_prot_delete(sec_prot_t *prot); static int8_t radius_client_sec_prot_receive_check(sec_prot_t *prot, const void *pdu, uint16_t size); static int8_t radius_client_sec_prot_init_radius_eap_tls(sec_prot_t *prot); +static void radius_client_sec_prot_radius_eap_tls_deleted(sec_prot_t *prot); static uint16_t radius_client_sec_prot_eap_avps_handle(uint16_t avp_length, uint8_t *avp_ptr, uint8_t *copy_to_ptr); -static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size); +static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number); static int8_t radius_client_sec_prot_radius_eap_receive(sec_prot_t *prot, void *pdu, uint16_t size); static void radius_client_sec_prot_allocate_and_create_radius_message(sec_prot_t *prot); static int8_t radius_client_sec_prot_radius_msg_send(sec_prot_t *prot); -static uint8_t radius_client_sec_prot_identifier_allocate(void); +static void radius_client_sec_prot_radius_msg_free(sec_prot_t *prot); +static uint8_t radius_client_sec_prot_identifier_allocate(sec_prot_t *prot, uint8_t value); +static void radius_client_sec_prot_identifier_free(sec_prot_t *prot); static uint8_t radius_client_sec_prot_hex_to_ascii(uint8_t value); static int8_t radius_client_sec_prot_eui_64_hash_generate(uint8_t *eui_64, uint8_t *hashed_eui_64); static void radius_client_sec_prot_station_id_generate(uint8_t *eui_64, uint8_t *station_id_ptr); @@ -152,12 +169,55 @@ static uint16_t radius_client_sec_prot_size(void) return sizeof(radius_client_sec_prot_int_t); } +static int8_t radius_client_sec_prot_shared_data_timeout(uint16_t ticks) +{ + if (shared_data == NULL || !shared_data->radius_id_timer_running) { + return -1; + } + + bool timer_running = false; + + for (uint8_t conn_num = 0; conn_num < RADIUS_CONN_NUMBER; conn_num++) { + for (uint8_t id_range = 0; id_range < RADIUS_ID_RANGE_NUM; id_range++) { + if (shared_data->radius_identifier_timer[conn_num][id_range] > ticks) { + shared_data->radius_identifier_timer[conn_num][id_range] -= ticks; + timer_running = true; + } else { + shared_data->radius_identifier_timer[conn_num][id_range] = 0; + } + } + } + + if (!timer_running) { + shared_data->radius_id_timer_running = false; + } + + return 0; +} + +static void radius_identifier_timer_value_set(uint8_t conn_num, uint8_t id_range, uint8_t value) +{ + shared_data->radius_identifier_timer[conn_num][id_range] = value; + shared_data->radius_id_timer_running = true; +} + +static int8_t radius_client_sec_prot_shared_data_delete(void) +{ + if (shared_data == NULL) { + return -1; + } + ns_dyn_mem_free(shared_data); + shared_data = NULL; + return 0; +} + static int8_t radius_client_sec_prot_init(sec_prot_t *prot) { prot->create_req = NULL; prot->create_resp = radius_client_sec_prot_create_response; - prot->receive = radius_client_sec_prot_receive; + prot->conn_receive = radius_client_sec_prot_receive; prot->receive_peer = radius_client_sec_prot_radius_eap_receive; + prot->peer_deleted = radius_client_sec_prot_radius_eap_tls_deleted; prot->delete = radius_client_sec_prot_delete; prot->state_machine = radius_client_sec_prot_state_machine; prot->timer_timeout = radius_client_sec_prot_timer_timeout; @@ -192,11 +252,14 @@ static int8_t radius_client_sec_prot_init(sec_prot_t *prot) if (!shared_data) { return -1; } - shared_data->radius_client_identifier = 0; - memset(shared_data->local_eui64_hash, 0, 8); - memset(shared_data->hash_random, 0, 16); + memset(shared_data, 0, sizeof(radius_client_sec_prot_shared_t)); shared_data->local_eui64_hash_set = false; shared_data->hash_random_set = false; + shared_data->radius_id_timer_running = false; + // Add as shared component to enable timers and delete + shared_data->comp_data.timeout = radius_client_sec_prot_shared_data_timeout; + shared_data->comp_data.delete = radius_client_sec_prot_shared_data_delete; + prot->shared_comp_add(prot, &shared_data->comp_data); } return 0; @@ -256,10 +319,22 @@ static int8_t radius_client_sec_prot_init_radius_eap_tls(sec_prot_t *prot) } data->radius_eap_tls_header_size = data->radius_eap_tls_prot->receive_peer_hdr_size; data->radius_eap_tls_send = data->radius_eap_tls_prot->receive_peer; + data->radius_eap_tls_deleted = data->radius_eap_tls_prot->peer_deleted; return 0; } +static void radius_client_sec_prot_radius_eap_tls_deleted(sec_prot_t *prot) +{ + radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot); + + tr_info("Radius: EAP-TLS deleted"); + + data->radius_eap_tls_prot = NULL; + data->radius_eap_tls_send = NULL; + data->radius_eap_tls_deleted = NULL; +} + static uint16_t radius_client_sec_prot_eap_avps_handle(uint16_t avp_length, uint8_t *avp_ptr, uint8_t *copy_to_ptr) { // Calculate EAP AVPs length and copy EAP AVPs to continuous buffer if buffer is give @@ -290,8 +365,10 @@ static uint16_t radius_client_sec_prot_eap_avps_handle(uint16_t avp_length, uint return eap_len; } -static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size) +static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number) { + (void) conn_number; + radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot); if (size < RADIUS_MSG_FIXED_LENGTH) { @@ -312,6 +389,10 @@ static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16 uint16_t length = common_read_16_bit(radius_msg_ptr); radius_msg_ptr += 2; + if (length < RADIUS_MSG_FIXED_LENGTH) { + return -1; + } + // Store response authenticator uint8_t recv_response_authenticator[16]; memcpy(recv_response_authenticator, radius_msg_ptr, 16); @@ -333,11 +414,23 @@ static int8_t radius_client_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16 return -1; } - uint16_t avp_length = length - RADIUS_MSG_FIXED_LENGTH; + // Response authenticator matches, start validating radius EAP-TLS specific fields + data->recv_eap_msg = NULL; + data->recv_eap_msg_len = 0; + + uint16_t avp_length = 0; + if (length >= RADIUS_MSG_FIXED_LENGTH) { + avp_length = length - RADIUS_MSG_FIXED_LENGTH; + } uint8_t *message_authenticator = avp_message_authenticator_read(radius_msg_ptr, avp_length); - if (message_authenticator == NULL) { + if (message_authenticator == NULL || avp_length == 0) { tr_error("No message authenticator"); + // Message does not have radius EAP-TLS specific fields + data->radius_code = code; + prot->state_machine(prot); + + return 0; } // Store message authenticator @@ -415,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 } } } @@ -442,9 +537,43 @@ static int8_t radius_client_sec_prot_radius_eap_receive(sec_prot_t *prot, void * return 0; } -static uint8_t radius_client_sec_prot_identifier_allocate(void) +static uint8_t radius_client_sec_prot_identifier_allocate(sec_prot_t *prot, uint8_t value) +{ + radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot); + + if (!data->radius_id_range_set || value >= (data->radius_id_range * RADIUS_ID_RANGE_SIZE) + RADIUS_ID_RANGE_SIZE) { + for (uint8_t conn_num = 0; conn_num < RADIUS_CONN_NUMBER; conn_num++) { + for (uint8_t id_range = 0; id_range < RADIUS_ID_RANGE_NUM; id_range++) { + if (shared_data->radius_identifier_timer[conn_num][id_range] == 0) { + // If range has been already reserved + if (data->radius_id_range_set) { + // Set previous range to timeout in 5 seconds + radius_identifier_timer_value_set(data->radius_id_conn_num, data->radius_id_range, 5); + } + // Set timeout for new range to 60 seconds + radius_identifier_timer_value_set(conn_num, id_range, 60); + data->radius_id_conn_num = conn_num; + data->radius_id_range = id_range; + data->radius_id_range_set = true; + return id_range * RADIUS_ID_RANGE_SIZE; + } + } + } + } else { + radius_identifier_timer_value_set(data->radius_id_conn_num, data->radius_id_range, 60); + return value + 1; + } + + return 0; +} + +static void radius_client_sec_prot_identifier_free(sec_prot_t *prot) { - return shared_data->radius_client_identifier++; + radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot); + + if (data->radius_id_range_set) { + radius_identifier_timer_value_set(data->radius_id_conn_num, data->radius_id_range, 5); + } } static uint8_t radius_client_sec_prot_eui_64_hash_get(sec_prot_t *prot, uint8_t *local_eui_64_hash, uint8_t *remote_eui_64_hash, bool remote_eui_64_hash_set) @@ -524,7 +653,7 @@ static void radius_client_sec_prot_allocate_and_create_radius_message(sec_prot_t uint8_t *radius_msg_start_ptr = radius_msg_ptr; *radius_msg_ptr++ = RADIUS_ACCESS_REQUEST; // code - data->radius_identifier = radius_client_sec_prot_identifier_allocate(); + data->radius_identifier = radius_client_sec_prot_identifier_allocate(prot, data->radius_identifier); *radius_msg_ptr++ = data->radius_identifier; // identifier radius_msg_ptr = common_write_16_bit(radius_msg_length, radius_msg_ptr); // length @@ -604,15 +733,25 @@ static int8_t radius_client_sec_prot_radius_msg_send(sec_prot_t *prot) return -1; } - if (prot->send(prot, data->send_radius_msg, data->send_radius_msg_len) < 0) { + if (prot->conn_send(prot, data->send_radius_msg, data->send_radius_msg_len, data->radius_id_conn_num, SEC_PROT_SEND_FLAG_NO_DEALLOC) < 0) { return -1; } - data->send_radius_msg = NULL; - data->send_radius_msg_len = 0; return 0; } +static void radius_client_sec_prot_radius_msg_free(sec_prot_t *prot) +{ + radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot); + + if (data->send_radius_msg != NULL) { + ns_dyn_mem_free(data->send_radius_msg); + } + + data->send_radius_msg = NULL; + data->send_radius_msg_len = 0; +} + static int8_t radius_client_sec_prot_eui_64_hash_generate(uint8_t *eui_64, uint8_t *hashed_eui_64) { int8_t ret_val = 0; @@ -678,12 +817,13 @@ static void radius_client_sec_prot_station_id_generate(uint8_t *eui_64, uint8_t static int8_t radius_client_sec_prot_message_authenticator_calc(sec_prot_t *prot, uint16_t msg_len, uint8_t *msg_ptr, uint8_t *auth_ptr) { - const uint8_t *key = prot->sec_cfg->radius_cfg.radius_shared_secret; - uint16_t key_len = prot->sec_cfg->radius_cfg.radius_shared_secret_len; - if (prot->sec_cfg->radius_cfg.radius_shared_secret_len == 0) { + if (prot->sec_cfg->radius_cfg->radius_shared_secret == NULL || prot->sec_cfg->radius_cfg->radius_shared_secret_len == 0) { return -1; } + const uint8_t *key = prot->sec_cfg->radius_cfg->radius_shared_secret; + uint16_t key_len = prot->sec_cfg->radius_cfg->radius_shared_secret_len; + #ifndef MBEDTLS_MD5_C tr_error("FATAL: MD5 MBEDTLS_MD5_C not enabled"); #endif @@ -698,9 +838,13 @@ static int8_t radius_client_sec_prot_message_authenticator_calc(sec_prot_t *prot static int8_t radius_client_sec_prot_response_authenticator_calc(sec_prot_t *prot, uint16_t msg_len, uint8_t *msg_ptr, uint8_t *auth_ptr) { #ifdef MBEDTLS_MD5_C - const uint8_t *key = prot->sec_cfg->radius_cfg.radius_shared_secret; - uint16_t key_len = prot->sec_cfg->radius_cfg.radius_shared_secret_len; - if (prot->sec_cfg->radius_cfg.radius_shared_secret_len == 0) { + if (prot->sec_cfg->radius_cfg->radius_shared_secret == NULL || prot->sec_cfg->radius_cfg->radius_shared_secret_len == 0) { + return -1; + } + + const uint8_t *key = prot->sec_cfg->radius_cfg->radius_shared_secret; + uint16_t key_len = prot->sec_cfg->radius_cfg->radius_shared_secret_len; + if (prot->sec_cfg->radius_cfg->radius_shared_secret_len == 0) { return -1; } @@ -747,9 +891,13 @@ static int8_t radius_client_sec_prot_response_authenticator_calc(sec_prot_t *pro static int8_t radius_client_sec_prot_ms_mppe_recv_key_pmk_decrypt(sec_prot_t *prot, uint8_t *recv_key, uint8_t recv_key_len, uint8_t *request_authenticator, uint8_t *pmk_ptr) { #ifdef MBEDTLS_MD5_C - const uint8_t *key = prot->sec_cfg->radius_cfg.radius_shared_secret; - uint16_t key_len = prot->sec_cfg->radius_cfg.radius_shared_secret_len; - if (prot->sec_cfg->radius_cfg.radius_shared_secret_len == 0) { + if (prot->sec_cfg->radius_cfg->radius_shared_secret == NULL || prot->sec_cfg->radius_cfg->radius_shared_secret_len == 0) { + return -1; + } + + const uint8_t *key = prot->sec_cfg->radius_cfg->radius_shared_secret; + uint16_t key_len = prot->sec_cfg->radius_cfg->radius_shared_secret_len; + if (prot->sec_cfg->radius_cfg->radius_shared_secret_len == 0) { return -1; } @@ -852,8 +1000,7 @@ static void radius_client_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t tick { radius_client_sec_prot_int_t *data = radius_client_sec_prot_get(prot); - sec_prot_timer_timeout_handle(prot, &data->common, - &prot->sec_cfg->prot_cfg.sec_prot_trickle_params, ticks); + sec_prot_timer_timeout_handle(prot, &data->common, &prot->sec_cfg->radius_cfg->radius_retry_trickle_params, ticks); } static void radius_client_sec_prot_state_machine(sec_prot_t *prot) @@ -862,14 +1009,14 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot) switch (sec_prot_state_get(&data->common)) { case RADIUS_STATE_INIT: - tr_debug("Radius: init"); + tr_info("Radius: init"); sec_prot_state_set(prot, &data->common, RADIUS_STATE_STATE_RESPONSE_ID); prot->timer_start(prot); break; // Wait EAP response, Identity (starts RADIUS Client protocol) case RADIUS_STATE_STATE_RESPONSE_ID: - tr_debug("Radius: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + tr_info("Radius: start, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); // Set default timeout for the total maximum length of the negotiation sec_prot_default_timeout_set(&data->common); @@ -899,14 +1046,14 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot) break; case RADIUS_STATE_SEND_INITIAL_ACCESS_REQUEST: - tr_debug("Radius: send initial access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + tr_info("Radius: send initial access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); if (radius_client_sec_prot_radius_msg_send(prot) < 0) { tr_error("Radius: msg send error"); } // Start trickle timer to re-send if no response - sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->prot_cfg.sec_prot_trickle_params); + sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->radius_cfg->radius_retry_trickle_params); sec_prot_state_set(prot, &data->common, RADIUS_STATE_ACCESS_ACCEPT_REJECT_CHALLENGE); break; @@ -915,14 +1062,32 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot) // On timeout if (sec_prot_result_timeout_check(&data->common)) { - // Do nothing for now + tr_info("Radius: retry access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + if (radius_client_sec_prot_radius_msg_send(prot) < 0) { + tr_error("Radius: retry msg send error"); + } return; } - tr_debug("Radius: received access accept/reject/challenge, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + tr_info("Radius: received access accept/reject/challenge, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + + // Free radius access-request buffer since answer received and retries not needed + radius_client_sec_prot_radius_msg_free(prot); + + // Stop trickle timer, EAP-TLS will continue and on reject/accept negotiation will end + sec_prot_timer_trickle_stop(&data->common); + + // Set timeout to wait for EAP-TLS to continue + data->common.ticks = prot->sec_cfg->prot_cfg.sec_prot_retry_timeout; // Send to radius EAP-TLS - data->radius_eap_tls_send(data->radius_eap_tls_prot, (void *) data->recv_eap_msg, data->recv_eap_msg_len); + if (data->radius_eap_tls_send && data->radius_eap_tls_prot && data->recv_eap_msg && data->recv_eap_msg_len > 0) { + data->radius_eap_tls_send(data->radius_eap_tls_prot, (void *) data->recv_eap_msg, data->recv_eap_msg_len); + } else { + if (data->recv_eap_msg) { + ns_dyn_mem_free(data->recv_eap_msg); + } + } data->recv_eap_msg = NULL; data->recv_eap_msg_len = 0; @@ -945,11 +1110,14 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot) // On timeout if (sec_prot_result_timeout_check(&data->common)) { - // Do nothing for now + tr_info("Radius: retry access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + if (radius_client_sec_prot_radius_msg_send(prot) < 0) { + tr_error("Radius: retry msg send error"); + } return; } - tr_debug("Radius: send access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + tr_info("Radius: send access request, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); radius_client_sec_prot_allocate_and_create_radius_message(prot); @@ -957,11 +1125,14 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot) tr_error("Radius: msg send error"); } + // Start trickle timer to re-send if no response + sec_prot_timer_trickle_start(&data->common, &prot->sec_cfg->radius_cfg->radius_retry_trickle_params); + sec_prot_state_set(prot, &data->common, RADIUS_STATE_ACCESS_ACCEPT_REJECT_CHALLENGE); break; case RADIUS_STATE_FINISH: - tr_debug("Radius: finish, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); + tr_info("Radius: finish, eui-64: %s", trace_array(sec_prot_remote_eui_64_addr_get(prot), 8)); if (sec_prot_result_ok_check(&data->common)) { sec_prot_keys_pmk_write(prot->sec_keys, data->new_pmk, prot->sec_cfg->timer_cfg.pmk_lifetime); @@ -980,7 +1151,14 @@ static void radius_client_sec_prot_state_machine(sec_prot_t *prot) case RADIUS_STATE_FINISHED: { uint8_t *remote_eui_64 = sec_prot_remote_eui_64_addr_get(prot); - tr_debug("Radius: finished, eui-64: %s", remote_eui_64 ? trace_array(remote_eui_64, 8) : "not set"); + tr_info("Radius: finished, eui-64: %s", remote_eui_64 ? trace_array(remote_eui_64, 8) : "not set"); + + radius_client_sec_prot_identifier_free(prot); + + // Indicate to radius EAP-TLS peer protocol that radius client has been deleted + if (data->radius_eap_tls_deleted) { + data->radius_eap_tls_deleted(data->radius_eap_tls_prot); + } prot->timer_stop(prot); prot->finished(prot); diff --git a/source/Security/protocols/sec_prot.h b/source/Security/protocols/sec_prot.h index 3c7724124ee..565ad5148a5 100644 --- a/source/Security/protocols/sec_prot.h +++ b/source/Security/protocols/sec_prot.h @@ -61,6 +61,9 @@ typedef enum { SEC_PROT_TX_ERR_UNSPEC = -2, // Other reason } sec_prot_tx_status_e; +// On security protocol send, do not deallocate pdu buffer +#define SEC_PROT_SEND_FLAG_NO_DEALLOC 0x01 + /** * sec_prot_create_request KMP-CREATE.request to security protocol * @@ -128,6 +131,7 @@ typedef void sec_prot_finished_send(sec_prot_t *prot); * \param prot protocol * \param pdu pdu * \param size pdu size + * \param conn_number connection number * * \return < 0 failure * \return >= 0 success @@ -148,6 +152,35 @@ typedef int8_t sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size); */ typedef int8_t sec_prot_send(sec_prot_t *prot, void *pdu, uint16_t size); +/** + * sec_prot_conn_receive receive a message for a connection number + * + * \param prot protocol + * \param pdu pdu + * \param size pdu size + * \param conn_number connection number + * + * \return < 0 failure + * \return >= 0 success + * + */ +typedef int8_t sec_prot_conn_receive(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number); + +/** + * sec_prot_conn_send send a message for a connection number and/or with flags + * + * \param prot protocol + * \param pdu pdu + * \param size pdu size + * \param conn_number connection number + * \param flags flags + * + * \return < 0 failure + * \return >= 0 success + * + */ +typedef int8_t sec_prot_conn_send(sec_prot_t *prot, void *pdu, uint16_t size, uint8_t conn_number, uint8_t flags); + /** * sec_prot_tx_status_ind tx status indication * @@ -184,6 +217,14 @@ typedef void sec_prot_state_machine(sec_prot_t *prot); */ typedef void sec_prot_state_machine_call(sec_prot_t *prot); +/** + * sec_prot_cont_timer_timeout cont timer timeout + * + * \param ticks timer ticks + * + */ +typedef void sec_prot_cont_timer_timeout(uint16_t ticks); + /** * sec_prot_timer_start start timer * @@ -209,6 +250,55 @@ typedef void sec_prot_timer_stop(sec_prot_t *prot); */ typedef void sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks); +/** + * sec_prot_shared_comp_timer_timeout shared component timer timeout + * + * \param ticks timer ticks + * + * \return < 0 failure + * \return >= 0 success + * + */ +typedef int8_t sec_prot_shared_comp_timer_timeout(uint16_t ticks); + +/** + * sec_prot_shared_comp_delete shared component delete + * + * \return < 0 failure + * \return >= 0 success + * + */ +typedef int8_t sec_prot_shared_comp_delete(void); + +typedef struct { + sec_prot_shared_comp_timer_timeout *timeout; + sec_prot_shared_comp_delete *delete; +} shared_comp_data_t; + +/** + * sec_prot_shared_comp_add add shared component + * + * \param prot protocol + * \param data shared component data + * + * \return < 0 failure + * \return >= 0 success + * + */ +typedef int8_t sec_prot_shared_comp_add(sec_prot_t *prot, shared_comp_data_t *data); + +/** + * sec_prot_shared_comp_remove remove shared component + * + * \param prot protocol + * \param data shared component data + * + * \return < 0 failure + * \return >= 0 success + * + */ +typedef int8_t sec_prot_shared_comp_remove(sec_prot_t *prot, shared_comp_data_t *data); + /** * sec_prot_eui64_addr_get gets EUI-64 addresses * @@ -277,7 +367,10 @@ struct sec_prot_s { sec_prot_send *send; /**< Protocol send */ sec_prot_receive *receive; /**< Protocol receive */ + sec_prot_conn_send *conn_send; /**< Protocol connection send */ + sec_prot_conn_receive *conn_receive; /**< Protocol connection receive */ sec_prot_receive *receive_peer; /**< Protocol receive from peer (used by peer protocol for send) */ + sec_prot_delete *peer_deleted; /**< Protocol peer has been deleted (notifies that peer no longer exists */ sec_prot_tx_status_ind *tx_status_ind; /**< TX status indication */ @@ -290,6 +383,9 @@ struct sec_prot_s { sec_prot_timer_stop *timer_stop; /**< Stop timer */ sec_prot_timer_timeout *timer_timeout; /**< Timer timeout */ + sec_prot_shared_comp_add *shared_comp_add; /**< Shared component add */ + sec_prot_shared_comp_remove *shared_comp_remove; /**< Shared component remove */ + sec_prot_eui64_addr_get *addr_get; /**< Gets EUI-64 addresses */ sec_prot_ip_addr_get *ip_addr_get; /**< Gets IP address */ sec_prot_by_type_get *type_get; /**< Gets security protocol by type */ @@ -300,6 +396,7 @@ struct sec_prot_s { sec_cfg_t *sec_cfg; /**< Security configuration configuration pointer */ uint8_t header_size; /**< Header size */ uint8_t receive_peer_hdr_size; /**< Receive from peer header size */ + uint8_t number_of_conn; /**< Number of connections */ uint8_t msg_if_instance_id; /**< Message interface instance identifier */ sec_prot_int_data_t *data; /**< Protocol internal data */ }; diff --git a/source/Security/protocols/sec_prot_cfg.h b/source/Security/protocols/sec_prot_cfg.h index b7bed75d1fc..dd75e2c226d 100644 --- a/source/Security/protocols/sec_prot_cfg.h +++ b/source/Security/protocols/sec_prot_cfg.h @@ -47,15 +47,16 @@ typedef struct sec_timer_cfg_s { typedef struct sec_radius_cfg_s { uint8_t radius_addr[16]; /**< Radius server IPv6 address */ - uint8_t *radius_shared_secret; /**< Radius shared secret */ + const uint8_t *radius_shared_secret; /**< Radius shared secret */ uint16_t radius_shared_secret_len; /**< Radius shared secret length */ + trickle_params_t radius_retry_trickle_params; /**< Radius retry trickle params */ bool radius_addr_set : 1; /**< Radius server address is set */ } sec_radius_cfg_t; typedef struct sec_cfg_s { sec_prot_cfg_t prot_cfg; sec_timer_cfg_t timer_cfg; - sec_radius_cfg_t radius_cfg; + sec_radius_cfg_t *radius_cfg; } sec_cfg_t; #endif /* SEC_PROT_CONF_H_ */ diff --git a/source/Service_Libs/fhss/fhss_ws.c b/source/Service_Libs/fhss/fhss_ws.c index d37ff27a77f..78cb5154d57 100644 --- a/source/Service_Libs/fhss/fhss_ws.c +++ b/source/Service_Libs/fhss/fhss_ws.c @@ -419,7 +419,7 @@ static uint32_t fhss_ws_calculate_ufsi(fhss_structure_t *fhss_structure, uint32_ cur_slot--; uint32_t remaining_time_ms = 0; if (fhss_structure->ws->unicast_timer_running == true) { - remaining_time_ms = US_TO_MS(get_remaining_slots_us(fhss_structure, fhss_unicast_handler, MS_TO_US(dwell_time) - NS_TO_US(dwell_time * fhss_structure->ws->drift_per_millisecond_ns))); + remaining_time_ms = US_TO_MS(get_remaining_slots_us(fhss_structure, fhss_unicast_handler, MS_TO_US(dwell_time) - NS_TO_US((int64_t)(fhss_structure->ws->drift_per_millisecond_ns * dwell_time)))); } uint32_t time_to_tx = 0; uint32_t cur_time = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api); @@ -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; @@ -980,7 +980,6 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], if (fhss_structure->ws->fhss_configuration.ws_bc_channel_function == WS_TR51CF) { fhss_structure->ws->bc_slot %= fhss_structure->number_of_channels; } - platform_exit_critical(); //TODO: support multiple parents fhss_structure->ws->parent_bc_info = bc_timing_info; if (prev_synchronization_time && fhss_structure->ws->fhss_configuration.ws_bc_channel_function != WS_FIXED_CHANNEL) { @@ -993,11 +992,15 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8], } else if (drift_per_ms_tmp < -MAX_DRIFT_COMPENSATION_STEP) { drift_per_ms_tmp = -MAX_DRIFT_COMPENSATION_STEP; } + // Timer drift is unpredictable with linux platform. Do not set drift compensation +#ifndef __linux__ fhss_structure->ws->drift_per_millisecond_ns += drift_per_ms_tmp; +#endif fhss_stats_update(fhss_structure, STATS_FHSS_DRIFT_COMP, NS_TO_US((int64_t)(fhss_structure->ws->drift_per_millisecond_ns * bc_timing_info->broadcast_dwell_interval))); } tr_debug("synch to parent: %s, drift: %"PRIi32"ms in %"PRIu64" seconds, compensation: %"PRIi32"ns per ms", trace_array(eui64, 8), true_bc_interval_offset - own_bc_interval_offset + ((int32_t)(fhss_structure->ws->bc_slot - own_bc_slot) * bc_timing_info->broadcast_interval), US_TO_S(time_since_last_synch_us), fhss_structure->ws->drift_per_millisecond_ns); } + platform_exit_critical(); fhss_stats_update(fhss_structure, STATS_FHSS_SYNCH_INTERVAL, US_TO_S(time_since_last_synch_us)); return 0; } diff --git a/source/libDHCPv6/dhcp_service_api.c b/source/libDHCPv6/dhcp_service_api.c index 47c09ec5e26..c720a14c01b 100644 --- a/source/libDHCPv6/dhcp_service_api.c +++ b/source/libDHCPv6/dhcp_service_api.c @@ -86,10 +86,18 @@ typedef struct { } msg_tr_t; typedef NS_LIST_HEAD(msg_tr_t, link) tr_list_t; +typedef struct { + dhcp_relay_neighbour_cb *recv_notify_cb; + int8_t interface_id; + ns_list_link_t link; +} relay_notify_t; +typedef NS_LIST_HEAD(relay_notify_t, link) relay_notify_list_t; + typedef struct { ns_address_t src_address; server_instance_list_t srv_list; relay_instance_list_t relay_list; + relay_notify_list_t notify_list; tr_list_t tr_list; int8_t dhcp_server_socket; int8_t dhcp_client_socket; @@ -134,6 +142,7 @@ bool dhcp_service_allocate(void) if (dhcp_service) { ns_list_init(&dhcp_service->srv_list); ns_list_init(&dhcp_service->relay_list); + ns_list_init(&dhcp_service->notify_list); ns_list_init(&dhcp_service->tr_list); dhcp_service->dhcp_client_socket = -1; dhcp_service->dhcp_server_socket = -1; @@ -255,6 +264,16 @@ static uint16_t dhcp_service_relay_interface_get(int8_t interface_id) return 0; } +static relay_notify_t *dhcp_service_notify_find(int8_t interface_id) +{ + relay_notify_t *result = NULL; + ns_list_foreach(relay_notify_t, cur_ptr, &dhcp_service->notify_list) { + if (cur_ptr->interface_id == interface_id) { + result = cur_ptr; + } + } + return result; +} static relay_instance_t *dhcp_service_relay_find(uint16_t instance_id) @@ -294,6 +313,8 @@ void recv_dhcp_server_msg(void *cb_res) if (sckt_data->event_type != SOCKET_DATA || sckt_data->d_len < 4) { return; } + relay_notify_t *neigh_notify = NULL; + tr_debug("dhcp Server recv request"); msg_tr_ptr = dhcp_tr_create(); msg_ptr = ns_dyn_mem_temporary_alloc(sckt_data->d_len); @@ -322,6 +343,9 @@ void recv_dhcp_server_msg(void *cb_res) } else if (msg_type == DHCPV6_RELAY_REPLY) { tr_error("Relay reply drop at server"); goto cleanup; + } else { + //Search only for direct messages here + neigh_notify = dhcp_service_notify_find(sckt_data->interface_id); } //TODO use real function from lib also call validity check @@ -331,6 +355,11 @@ void recv_dhcp_server_msg(void *cb_res) tr_error("Malformed packet"); goto cleanup; } + + if (neigh_notify && neigh_notify->recv_notify_cb) { + neigh_notify->recv_notify_cb(sckt_data->interface_id, msg_tr_ptr->addr.address); + } + msg_tr_ptr->socket = sckt_data->socket_id; // call all receivers until found. ns_list_foreach(server_instance_t, cur_ptr, &dhcp_service->srv_list) { @@ -451,6 +480,12 @@ void recv_dhcp_relay_msg(void *cb_res) libdhcpv6_dhcp_relay_msg_write(relay_frame, DHCPV6_RELAY_FORWARD, 0, src_address.address, gp_address); libdhcpv6_dhcp_option_header_write(relay_frame + 34, msg_len); + //Update Neighbour table if necessary + relay_notify_t *neigh_notify = dhcp_service_notify_find(sckt_data->interface_id); + if (neigh_notify && neigh_notify->recv_notify_cb) { + neigh_notify->recv_notify_cb(sckt_data->interface_id, src_address.address); + } + //Copy DST address memcpy(src_address.address, relay_srv->server_address, 16); src_address.type = ADDRESS_IPV6; @@ -884,6 +919,31 @@ bool dhcp_service_timer_tick(uint16_t ticks) } return activeTimerNeed; } + +int dhcp_service_link_local_rx_cb_set(int8_t interface_id, dhcp_relay_neighbour_cb *notify_cb) +{ + if (dhcp_service == NULL) { + return -1; + } + + relay_notify_t *notify_srv = dhcp_service_notify_find(interface_id); + if (notify_srv) { + notify_srv->recv_notify_cb = notify_cb; + return 0; + } + + + notify_srv = ns_dyn_mem_alloc(sizeof(relay_notify_t)); + if (!notify_srv) { + return -1; + } + ns_list_add_to_start(&dhcp_service->notify_list, notify_srv); + + notify_srv->recv_notify_cb = notify_cb; + notify_srv->interface_id = interface_id; + return 0; +} + #else uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_type, dhcp_service_receive_req_cb *receive_req_cb) { @@ -948,4 +1008,11 @@ void dhcp_service_req_remove_all(void *msg_class_ptr) (void)msg_class_ptr; } +int dhcp_service_link_local_rx_cb_set(int8_t interface_id, dhcp_relay_neighbour_cb *notify_cb) +{ + (void) interface_id; + (void) notify_cb; + return -1; +} + #endif diff --git a/source/libDHCPv6/libDHCPv6.c b/source/libDHCPv6/libDHCPv6.c index 7b021aba399..722e41f46e1 100644 --- a/source/libDHCPv6/libDHCPv6.c +++ b/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/source/libDHCPv6/libDHCPv6.h b/source/libDHCPv6/libDHCPv6.h index c495a18fe44..dd2bd6309fe 100644 --- a/source/libDHCPv6/libDHCPv6.h +++ b/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/source/libDHCPv6/libDHCPv6_server.c b/source/libDHCPv6/libDHCPv6_server.c index f3c0ccba8c6..d324c812691 100644 --- a/source/libDHCPv6/libDHCPv6_server.c +++ b/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/source/libDHCPv6/libDHCPv6_server.h b/source/libDHCPv6/libDHCPv6_server.h index 3b4c0643e2e..3ea3e5f2abb 100644 --- a/source/libDHCPv6/libDHCPv6_server.h +++ b/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/source/libDHCPv6/libDHCPv6_vendordata.c b/source/libDHCPv6/libDHCPv6_vendordata.c new file mode 100644 index 00000000000..2854517d5e3 --- /dev/null +++ b/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/source/libDHCPv6/libDHCPv6_vendordata.h b/source/libDHCPv6/libDHCPv6_vendordata.h new file mode 100644 index 00000000000..1a1ef44f7f6 --- /dev/null +++ b/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/source/libNET/src/net_dns.c b/source/libNET/src/net_dns.c new file mode 100644 index 00000000000..b7c7c3eec5f --- /dev/null +++ b/source/libNET/src/net_dns.c @@ -0,0 +1,330 @@ +/* + * 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 "net_dns_internal.h" +#include "net_interface.h" +#include "NWK_INTERFACE/Include/protocol.h" +#include "nsdynmemLIB.h" +#include "ns_list.h" +#include "libNET/src/net_dns_internal.h" +#define TRACE_GROUP "Ndns" + + +typedef struct dns_server_info { + uint8_t address[16]; + uint8_t dns_server_address[16]; + uint32_t lifetime; + uint8_t *dns_search_list_ptr; + uint16_t dns_search_list_len; + int8_t interface_id; + ns_list_link_t link; +} dns_server_info_t; + +static NS_LIST_DEFINE(dns_server_list, dns_server_info_t, link); + +typedef struct dns_query { + uint8_t address[16]; + char *domain_str; + uint32_t lifetime; + int8_t interface_id; + ns_list_link_t link; +} dns_query_t; + +static NS_LIST_DEFINE(dns_query_list, dns_query_t, link); + +static dns_server_info_t *dns_server_info_find(int8_t interface_id, const uint8_t address[16]) +{ + dns_server_info_t *this = NULL; + ns_list_foreach(dns_server_info_t, cur_ptr, &dns_server_list) { + if (interface_id != -1 && cur_ptr->interface_id != interface_id) { + continue; + } + if (address && memcmp(cur_ptr->address, address, 16) == 0) { + this = cur_ptr; + break; + } + } + return this; +} + +static dns_server_info_t *dns_server_info_create(int8_t interface_id, const uint8_t address[16]) +{ + dns_server_info_t *this = ns_dyn_mem_alloc(sizeof(dns_server_info_t)); + + if (!this) { + return NULL; + } + + memset(this, 0, sizeof(dns_server_info_t)); + this->interface_id = interface_id; + memcpy(this->address, address, 16); + ns_list_add_to_start(&dns_server_list, this); + tr_debug("Create DNS entry for %s", trace_ipv6(address)); + + return this; +} + +static void dns_server_info_delete(dns_server_info_t *this) +{ + if (!this) { + return; + } + + tr_debug("delete DNS entry for %s", trace_ipv6(this->address)); + ns_list_remove(&dns_server_list, this); + ns_dyn_mem_free(this->dns_search_list_ptr); + ns_dyn_mem_free(this); +} + + +int8_t net_dns_server_address_set(int8_t interface_id, const uint8_t address[16], const uint8_t dns_server_address[16], uint32_t lifetime) +{ + dns_server_info_t *info_ptr; + + if (!address || interface_id < 0) { + return -1; + } + info_ptr = dns_server_info_find(interface_id, address); + + if (!dns_server_address || lifetime == 0) { + // Delete the entry + dns_server_info_delete(info_ptr); + return 0; + } + + if (!info_ptr) { + info_ptr = dns_server_info_create(interface_id, address); + } + info_ptr->lifetime = lifetime; + memcpy(info_ptr->dns_server_address, dns_server_address, 16); + 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; +} + +int8_t net_dns_server_search_list_set(int8_t interface_id, const uint8_t address[16], uint8_t *dns_search_list_ptr, uint8_t dns_search_list_len, uint32_t lifetime) +{ + dns_server_info_t *info_ptr; + + if (!address || interface_id < 0) { + return -1; + } + info_ptr = dns_server_info_find(interface_id, address); + + if (info_ptr && (!dns_search_list_ptr || lifetime == 0)) { + // remove search list information + tr_debug("DNS Search List clear"); + ns_dyn_mem_free(info_ptr->dns_search_list_ptr); + info_ptr->dns_search_list_ptr = NULL; + info_ptr->dns_search_list_len = 0; + return 0; + } + + if (!info_ptr) { + info_ptr = dns_server_info_create(interface_id, address); + if (!info_ptr) { + return -1; + } + info_ptr->lifetime = lifetime; + } + + if (info_ptr->dns_search_list_ptr && info_ptr->dns_search_list_len != dns_search_list_len) { + ns_dyn_mem_free(info_ptr->dns_search_list_ptr); + info_ptr->dns_search_list_ptr = NULL; + } + + if (!info_ptr->dns_search_list_ptr) { + info_ptr->dns_search_list_ptr = ns_dyn_mem_alloc(dns_search_list_len); + } + + if (!info_ptr->dns_search_list_ptr) { + return -2; + } + + memcpy(info_ptr->dns_search_list_ptr, dns_search_list_ptr, dns_search_list_len); + info_ptr->dns_search_list_len = dns_search_list_len; + tr_info("DNS Search List: %s Lifetime: %lu", trace_array(info_ptr->dns_search_list_ptr, info_ptr->dns_search_list_len), (unsigned long) info_ptr->lifetime); + + return 0; +} + +int8_t net_dns_server_get(int8_t interface_id, uint8_t dns_server_address[16], uint8_t **dns_search_list_ptr, uint8_t *dns_search_list_len, uint8_t index) +{ + dns_server_info_t *info_ptr = NULL; + uint8_t n = 0; + ns_list_foreach(dns_server_info_t, cur_ptr, &dns_server_list) { + if (interface_id != -1 && cur_ptr->interface_id != interface_id) { + continue; + } + if (index == n) { + info_ptr = cur_ptr; + break; + } + n++; + } + + if (!info_ptr) { + return -1; + } + if (dns_server_address) { + memcpy(dns_server_address, info_ptr->dns_server_address, 16); + } + if (dns_search_list_ptr) { + *dns_search_list_ptr = info_ptr->dns_search_list_ptr; + } + if (dns_search_list_len) { + *dns_search_list_len = info_ptr->dns_search_list_len; + } + return 0; +} + +/** + * Storage for DNS query results + */ + +static dns_query_t *dns_query_result_find(int8_t interface_id, const char *domain_str) +{ + dns_query_t *this = NULL; + ns_list_foreach(dns_query_t, cur_ptr, &dns_query_list) { + if (interface_id != -1 && cur_ptr->interface_id != interface_id) { + continue; + } + if (strcasecmp(cur_ptr->domain_str, domain_str) == 0) { + this = cur_ptr; + break; + } + } + return this; +} + +static dns_query_t *dns_query_result_create(int8_t interface_id, const char *domain_str) +{ + dns_query_t *this = NULL; + + if (!domain_str) { + return NULL; + } + this = ns_dyn_mem_alloc(sizeof(dns_query_t)); + if (!this) { + return NULL; + } + memset(this, 0, sizeof(dns_query_t)); + + this->domain_str = ns_dyn_mem_alloc(strlen(domain_str) + 1); + if (!this->domain_str) { + ns_dyn_mem_free(this); + return NULL; + } + this->interface_id = interface_id; + strcpy(this->domain_str, domain_str); + //tr_debug("Create DNS query entry for %s", this->domain_str); + ns_list_add_to_start(&dns_query_list, this); + return this; +} + +static void dns_query_result_delete(dns_query_t *this) +{ + if (!this) { + return; + } + + tr_debug("Delete DNS query entry for %s", this->domain_str); + ns_list_remove(&dns_query_list, this); + ns_dyn_mem_free(this->domain_str); + ns_dyn_mem_free(this); +} + +int8_t net_dns_query_result_set(int8_t interface_id, const uint8_t address[16], const char *domain_name_ptr, uint32_t lifetime) +{ + dns_query_t *this; + + if (!domain_name_ptr || interface_id < 0) { + return -1; + } + this = dns_query_result_find(interface_id, domain_name_ptr); + + if (!address || lifetime == 0) { + // Delete the entry + dns_query_result_delete(this); + return 0; + } + + if (!this) { + this = dns_query_result_create(interface_id, domain_name_ptr); + } + + if (!this) { + return -2; + } + // update address and lifetime also to old query results + memcpy(this->address, address, 16); + this->lifetime = lifetime; + tr_info("DNS query set: %s address %s Lifetime: %lu", this->domain_str, trace_ipv6(this->address), (unsigned long) this->lifetime); + + return 0; +} + +int8_t net_dns_query_result_get(int8_t interface_id, uint8_t address[16], const char *domain_name_ptr) +{ + dns_query_t *this; + + if (!domain_name_ptr) { + return -1; + } + this = dns_query_result_find(interface_id, domain_name_ptr); + + if (!this) { + return -1; + } + if (address) { + memcpy(address, this->address, 16); + } + + return 0; +} + +/** + * Generic timeout handler for all interfaces and entries. + */ +void net_dns_timer_seconds(uint32_t seconds) +{ + ns_list_foreach_safe(dns_query_t, cur_ptr, &dns_query_list) { + if (cur_ptr->lifetime == 0xffffffff) { + continue; + } + if (cur_ptr->lifetime <= seconds) { + dns_query_result_delete(cur_ptr); + continue; + } + cur_ptr->lifetime -= seconds; + } + + ns_list_foreach_safe(dns_server_info_t, cur_ptr, &dns_server_list) { + if (cur_ptr->lifetime == 0xffffffff) { + continue; + } + if (cur_ptr->lifetime <= seconds) { + dns_server_info_delete(cur_ptr); + continue; + } + cur_ptr->lifetime -= seconds; + } + return; +} diff --git a/source/libNET/src/net_dns_internal.h b/source/libNET/src/net_dns_internal.h new file mode 100644 index 00000000000..bd58dbb51b2 --- /dev/null +++ b/source/libNET/src/net_dns_internal.h @@ -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. + */ + +#ifndef NET_DNS_INTERNAL_H_ +#define NET_DNS_INTERNAL_H_ + +/** + * These functions are used to store DNS server related information + * IF DNS information is learned from IPv6 Router advertisements + * or from the DHCPv6 elements + * + * Address is the link local address of the default router or DHCPv6 server address + */ + +int8_t net_dns_server_address_set(int8_t interface_id, const uint8_t address[16], const uint8_t dns_server_address[16], uint32_t lifetime); +int8_t net_dns_server_search_list_set(int8_t interface_id, const uint8_t address[16], uint8_t *dns_search_list_ptr, uint8_t dns_search_list_len, uint32_t lifetime); + +int8_t net_dns_server_get(int8_t interface_id, uint8_t dns_server_address[16], uint8_t **dns_search_list_ptr, uint8_t *dns_search_list_len, uint8_t index); + +/** + * Storage for DNS query results + */ + +int8_t net_dns_query_result_set(int8_t interface_id, const uint8_t address[16], const char *domain_name_ptr, uint32_t lifetime); + +int8_t net_dns_query_result_get(int8_t interface_id, uint8_t address[16], const char *domain_name_ptr); + +/** + * Generic timeout handler for all interfaces and entries. + */ +void net_dns_timer_seconds(uint32_t seconds); + +#endif /* NET_DNS_INTERNAL_H_ */ diff --git a/source/libNET/src/ns_net.c b/source/libNET/src/ns_net.c index ed35581c5e7..b863aa29922 100644 --- a/source/libNET/src/ns_net.c +++ b/source/libNET/src/ns_net.c @@ -61,6 +61,7 @@ #include "Security/Common/sec_lib_definitions.h" #include "ipv6_stack/protocol_ipv6.h" #include "ipv6_stack/ipv6_routing_table.h" +#include "libNET/src/net_dns_internal.h" #include "net_thread_test.h" #include "6LoWPAN/Thread/thread_common.h" #include "6LoWPAN/Thread/thread_routing.h" @@ -656,6 +657,24 @@ int8_t arm_net_address_delete_from_interface(int8_t interface_id, const uint8_t return addr_delete(cur, address); } +/* DNS cache functions + */ +int8_t arm_net_dns_server_get(int8_t interface_id, uint8_t address[16], uint8_t **dns_search_list_ptr, uint8_t *dns_search_list_len, uint8_t index) +{ + return net_dns_server_get(interface_id, address, dns_search_list_ptr, dns_search_list_len, index); +} + +int8_t arm_net_dns_query_result_set(int8_t interface_id, const uint8_t address[16], const char *domain_name_ptr, uint32_t lifetime) +{ + return net_dns_query_result_set(interface_id, address, domain_name_ptr, lifetime); +} + +int8_t arm_net_dns_query_result_get(int8_t interface_id, uint8_t address[16], char *domain_name_ptr) +{ + return net_dns_query_result_get(interface_id, address, domain_name_ptr); +} + + int8_t arm_net_route_add(const uint8_t *prefix, uint8_t prefix_len, const uint8_t *next_hop, uint32_t lifetime, uint8_t metric, int8_t interface_id) { ipv6_route_t *entry; @@ -682,7 +701,6 @@ int8_t arm_net_route_delete(const uint8_t *prefix, uint8_t prefix_len, const uin return ipv6_route_delete(prefix, prefix_len, interface_id, next_hop, ROUTE_USER); } - int8_t arm_nwk_interface_ethernet_init(eth_mac_api_t *api, const char *interface_name_ptr) { #ifdef HAVE_ETHERNET diff --git a/sources.mk b/sources.mk index 97b4113c207..2d895e803a7 100644 --- a/sources.mk +++ b/sources.mk @@ -67,6 +67,7 @@ SRCS += \ source/libNET/src/net_mle.c \ source/libNET/src/net_rpl.c \ source/libNET/src/net_load_balance.c \ + source/libNET/src/net_dns.c \ source/libNET/src/ns_net.c \ source/libNET/src/socket_api.c \ source/libNET/src/multicast_api.c \ @@ -204,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 \