diff --git a/src/ft.c b/src/ft.c index de628941..a4277cbe 100644 --- a/src/ft.c +++ b/src/ft.c @@ -1123,9 +1123,19 @@ static void ft_info_destroy(void *data) static void ft_prepare_handshake(struct ft_info *info, struct handshake_state *hs) { + handshake_state_set_authenticator_address(hs, info->aa); + + memcpy(hs->mde + 2, info->mde, 3); + + handshake_state_set_chandef(hs, NULL); + if (!hs->supplicant_ie) return; + if (info->authenticator_ie) + handshake_state_set_authenticator_ie(hs, + info->authenticator_ie); + memcpy(hs->snonce, info->snonce, sizeof(hs->snonce)); handshake_state_set_fte(hs, info->fte); diff --git a/src/netdev.c b/src/netdev.c index 029e96ad..d9f75567 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -1413,6 +1413,15 @@ static void netdev_connect_ok(struct netdev *netdev) scan_bss_free(netdev->fw_roam_bss); netdev->fw_roam_bss = NULL; + } else if (netdev->in_ft) { + if (netdev->event_filter) + netdev->event_filter(netdev, NETDEV_EVENT_FT_ROAMED, + NULL, netdev->user_data); + netdev->in_ft = false; + } else if (netdev->connect_cb) { + netdev->connect_cb(netdev, NETDEV_RESULT_OK, NULL, + netdev->user_data); + netdev->connect_cb = NULL; } if (netdev->ft_ds_list) { @@ -1420,12 +1429,6 @@ static void netdev_connect_ok(struct netdev *netdev) netdev->ft_ds_list = NULL; } - if (netdev->connect_cb) { - netdev->connect_cb(netdev, NETDEV_RESULT_OK, NULL, - netdev->user_data); - netdev->connect_cb = NULL; - } - netdev_rssi_polling_update(netdev); if (netdev->work.id) @@ -3293,7 +3296,6 @@ static void netdev_associate_event(struct l_genl_msg *msg, eapol_sm_set_require_handshake(netdev->sm, false); - netdev->in_ft = false; netdev->in_reassoc = false; netdev->associated = true; return; @@ -4459,6 +4461,7 @@ static int netdev_ft_tx_associate(uint32_t ifindex, uint32_t freq, struct iovec *ft_iov, size_t n_ft_iov) { struct netdev *netdev = netdev_find(ifindex); + struct netdev_handshake_state *nhs; struct handshake_state *hs = netdev->handshake; struct l_genl_msg *msg; struct iovec iov[64]; @@ -4467,6 +4470,54 @@ static int netdev_ft_tx_associate(uint32_t ifindex, uint32_t freq, enum mpdu_management_subtype subtype = MPDU_MANAGEMENT_SUBTYPE_REASSOCIATION_REQUEST; + /* + * At this point there is no going back with FT so reset all the flags + * needed to associate with a new BSS. + */ + netdev->frequency = freq; + netdev->handshake->active_tk_index = 0; + netdev->associated = false; + netdev->operational = false; + netdev->in_ft = true; + + /* + * Cancel commands that could be running because of EAPoL activity + * like re-keying, this way the callbacks for those commands don't + * have to check if failures resulted from the transition. + */ + nhs = l_container_of(netdev->handshake, + struct netdev_handshake_state, super); + + /* reset key states just as we do in initialization */ + nhs->complete = false; + nhs->ptk_installed = false; + nhs->gtk_installed = true; + nhs->igtk_installed = true; + + if (nhs->group_new_key_cmd_id) { + l_genl_family_cancel(nl80211, nhs->group_new_key_cmd_id); + nhs->group_new_key_cmd_id = 0; + } + + if (nhs->group_management_new_key_cmd_id) { + l_genl_family_cancel(nl80211, + nhs->group_management_new_key_cmd_id); + nhs->group_management_new_key_cmd_id = 0; + } + + if (netdev->rekey_offload_cmd_id) { + l_genl_family_cancel(nl80211, netdev->rekey_offload_cmd_id); + netdev->rekey_offload_cmd_id = 0; + } + + netdev_rssi_polling_update(netdev); + netdev_cqm_rssi_update(netdev); + + if (netdev->sm) { + eapol_sm_free(netdev->sm); + netdev->sm = NULL; + } + msg = netdev_build_cmd_associate_common(netdev); c_iov = netdev_populate_common_ies(netdev, hs, msg, iov, n_iov, c_iov);