Skip to content

Commit 8a917fb

Browse files
author
Mika Leppänen
committed
Continue trickle on initial EAPOL-key TX failure
On medium and large networks, if initial EAPOL-key fails to TX failure, supplicant now continues trickle sequence, and before next initial EAPOL-key is sent, asks bootstrap the best parent from the same PAN ID to try the authentication. If bootstrap does not have the next best parent, supplicant continues with the current target and attempts to send to it. If TX still fails, then a next target selection is made, when trickle expires. Continuing the trickle sequence on all cases, should balance the network load. If initial EAPOL-key TX does not fail, then supplicant sticks to current parent as previously. It retry is made shortly, parent might have e.g. neighbor table entry already for the node.
1 parent cfdb193 commit 8a917fb

File tree

7 files changed

+115
-33
lines changed

7 files changed

+115
-33
lines changed

source/6LoWPAN/ws/ws_bootstrap.c

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,14 @@ static void ws_bootstrap_nw_frame_counter_set(protocol_interface_info_entry_t *c
9797
static void ws_bootstrap_nw_frame_counter_read(protocol_interface_info_entry_t *cur, uint32_t *counter, uint8_t slot);
9898
static void ws_bootstrap_nw_info_updated(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name);
9999
static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_t *cur, auth_result_e result, uint8_t *target_eui_64);
100+
static const uint8_t *ws_bootstrap_authentication_next_target(protocol_interface_info_entry_t *cur, const uint8_t *previous_eui_64, uint16_t *pan_id);
100101
static void ws_bootstrap_pan_version_increment(protocol_interface_info_entry_t *cur);
101102
static ws_nud_table_entry_t *ws_nud_entry_discover(protocol_interface_info_entry_t *cur, void *neighbor);
102103
static void ws_nud_entry_remove(protocol_interface_info_entry_t *cur, mac_neighbor_table_entry_t *entry_ptr);
103104
static bool ws_neighbor_entry_nud_notify(mac_neighbor_table_entry_t *entry_ptr, void *user_data);
104105

105106
static void ws_address_registration_update(protocol_interface_info_entry_t *interface, const uint8_t addr[16]);
106-
107+
static int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, parent_info_t *parent_ptr);
107108

108109
static void ws_bootstrap_candidate_table_reset(protocol_interface_info_entry_t *cur);
109110
static parent_info_t *ws_bootstrap_candidate_parent_get(struct protocol_interface_info_entry *cur, const uint8_t *addr, bool create);
@@ -1129,7 +1130,7 @@ static parent_info_t *ws_bootstrap_candidate_parent_allocate(protocol_interface_
11291130
return entry;
11301131
}
11311132

1132-
static void ws_bootstrap_candidate_parent_free(protocol_interface_info_entry_t *cur, uint8_t *addr)
1133+
static void ws_bootstrap_candidate_parent_free(protocol_interface_info_entry_t *cur, const uint8_t *addr)
11331134
{
11341135
ns_list_foreach_safe(parent_info_t, entry, &cur->ws_info->parent_list_reserved) {
11351136
if (memcmp(entry->addr, addr, 8) == 0) {
@@ -1986,7 +1987,7 @@ int ws_bootstrap_init(int8_t interface_id, net_6lowpan_mode_e bootstrap_mode)
19861987
ret_val = -4;
19871988
goto init_fail;
19881989
}
1989-
if (ws_pae_controller_cb_register(cur, &ws_bootstrap_authentication_completed, &ws_bootstrap_nw_key_set, &ws_bootstrap_nw_key_clear, &ws_bootstrap_nw_key_index_set, &ws_bootstrap_nw_frame_counter_set, &ws_bootstrap_nw_frame_counter_read, &ws_bootstrap_pan_version_increment, &ws_bootstrap_nw_info_updated) < 0) {
1990+
if (ws_pae_controller_cb_register(cur, &ws_bootstrap_authentication_completed, &ws_bootstrap_authentication_next_target, &ws_bootstrap_nw_key_set, &ws_bootstrap_nw_key_clear, &ws_bootstrap_nw_key_index_set, &ws_bootstrap_nw_frame_counter_set, &ws_bootstrap_nw_frame_counter_read, &ws_bootstrap_pan_version_increment, &ws_bootstrap_nw_info_updated) < 0) {
19901991
ret_val = -4;
19911992
goto init_fail;
19921993
}
@@ -2759,6 +2760,24 @@ static void ws_bootstrap_authentication_completed(protocol_interface_info_entry_
27592760
}
27602761
}
27612762

2763+
static const uint8_t *ws_bootstrap_authentication_next_target(protocol_interface_info_entry_t *cur, const uint8_t *previous_eui_64, uint16_t *pan_id)
2764+
{
2765+
ws_bootstrap_candidate_parent_free(cur, previous_eui_64);
2766+
2767+
// Gets best target
2768+
parent_info_t *parent_info = ws_bootstrap_candidate_parent_get_best(cur);
2769+
if (parent_info) {
2770+
/* On failure still continues with the new parent, and on next call,
2771+
will try to set the neighbor again */
2772+
ws_bootstrap_neighbor_set(cur, parent_info);
2773+
*pan_id = parent_info->pan_id;
2774+
return parent_info->addr;
2775+
}
2776+
2777+
// If no targets found, retries the last one
2778+
return previous_eui_64;
2779+
}
2780+
27622781
// Start configuration learning
27632782
static void ws_bootstrap_start_configuration_learn(protocol_interface_info_entry_t *cur)
27642783
{
@@ -3148,6 +3167,34 @@ static void ws_bootstrap_event_handler(arm_event_s *event)
31483167
}
31493168
}
31503169

3170+
static int8_t ws_bootstrap_neighbor_set(protocol_interface_info_entry_t *cur, parent_info_t *parent_ptr)
3171+
{
3172+
uint16_t pan_id = cur->ws_info->network_pan_id;
3173+
3174+
// Add EAPOL neighbor
3175+
cur->ws_info->network_pan_id = parent_ptr->pan_id;
3176+
cur->ws_info->pan_information = parent_ptr->pan_information;
3177+
cur->ws_info->pan_information.pan_version = 0; // This is learned from actual configuration
3178+
3179+
// If PAN ID changes, clear learned neighbors and activate FHSS
3180+
if (pan_id != cur->ws_info->network_pan_id) {
3181+
ws_bootstrap_neighbor_list_clean(cur);
3182+
ws_bootstrap_fhss_activate(cur);
3183+
}
3184+
3185+
llc_neighbour_req_t neighbor_info;
3186+
if (!ws_bootstrap_neighbor_info_request(cur, parent_ptr->addr, &neighbor_info, true)) {
3187+
//Remove Neighbour and set Link setup back
3188+
ns_list_remove(&cur->ws_info->parent_list_reserved, parent_ptr);
3189+
ns_list_add_to_end(&cur->ws_info->parent_list_free, parent_ptr);
3190+
return -1;
3191+
}
3192+
3193+
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &parent_ptr->ws_utt, parent_ptr->timestamp);
3194+
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &parent_ptr->ws_us);
3195+
return 0;
3196+
}
3197+
31513198
/*
31523199
* State machine
31533200
*
@@ -3174,23 +3221,10 @@ void ws_bootstrap_network_scan_process(protocol_interface_info_entry_t *cur)
31743221
}
31753222
tr_info("selected parent:%s panid %u", trace_array(selected_parent_ptr->addr, 8), selected_parent_ptr->pan_id);
31763223

3177-
// Add EAPOL neighbour
3178-
cur->ws_info->network_pan_id = selected_parent_ptr->pan_id;
3179-
cur->ws_info->pan_information = selected_parent_ptr->pan_information;
3180-
cur->ws_info->pan_information.pan_version = 0; // This is learned from actual configuration
3181-
3182-
ws_bootstrap_fhss_activate(cur);
3183-
llc_neighbour_req_t neighbor_info;
3184-
if (!ws_bootstrap_neighbor_info_request(cur, selected_parent_ptr->addr, &neighbor_info, true)) {
3185-
//Remove Neighbour and set Link setup back
3186-
ns_list_remove(&cur->ws_info->parent_list_reserved, selected_parent_ptr);
3187-
ns_list_add_to_end(&cur->ws_info->parent_list_free, selected_parent_ptr);
3224+
if (ws_bootstrap_neighbor_set(cur, selected_parent_ptr) < 0) {
31883225
goto select_best_candidate;
31893226
}
31903227

3191-
ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &selected_parent_ptr->ws_utt, selected_parent_ptr->timestamp);
3192-
ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &selected_parent_ptr->ws_us);
3193-
31943228
ws_pae_controller_set_target(cur, selected_parent_ptr->pan_id, selected_parent_ptr->addr); // temporary!!! store since auth
31953229
ws_bootstrap_event_authentication_start(cur);
31963230
return;

source/6LoWPAN/ws/ws_config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ extern uint8_t DEVICE_MIN_SENS;
207207
// Maximum number of simultaneous security negotiations
208208
#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_SMALL 3
209209
#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_MEDIUM 20
210-
#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE 100
210+
#define MAX_SIMULTANEOUS_SECURITY_NEGOTIATIONS_LARGE 50
211211

212212
/*
213213
* Security protocol timer configuration parameters

source/6LoWPAN/ws/ws_pae_controller.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ typedef struct {
8787
ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read; /**< Frame counter read callback */
8888
ws_pae_controller_pan_ver_increment *pan_ver_increment; /**< PAN version increment callback */
8989
ws_pae_controller_nw_info_updated *nw_info_updated; /**< Network information updated callback */
90+
ws_pae_controller_auth_next_target *auth_next_target; /**< Authentication next target callback */
9091
ws_pae_delete *pae_delete; /**< PAE delete callback */
9192
ws_pae_timer *pae_fast_timer; /**< PAE fast timer callback */
9293
ws_pae_timer *pae_slow_timer; /**< PAE slow timer callback */
@@ -221,7 +222,7 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in
221222
return 0;
222223
}
223224

224-
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated)
225+
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated)
225226
{
226227
if (!interface_ptr) {
227228
return -1;
@@ -240,7 +241,7 @@ int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_
240241
controller->nw_frame_counter_read = nw_frame_counter_read;
241242
controller->pan_ver_increment = pan_ver_increment;
242243
controller->nw_info_updated = nw_info_updated;
243-
244+
controller->auth_next_target = auth_next_target;
244245
return 0;
245246
}
246247

@@ -602,6 +603,9 @@ int8_t ws_pae_controller_init(protocol_interface_info_entry_t *interface_ptr)
602603
controller->nw_send_key_index_set = NULL;
603604
controller->nw_frame_counter_set = NULL;
604605
controller->pan_ver_increment = NULL;
606+
controller->nw_info_updated = NULL;
607+
controller->auth_next_target = NULL;
608+
605609
memset(&controller->sec_timer_cfg, 0, sizeof(ws_sec_timer_cfg_t));
606610
memset(&controller->sec_prot_cfg, 0, sizeof(sec_prot_cfg_t));
607611

@@ -801,7 +805,7 @@ int8_t ws_pae_controller_supp_init(protocol_interface_info_entry_t *interface_pt
801805
controller->pae_nw_key_index_update = ws_pae_supp_nw_key_index_update;
802806
controller->pae_nw_info_set = NULL;
803807

804-
ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_active_nw_key_set, ws_pae_controller_gtk_hash_ptr_get, ws_pae_controller_nw_info_updated_check);
808+
ws_pae_supp_cb_register(controller->interface_ptr, controller->auth_completed, controller->auth_next_target, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_active_nw_key_set, ws_pae_controller_gtk_hash_ptr_get, ws_pae_controller_nw_info_updated_check);
805809

806810
ws_pae_controller_frame_counter_read(controller);
807811
ws_pae_controller_nw_info_read(controller, controller->sec_keys_nw_info.gtks);

source/6LoWPAN/ws/ws_pae_controller.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,18 @@ typedef void ws_pae_controller_nw_frame_counter_read(protocol_interface_info_ent
492492
*/
493493
typedef void ws_pae_controller_auth_completed(protocol_interface_info_entry_t *interface_ptr, auth_result_e result, uint8_t *target_eui_64);
494494

495+
/**
496+
* ws_pae_controller_auth_next_target get next target to attempt authentication
497+
*
498+
* \param interface_ptr interface
499+
* \param previous_eui_64 EUI-64 of previous target
500+
* \param pan_id pan id
501+
*
502+
* \return EUI-64 of the next target or previous target if new one not available
503+
*
504+
*/
505+
typedef const uint8_t *ws_pae_controller_auth_next_target(protocol_interface_info_entry_t *interface_ptr, const uint8_t *previous_eui_64, uint16_t *pan_id);
506+
495507
/**
496508
* ws_pae_controller_pan_ver_increment PAN version increment callback
497509
*
@@ -515,6 +527,7 @@ typedef void ws_pae_controller_nw_info_updated(protocol_interface_info_entry_t *
515527
*
516528
* \param interface_ptr interface
517529
* \param completed authentication completed callback
530+
* \param next_target authentication next target callback
518531
* \param nw_key_set network key set callback
519532
* \param nw_key_clear network key clear callback
520533
* \param nw_send_key_index_set network send key index set callback
@@ -527,7 +540,7 @@ typedef void ws_pae_controller_nw_info_updated(protocol_interface_info_entry_t *
527540
* \return >= 0 success
528541
*
529542
*/
530-
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated);
543+
int8_t ws_pae_controller_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_controller_auth_completed *completed, ws_pae_controller_auth_next_target *auth_next_target, ws_pae_controller_nw_key_set *nw_key_set, ws_pae_controller_nw_key_clear *nw_key_clear, ws_pae_controller_nw_send_key_index_set *nw_send_key_index_set, ws_pae_controller_nw_frame_counter_set *nw_frame_counter_set, ws_pae_controller_nw_frame_counter_read *nw_frame_counter_read, ws_pae_controller_pan_ver_increment *pan_ver_increment, ws_pae_controller_nw_info_updated *nw_info_updated);
531544

532545
/**
533546
* ws_pae_controller_fast_timer PAE controller fast timer call

source/6LoWPAN/ws/ws_pae_supp.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ typedef struct {
8686
kmp_service_t *kmp_service; /**< KMP service */
8787
protocol_interface_info_entry_t *interface_ptr; /**< Interface */
8888
ws_pae_supp_auth_completed *auth_completed; /**< Authentication completed callback, continue bootstrap */
89+
ws_pae_supp_auth_next_target *auth_next_target; /**< Authentication next target callback */
8990
ws_pae_supp_nw_key_insert *nw_key_insert; /**< Key insert callback */
9091
ws_pae_supp_nw_key_index_set *nw_key_index_set; /**< Key index set callback */
9192
ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get; /**< Get pointer to GTK hash storage callback */
@@ -107,7 +108,8 @@ typedef struct {
107108
bool timer_running : 1; /**< Timer is running */
108109
bool new_br_eui_64_set : 1; /**< Border router address has been set */
109110
bool new_br_eui_64_fresh : 1; /**< Border router address is fresh (set during this authentication attempt) */
110-
bool entry_address_active: 1;
111+
bool entry_address_active: 1; /**< EAPOL target address is set */
112+
bool tx_failure_on_initial_key: 1; /**< TX failure has happened on initial EAPOL-key sequence */
111113
} pae_supp_t;
112114

113115
// How many times sending of initial EAPOL-key is initiated on key update
@@ -492,14 +494,15 @@ static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan
492494
}
493495
}
494496

495-
void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set, ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get, ws_pae_supp_nw_info_updated *nw_info_updated)
497+
void ws_pae_supp_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_supp_auth_completed *completed, ws_pae_supp_auth_next_target *auth_next_target, ws_pae_supp_nw_key_insert *nw_key_insert, ws_pae_supp_nw_key_index_set *nw_key_index_set, ws_pae_supp_gtk_hash_ptr_get *gtk_hash_ptr_get, ws_pae_supp_nw_info_updated *nw_info_updated)
496498
{
497499
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
498500
if (!pae_supp) {
499501
return;
500502
}
501503

502504
pae_supp->auth_completed = completed;
505+
pae_supp->auth_next_target = auth_next_target;
503506
pae_supp->nw_key_insert = nw_key_insert;
504507
pae_supp->nw_key_index_set = nw_key_index_set;
505508
pae_supp->gtk_hash_ptr_get = gtk_hash_ptr_get;
@@ -523,6 +526,7 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
523526

524527
pae_supp->interface_ptr = interface_ptr;
525528
pae_supp->auth_completed = NULL;
529+
pae_supp->auth_next_target = NULL;
526530
pae_supp->nw_key_insert = NULL;
527531
pae_supp->nw_key_index_set = NULL;
528532
pae_supp->gtk_hash_ptr_get = NULL;
@@ -763,6 +767,16 @@ void ws_pae_supp_slow_timer(uint16_t seconds)
763767
// Checks if trickle timer expires
764768
if (trickle_timer(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params, seconds)) {
765769
if (pae_supp->initial_key_retry_cnt > 0) {
770+
// On initial EAPOL-key TX failure, check for other parents
771+
if (pae_supp->auth_requested && pae_supp->tx_failure_on_initial_key) {
772+
// Returns same target if no other valid targets found
773+
const uint8_t *next_target = pae_supp->auth_next_target(pae_supp->interface_ptr, kmp_address_eui_64_get(&pae_supp->target_addr), &pae_supp->sec_keys_nw_info->key_pan_id);
774+
kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, next_target);
775+
// Sets target address in use
776+
ws_pae_supp_address_set(pae_supp, &pae_supp->target_addr);
777+
}
778+
pae_supp->tx_failure_on_initial_key = false;
779+
// Sends initial EAPOL-key
766780
if (ws_pae_supp_initial_key_send(pae_supp) < 0) {
767781
tr_info("EAPOL-Key send failed");
768782
}
@@ -777,7 +791,12 @@ void ws_pae_supp_slow_timer(uint16_t seconds)
777791
tr_info("GTKs do not match to GTK hash");
778792
retry = true;
779793
}
780-
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC);
794+
auth_result_e result = AUTH_RESULT_ERR_UNSPEC;
795+
if (pae_supp->tx_failure_on_initial_key) {
796+
result = AUTH_RESULT_ERR_TX_NO_ACK;
797+
pae_supp->tx_failure_on_initial_key = false;
798+
}
799+
ws_pae_supp_authenticate_response(pae_supp, result);
781800
if (retry) {
782801
// Start trickle timer to try re-authentication
783802
ws_pae_supp_initial_key_update_trickle_timer_start(pae_supp, KEY_UPDATE_RETRY_COUNT);
@@ -815,7 +834,7 @@ void ws_pae_supp_slow_timer(uint16_t seconds)
815834
pae_supp->initial_key_timer -= seconds;
816835
} else {
817836
pae_supp->initial_key_timer = 0;
818-
837+
pae_supp->tx_failure_on_initial_key = false;
819838
// Sends initial EAPOL-Key message
820839
if (ws_pae_supp_initial_key_send(pae_supp) < 0) {
821840
tr_info("EAPOL-Key send failed");
@@ -1188,7 +1207,8 @@ static void ws_pae_supp_kmp_api_finished_indication(kmp_api_t *kmp, kmp_result_e
11881207
/* Fails authentication only if other authentication protocols are not yet
11891208
started by authenticator */
11901209
if (ws_pae_lib_kmp_list_count(&pae_supp->entry.kmp_list) <= 1) {
1191-
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_TX_NO_ACK);
1210+
// Continues with trickle but selects different parent
1211+
pae_supp->tx_failure_on_initial_key = true;
11921212
}
11931213
}
11941214
}

0 commit comments

Comments
 (0)