This modifies the FT logic to fist call get_oci() before
reassociation. This allows the OCI to be included in reassociation
and in the 4-way handshake later on.
---
src/ft.c | 13 ++++++++++++-
src/ft.h | 2 ++
src/netdev.c | 20 +++++++++++++++++++-
3 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/src/ft.c b/src/ft.c
index 6897f6d7..40e29341 100644
--- a/src/ft.c
+++ b/src/ft.c
@@ -40,6 +40,7 @@ struct ft_sm {
ft_tx_authenticate_func_t tx_auth;
ft_tx_associate_func_t tx_assoc;
+ ft_get_oci get_oci;
void *user_data;
};
@@ -640,7 +641,7 @@ static int ft_rx_authenticate(struct auth_proto *ap, const uint8_t
*frame,
if (ret < 0)
goto auth_error;
- return ft_tx_reassociate(ft);
+ return ft->get_oci(ft->user_data);
auth_error:
return (int)status_code;
@@ -783,6 +784,13 @@ static int ft_rx_associate(struct auth_proto *ap, const uint8_t
*frame,
return 0;
}
+static int ft_rx_oci(struct auth_proto *ap)
+{
+ struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
+
+ return ft_tx_reassociate(ft);
+}
+
static void ft_sm_free(struct auth_proto *ap)
{
struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
@@ -890,12 +898,14 @@ static bool ft_start(struct auth_proto *ap)
struct auth_proto *ft_over_air_sm_new(struct handshake_state *hs,
ft_tx_authenticate_func_t tx_auth,
ft_tx_associate_func_t tx_assoc,
+ ft_get_oci get_oci,
void *user_data)
{
struct ft_sm *ft = l_new(struct ft_sm, 1);
ft->tx_auth = tx_auth;
ft->tx_assoc = tx_assoc;
+ ft->get_oci = get_oci;
ft->hs = hs;
ft->user_data = user_data;
@@ -903,6 +913,7 @@ struct auth_proto *ft_over_air_sm_new(struct handshake_state *hs,
ft->ap.rx_associate = ft_rx_associate;
ft->ap.start = ft_start;
ft->ap.free = ft_sm_free;
+ ft->ap.rx_oci = ft_rx_oci;
return &ft->ap;
}
diff --git a/src/ft.h b/src/ft.h
index 6167e0d7..cc25463f 100644
--- a/src/ft.h
+++ b/src/ft.h
@@ -26,6 +26,7 @@ typedef void (*ft_tx_authenticate_func_t)(struct iovec *iov, size_t
iov_len,
void *user_data);
typedef int (*ft_tx_associate_func_t)(struct iovec *ie_iov, size_t iov_len,
void *user_data);
+typedef int (*ft_get_oci)(void *user_data);
typedef void (*ft_ds_free_func_t)(void *user_data);
@@ -60,6 +61,7 @@ bool ft_over_ds_parse_action_ies(struct ft_ds_info *info,
struct auth_proto *ft_over_air_sm_new(struct handshake_state *hs,
ft_tx_authenticate_func_t tx_auth,
ft_tx_associate_func_t tx_assoc,
+ ft_get_oci get_oci,
void *user_data);
struct auth_proto *ft_over_ds_sm_new(struct handshake_state *hs,
diff --git a/src/netdev.c b/src/netdev.c
index 5a44895d..91d1316c 100644
--- a/src/netdev.c
+++ b/src/netdev.c
@@ -2074,6 +2074,21 @@ static void netdev_get_oci_cb(struct l_genl_msg *msg, void
*user_data)
handshake_state_set_chandef(netdev->handshake, l_steal_ptr(chandef));
done:
+ if (netdev->ap) {
+ /*
+ * Cant do much here. IWD assumes every kernel/driver supports
+ * this. There is no way of detecting support either.
+ */
+ if (L_WARN_ON(err < 0))
+ netdev_connect_failed(netdev,
+ NETDEV_RESULT_AUTHENTICATION_FAILED,
+ MMPDU_STATUS_CODE_UNSPECIFIED);
+ else
+ auth_proto_rx_oci(netdev->ap);
+
+ return;
+ }
+
L_WARN_ON(!eapol_start(netdev->sm));
}
@@ -4099,6 +4114,8 @@ static void prepare_ft(struct netdev *netdev, const struct scan_bss
*target_bss)
netdev->operational = false;
netdev->in_ft = true;
+ handshake_state_set_chandef(netdev->handshake, NULL);
+
/*
* Cancel commands that could be running because of EAPoL activity
* like re-keying, this way the callbacks for those commands don't
@@ -4274,7 +4291,8 @@ int netdev_fast_transition(struct netdev *netdev,
netdev->ap = ft_over_air_sm_new(netdev->handshake,
netdev_ft_tx_authenticate,
- netdev_ft_tx_associate, netdev);
+ netdev_ft_tx_associate,
+ netdev_get_oci, netdev);
memcpy(netdev->ap->prev_bssid, orig_bss->addr, ETH_ALEN);
wiphy_radio_work_insert(netdev->wiphy, &netdev->work, 1,
--
2.31.1