diff --git a/Makefile b/Makefile index 17a7f5512b73..c9b7d2402b7c 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 53c26ecdd414..dbfb20b25adc 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 e6b009e500aa..e78b91c088a2 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 84586a519aa7..317ab8ac7858 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 55df3b5227bb..8483b7de8e7f 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 63004dcf54bc..e9a8e025c11b 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 510f3d968164..6a89708fe6ed 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 b5b970610a74..4be2964e1ee5 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 1104431e70c4..33891f05a382 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 d5e44f09fb57..93cb58544530 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 7fa0c9b69571..2a0cbe2c1229 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 e8ea19ac19c5..8e20e856fb17 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 dec5eb69ec0a..5c0f35d96091 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 c001c2364a6a..086ec0639367 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 2f1b6ce05020..b34a61ae3744 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 6886a71408e6..d01917d955a8 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 2569637dee13..69b4a7aeda90 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 a89bf1cdaeb1..ae7abe7a0d57 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 4d22d73f91d7..24de962fe3cb 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 bcd659f9b997..a1cb4042e8d6 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 5377fb0962a0..54d6ecaceacb 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 2e7b76320889..f176350b9e75 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 f9c1b39e0943..c9c1d7f176f0 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 3c6da959dadd..ad9cde193c78 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 d562e90601e2..3e1c1c7fb672 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 cbe295247a0a..8c3e1185b9c6 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 ebbed366860c..dadbdc17d336 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 78ececd7bcec..2b1dded5e885 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 99cbcd5749fb..ed91c306d60b 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 efeab123d2e2..67b96a41e01f 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 775e4160de89..7faa7e7f433e 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 2cb2284e3c16..8369625847b8 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 2c8ddc304c9e..ac95f9178300 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 2ec9829bd0c4..daf09a4c3b42 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 0b54aa67ef5c..15b8dcce2ce9 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 0232bc3178b3..b6cec1412d31 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 cc2e935ad909..6f717104c41d 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); } } diff --git a/test/nanostack/unittest/6LoWPAN/ws_llc_data_service/test_ws_llc_data_service.c b/test/nanostack/unittest/6LoWPAN/ws_llc_data_service/test_ws_llc_data_service.c index 2fb405c4559d..50c1afbe9256 100644 --- a/test/nanostack/unittest/6LoWPAN/ws_llc_data_service/test_ws_llc_data_service.c +++ b/test/nanostack/unittest/6LoWPAN/ws_llc_data_service/test_ws_llc_data_service.c @@ -153,7 +153,7 @@ bool test_ws_llc_create() return false; } - nsdynmemlib_stub.returnCounter = 1; + nsdynmemlib_stub.returnCounter = 2; if (ws_llc_create(&interface, test_ws_asynch_ind, test_ws_asynch_confirm, test_neighbor_info_request) != 0) { return false; } @@ -171,7 +171,7 @@ bool test_ws_llc_reset() mac_api_t api; interface_api_init(&api); - nsdynmemlib_stub.returnCounter = 1; + nsdynmemlib_stub.returnCounter = 2; ws_llc_create(&interface, test_ws_asynch_ind, test_ws_asynch_confirm, test_neighbor_info_request); mpx_api_t *mpx_api = ws_llc_mpx_api_get(&interface); register_mpx_user(mpx_api); @@ -202,7 +202,7 @@ bool test_asynch_msg_send() mac_api_t api; interface_api_init(&api); - nsdynmemlib_stub.returnCounter = 1; + nsdynmemlib_stub.returnCounter = 2; ws_llc_create(&interface, test_ws_asynch_ind, test_ws_asynch_confirm, test_neighbor_info_request); mpx_api_t *mpx_api = ws_llc_mpx_api_get(&interface); register_mpx_user(mpx_api); @@ -282,7 +282,7 @@ bool test_mpx_msg_send() mac_api_t api; interface_api_init(&api); - nsdynmemlib_stub.returnCounter = 1; + nsdynmemlib_stub.returnCounter = 2; ws_llc_create(&interface, test_ws_asynch_ind, test_ws_asynch_confirm, test_neighbor_info_request); mpx_api_t *mpx_api = ws_llc_mpx_api_get(&interface); register_mpx_user(mpx_api); @@ -385,7 +385,7 @@ bool test_mpx_msg_rx() mac_api_t api; interface_api_init(&api); - nsdynmemlib_stub.returnCounter = 1; + nsdynmemlib_stub.returnCounter = 2; ws_llc_create(&interface, test_ws_asynch_ind, test_ws_asynch_confirm, test_neighbor_info_request); mpx_api_t *mpx_api = ws_llc_mpx_api_get(&interface); register_mpx_user(mpx_api); diff --git a/test/nanostack/unittest/Core/monitor/Makefile b/test/nanostack/unittest/Core/monitor/Makefile index f42ce4fd814c..6b83d8d0f5d7 100644 --- a/test/nanostack/unittest/Core/monitor/Makefile +++ b/test/nanostack/unittest/Core/monitor/Makefile @@ -22,6 +22,7 @@ TEST_SRC_FILES = \ ../../stub/ipv6_routing_table_stub.c \ ../../stub/protocol_core_stub.c \ ../../stub/ip6tos_stub.c \ + ../../stub/ws_pae_controller_stub.c \ include ../../MakefileWorker.mk diff --git a/test/nanostack/unittest/makefile_defines.txt b/test/nanostack/unittest/makefile_defines.txt index e413b5b7dc98..da1448b1e5b2 100755 --- a/test/nanostack/unittest/makefile_defines.txt +++ b/test/nanostack/unittest/makefile_defines.txt @@ -41,6 +41,7 @@ INCLUDE_DIRS =\ ../../../../../../event-loop/nanostack-event-loop/\ ../../../../../../event-loop/source/ \ ../../../../../../mbedtls/include/ \ + ../../../../../../mbedtls/crypto/include/ \ ../../../../../../nsdl-c/nsdl-c/ \ /usr/include\ $(CPPUTEST_HOME)/include\ diff --git a/test/nanostack/unittest/stub/rpl_control_stub.c b/test/nanostack/unittest/stub/rpl_control_stub.c index d202ca206d59..e08ce2029ee2 100644 --- a/test/nanostack/unittest/stub/rpl_control_stub.c +++ b/test/nanostack/unittest/stub/rpl_control_stub.c @@ -99,7 +99,7 @@ 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) { } diff --git a/test/nanostack/unittest/stub/ws_pae_controller_stub.c b/test/nanostack/unittest/stub/ws_pae_controller_stub.c index 9f59f404fdff..07e707022083 100644 --- a/test/nanostack/unittest/stub/ws_pae_controller_stub.c +++ b/test/nanostack/unittest/stub/ws_pae_controller_stub.c @@ -58,3 +58,8 @@ int8_t ws_pae_controller_border_router_addr_read(protocol_interface_info_entry_t { return 0; } + +void ws_pae_controller_forced_gc(bool full_gc) +{ + return; +}