diff --git a/src/ft.c b/src/ft.c index d3b9234a..c612a433 100644 --- a/src/ft.c +++ b/src/ft.c @@ -1276,6 +1276,46 @@ int ft_associate(uint32_t ifindex, const uint8_t *addr) return ret; } +int ft_handshake_setup(uint32_t ifindex, const uint8_t *target) +{ + struct netdev *netdev = netdev_find(ifindex); + struct handshake_state *hs = netdev_get_handshake(netdev); + struct ft_info *info; + int ret = 0; + + info = ft_info_find(ifindex, target); + if (!info) + return -ENOENT; + + /* + * Either failed or no response. This may have been an FT-over-DS + * attempt so clear out the entry so FT-over-Air can try again. + */ + if (info->status != 0) { + int status = info->status; + + l_queue_remove(info_list, info); + ft_info_destroy(info); + + return status; + } + + /* + * This shouldn't ever fail: + * - supplicant_ie has already been validated long ago + * - l_checksum_* shouldn't fail since we presumable have kernel + * support, how else could we have made it this far. + * But just in case... + */ + if (L_WARN_ON(!ft_prepare_handshake(info, hs))) + ret = -EINVAL; + + /* After this no previous auths will be valid */ + ft_clear_authentications(ifindex); + + return ret; +} + static bool remove_ifindex(void *data, void *user_data) { struct ft_info *info = data; diff --git a/src/ft.h b/src/ft.h index 51bbe3bc..23d0136e 100644 --- a/src/ft.h +++ b/src/ft.h @@ -39,6 +39,8 @@ void __ft_rx_action(uint32_t ifindex, const uint8_t *frame, size_t frame_len); void __ft_rx_authenticate(uint32_t ifindex, const uint8_t *frame, size_t frame_len); +int ft_handshake_setup(uint32_t ifindex, const uint8_t *target); + void ft_clear_authentications(uint32_t ifindex); int ft_action(uint32_t ifindex, uint32_t freq, const struct scan_bss *target); int ft_associate(uint32_t ifindex, const uint8_t *addr);