From 396dae52ab4eef15910011432f2c7a4261fc22b7 Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Thu, 5 Sep 2019 14:28:22 +0300 Subject: [PATCH] Squashed 'features/nanostack/sal-stack-nanostack/' changes from 4a19dc4..c473148 c473148 Merge branch 'release_internal' into release_external d7ad405 Merge pull request #2179 from ARMmbed/release_internal_merge 668fc82 Merge branch 'master' into release_internal 9458a30 Added crypto library to unit test makefile ff83e4b Added crypto library include path 4292326 Updated eapol TLS library to use extended version of export keys callback f8f0762 Corrected authenticator EAP-TLS start retries 00fdf8d Added sending of initial EAPOL-key to original target during bootstrap 313794cf Wi-sun neighbor temporary neigh update 05fa359 added support for EAPOL timing adjustment cfc3223 RPL parent confirmation process update c3a2c5c Added limit to BR supplicant entries 21de90d RPL dio handler update 425a04a Fix Slaac Handler for not native IPv6 stack. 5722a4a Wi-sun multicast neighbour and RPL update git-subtree-dir: features/nanostack/sal-stack-nanostack git-subtree-split: c4731481674d25a516142d1d89f784fbd5e2d58e --- Makefile | 4 +- nanostack/ws_bbr_api.h | 20 +++ .../Generic/protocol_6lowpan_bootstrap.c | 4 +- source/6LoWPAN/ws/ws_bbr_api.c | 12 +- source/6LoWPAN/ws/ws_bootstrap.c | 114 ++++++++----- source/6LoWPAN/ws/ws_common.c | 7 +- source/6LoWPAN/ws/ws_common.h | 1 - source/6LoWPAN/ws/ws_common_defines.h | 3 +- source/6LoWPAN/ws/ws_llc.h | 23 ++- source/6LoWPAN/ws/ws_llc_data_service.c | 156 +++++++++++++++--- source/6LoWPAN/ws/ws_neighbor_class.h | 1 + source/6LoWPAN/ws/ws_pae_auth.c | 53 ++++++ source/6LoWPAN/ws/ws_pae_auth.h | 45 +++++ source/6LoWPAN/ws/ws_pae_controller.c | 76 ++++++++- source/6LoWPAN/ws/ws_pae_controller.h | 56 ++++++- source/6LoWPAN/ws/ws_pae_lib.c | 24 +++ source/6LoWPAN/ws/ws_pae_lib.h | 14 +- source/6LoWPAN/ws/ws_pae_supp.c | 58 +++++-- source/6LoWPAN/ws/ws_pae_supp.h | 36 ++++ source/Common_Protocols/icmpv6.c | 6 +- source/Core/ns_monitor.c | 5 +- source/RPL/rpl_control.c | 12 +- source/RPL/rpl_control.h | 5 +- source/RPL/rpl_downward.c | 45 ++++- .../eap_tls_sec_prot/auth_eap_tls_sec_prot.c | 32 +++- .../eap_tls_sec_prot/auth_eap_tls_sec_prot.h | 22 +++ .../eap_tls_sec_prot/supp_eap_tls_sec_prot.c | 44 +++-- .../eap_tls_sec_prot/supp_eap_tls_sec_prot.h | 22 +++ .../fwh_sec_prot/auth_fwh_sec_prot.c | 28 +++- .../fwh_sec_prot/auth_fwh_sec_prot.h | 22 +++ .../fwh_sec_prot/supp_fwh_sec_prot.c | 22 ++- .../fwh_sec_prot/supp_fwh_sec_prot.h | 22 +++ .../gkh_sec_prot/auth_gkh_sec_prot.c | 28 +++- .../gkh_sec_prot/auth_gkh_sec_prot.h | 22 +++ .../gkh_sec_prot/supp_gkh_sec_prot.c | 9 +- .../protocols/tls_sec_prot/tls_sec_prot_lib.c | 90 +++------- source/ipv6_stack/protocol_ipv6.c | 2 +- 37 files changed, 920 insertions(+), 225 deletions(-) diff --git a/Makefile b/Makefile index 17a7f5512b7..c9b7d2402b7 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ override CFLAGS += -I$(EVENTLOOP_DIR)/nanostack-event-loop override CFLAGS += -I$(NSDL_DIR)/nsdl-c override CFLAGS += -I$(COAP_DIR) override CFLAGS += -I$(COAP_SERVICE_LIB)/coap-service -override CFLAGS += -I$(MBEDTLS_DIR)/include +override CFLAGS += -I$(MBEDTLS_DIR)/include -I$(MBEDTLS_DIR)/crypto/include override CFLAGS += $(addprefix -I,$(INCLUDE_DIRS)) override CFLAGS += $(addprefix -D,$(FLAGS)) @@ -153,7 +153,7 @@ mbed-release-build-$(1): $(1)-$(2)-$(3)-build .PHONY: $(1)-$(2)-build $(1)-$(2)-$(3)-build: export-headers @echo Build $(2) on $(1) for $(3) - make CC=$(CC_$(1)) CONFIG=$(2) CPU=$(3) APPEND_LIB_NAME=1 CFLAGS="-DNS_USE_EXTERNAL_MBED_TLS -I../mbedtls/include/" + make CC=$(CC_$(1)) CONFIG=$(2) CPU=$(3) APPEND_LIB_NAME=1 CFLAGS="-DNS_USE_EXTERNAL_MBED_TLS -I../mbedtls/include/ -I../crypto/include/" # Generate target directory name # Like: FEATURE_NANOSTACK/FEATURE_LOWPAN_ROUTER/TOOLCHAIN_ARM/TARGET_CORTEX_M0P diff --git a/nanostack/ws_bbr_api.h b/nanostack/ws_bbr_api.h index 53c26ecdd41..dbfb20b25ad 100644 --- a/nanostack/ws_bbr_api.h +++ b/nanostack/ws_bbr_api.h @@ -120,4 +120,24 @@ int ws_bbr_node_keys_remove(int8_t interface_id, uint8_t *eui64); */ int ws_bbr_node_access_revoke_start(int8_t interface_id); +/** + * Set EAPOL node limit + * + * Border router stores EAPOL key information for each authenticated node. + * Sets the maximum number of EAPOL nodes stored by border router. If count + * of node's exceed the limit, border router deletes the node information + * starting from oldest node (node that has authenticated longest time + * ago), to make room for new nodes. When network keys are updated, nodes + * which have been removed from storage, must make full authentication again. + * Value for this parameter should be set to be more than maximum amount of + * nodes that are expected to be connected to border router. + * + * \param interface_id Network interface ID. + * \param limit Limit for nodes + * + * \return 0, Node limit set + * \return <0 Node limit set failed. + */ +int ws_bbr_eapol_node_limit_set(int8_t interface_id, uint16_t limit); + #endif /* WS_BBR_API_H_ */ diff --git a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c index e6b009e500a..e78b91c088a 100644 --- a/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c +++ b/source/6LoWPAN/Bootstraps/Generic/protocol_6lowpan_bootstrap.c @@ -1787,7 +1787,7 @@ int8_t arm_6lowpan_bootstarp_bootstrap_set(int8_t interface_id, net_6lowpan_mode */ if (cur->lowpan_info & INTERFACE_NWK_ROUTER_DEVICE) { //rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true); - //rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, cur); + //rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, NULL, cur); } #endif cur->configure_flags |= INTERFACE_BOOTSTRAP_DEFINED; @@ -2182,7 +2182,7 @@ void nwk_6lowpan_nd_address_registartion_ready(protocol_interface_info_entry_t * // arm_nwk_6lowpan_rpl_dodag_poison from a previous connection may have left force_leaf set rpl_control_force_leaf(protocol_6lowpan_rpl_domain, false); rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, true); - rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, cur); + rpl_control_set_callback(protocol_6lowpan_rpl_domain, protocol_6lowpan_bootstrap_rpl_callback, NULL, NULL, cur); } // Send unicast DIS to coordinator nwk_bootstrap_icmp_rpl_dis_coord_msg_tx(cur); diff --git a/source/6LoWPAN/ws/ws_bbr_api.c b/source/6LoWPAN/ws/ws_bbr_api.c index 84586a519aa..317ab8ac785 100644 --- a/source/6LoWPAN/ws/ws_bbr_api.c +++ b/source/6LoWPAN/ws/ws_bbr_api.c @@ -609,7 +609,6 @@ int ws_bbr_node_keys_remove(int8_t interface_id, uint8_t *eui64) { (void) interface_id; (void) eui64; - #ifdef HAVE_WS_BORDER_ROUTER return ws_pae_controller_node_keys_remove(interface_id, eui64); #else @@ -620,7 +619,6 @@ int ws_bbr_node_keys_remove(int8_t interface_id, uint8_t *eui64) int ws_bbr_node_access_revoke_start(int8_t interface_id) { (void) interface_id; - #ifdef HAVE_WS_BORDER_ROUTER return ws_pae_controller_node_access_revoke_start(interface_id); #else @@ -628,3 +626,13 @@ int ws_bbr_node_access_revoke_start(int8_t interface_id) #endif } +int ws_bbr_eapol_node_limit_set(int8_t interface_id, uint16_t limit) +{ + (void) interface_id; +#ifdef HAVE_WS_BORDER_ROUTER + return ws_pae_controller_node_limit_set(interface_id, limit); +#else + (void) limit; + return -1; +#endif +} diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 55df3b5227b..8483b7de8e7 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -81,7 +81,7 @@ static void ws_bootstrap_state_change(protocol_interface_info_entry_t *cur, icmp static bool ws_bootstrap_state_discovery(struct protocol_interface_info_entry *cur); static int8_t ws_bootsrap_event_trig(ws_bootsrap_event_type_e event_type, int8_t interface_id, arm_library_event_priority_e priority, void *event_data); -static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new, bool multicast); +static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new); static uint16_t ws_bootstrap_routing_cost_calculate(protocol_interface_info_entry_t *cur); static uint16_t ws_bootstrap_rank_get(protocol_interface_info_entry_t *cur); static uint16_t ws_bootstrap_min_rank_inc_get(protocol_interface_info_entry_t *cur); @@ -97,6 +97,7 @@ static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t * static ws_nud_table_entry_t *ws_nud_entry_discover(protocol_interface_info_entry_t *cur, void *neighbor); static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_ptr); static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data); +static bool ws_rpl_dio_new_parent_accept(struct protocol_interface_info_entry *interface); typedef enum { WS_PARENT_SOFT_SYNCH = 0, /**< let FHSS make decision if synchronization is needed*/ @@ -104,6 +105,7 @@ typedef enum { WS_EAPOL_PARENT_SYNCH, /**< Broadcast synch with EAPOL parent*/ } ws_parent_synch_e; + static void ws_bootsrap_create_ll_address(uint8_t *ll_address, const uint8_t *mac64) { memcpy(ll_address, ADDR_LINK_LOCAL_PREFIX, 8); @@ -925,7 +927,7 @@ static void ws_bootstrap_pan_advertisement_analyse(struct protocol_interface_inf // Save route cost for all neighbours llc_neighbour_req_t neighbor_info; neighbor_info.neighbor = NULL; - if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false, false)) { + if (ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false)) { neighbor_info.ws_neighbor->routing_cost = pan_information.routing_cost; } @@ -1080,10 +1082,10 @@ static void ws_bootstrap_pan_config_analyse(struct protocol_interface_info_entry if (cur->ws_info->configuration_learned || cur->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { //If we are border router or learned configuration we only update already learned neighbours. - neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false, true); + neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, false); } else { - neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, true, true); + neighbour_pointer_valid = ws_bootstrap_neighbor_info_request(cur, data->SrcAddr, &neighbor_info, true); if (!neighbour_pointer_valid) { return; } @@ -1169,7 +1171,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, false)) { + 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); ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, ws_utt, data->timestamp); ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, ws_us); @@ -1366,19 +1368,10 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent } } - uint32_t link_min_timeout; //Read current timestamp uint32_t time_from_last_unicast_shedule = ws_time_from_last_unicast_traffic(current_time_stamp, ws_neighbor); - - if (cur->trusted_device) { - link_min_timeout = WS_NEIGHBOR_TRUSTED_LINK_MIN_TIMEOUT; - } else { - - link_min_timeout = WS_NEIGHBOR_NOT_TRUSTED_LINK_MIN_TIMEOUT; - } - - if (time_from_last_unicast_shedule > link_min_timeout || !ws_neighbor->unicast_data_rx) { + if (time_from_last_unicast_shedule > WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT || !ws_neighbor->unicast_data_rx) { //Accept only Enough Old Device if (!neighbor_entry_ptr) { //Accept first compare @@ -1399,8 +1392,9 @@ static void ws_bootstrap_neighbor_table_clean(struct protocol_interface_info_ent } -static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new, bool multicast) +static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new) { + neighbor_buffer->ws_neighbor = NULL; neighbor_buffer->neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(interface), mac_64, ADDR_802_15_4_LONG); if (neighbor_buffer->neighbor) { neighbor_buffer->ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbor_buffer->neighbor->index); @@ -1421,27 +1415,6 @@ static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_en return false; } - if (multicast) { - //for multicast neighbour we must limit if we have already enough information - if (interface->bootsrap_mode == ARM_NWK_BOOTSRAP_MODE_6LoWPAN_BORDER_ROUTER) { - //Border router never allocate neighbors by multicast - return false; - } - - uint16_t parent_candidate_size = rpl_control_parent_candidate_list_size(interface, false); - - //if we have enough candidates at list do not accept new multicast neighbours - if (parent_candidate_size >= 4) { - return false; - } - - parent_candidate_size = rpl_control_parent_candidate_list_size(interface, true); - //If we have already enough parent selected Candidates count is bigger tahn 4 - if (parent_candidate_size >= 2) { - return false; - } - } - ws_bootstrap_neighbor_table_clean(interface); neighbor_buffer->neighbor = ws_bootstrap_mac_neighbor_add(interface, mac_64); @@ -1458,6 +1431,24 @@ static bool ws_bootstrap_neighbor_info_request(struct protocol_interface_info_en return true; } +static bool ws_rpl_dio_new_parent_accept(struct protocol_interface_info_entry *interface) +{ + uint16_t parent_candidate_size = rpl_control_parent_candidate_list_size(interface, false); + //TODO check bootstarap state for review + //if we have enough candidates at list do not accept new multicast neighbours + if (parent_candidate_size > WS_NEIGHBOUR_MAX_CANDIDATE_PROBE) { + return false; + } + + parent_candidate_size = rpl_control_parent_candidate_list_size(interface, true); + //If we have already enough parent selected Candidates count is bigger tahn 4 + if (parent_candidate_size >= 2) { + return false; + } + + return true; +} + static void ws_neighbor_entry_remove_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data) { @@ -2010,6 +2001,48 @@ static void ws_rpl_prefix_callback(prefix_entry_t *prefix, void *handle, uint8_t } } +static bool ws_rpl_new_parent_callback_t(uint8_t *ll_parent_address, void *handle) +{ + + protocol_interface_info_entry_t *cur = handle; + if (!cur->rpl_domain || cur->interface_mode != INTERFACE_UP) { + return false; + } + + uint8_t mac64[8]; + memcpy(mac64, ll_parent_address + 8, 8); + mac64[0] ^= 2; + llc_neighbour_req_t neigh_buffer; + if (ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, false)) { + return true; + } + + if (!ws_rpl_dio_new_parent_accept(cur)) { + return false; + } + + //Discover Multicast temporary entry + + ws_neighbor_temp_class_t *entry = ws_llc_get_multicast_temp_entry(cur, mac64); + if (!entry) { + return false; + } + //Create entry + bool create_ok = ws_bootstrap_neighbor_info_request(cur, mac64, &neigh_buffer, true); + if (create_ok) { + ws_neighbor_class_entry_t *ws_neigh = neigh_buffer.ws_neighbor; + //Copy fhss temporary data + *ws_neigh = entry->neigh_info_list; + //ETX Create here + etx_lqi_dbm_update(cur->id, entry->mpduLinkQuality, entry->signal_dbm, neigh_buffer.neighbor->index); + mac_neighbor_table_trusted_neighbor(mac_neighbor_info(cur), neigh_buffer.neighbor, true); + } + ws_llc_free_multicast_temp_entry(cur, entry); + + + return create_ok; +} + static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur) { tr_debug("RPL Activate"); @@ -2018,7 +2051,7 @@ static void ws_bootstrap_rpl_activate(protocol_interface_info_entry_t *cur) addr_add_router_groups(cur); rpl_control_set_domain_on_interface(cur, protocol_6lowpan_rpl_domain, downstream); - rpl_control_set_callback(protocol_6lowpan_rpl_domain, ws_bootstrap_rpl_callback, ws_rpl_prefix_callback, cur); + rpl_control_set_callback(protocol_6lowpan_rpl_domain, ws_bootstrap_rpl_callback, ws_rpl_prefix_callback, ws_rpl_new_parent_callback_t, cur); // If i am router I Do this rpl_control_force_leaf(protocol_6lowpan_rpl_domain, leaf); rpl_control_request_parent_link_confirmation(true); @@ -2493,6 +2526,9 @@ static void ws_bootstrap_event_handler(arm_event_s *event) cur->ws_info->trickle_pas_running = false; cur->ws_info->trickle_pcs_running = false; + // Indicate PAE controller that bootstrap is ready + ws_pae_controller_bootstrap_done(cur); + ws_bootstrap_advertise_start(cur); ws_bootstrap_state_change(cur, ER_BOOTSRAP_DONE); break; @@ -2520,7 +2556,7 @@ void ws_bootstrap_network_scan_process(protocol_interface_info_entry_t *cur) // Add EAPOL neighbour llc_neighbour_req_t neighbor_info; - if (!ws_bootstrap_neighbor_info_request(cur, cur->ws_info->parent_info.addr, &neighbor_info, true, false)) { + if (!ws_bootstrap_neighbor_info_request(cur, cur->ws_info->parent_info.addr, &neighbor_info, true)) { return; } diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index 63004dcf54b..e9a8e025c11 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -27,6 +27,7 @@ #include "6LoWPAN/ws/ws_common.h" #include "6LoWPAN/ws/ws_bootstrap.h" #include "6LoWPAN/ws/ws_bbr_api_internal.h" +#include "6LoWPAN/ws/ws_pae_controller.h" #include "Service_Libs/etx/etx.h" #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" #include "Service_Libs/blacklist/blacklist.h" @@ -327,7 +328,7 @@ void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint } else { ws_bbr_rpl_config(0, 0, 0); } - + ws_pae_controller_timing_adjust(1); // Fast and reactive network } else if (network_size < 300) { // Configure the Wi-SUN discovery trickle parameters cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_medium; @@ -336,6 +337,7 @@ void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint // doublings:5 (960s) // redundancy; 10 ws_bbr_rpl_config(15, 5, 10); + ws_pae_controller_timing_adjust(9); // medium limited network } else { // Configure the Wi-SUN discovery trickle parameters cur->ws_info->trickle_params_pan_discovery = trickle_params_pan_discovery_large; @@ -344,6 +346,7 @@ void ws_common_network_size_configure(protocol_interface_info_entry_t *cur, uint // doublings:1 (1048s, 17 min) // redundancy; 10 May need some tuning still ws_bbr_rpl_config(19, 1, 10); + ws_pae_controller_timing_adjust(24); // Very slow and high latency network } return; } @@ -423,7 +426,7 @@ bool ws_common_negative_aro_mark(protocol_interface_info_entry_t *interface, con } ws_neighbor_class_entry_t *ws_neighbor = ws_neighbor_class_entry_get(&interface->ws_info->neighbor_storage, neighbour->index); ws_neighbor->negative_aro_send = true; - neighbour->lifetime = WS_NEIGHBOR_NOT_TRUSTED_LINK_MIN_TIMEOUT; //Remove anyway if Packet is freed before MAC push + neighbour->lifetime = WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT; //Remove anyway if Packet is freed before MAC push return true; } diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 510f3d96816..6a89708fe6e 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -143,6 +143,5 @@ uint32_t ws_common_version_timeout_get(uint8_t config); #define ws_common_etx_validate(interface, neigh) ((void) 0) #define ws_common_negative_aro_mark(interface, eui64)(false) - #endif //HAVE_WS #endif //WS_COMMON_H_ diff --git a/source/6LoWPAN/ws/ws_common_defines.h b/source/6LoWPAN/ws/ws_common_defines.h index b5b970610a7..4be2964e1ee 100644 --- a/source/6LoWPAN/ws/ws_common_defines.h +++ b/source/6LoWPAN/ws/ws_common_defines.h @@ -186,8 +186,7 @@ typedef struct ws_bs_ie { #define WS_FAN_VERSION_1_0 1 #define WS_NEIGHBOR_LINK_TIMEOUT 2200 -#define WS_NEIGHBOR_NOT_TRUSTED_LINK_MIN_TIMEOUT 60 -#define WS_NEIGHBOR_TRUSTED_LINK_MIN_TIMEOUT 15 +#define WS_NEIGHBOR_TEMPORARY_LINK_MIN_TIMEOUT 120 #define WS_NEIGHBOR_NUD_TIMEOUT WS_NEIGHBOR_LINK_TIMEOUT / 2 #define WS_NEIGBOR_ETX_SAMPLE_MAX 3 diff --git a/source/6LoWPAN/ws/ws_llc.h b/source/6LoWPAN/ws/ws_llc.h index 1104431e70c..33891f05a38 100644 --- a/source/6LoWPAN/ws/ws_llc.h +++ b/source/6LoWPAN/ws/ws_llc.h @@ -30,6 +30,7 @@ struct mlme_security_s; struct ws_hopping_schedule_s; struct ws_neighbor_class_entry; struct mac_neighbor_table_entry; +struct ws_neighbor_temp_class_s; /** @@ -73,10 +74,23 @@ typedef struct asynch_request_s { * @brief LLC neighbour info request parameters */ typedef struct llc_neighbour_req { - struct mac_neighbor_table_entry *neighbor; /**< Generic Link Layer Neighbor information entry. */ - struct ws_neighbor_class_entry *ws_neighbor; /**< Wi-sun Neighbor information entry. */ + struct mac_neighbor_table_entry *neighbor; /**< Generic Link Layer Neighbor information entry. */ + struct ws_neighbor_class_entry *ws_neighbor; /**< Wi-sun Neighbor information entry. */ } llc_neighbour_req_t; +/** + * Neighbor temporary structure for storage FHSS data before create a real Neighbour info + */ +typedef struct ws_neighbor_temp_class_s { + struct ws_neighbor_class_entry neigh_info_list; /*!< Allocated hopping info array*/ + uint8_t mac64[8]; + uint8_t mpduLinkQuality; + int8_t signal_dbm; + ns_list_link_t link; +} ws_neighbor_temp_class_t; + +typedef NS_LIST_HEAD(ws_neighbor_temp_class_t, link) ws_neighbor_temp_list_t; + /** * @brief ws_asynch_ind ws asynch data indication * @param interface Interface pointer @@ -99,12 +113,11 @@ typedef void ws_asynch_confirm(struct protocol_interface_info_entry *interface, * @param mac_64 Neighbor 64-bit address * @param neighbor_buffer Buffer where neighbor infor is buffered * @param request_new true if is possible to allocate new entry - * @param multicast true if packet is multicast * * @return true when neighbor info is available * @return false when no neighbor info */ -typedef bool ws_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new, bool multicast); +typedef bool ws_neighbor_info_request(struct protocol_interface_info_entry *interface, const uint8_t *mac_64, llc_neighbour_req_t *neighbor_buffer, bool request_new); /** * @brief ws_llc_create ws LLC module create @@ -204,6 +217,8 @@ void ws_llc_set_pan_information_pointer(struct protocol_interface_info_entry *in */ void ws_llc_hopping_schedule_config(struct protocol_interface_info_entry *interface, struct ws_hopping_schedule_s *hopping_schedule); +ws_neighbor_temp_class_t *ws_llc_get_multicast_temp_entry(struct protocol_interface_info_entry *interface, const uint8_t *mac64); +void ws_llc_free_multicast_temp_entry(struct protocol_interface_info_entry *interface, ws_neighbor_temp_class_t *neighbor); #endif /* WS_LLC_H_ */ diff --git a/source/6LoWPAN/ws/ws_llc_data_service.c b/source/6LoWPAN/ws/ws_llc_data_service.c index d5e44f09fb5..93cb5854453 100644 --- a/source/6LoWPAN/ws/ws_llc_data_service.c +++ b/source/6LoWPAN/ws/ws_llc_data_service.c @@ -95,18 +95,29 @@ typedef struct { typedef NS_LIST_HEAD(llc_message_t, link) llc_message_list_t; +#define MAX_NEIGH_TEMPORRY_MULTICAST_SIZE 5 + +typedef struct { + ws_neighbor_temp_class_t neighbour_temporary_table[MAX_NEIGH_TEMPORRY_MULTICAST_SIZE]; + ws_neighbor_temp_list_t active_temp_neigh; + ws_neighbor_temp_list_t free_temp_neigh; +} temp_entriest_t; + typedef struct { uint8_t mac_handle_base; /**< Mac handle id base this will be updated by 1 after use */ uint8_t llc_message_list_size; /**< llc_message_list list size */ mpx_class_t mpx_data_base; /**< MPX data be including USER API Class and user call backs */ llc_message_list_t llc_message_list; /**< Active Message list */ llc_ie_params_t ie_params; /**< LLC IE header and Payload data configuration */ + temp_entriest_t *temp_entries; + ws_asynch_ind *asynch_ind; /**< LLC Asynch data indication call back configured by user */ ws_asynch_confirm *asynch_confirm; /**< LLC Asynch data confirmation call back configured by user */ ws_neighbor_info_request *ws_neighbor_info_request_cb; /**< LLC Neighbour discover API*/ uint8_t ws_enhanced_ack_elements[WH_IE_ELEMENT_HEADER_LENGTH + 4 + WH_IE_ELEMENT_HEADER_LENGTH + 1]; ns_ie_iovec_t ws_header_vector; protocol_interface_info_entry_t *interface_ptr; /**< List link entry */ + ns_list_link_t link; /**< List link entry */ } llc_data_base_t; @@ -138,6 +149,9 @@ static uint16_t ws_llc_mpx_header_size_get(const mpx_api_t *api, uint16_t user_i static uint8_t ws_llc_mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id); static void ws_llc_mpx_init(mpx_class_t *mpx_class); +static void ws_llc_temp_neigh_info_table_reset(temp_entriest_t *base); +static ws_neighbor_temp_class_t *ws_allocate_multicast_temp_entry(temp_entriest_t *base, const uint8_t *mac64); + /** Discover Message by message handle id */ static llc_message_t *llc_message_discover_by_mac_handle(uint8_t handle, llc_message_list_t *list) { @@ -352,12 +366,19 @@ static mpx_user_t *ws_llc_mpx_user_discover(mpx_class_t *mpx_class, uint16_t use static llc_data_base_t *ws_llc_base_allocate(void) { - llc_data_base_t *base = ns_dyn_mem_temporary_alloc(sizeof(llc_data_base_t)); - if (!base) { + llc_data_base_t *base = ns_dyn_mem_alloc(sizeof(llc_data_base_t)); + temp_entriest_t *temp_entries = ns_dyn_mem_alloc(sizeof(temp_entriest_t)); + if (!base || !temp_entries) { + ns_dyn_mem_free(base); + ns_dyn_mem_free(temp_entries); return NULL; } memset(base, 0, sizeof(llc_data_base_t)); + memset(temp_entries, 0, sizeof(temp_entriest_t)); + ns_list_init(&temp_entries->active_temp_neigh); + ns_list_init(&temp_entries->free_temp_neigh); + base->temp_entries = temp_entries; ns_list_init(&base->llc_message_list); ns_list_add_to_end(&llc_data_base_list, base); @@ -395,7 +416,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, false)) { + if (message->dst_address_type == MAC_ADDR_MODE_64_BIT && base->ws_neighbor_info_request_cb(interface, message->dst_address, &neighbor_info, false)) { etx_transm_attempts_update(interface->id, 1 + data->tx_retries, success, neighbor_info.neighbor->index); //TODO discover RSL from Enchanced ACK Header IE elements ws_utt_ie_t ws_utt; @@ -523,27 +544,37 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t llc_neighbour_req_t neighbor_info; bool multicast; + bool request_new_entry; if (data->DstAddrMode == ADDR_802_15_4_LONG) { multicast = false; + request_new_entry = us_ie_inline; } else { multicast = true; + request_new_entry = false; } - if (!base->ws_neighbor_info_request_cb(interface, data->SrcAddr, &neighbor_info, us_ie_inline, multicast)) { + if (!base->ws_neighbor_info_request_cb(interface, data->SrcAddr, &neighbor_info, request_new_entry)) { if (!multicast || ws_utt.message_type == WS_FT_EAPOL) { tr_debug("Drop message no neighbor"); return; } else { - goto mpx_data_ind; + //Allocate temporary entry + ws_neighbor_temp_class_t *temp_entry = ws_allocate_multicast_temp_entry(base->temp_entries, data->SrcAddr); + neighbor_info.ws_neighbor = &temp_entry->neigh_info_list; + //Storage Signal info for future ETX update possibility + temp_entry->mpduLinkQuality = data->mpduLinkQuality; + temp_entry->signal_dbm = data->signal_dbm; } } - multicast = false; - ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp); if (us_ie_inline) { ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &us_ie); } + //Update BS if it is part of message + if (bs_ie_inline) { + ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie); + } if (ws_utt.message_type == WS_FT_EAPOL) { uint8_t auth_eui64[8]; @@ -551,22 +582,20 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t if (ws_wh_ea_read(ie_ext->headerIeList, ie_ext->headerIeListLength, auth_eui64)) { ws_pae_controller_border_router_addr_write(base->interface_ptr, auth_eui64); } - - } - //Update BS if it is part of message - if (bs_ie_inline) { - ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie); } + //Update BT if it is part of message ws_bt_ie_t ws_bt; if (ws_wh_bt_read(ie_ext->headerIeList, ie_ext->headerIeListLength, &ws_bt)) { ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor_info.ws_neighbor, &ws_bt, data->timestamp); - if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { - // We have broadcast schedule set up set the broadcast parent schedule - ns_fhss_ws_set_parent(interface->ws_info->fhss_api, neighbor_info.neighbor->mac64, &neighbor_info.ws_neighbor->fhss_data.bc_timing_info, false); - } else if (ws_utt.message_type == WS_FT_EAPOL) { - ws_bootstrap_eapol_parent_synch(interface, &neighbor_info); + if (neighbor_info.neighbor) { + if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { + // We have broadcast schedule set up set the broadcast parent schedule + ns_fhss_ws_set_parent(interface->ws_info->fhss_api, neighbor_info.neighbor->mac64, &neighbor_info.ws_neighbor->fhss_data.bc_timing_info, false); + } else if (ws_utt.message_type == WS_FT_EAPOL) { + ws_bootstrap_eapol_parent_synch(interface, &neighbor_info); + } } } @@ -576,24 +605,25 @@ static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t neighbor_info.ws_neighbor->unicast_data_rx = true; } - //Refresh ETX dbm - etx_lqi_dbm_update(interface->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index); // Calculate RSL for all UDATA packages heard ws_neighbor_class_rsl_in_calculate(neighbor_info.ws_neighbor, data->signal_dbm); - if (data->Key.SecurityLevel) { - //SET trusted state - mac_neighbor_table_trusted_neighbor(mac_neighbor_info(interface), neighbor_info.neighbor, true); + if (neighbor_info.neighbor) { + //Refresh ETX dbm + etx_lqi_dbm_update(interface->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index); + if (data->Key.SecurityLevel) { + //SET trusted state + mac_neighbor_table_trusted_neighbor(mac_neighbor_info(interface), neighbor_info.neighbor, true); + } } } -mpx_data_ind: // Discover MPX user_cb = ws_llc_mpx_user_discover(&base->mpx_data_base, mpx_frame.multiplex_id); if (user_cb && user_cb->data_ind) { mcps_data_ind_t data_ind = *data; - if (multicast) { + if (!neighbor_info.neighbor) { data_ind.Key.SecurityLevel = 0; //Mark unknow device } data_ind.msdu_ptr = mpx_frame.frame_ptr; @@ -892,6 +922,82 @@ static void ws_llc_clean(llc_data_base_t *base) } memset(&base->ie_params, 0, sizeof(llc_ie_params_t)); + + ws_llc_temp_neigh_info_table_reset(base->temp_entries); +} + +static void ws_llc_temp_neigh_info_table_reset(temp_entriest_t *base) +{ + //Empty active list + ns_list_init(&base->active_temp_neigh); + ns_list_init(&base->free_temp_neigh); + + //Add to free list to full + for (int i = 0; i < MAX_NEIGH_TEMPORRY_MULTICAST_SIZE; i++) { + ns_list_add_to_end(&base->free_temp_neigh, &base->neighbour_temporary_table[i]); + } +} + +static ws_neighbor_temp_class_t *ws_llc_discover_temp_entry(temp_entriest_t *base, const uint8_t *mac64) +{ + ns_list_foreach_safe(ws_neighbor_temp_class_t, entry, &base->active_temp_neigh) { + if (memcmp(entry->mac64, mac64, 8) == 0) { + return entry; + } + } + return NULL; +} + +ws_neighbor_temp_class_t *ws_llc_get_multicast_temp_entry(protocol_interface_info_entry_t *interface, const uint8_t *mac64) +{ + llc_data_base_t *base = ws_llc_discover_by_interface(interface); + if (!base) { + return NULL; + } + + return ws_llc_discover_temp_entry(base->temp_entries, mac64); +} + + + + +static ws_neighbor_temp_class_t *ws_allocate_multicast_temp_entry(temp_entriest_t *base, const uint8_t *mac64) +{ + + ws_neighbor_temp_class_t *entry = ws_llc_discover_temp_entry(base, mac64); + if (entry) { + ns_list_remove(&base->active_temp_neigh, entry); + ns_list_add_to_start(&base->active_temp_neigh, entry); + return entry; + } + + entry = ns_list_get_first(&base->free_temp_neigh); + + if (entry) { + ns_list_remove(&base->free_temp_neigh, entry); + } else { + //Replace last entry and put it to first + entry = ns_list_get_last(&base->active_temp_neigh); + ns_list_remove(&base->active_temp_neigh, entry); + } + //Add to list + ns_list_add_to_start(&base->active_temp_neigh, entry); + //Clear Old data + memset(&entry->neigh_info_list, 0, sizeof(ws_neighbor_class_entry_t)); + entry->neigh_info_list.rsl_in = RSL_UNITITIALIZED; + entry->neigh_info_list.rsl_out = RSL_UNITITIALIZED; + memcpy(entry->mac64, mac64, 8); + return entry; +} + +void ws_llc_free_multicast_temp_entry(protocol_interface_info_entry_t *cur, ws_neighbor_temp_class_t *neighbor) +{ + llc_data_base_t *base = ws_llc_discover_by_interface(cur); + if (!base) { + return; + } + ns_list_remove(&base->temp_entries->active_temp_neigh, neighbor); + ns_list_add_to_end(&base->temp_entries->free_temp_neigh, neighbor); } @@ -917,6 +1023,7 @@ int8_t ws_llc_create(struct protocol_interface_info_entry *interface, ws_asynch_ base->interface_ptr->mac_api->mac_mcps_extension_enable(base->interface_ptr->mac_api, &ws_llc_mac_indication_cb, &ws_llc_mac_confirm_cb, &ws_llc_ack_data_req_ext); //Init MPX class ws_llc_mpx_init(&base->mpx_data_base); + ws_llc_temp_neigh_info_table_reset(base->temp_entries); return 0; } @@ -932,6 +1039,7 @@ int8_t ws_llc_delete(struct protocol_interface_info_entry *interface) ns_list_remove(&llc_data_base_list, base); //Disable Mac extension base->interface_ptr->mac_api->mac_mcps_extension_enable(base->interface_ptr->mac_api, NULL, NULL, NULL); + ns_dyn_mem_free(base->temp_entries); ns_dyn_mem_free(base); return 0; } diff --git a/source/6LoWPAN/ws/ws_neighbor_class.h b/source/6LoWPAN/ws/ws_neighbor_class.h index 7fa0c9b6957..2a0cbe2c122 100644 --- a/source/6LoWPAN/ws/ws_neighbor_class.h +++ b/source/6LoWPAN/ws/ws_neighbor_class.h @@ -45,6 +45,7 @@ typedef struct ws_neighbor_class_s { uint8_t list_size; /*!< List size*/ } ws_neighbor_class_t; + /** * ws_neighbor_class_alloc a function for allocate giving list size * diff --git a/source/6LoWPAN/ws/ws_pae_auth.c b/source/6LoWPAN/ws/ws_pae_auth.c index e8ea19ac19c..8e20e856fb1 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.c +++ b/source/6LoWPAN/ws/ws_pae_auth.c @@ -63,6 +63,13 @@ long to wait for previous negotiation to complete */ #define EAP_TLS_NEGOTIATION_TRIGGER_TIMEOUT 60 * 10 // 60 seconds +// Default for maximum number of supplicants +#define SUPPLICANT_MAX_NUMBER 1000 + +/* Default for number of supplicants to purge per garbage collect call from + nanostack monitor */ +#define SUPPLICANT_NUMBER_TO_PURGE 5 + typedef struct { ns_list_link_t link; /**< Link */ kmp_service_t *kmp_service; /**< KMP service */ @@ -77,6 +84,7 @@ typedef struct { sec_prot_gtk_keys_t *next_gtks; /**< Next GTKs */ const sec_prot_certs_t *certs; /**< Certificates */ timer_settings_t *timer_settings; /**< Timer settings */ + uint16_t supp_max_number; /**< Max number of stored supplicants */ uint16_t slow_timer_seconds; /**< Slow timer seconds */ bool timer_running : 1; /**< Timer is running */ bool gtk_new_inst_req_exp : 1; /**< GTK new install required timer expired */ @@ -140,6 +148,8 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot pae_auth->next_gtks = next_gtks; pae_auth->certs = certs; pae_auth->timer_settings = timer_settings; + pae_auth->supp_max_number = SUPPLICANT_MAX_NUMBER; + pae_auth->slow_timer_seconds = 0; pae_auth->gtk_new_inst_req_exp = false; pae_auth->gtk_new_act_time_exp = false; @@ -202,6 +212,14 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot return -1; } +int8_t ws_pae_auth_timing_adjust(uint8_t timing) +{ + auth_gkh_sec_prot_timing_adjust(timing); + auth_fwh_sec_prot_timing_adjust(timing); + auth_eap_tls_sec_prot_timing_adjust(timing); + return 0; +} + int8_t ws_pae_auth_addresses_set(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port) { if (!interface_ptr || !remote_addr) { @@ -407,6 +425,38 @@ int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *int return 0; } +int8_t ws_pae_auth_node_limit_set(protocol_interface_info_entry_t *interface_ptr, uint16_t limit) +{ + if (!interface_ptr) { + return -1; + } + + pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); + if (!pae_auth) { + return -1; + } + + pae_auth->supp_max_number = limit; + + return 0; +} + +void ws_pae_auth_forced_gc(protocol_interface_info_entry_t *interface_ptr) +{ + if (!interface_ptr) { + return; + } + + pae_auth_t *pae_auth = ws_pae_auth_get(interface_ptr); + if (!pae_auth) { + return; + } + + /* Purge in maximum five entries from supplicant list (starting from oldest one) + per call to the function (called by nanostack monitor) */ + ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, 0, SUPPLICANT_NUMBER_TO_PURGE); +} + static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth) { // Authenticator keys are always fresh @@ -758,6 +808,9 @@ static kmp_api_t *ws_pae_auth_kmp_incoming_ind(kmp_service_t *service, kmp_type_ // If does not exists add it to list if (!supp_entry) { + // Checks if maximum number of supplicants is reached and purge supplicant list (starting from oldest one) + ws_pae_lib_supp_list_purge(&pae_auth->active_supp_list, &pae_auth->inactive_supp_list, pae_auth->supp_max_number, 0); + supp_entry = ws_pae_lib_supp_list_add(&pae_auth->active_supp_list, addr); if (!supp_entry) { return 0; diff --git a/source/6LoWPAN/ws/ws_pae_auth.h b/source/6LoWPAN/ws/ws_pae_auth.h index dec5eb69ec0..5c0f35d9609 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.h +++ b/source/6LoWPAN/ws/ws_pae_auth.h @@ -54,6 +54,28 @@ */ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, timer_settings_t *timer_settings); +/** + * ws_pae_auth_timing_adjust Adjust retries and timings of the security protocols + * + * Timing value is a generic number between 0 to 32 that goes from fast and + * reactive network to low bandwidth and long latency. + * + * example value definitions: + * 0-8 very fast network + * 9-16 medium network + * 16-24 slow network + * 25-32 extremely slow network + * + * There is no need to have lots variations in every layer if protocol is not very active in any case. + * + * \param timing Timing value. + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_auth_timing_adjust(uint8_t timing); + /** * ws_pae_auth_addresses_set set relay addresses * @@ -146,6 +168,26 @@ int8_t ws_pae_auth_node_keys_remove(protocol_interface_info_entry_t *interface_p */ int8_t ws_pae_auth_node_access_revoke_start(protocol_interface_info_entry_t *interface_ptr); +/** + * ws_pae_auth_node_limit_set set node limit + * + * \param interface_ptr interface + * \param limit limit for nodes + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_auth_node_limit_set(protocol_interface_info_entry_t *interface_ptr, uint16_t limit); + +/** + * ws_pae_auth_forced_gc garbage cleanup call + * + * \param interface_ptr interface + * + */ +void ws_pae_auth_forced_gc(protocol_interface_info_entry_t *interface_ptr); + /** * ws_pae_auth_gtk_hash_set GTK hash set callback * @@ -190,6 +232,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ #else #define ws_pae_auth_init(interface_ptr, gtks, next_gtks, certs, timer_settings) 1 +#define ws_pae_auth_timing_adjust(timing) 1 #define ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) 1 #define ws_pae_auth_delete NULL #define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set) {(void) hash_set;} @@ -198,6 +241,8 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ #define ws_pae_auth_nw_key_index_update NULL #define ws_pae_auth_node_keys_remove(interface_ptr, eui64) -1 #define ws_pae_auth_node_access_revoke_start(interface_ptr) +#define ws_pae_auth_node_limit_set(interface_ptr, limit) +#define ws_pae_auth_forced_gc(interface_ptr) #define ws_pae_auth_fast_timer NULL #define ws_pae_auth_slow_timer NULL diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index c001c2364a6..086ec063936 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -97,6 +97,11 @@ typedef struct { bool key_index_set : 1; /**< NW key index is set */ } pae_controller_t; +typedef struct { + uint16_t node_limit; /**< Max number of stored supplicants */ + bool node_limit_set : 1; /**< Node limit set */ +} pae_controller_config_t; + static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr); static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry); static void ws_pae_controller_frame_counter_store(pae_controller_t *entry); @@ -119,6 +124,11 @@ static const char *FRAME_COUNTER_FILE = FRAME_COUNTER_FILE_NAME; static NS_LIST_DEFINE(pae_controller_list, pae_controller_t, link); +pae_controller_config_t pae_controller_config = { + .node_limit = 0, + .node_limit_set = false +}; + #if !defined(HAVE_PAE_SUPP) && !defined(HAVE_PAE_AUTH) static void ws_pae_controller_test_keys_set(sec_prot_gtk_keys_t *gtks) @@ -172,6 +182,25 @@ int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface return 0; } +int8_t ws_pae_controller_bootstrap_done(protocol_interface_info_entry_t *interface_ptr) +{ + pae_controller_t *controller = ws_pae_controller_get(interface_ptr); + if (!controller) { + return -1; + } + +#ifdef HAVE_PAE_SUPP + // RPL parent is known, remove EAPOL target that what was set using the authenticate call */ + ws_pae_supp_eapol_target_remove(interface_ptr); + + /* Trigger GTK hash update to supplicant, so it can check whether keys have been updated + during bootstrap. Does nothing if GTKs are up to date. */ + ws_pae_supp_gtk_hash_update(interface_ptr, controller->gtkhash); +#endif + + return 0; +} + int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *interface_ptr, uint16_t local_port, const uint8_t *remote_addr, uint16_t remote_port) { (void) local_port; @@ -204,6 +233,10 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in return -1; } + if (pae_controller_config.node_limit_set) { + ws_pae_auth_node_limit_set(controller->interface_ptr, pae_controller_config.node_limit); + } + ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set); ws_pae_auth_start(interface_ptr); @@ -696,6 +729,13 @@ int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr) return 0; } +int8_t ws_pae_controller_timing_adjust(uint8_t timing) +{ + ws_pae_supp_timing_adjust(timing); + ws_pae_auth_timing_adjust(timing); + return 0; +} + int8_t ws_pae_controller_certificate_chain_set(const arm_certificate_chain_entry_s *new_chain) { if (!new_chain) { @@ -990,6 +1030,41 @@ int8_t ws_pae_controller_node_access_revoke_start(int8_t interface_id) return -1; } +int8_t ws_pae_controller_node_limit_set(int8_t interface_id, uint16_t limit) +{ +#ifdef HAVE_PAE_AUTH + pae_controller_config.node_limit = limit; + pae_controller_config.node_limit_set = true; + + pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id); + if (!controller) { + return -1; + } + + ws_pae_auth_node_limit_set(controller->interface_ptr, limit); + + return 0; +#else + (void) interface_id; + (void) limit; + return -1; +#endif +} + +void ws_pae_controller_forced_gc(bool full_gc) +{ + /* Purge only when on critical limit since node limit should handle limiting + of entries in normal case */ + if (!full_gc) { + return; + } + + // Purge authenticators for each interface + ns_list_foreach(pae_controller_t, entry, &pae_controller_list) { + ws_pae_auth_forced_gc(entry->interface_ptr); + } +} + static void ws_pae_controller_gtk_hash_set(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash) { pae_controller_t *controller = ws_pae_controller_get(interface_ptr); @@ -1086,7 +1161,6 @@ static void ws_pae_controller_frame_counter_store(pae_controller_t *entry) } } - static int8_t ws_pae_controller_nvm_frame_counter_read(uint8_t *index, uint8_t *hash, uint32_t *frame_counter) { nvm_tlv_list_t tlv_list; diff --git a/source/6LoWPAN/ws/ws_pae_controller.h b/source/6LoWPAN/ws/ws_pae_controller.h index 2f1b6ce0502..b34a61ae374 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.h +++ b/source/6LoWPAN/ws/ws_pae_controller.h @@ -45,6 +45,17 @@ int8_t ws_pae_controller_set_target(protocol_interface_info_entry_t *interface_p */ int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface_ptr); +/** + * ws_pae_controller_bootstrap_done indicates to PAE controller that bootstrap is ready + * + * \param interface_ptr interface + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_controller_bootstrap_done(protocol_interface_info_entry_t *interface_ptr); + /** * ws_pae_controller_authenticator_start start PAE authenticator * @@ -114,6 +125,28 @@ int8_t ws_pae_controller_stop(protocol_interface_info_entry_t *interface_ptr); */ int8_t ws_pae_controller_delete(protocol_interface_info_entry_t *interface_ptr); +/** + * ws_pae_controller_timing_adjust Adjust retries and timings of the security protocols + * + * Timing value is a generic number between 0 to 32 that goes from fast and + * reactive network to low bandwidth and long latency. + * + * example value definitions: + * 0-8 very fast network + * 9-16 medium network + * 16-24 slow network + * 25-32 extremely slow network + * + * There is no need to have lots variations in every layer if protocol is not very active in any case. + * + * \param timing Timing value. + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_controller_timing_adjust(uint8_t timing); + /** * ws_pae_controller_certificate_chain_set set certificate chain * @@ -293,6 +326,18 @@ int8_t ws_pae_controller_node_keys_remove(int8_t interface_id, uint8_t *eui_64); */ int8_t ws_pae_controller_node_access_revoke_start(int8_t interface_id); +/** + * ws_pae_controller_node_limit_set set node limit + * + * \param interface_id interface identifier + * \param limit limit for nodes + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_controller_node_limit_set(int8_t interface_id, uint16_t limit); + /** * ws_pae_controller_active_key_update update active key (test interface) * @@ -437,7 +482,6 @@ int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ */ void ws_pae_controller_fast_timer(uint16_t ticks); - /** * ws_pae_controller_slow_timer PAE controller slow timer call * @@ -448,6 +492,14 @@ void ws_pae_controller_slow_timer(uint16_t seconds); struct nvm_tlv_entry *ws_pae_controller_nvm_tlv_get(protocol_interface_info_entry_t *interface_ptr); +/** + * ws_pae_controller_forced_gc PAE controller garbage cleanup callback + * + * \param full_gc Full cleanup (true for critical garbage cleanup) + * + */ +void ws_pae_controller_forced_gc(bool full_gc); + #else #define ws_pae_controller_set_target(interface_ptr, target_pan_id, target_dest_eui_64) @@ -470,6 +522,8 @@ struct nvm_tlv_entry *ws_pae_controller_nvm_tlv_get(protocol_interface_info_entr #define ws_pae_controller_cb_register(interface_ptr, completed, nw_key_set, nw_key_clear, nw_send_key_index_set, pan_ver_increment) 1 #define ws_pae_controller_nvm_tlv_get(interface_ptr) NULL +#define ws_pae_controller_forced_gc NULL + #endif #endif /* WS_PAE_CONTROLLER_H_ */ diff --git a/source/6LoWPAN/ws/ws_pae_lib.c b/source/6LoWPAN/ws/ws_pae_lib.c index 6886a71408e..d01917d955a 100644 --- a/source/6LoWPAN/ws/ws_pae_lib.c +++ b/source/6LoWPAN/ws/ws_pae_lib.c @@ -316,6 +316,30 @@ void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t memset(entry->addr.relay_address, 0, 16); } +void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, uint16_t max_number, uint8_t max_purge) +{ + uint16_t active_supp = ns_list_count(active_supp_list); + uint16_t inactive_supp = ns_list_count(inactive_supp_list); + + if (active_supp + inactive_supp > max_number) { + uint16_t remove_count = active_supp + inactive_supp - max_number; + if (max_purge > 0 && remove_count > max_purge) { + remove_count = max_purge; + } + + // Remove entries from inactive list + ns_list_foreach_safe(supp_entry_t, entry, inactive_supp_list) { + if (remove_count > 0) { + tr_info("Inactive supplicant removed, eui-64: %s", trace_array(kmp_address_eui_64_get(&entry->addr), 8)); + ws_pae_lib_supp_list_remove(inactive_supp_list, entry); + remove_count--; + } else { + break; + } + } + } +} + uint16_t ws_pae_lib_supp_list_kmp_count(supp_list_t *supp_list, kmp_type_e type) { uint16_t kmp_count = 0; diff --git a/source/6LoWPAN/ws/ws_pae_lib.h b/source/6LoWPAN/ws/ws_pae_lib.h index 2569637dee1..69b4a7aeda9 100644 --- a/source/6LoWPAN/ws/ws_pae_lib.h +++ b/source/6LoWPAN/ws/ws_pae_lib.h @@ -33,7 +33,7 @@ typedef NS_LIST_HEAD(kmp_entry_t, link) kmp_list_t; typedef struct { kmp_list_t kmp_list; /**< Ongoing KMP negotiations */ - kmp_addr_t addr; /**< EUI-64 (Relay IP address, Relay port) */ + kmp_addr_t addr; /**< EUI-64 (Relay IP address, Relay port) */ sec_prot_keys_t sec_keys; /**< Security keys */ uint32_t ticks; /**< Ticks */ uint16_t retry_ticks; /**< Retry ticks */ @@ -280,6 +280,18 @@ void ws_pae_lib_supp_list_to_active(supp_list_t *active_supp_list, supp_list_t * */ void ws_pae_lib_supp_list_to_inactive(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, supp_entry_t *entry); +/** + * ws_pae_lib_supp_list_purge purge inactive supplicants list + * + * \param active_supp_list list of active supplicants + * \param inactive_supp_list list of inactive supplicants + * \param max_number maximum number of supplicant entries, can be set to 0 in combination with max_purge + * to free list entries even when maximum number supplicant entries has not been reached + * \param max_purge maximum number of supplicants to purge in one call, 0 means not limited + * + */ +void ws_pae_lib_supp_list_purge(supp_list_t *active_supp_list, supp_list_t *inactive_supp_list, uint16_t max_number, uint8_t max_purge); + /** * ws_pae_lib_supp_list_kmp_count counts the number of KMPs of a certain type in a list of supplicants * diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index a89bf1cdaeb..ae7abe7a0d5 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -166,6 +166,11 @@ static void ws_pae_supp_address_set(pae_supp_t *pae_supp, kmp_addr_t *address) } } +static bool ws_pae_supp_address_is_set(pae_supp_t *pae_supp) +{ + return pae_supp->entry_address_active; +} + int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr, uint16_t dest_pan_id, uint8_t *dest_eui_64) { pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr); @@ -321,6 +326,9 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt ws_pae_supp_timer_start(pae_supp); tr_info("GTK update start imin: %i, imax: %i, max mismatch: %i, tr time: %i", pae_supp->timer_settings->gtk_request_imin, pae_supp->timer_settings->gtk_request_imax, pae_supp->timer_settings->gtk_max_mismatch, pae_supp->auth_trickle_timer.t); + } else { + // If trickle is already running, set inconsistent heard to speed up the trickle + trickle_inconsistent_heard(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params); } } @@ -346,6 +354,19 @@ int8_t ws_pae_supp_nw_key_index_update(protocol_interface_info_entry_t *interfac return 0; } +int8_t ws_pae_supp_eapol_target_remove(protocol_interface_info_entry_t *interface_ptr) +{ + pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr); + if (!pae_supp) { + return -1; + } + + // Sets target/parent address to null + ws_pae_supp_address_set(pae_supp, NULL); + + return 0; +} + static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp) { // Check if NW info or GTKs have been changed @@ -450,15 +471,21 @@ static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp) if (!pae_supp->auth_requested) { // If not making initial authentication updates target (RPL parent) for each EAPOL-key message uint8_t parent_eui_64[8]; - if (ws_pae_supp_parent_eui_64_get(pae_supp->interface_ptr, parent_eui_64) < 0) { + if (ws_pae_supp_parent_eui_64_get(pae_supp->interface_ptr, parent_eui_64) >= 0) { + // Stores target/parent address + kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, parent_eui_64); + // Sets parent address in use + ws_pae_supp_address_set(pae_supp, &pae_supp->target_addr); + } else if (ws_pae_supp_address_is_set(pae_supp)) { + /* If there is no RPL parent but there is target address from initial authentication + bootstrap, tries to use it. This can happen if BR updates keys after EAPOL authentication + but before bootstrap is completed and RPL parent is known */ + tr_info("EAPOL initial auth target used"); + } else { + // No target, failure return -1; } - // Stores target/parent address - kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, parent_eui_64); - // Sets parent address in use - ws_pae_supp_address_set(pae_supp, &pae_supp->target_addr); - ws_pae_lib_supp_timer_ticks_set(&pae_supp->entry, WAIT_FOR_REAUTHENTICATION_TICKS); tr_info("PAE wait for auth seconds: %i", WAIT_FOR_REAUTHENTICATION_TICKS / 10); } @@ -656,6 +683,13 @@ int8_t ws_pae_supp_delete(protocol_interface_info_entry_t *interface_ptr) return 0; } +int8_t ws_pae_supp_timing_adjust(uint8_t timing) +{ + supp_fwh_sec_prot_timing_adjust(timing); + supp_eap_sec_prot_timing_adjust(timing); + return 0; +} + static void ws_pae_supp_free(pae_supp_t *pae_supp) { if (!pae_supp) { @@ -751,10 +785,7 @@ void ws_pae_supp_fast_timer(uint16_t ticks) // Checks whether timer needs to be active if (!pae_supp->initial_key_timer && !pae_supp->auth_trickle_running && !running) { - tr_debug("PAE idle"); - // Sets target/parent address to null - ws_pae_supp_address_set(pae_supp, NULL); // If not already completed, restart bootstrap ws_pae_supp_authenticate_response(pae_supp, false); @@ -770,7 +801,9 @@ void ws_pae_supp_slow_timer(uint16_t seconds) // Checks whether initial EAPOL-Key message needs to be re-send or new GTK request to be sent if (pae_supp->auth_trickle_running) { if (trickle_timer(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params, seconds)) { - ws_pae_supp_initial_key_send(pae_supp); + if (ws_pae_supp_initial_key_send(pae_supp) < 0) { + tr_info("EAPOL-Key send failed"); + } } // Maximum number of trickle expires, authentication fails if (!trickle_running(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params)) { @@ -793,14 +826,15 @@ void ws_pae_supp_slow_timer(uint16_t seconds) pae_supp->initial_key_timer = 0; // Sends initial EAPOL-Key message - ws_pae_supp_initial_key_send(pae_supp); + if (ws_pae_supp_initial_key_send(pae_supp) < 0) { + tr_info("EAPOL-Key send failed"); + } // Starts trickle pae_supp->auth_trickle_params = initial_eapol_key_trickle_params; trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params); pae_supp->auth_trickle_running = true; } - } } } diff --git a/source/6LoWPAN/ws/ws_pae_supp.h b/source/6LoWPAN/ws/ws_pae_supp.h index 4d22d73f91d..24de962fe3c 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.h +++ b/source/6LoWPAN/ws/ws_pae_supp.h @@ -57,6 +57,29 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se */ int8_t ws_pae_supp_delete(protocol_interface_info_entry_t *interface_ptr); + +/** + * ws_pae_supp_timing_adjust Adjust retries and timings of the 4WH protocol + * + * Timing value is a generic number between 0 to 32 that goes from fast and + * reactive network to low bandwidth and long latency. + * + * example value definitions: + * 0-8 very fast network + * 9-16 medium network + * 16-24 slow network + * 25-32 extremely slow network + * + * There is no need to have lots variations in every layer if protocol is not very active in any case. + * + * \param timing Timing value. + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_supp_timing_adjust(uint8_t timing); + /** * ws_pae_supp_fast_timer PAE supplicant fast timer call * @@ -159,6 +182,17 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt */ int8_t ws_pae_supp_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index); +/** + * ws_pae_supp_eapol_target_remove remove EAPOL target set using authentication start + * + * \param interface_ptr interface + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t ws_pae_supp_eapol_target_remove(protocol_interface_info_entry_t *interface_ptr); + /** * ws_pae_supp_nw_key_index_set network send key index set callback * @@ -204,6 +238,7 @@ void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ #define ws_pae_supp_init(interface_ptr, certs, timer_settings) 1 #define ws_pae_supp_delete NULL +#define ws_pae_supp_timing_adjust(timing) 1 #define ws_pae_supp_cb_register(interface_ptr, completed, nw_key_insert, nw_key_index_set) #define ws_pae_supp_nw_info_set(interface_ptr, pan_id, network_name) -1 #define ws_pae_supp_nw_key_valid(interface_ptr) -1 @@ -214,6 +249,7 @@ void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ #define ws_pae_supp_border_router_addr_read NULL #define ws_pae_supp_gtk_hash_update NULL #define ws_pae_supp_nw_key_index_update NULL +#define ws_pae_supp_eapol_target_remove(interface_ptr) #endif diff --git a/source/Common_Protocols/icmpv6.c b/source/Common_Protocols/icmpv6.c index bcd659f9b99..a1cb4042e8d 100644 --- a/source/Common_Protocols/icmpv6.c +++ b/source/Common_Protocols/icmpv6.c @@ -1049,8 +1049,10 @@ buffer_t *icmpv6_up(buffer_t *buf) buf->options.code = *dptr++; if (buf->options.ll_security_bypass_rx) { - if (!ws_info(buf->interface) || !(buf->options.type == ICMPV6_TYPE_INFO_RPL_CONTROL && buf->options.code == ICMPV6_CODE_RPL_DIS)) { - //tr_debug("ICMP: Drop by EP"); + if (!ws_info(buf->interface) + || (buf->options.type == ICMPV6_TYPE_INFO_RPL_CONTROL + && (buf->options.code != ICMPV6_CODE_RPL_DIO + && buf->options.code != ICMPV6_CODE_RPL_DIS))) { goto drop; } } diff --git a/source/Core/ns_monitor.c b/source/Core/ns_monitor.c index 5377fb0962a..54d6ecaceac 100644 --- a/source/Core/ns_monitor.c +++ b/source/Core/ns_monitor.c @@ -33,6 +33,8 @@ #include "nsdynmemLIB.h" #include "ipv6_stack/ipv6_routing_table.h" #include "NWK_INTERFACE/Include/protocol.h" +#include "6LoWPAN/ws/ws_pae_controller.h" +#include "NWK_INTERFACE/Include/protocol.h" #define TRACE_GROUP "mntr" @@ -68,7 +70,8 @@ typedef void (ns_maintenance_gc_cb)(bool full_gc); * */ static ns_maintenance_gc_cb *ns_maintenance_gc_functions[] = { - ipv6_destination_cache_forced_gc + ipv6_destination_cache_forced_gc, + ws_pae_controller_forced_gc }; static void ns_monitor_heap_gc(bool full_gc) diff --git a/source/RPL/rpl_control.c b/source/RPL/rpl_control.c index 2e7b7632088..f176350b9e7 100644 --- a/source/RPL/rpl_control.c +++ b/source/RPL/rpl_control.c @@ -380,11 +380,12 @@ void rpl_control_remove_domain_from_interface(protocol_interface_info_entry_t *c } } -void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, void *cb_handle) +void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, rpl_new_parent_callback_t new_parent_add, void *cb_handle) { domain->callback = callback; domain->prefix_cb = prefix_learn_cb; domain->cb_handle = cb_handle; + domain->new_parent_add = new_parent_add; } /* To do - this should live somewhere nicer. Basically a bootstrap @@ -976,6 +977,9 @@ static buffer_t *rpl_control_dio_handler(protocol_interface_info_entry_t *cur, r const rpl_dodag_conf_t *conf = rpl_dodag_get_config(dodag); if (!conf) { /* TODO - rate limit DIS? */ + if (domain->new_parent_add && !domain->new_parent_add(buf->src_sa.address, domain->cb_handle)) { + goto invalid_parent; + } rpl_control_transmit_dis(domain, cur, RPL_SOLINFO_PRED_DODAGID | RPL_SOLINFO_PRED_INSTANCEID, instance_id, dodagid, 0, buf->src_sa.address); goto invalid_parent; } @@ -1008,9 +1012,15 @@ static buffer_t *rpl_control_dio_handler(protocol_interface_info_entry_t *cur, r /* Now we create the neighbour, if we don't already have a record */ if (!neighbour) { neighbour = rpl_create_neighbour(version, buf->src_sa.address, cur->id, g_mop_prf, dtsn); + //Call Here new parent create if (!neighbour) { goto invalid_parent; } + + if (domain->new_parent_add && !domain->new_parent_add(buf->src_sa.address, domain->cb_handle)) { + goto invalid_parent; + } + } /* Update neighbour info */ diff --git a/source/RPL/rpl_control.h b/source/RPL/rpl_control.h index f9c1b39e094..c9c1d7f176f 100644 --- a/source/RPL/rpl_control.h +++ b/source/RPL/rpl_control.h @@ -42,6 +42,8 @@ typedef void rpl_domain_callback_t(rpl_event_t event, void *handle); typedef void rpl_prefix_callback_t(struct prefix_entry_t *prefix, void *handle, uint8_t *parent_link_local); +typedef bool rpl_new_parent_callback_t(uint8_t *ll_parent_address, void *handle); + typedef struct rpl_domain { NS_LIST_HEAD_INCOMPLETE(struct rpl_instance) instances; ns_list_link_t link; @@ -54,6 +56,7 @@ typedef struct rpl_domain { bool force_leaf; rpl_domain_callback_t *callback; rpl_prefix_callback_t *prefix_cb; + rpl_new_parent_callback_t *new_parent_add; void *cb_handle; } rpl_domain_t; @@ -142,7 +145,7 @@ rpl_domain_t *rpl_control_create_domain(void); void rpl_control_delete_domain(rpl_domain_t *domain); void rpl_control_set_domain_on_interface(struct protocol_interface_info_entry *cur, rpl_domain_t *domain, bool downstream); void rpl_control_remove_domain_from_interface(struct protocol_interface_info_entry *cur); -void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, void *cb_handle); +void rpl_control_set_callback(rpl_domain_t *domain, rpl_domain_callback_t callback, rpl_prefix_callback_t prefix_learn_cb, rpl_new_parent_callback_t new_parent_add, void *cb_handle); /* Target publishing */ void rpl_control_publish_host_address(rpl_domain_t *domain, const uint8_t addr[16], uint32_t lifetime); diff --git a/source/RPL/rpl_downward.c b/source/RPL/rpl_downward.c index 3c6da959dad..ad9cde193c7 100644 --- a/source/RPL/rpl_downward.c +++ b/source/RPL/rpl_downward.c @@ -180,6 +180,16 @@ static void rpl_downward_target_refresh(rpl_dao_target_t *target) target->info.non_root.path_lifetime = 0; } +static bool rpl_instance_parent_selection_ready(rpl_instance_t *instance) +{ + rpl_neighbour_t *neighbour = ns_list_get_first(&instance->candidate_neighbours); + if (neighbour && neighbour->dodag_parent && neighbour->dao_path_control) { + //We have a Primary parent with Dao patha control + return true; + } + return false; +} + void rpl_downward_neighbour_gone(rpl_instance_t *instance, rpl_neighbour_t *neighbour) { if (neighbour->dao_path_control == 0) { @@ -380,6 +390,7 @@ void rpl_instance_publish_dao_target(rpl_instance_t *instance, const uint8_t *pr tr_debug("New Target %s", trace_ipv6(target->prefix)); /* Path lifetime left as 0 for now - will be filled in on transmission, along with refresh timer */ rpl_instance_dao_trigger(instance, 0); + } void rpl_instance_dao_trigger(rpl_instance_t *instance, uint16_t delay) @@ -627,6 +638,11 @@ static rpl_dao_target_t *rpl_instance_get_pending_target_confirmation(rpl_instan void rpl_instance_send_address_registration(rpl_instance_t *instance, const uint8_t addr[16]) { + if (!rpl_instance_parent_selection_ready(instance)) { + return; + } + + if (addr) { rpl_dao_target_t *target = rpl_instance_get_pending_target_confirmation_for_address(instance, addr); if (!target) { @@ -1751,7 +1767,18 @@ static if_address_entry_t *rpl_interface_addr_get(protocol_interface_info_entry_ return NULL; } +static void rpl_instance_address_registration_cancel(rpl_instance_t *instance) +{ + ns_list_foreach_safe(rpl_dao_target_t, n, &instance->dao_targets) { + n->active_confirmation_state = false; + n->trig_confirmation_state = false; + n->response_wait_time = 0; + } + instance->wait_response = NULL; + instance->pending_neighbour_confirmation = false; + instance->delay_dao_timer = 0; +} void rpl_instance_parent_address_reg_timer_update(rpl_instance_t *instance, uint16_t seconds) { @@ -1759,6 +1786,12 @@ void rpl_instance_parent_address_reg_timer_update(rpl_instance_t *instance, uint return; //No need validate any confirmation } + //Verify that we have selected parent and it have a dao path control + if (!rpl_instance_parent_selection_ready(instance)) { + rpl_instance_address_registration_cancel(instance); + return; + } + //Get Pendig active target rpl_dao_target_t *dao_target = rpl_instance_get_active_target_confirmation(instance); if (!dao_target) { @@ -1772,8 +1805,7 @@ void rpl_instance_parent_address_reg_timer_update(rpl_instance_t *instance, uint } if (instance->wait_response) { - uint16_t wait_time = dao_target->response_wait_time; - if (seconds < wait_time) { + if (seconds < dao_target->response_wait_time) { //Must Wait response time untill finish dao_target->response_wait_time -= seconds; return; @@ -1792,17 +1824,13 @@ void rpl_instance_parent_address_reg_timer_update(rpl_instance_t *instance, uint //Get address and buffer protocol_interface_info_entry_t *interface = protocol_stack_interface_info_get_by_id(neighbour->interface_id); if (!interface) { - dao_target->response_wait_time = 0; - instance->wait_response = NULL; - dao_target->active_confirmation_state = false; + rpl_instance_address_registration_cancel(instance); return; } if_address_entry_t *address = rpl_interface_addr_get(interface, dao_target->prefix); if (!address) { - dao_target->response_wait_time = 0; - instance->wait_response = NULL; - dao_target->active_confirmation_state = false; + rpl_instance_address_registration_cancel(instance); return; } @@ -1839,6 +1867,7 @@ void rpl_instance_address_registration_done(protocol_interface_info_entry_t *int } else { tr_error("Address registration failed"); rpl_delete_neighbour(instance, neighbour); + rpl_instance_address_registration_cancel(instance); } } diff --git a/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c b/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c index d562e90601e..3e1c1c7fb67 100644 --- a/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c +++ b/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.c @@ -69,9 +69,18 @@ typedef struct { bool send_pending: 1; /**< TLS data is not yet send to network */ } eap_tls_sec_prot_int_t; -static const trickle_params_t eap_tls_trickle_params = { - .Imin = 200, /* 20s; ticks are 100ms */ - .Imax = 450, /* 45s */ +/*Small network setup*/ +#define EAP_TLS_SMALL_IMIN 300 // retries done in 30 seconds +#define EAP_TLS_SMALL_IMAX 900 // Largest value 90 seconds + +/* Large network setup*/ +#define EAP_TLS_LARGE_IMIN 600 // retries done in 60 seconds +#define EAP_TLS_LARGE_IMAX 2400 // Largest value 240 seconds + + +static trickle_params_t eap_tls_trickle_params = { + .Imin = EAP_TLS_SMALL_IMIN, /* ticks are 100ms */ + .Imax = EAP_TLS_SMALL_IMAX, /* ticks are 100ms */ .k = 0, /* infinity - no consistency checking */ .TimerExpirations = 2 }; @@ -109,6 +118,19 @@ int8_t auth_eap_tls_sec_prot_register(kmp_service_t *service) return 0; } +int8_t auth_eap_tls_sec_prot_timing_adjust(uint8_t timing) +{ + + if (timing < 16) { + eap_tls_trickle_params.Imin = EAP_TLS_SMALL_IMIN; + eap_tls_trickle_params.Imax = EAP_TLS_SMALL_IMAX; + } else { + eap_tls_trickle_params.Imin = EAP_TLS_LARGE_IMIN; + eap_tls_trickle_params.Imax = EAP_TLS_LARGE_IMAX; + } + return 0; +} + static uint16_t auth_eap_tls_sec_prot_size(void) { return sizeof(eap_tls_sec_prot_int_t); @@ -430,8 +452,6 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot) return; } - sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE); - // EAP response if (data->eap_code == EAP_RESPONSE) { // Handle EAP response, TLS EAP @@ -445,6 +465,8 @@ static void auth_eap_tls_sec_prot_state_machine(sec_prot_t *prot) return; } + sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_RESPONSE); + // All fragments received for a message if (result == EAP_TLS_MSG_RECEIVE_DONE) { auth_eap_tls_sec_prot_init_tls(prot); diff --git a/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.h b/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.h index cbe295247a0..8c3e1185b9c 100644 --- a/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.h +++ b/source/Security/protocols/eap_tls_sec_prot/auth_eap_tls_sec_prot.h @@ -33,4 +33,26 @@ */ int8_t auth_eap_tls_sec_prot_register(kmp_service_t *service); +/** + * auth_eap_tls_sec_prot_timing_adjust Adjust retries and timings of the EAP-TLS protocol + * + * Timing value is a generic number between 0 to 32 that goes from fast and + * reactive network to low bandwidth and long latency. + * + * example value definitions: + * 0-8 very fast network + * 9-16 medium network + * 16-24 slow network + * 25-32 extremely slow network + * + * There is no need to have lots variations in every layer if protocol is not very active in any case. + * + * \param timing Timing value. + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t auth_eap_tls_sec_prot_timing_adjust(uint8_t timing); + #endif /* AUTH_EAP_TLS_SEC_PROT_H_ */ diff --git a/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c b/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c index ebbed366860..dadbdc17d33 100644 --- a/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c +++ b/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.c @@ -72,12 +72,10 @@ typedef struct { bool send_pending: 1; /**< TLS data is not yet send to network */ } eap_tls_sec_prot_int_t; -static const trickle_params_t eap_tls_trickle_params = { - .Imin = 200, /* 20s; ticks are 100ms */ - .Imax = 450, /* 45s */ - .k = 0, /* infinity - no consistency checking */ - .TimerExpirations = 2 -}; +#define FWH_RETRY_TIMEOUT_SMALL 330*10 // retry timeout for small network additional 30 seconds for authenticator delay +#define FWH_RETRY_TIMEOUT_LARGE 750*10 // retry timeout for large network additional 30 seconds for authenticator delay + +static uint16_t retry_timeout = FWH_RETRY_TIMEOUT_SMALL; static uint16_t supp_eap_tls_sec_prot_size(void); static int8_t supp_eap_tls_sec_prot_init(sec_prot_t *prot); @@ -112,6 +110,17 @@ int8_t supp_eap_tls_sec_prot_register(kmp_service_t *service) return 0; } +int8_t supp_eap_sec_prot_timing_adjust(uint8_t timing) +{ + if (timing < 16) { + retry_timeout = FWH_RETRY_TIMEOUT_SMALL; + } else { + retry_timeout = FWH_RETRY_TIMEOUT_LARGE; + } + return 0; +} + + static uint16_t supp_eap_tls_sec_prot_size(void) { return sizeof(eap_tls_sec_prot_int_t); @@ -281,7 +290,7 @@ static void supp_eap_tls_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks data->burst_filt_timer = 0; } - sec_prot_timer_timeout_handle(prot, &data->common, &eap_tls_trickle_params, ticks); + sec_prot_timer_timeout_handle(prot, &data->common, NULL, ticks); } static void supp_eap_tls_sec_prot_tls_create_confirm(sec_prot_t *tls_prot, sec_prot_result_e result) @@ -420,9 +429,6 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot) // Send EAP response, Identity supp_eap_tls_sec_prot_message_send(prot, EAP_RESPONSE, EAP_IDENTITY, EAP_TLS_EXCHANGE_NONE); - // Start trickle timer to re-send if no response - sec_prot_timer_trickle_start(&data->common, &eap_tls_trickle_params); - sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_REQUEST_TLS_EAP); } else { // Ready to be deleted @@ -431,12 +437,6 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot) break; case EAP_TLS_STATE_REQUEST_TLS_EAP: - // On timeout - if (sec_prot_result_timeout_check(&data->common)) { - /* Waits for next trickle expire. If trickle expirations reach the limit, - terminates EAP-TLS */ - return; - } // Handle EAP request (expected TLS EAP start) result = supp_eap_tls_sec_prot_message_handle(prot); @@ -456,6 +456,7 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot) supp_eap_tls_sec_prot_seq_id_update(prot); sec_prot_state_set(prot, &data->common, EAP_TLS_STATE_REQUEST); + data->common.ticks = retry_timeout; // Initialize TLS protocol supp_eap_tls_sec_prot_init_tls(prot); @@ -464,12 +465,6 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot) break; case EAP_TLS_STATE_REQUEST: - // On timeout - if (sec_prot_result_timeout_check(&data->common)) { - /* Waits for next trickle expire. If trickle expirations reach the limit, - terminates EAP-TLS */ - return; - } // EAP success if (data->eap_code == EAP_SUCCESS) { @@ -514,8 +509,9 @@ static void supp_eap_tls_sec_prot_state_machine(sec_prot_t *prot) supp_eap_tls_sec_prot_message_send(prot, EAP_RESPONSE, EAP_TLS, EAP_TLS_EXCHANGE_ONGOING); data->send_pending = false; - // Start trickle timer to re-send if no response - sec_prot_timer_trickle_start(&data->common, &eap_tls_trickle_params); + // Add more time for re-send if no response + data->common.ticks = retry_timeout; + break; case EAP_TLS_STATE_FINISH: diff --git a/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.h b/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.h index 78ececd7bce..2b1dded5e88 100644 --- a/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.h +++ b/source/Security/protocols/eap_tls_sec_prot/supp_eap_tls_sec_prot.h @@ -33,5 +33,27 @@ */ int8_t supp_eap_tls_sec_prot_register(kmp_service_t *service); +/** + * supp_eap_sec_prot_timing_adjust Adjust retries and timings of the 4WH protocol + * + * Timing value is a generic number between 0 to 32 that goes from fast and + * reactive network to low bandwidth and long latency. + * + * example value definitions: + * 0-8 very fast network + * 9-16 medium network + * 16-24 slow network + * 25-32 extremely slow network + * + * There is no need to have lots variations in every layer if protocol is not very active in any case. + * + * \param timing Timing value. + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t supp_eap_sec_prot_timing_adjust(uint8_t timing); + #endif /* SUPP_EAP_TLS_SEC_PROT_H_ */ diff --git a/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.c b/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.c index 99cbcd5749f..ed91c306d60 100644 --- a/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.c +++ b/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.c @@ -68,11 +68,19 @@ typedef struct { uint16_t recv_size; /**< received pdu size */ } fwh_sec_prot_int_t; -static const trickle_params_t fwh_trickle_params = { - .Imin = 50, /* 5000ms; ticks are 100ms */ - .Imax = 150, /* 15000ms */ +/*Small network setup*/ +#define FWH_SMALL_IMIN 300 // retries done in 30 seconds +#define FWH_SMALL_IMAX 900 // Largest value 90 seconds + +/* Large network setup*/ +#define FWH_LARGE_IMIN 600 // retries done in 60 seconds +#define FWH_LARGE_IMAX 2400 // Largest value 240 seconds + +static trickle_params_t fwh_trickle_params = { + .Imin = FWH_SMALL_IMIN, /* ticks are 100ms */ + .Imax = FWH_SMALL_IMAX, /* ticks are 100ms */ .k = 0, /* infinity - no consistency checking */ - .TimerExpirations = 4 + .TimerExpirations = 2 }; static uint16_t auth_fwh_sec_prot_size(void); @@ -105,6 +113,18 @@ int8_t auth_fwh_sec_prot_register(kmp_service_t *service) return 0; } +int8_t auth_fwh_sec_prot_timing_adjust(uint8_t timing) +{ + if (timing < 16) { + fwh_trickle_params.Imin = FWH_SMALL_IMIN; + fwh_trickle_params.Imax = FWH_SMALL_IMAX; + } else { + fwh_trickle_params.Imin = FWH_LARGE_IMIN; + fwh_trickle_params.Imax = FWH_LARGE_IMAX; + } + return 0; +} + static uint16_t auth_fwh_sec_prot_size(void) { return sizeof(fwh_sec_prot_int_t); diff --git a/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.h b/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.h index efeab123d2e..67b96a41e01 100644 --- a/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.h +++ b/source/Security/protocols/fwh_sec_prot/auth_fwh_sec_prot.h @@ -34,4 +34,26 @@ */ int8_t auth_fwh_sec_prot_register(kmp_service_t *service); +/** + * auth_fwh_sec_prot_timing_adjust Adjust retries and timings of the 4WH protocol + * + * Timing value is a generic number between 0 to 32 that goes from fast and + * reactive network to low bandwidth and long latency. + * + * example value definitions: + * 0-8 very fast network + * 9-16 medium network + * 16-24 slow network + * 25-32 extremely slow network + * + * There is no need to have lots variations in every layer if protocol is not very active in any case. + * + * \param timing Timing value. + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t auth_fwh_sec_prot_timing_adjust(uint8_t timing); + #endif /* AUTH_FWH_SEC_PROT_H_ */ diff --git a/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.c b/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.c index 775e4160de8..7faa7e7f433 100644 --- a/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.c +++ b/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.c @@ -82,6 +82,11 @@ typedef struct { bool recv_replay_cnt_set : 1; /**< received replay counter set */ } fwh_sec_prot_int_t; +#define FWH_RETRY_TIMEOUT_SMALL 300*10 // retry timeout for small network +#define FWH_RETRY_TIMEOUT_LARGE 720*10 // retry timeout for large network + +static uint16_t retry_timeout = FWH_RETRY_TIMEOUT_SMALL; + static uint16_t supp_fwh_sec_prot_size(void); static int8_t supp_fwh_sec_prot_init(sec_prot_t *prot); @@ -119,6 +124,15 @@ int8_t supp_fwh_sec_prot_register(kmp_service_t *service) return 0; } +int8_t supp_fwh_sec_prot_timing_adjust(uint8_t timing) +{ + if (timing < 16) { + retry_timeout = FWH_RETRY_TIMEOUT_SMALL; + } else { + retry_timeout = FWH_RETRY_TIMEOUT_LARGE; + } + return 0; +} static uint16_t supp_fwh_sec_prot_size(void) { @@ -138,7 +152,7 @@ static int8_t supp_fwh_sec_prot_init(sec_prot_t *prot) sec_prot_init(&data->common); sec_prot_state_set(prot, &data->common, FWH_STATE_INIT); - data->common.ticks = 30 * 10; // 30 seconds + data->common.ticks = retry_timeout; data->msg3_received = false; data->msg3_retry_wait = false; data->recv_replay_cnt = 0; @@ -332,7 +346,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot) if (sec_prot_result_ok_check(&data->common)) { // Send 4WH message 2 supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2); - data->common.ticks = 30 * 10; // 30 seconds + data->common.ticks = retry_timeout; sec_prot_state_set(prot, &data->common, FWH_STATE_MESSAGE_3); } else { // Ready to be deleted @@ -360,7 +374,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot) // Send 4WH message 2 supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_2); - data->common.ticks = 30 * 10; // 30 seconds + data->common.ticks = retry_timeout; return; } else if (data->recv_msg != FWH_MESSAGE_3) { return; @@ -387,7 +401,7 @@ static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot) // Sends 4WH Message 4 supp_fwh_sec_prot_message_send(prot, FWH_MESSAGE_4); - data->common.ticks = 30 * 10; // 30 seconds + data->common.ticks = retry_timeout; sec_prot_state_set(prot, &data->common, FWH_STATE_FINISH); break; diff --git a/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h b/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h index 2cb2284e3c1..8369625847b 100644 --- a/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h +++ b/source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.h @@ -34,4 +34,26 @@ */ int8_t supp_fwh_sec_prot_register(kmp_service_t *service); +/** + * supp_fwh_sec_prot_timing_adjust Adjust retries and timings of the 4WH protocol + * + * Timing value is a generic number between 0 to 32 that goes from fast and + * reactive network to low bandwidth and long latency. + * + * example value definitions: + * 0-8 very fast network + * 9-16 medium network + * 16-24 slow network + * 25-32 extremely slow network + * + * There is no need to have lots variations in every layer if protocol is not very active in any case. + * + * \param timing Timing value. + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t supp_fwh_sec_prot_timing_adjust(uint8_t timing); + #endif /* SUPP_FWH_SEC_PROT_H_ */ diff --git a/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.c b/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.c index 2c8ddc304c9..ac95f917830 100644 --- a/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.c +++ b/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.c @@ -60,11 +60,19 @@ typedef struct { uint16_t recv_size; /**< Received pdu size */ } gkh_sec_prot_int_t; -static const trickle_params_t gkh_trickle_params = { - .Imin = 50, /* 5000ms; ticks are 100ms */ - .Imax = 150, /* 15000ms */ +/*Small network setup*/ +#define GKH_SMALL_IMIN 300 // retries done in 30 seconds +#define GKH_SMALL_IMAX 900 // Largest value 90 seconds + +/* Large network setup*/ +#define GKH_LARGE_IMIN 600 // retries done in 60 seconds +#define GKH_LARGE_IMAX 2400 // Largest value 240 seconds + +static trickle_params_t gkh_trickle_params = { + .Imin = GKH_SMALL_IMIN, /* ticks are 100ms */ + .Imax = GKH_SMALL_IMAX, /* ticks are 100ms */ .k = 0, /* infinity - no consistency checking */ - .TimerExpirations = 4 + .TimerExpirations = 2 }; static uint16_t auth_gkh_sec_prot_size(void); @@ -95,6 +103,18 @@ int8_t auth_gkh_sec_prot_register(kmp_service_t *service) return 0; } +int8_t auth_gkh_sec_prot_timing_adjust(uint8_t timing) +{ + if (timing < 16) { + gkh_trickle_params.Imin = GKH_SMALL_IMIN; + gkh_trickle_params.Imax = GKH_SMALL_IMAX; + } else { + gkh_trickle_params.Imin = GKH_LARGE_IMIN; + gkh_trickle_params.Imax = GKH_LARGE_IMAX; + } + return 0; +} + static uint16_t auth_gkh_sec_prot_size(void) { return sizeof(gkh_sec_prot_int_t); diff --git a/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.h b/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.h index 2ec9829bd0c..daf09a4c3b4 100644 --- a/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.h +++ b/source/Security/protocols/gkh_sec_prot/auth_gkh_sec_prot.h @@ -28,4 +28,26 @@ */ int8_t auth_gkh_sec_prot_register(kmp_service_t *service); +/** + * auth_gkh_sec_prot_timing_adjust Adjust retries and timings of the GKH protocol + * + * Timing value is a generic number between 0 to 32 that goes from fast and + * reactive network to low bandwidth and long latency. + * + * example value definitions: + * 0-8 very fast network + * 9-16 medium network + * 16-24 slow network + * 25-32 extremely slow network + * + * There is no need to have lots variations in every layer if protocol is not very active in any case. + * + * \param timing Timing value. + * + * \return < 0 failure + * \return >= 0 success + * + */ +int8_t auth_gkh_sec_prot_timing_adjust(uint8_t timing); + #endif /* AUTH_GKH_SEC_PROT_H_ */ diff --git a/source/Security/protocols/gkh_sec_prot/supp_gkh_sec_prot.c b/source/Security/protocols/gkh_sec_prot/supp_gkh_sec_prot.c index 0b54aa67ef5..15b8dcce2ce 100644 --- a/source/Security/protocols/gkh_sec_prot/supp_gkh_sec_prot.c +++ b/source/Security/protocols/gkh_sec_prot/supp_gkh_sec_prot.c @@ -60,13 +60,6 @@ typedef struct { uint16_t recv_size; /**< Received pdu size */ } gkh_sec_prot_int_t; -static const trickle_params_t gkh_trickle_params = { - .Imin = 50, /* 5000ms; ticks are 100ms */ - .Imax = 150, /* 15000ms */ - .k = 0, /* infinity - no consistency checking */ - .TimerExpirations = 4 -}; - static uint16_t supp_gkh_sec_prot_size(void); static int8_t supp_gkh_sec_prot_init(sec_prot_t *prot); @@ -227,7 +220,7 @@ static int8_t supp_gkh_sec_prot_message_send(sec_prot_t *prot, gkh_sec_prot_msg_ static void supp_gkh_sec_prot_timer_timeout(sec_prot_t *prot, uint16_t ticks) { gkh_sec_prot_int_t *data = gkh_sec_prot_get(prot); - sec_prot_timer_timeout_handle(prot, &data->common, &gkh_trickle_params, ticks); + sec_prot_timer_timeout_handle(prot, &data->common, NULL, ticks); } static void supp_gkh_sec_prot_state_machine(sec_prot_t *prot) diff --git a/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c b/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c index 0232bc3178b..b6cec1412d3 100644 --- a/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c +++ b/source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c @@ -70,12 +70,6 @@ struct tls_security_s { mbedtls_x509_crl *crl; /**< Certificate Revocation List */ mbedtls_x509_crt owncert; /**< Own certificate(s) */ mbedtls_pk_context pkey; /**< Private key for own certificate */ - - uint8_t client_random[32]; /**< Client random (from Client Hello) */ - uint8_t server_random[32]; /**< Server random (from Server Hello) */ - - uint8_t step; /**< Random extract step */ - void *handle; /**< Handle provided in callbacks (defined by library user) */ tls_sec_prot_lib_send *send; /**< Send callback */ tls_sec_prot_lib_receive *receive; /**< Receive callback */ @@ -89,9 +83,11 @@ static int tls_sec_prot_lib_ssl_get_timer(void *ctx); static int tls_sec_lib_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen); static int tls_sec_prot_lib_ssl_send(void *ctx, const unsigned char *buf, size_t len); static int tls_sec_prot_lib_ssl_recv(void *ctx, unsigned char *buf, size_t len); -static int tls_sec_prot_lib_ssl_export_keys(void *ctx, const unsigned char *ms, - const unsigned char *kb, size_t maclen, size_t keylen, size_t ivlen); -static void tls_sec_prot_lib_random_extract(tls_security_t *sec, const uint8_t *buf, uint16_t len); +static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char *ms, + const unsigned char *kb, size_t maclen, size_t keylen, + size_t ivlen, unsigned char client_random[32], + unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type); #ifdef TLS_SEC_PROT_LIB_TLS_DEBUG static void tls_sec_prot_lib_debug(void *ctx, int level, const char *file, int line, const char *string); #endif @@ -126,7 +122,6 @@ int8_t tls_sec_prot_lib_init(tls_security_t *sec) mbedtls_pk_init(&sec->pkey); sec->crl = NULL; - sec->step = 0; if (mbedtls_entropy_add_source(&sec->entropy, tls_sec_lib_entropy_poll, NULL, 128, MBEDTLS_ENTROPY_SOURCE_WEAK) < 0) { @@ -331,7 +326,7 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p #endif // Export keys callback - mbedtls_ssl_conf_export_keys_cb(&sec->conf, tls_sec_prot_lib_ssl_export_keys, sec); + mbedtls_ssl_conf_export_keys_ext_cb(&sec->conf, tls_sec_prot_lib_ssl_export_keys, sec); mbedtls_ssl_conf_min_version(&sec->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MAJOR_VERSION_3); mbedtls_ssl_conf_max_version(&sec->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MAJOR_VERSION_3); @@ -394,9 +389,6 @@ static int tls_sec_prot_lib_ssl_get_timer(void *ctx) static int tls_sec_prot_lib_ssl_send(void *ctx, const unsigned char *buf, size_t len) { tls_security_t *sec = (tls_security_t *)ctx; - - tls_sec_prot_lib_random_extract(sec, buf, len); - return sec->send(sec->handle, buf, len); } @@ -408,74 +400,34 @@ static int tls_sec_prot_lib_ssl_recv(void *ctx, unsigned char *buf, size_t len) if (ret == TLS_SEC_PROT_LIB_NO_DATA) { return MBEDTLS_ERR_SSL_WANT_READ; } - - tls_sec_prot_lib_random_extract(sec, buf, len); - return ret; } -static void tls_sec_prot_lib_random_extract(tls_security_t *sec, const uint8_t *buf, uint16_t len) -{ - if (sec->step == 0) { - if (*buf++ != 22 && len < 5) { - return; - } - - buf++; // version - buf++; - - buf++; // length - buf++; - - sec->step++; - - if (len < 6) { - return; - } - } - - if (sec->step == 1) { - uint8_t *random_ptr; - if (*buf == 0x01) { // Client hello - random_ptr = sec->client_random; - } else if (*buf == 0x02) { // Server hello - random_ptr = sec->server_random; - } else { - return; - } - buf++; - - buf++; // length - buf++; - buf++; - - buf++; // version - buf++; - - memcpy(random_ptr, buf, 32); - - sec->step = 0; - } -} - -static int tls_sec_prot_lib_ssl_export_keys(void *ctx, const unsigned char *ms, - const unsigned char *kb, size_t maclen, - size_t keylen, size_t ivlen) +static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char *ms, + const unsigned char *kb, size_t maclen, size_t keylen, + size_t ivlen, unsigned char client_random[32], + unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type) { (void) kb; (void) maclen; (void) keylen; (void) ivlen; - tls_security_t *sec = (tls_security_t *)ctx; + tls_security_t *sec = (tls_security_t *)p_expkey; uint8_t eap_tls_key_material[128]; uint8_t random[64]; - memcpy(random, sec->client_random, 32); - memcpy(&random[32], sec->server_random, 32); + memcpy(random, client_random, 32); + memcpy(&random[32], server_random, 32); + + int ret = mbedtls_ssl_tls_prf(tls_prf_type, ms, 48, "client EAP encryption", + random, 64, eap_tls_key_material, 128); - sec->ssl.handshake->tls_prf(ms, 48, "client EAP encryption", - random, 64, eap_tls_key_material, 128); + if (ret != 0) { + tr_error("key material PRF error"); + return 0; + } sec->export_keys(sec->handle, ms, eap_tls_key_material); return 0; diff --git a/source/ipv6_stack/protocol_ipv6.c b/source/ipv6_stack/protocol_ipv6.c index cc2e935ad90..6f717104c41 100644 --- a/source/ipv6_stack/protocol_ipv6.c +++ b/source/ipv6_stack/protocol_ipv6.c @@ -969,7 +969,7 @@ void ipv6_interface_slaac_handler(protocol_interface_info_entry_t *cur, const ui cur->ipv6_configure->IPv6_ND_state = IPV6_GP_CONFIG; } // If DAD not enabled address is valid right away - if (cur->dup_addr_detect_transmits == 0) { + if (cur->ipv6_configure && cur->dup_addr_detect_transmits == 0) { address_entry->cb(cur, address_entry, ADDR_CALLBACK_DAD_COMPLETE); } }