ft: netdev: prep for FT isolation into ft.c
Currently netdev handles caching FT auth information and uses FT parsers/auth-proto to manage the protocol. This sets up to remove this state machine from netdev and isolate it into ft.c. This does not break the existing auth-proto (hence the slight modifications, which will be removed soon). Eventually the auth-proto will be removed from FT entirely, replaced just by an FT state machine, similar to how EAPoL works (netdev hooks to TX/RX frames).
This commit is contained in:
parent
4c6cc29f4a
commit
cd3f82ce8c
317
src/ft.c
317
src/ft.c
|
@ -33,6 +33,30 @@
|
||||||
#include "src/mpdu.h"
|
#include "src/mpdu.h"
|
||||||
#include "src/auth-proto.h"
|
#include "src/auth-proto.h"
|
||||||
#include "src/band.h"
|
#include "src/band.h"
|
||||||
|
#include "src/scan.h"
|
||||||
|
#include "src/util.h"
|
||||||
|
#include "src/netdev.h"
|
||||||
|
#include "src/module.h"
|
||||||
|
|
||||||
|
static ft_tx_frame_func_t tx_frame = NULL;
|
||||||
|
static ft_tx_associate_func_t tx_assoc = NULL;
|
||||||
|
static struct l_queue *info_list = NULL;
|
||||||
|
|
||||||
|
struct ft_info {
|
||||||
|
uint32_t ifindex;
|
||||||
|
uint8_t spa[6];
|
||||||
|
uint8_t aa[6];
|
||||||
|
uint8_t snonce[32];
|
||||||
|
uint8_t mde[3];
|
||||||
|
uint8_t *fte;
|
||||||
|
uint8_t *authenticator_ie;
|
||||||
|
uint8_t prev_bssid[6];
|
||||||
|
uint32_t frequency;
|
||||||
|
|
||||||
|
struct ie_ft_info ft_info;
|
||||||
|
|
||||||
|
bool parsed : 1;
|
||||||
|
};
|
||||||
|
|
||||||
struct ft_sm {
|
struct ft_sm {
|
||||||
struct auth_proto ap;
|
struct auth_proto ap;
|
||||||
|
@ -45,6 +69,8 @@ struct ft_sm {
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
|
||||||
bool over_ds : 1;
|
bool over_ds : 1;
|
||||||
|
|
||||||
|
uint8_t prev_bssid[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -202,11 +228,13 @@ static bool ft_parse_associate_resp_frame(const uint8_t *frame, size_t frame_len
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ft_tx_reassociate(struct ft_sm *ft)
|
static int ft_tx_reassociate(uint32_t ifindex, uint32_t freq,
|
||||||
|
const uint8_t *prev_bssid)
|
||||||
{
|
{
|
||||||
|
struct netdev *netdev = netdev_find(ifindex);
|
||||||
|
struct handshake_state *hs = netdev_get_handshake(netdev);
|
||||||
struct iovec iov[3];
|
struct iovec iov[3];
|
||||||
int iov_elems = 0;
|
int iov_elems = 0;
|
||||||
struct handshake_state *hs = ft->hs;
|
|
||||||
uint32_t kck_len = handshake_state_get_kck_len(hs);
|
uint32_t kck_len = handshake_state_get_kck_len(hs);
|
||||||
bool is_rsn = hs->supplicant_ie != NULL;
|
bool is_rsn = hs->supplicant_ie != NULL;
|
||||||
uint8_t *rsne = NULL;
|
uint8_t *rsne = NULL;
|
||||||
|
@ -233,8 +261,7 @@ static int ft_tx_reassociate(struct ft_sm *ft)
|
||||||
rsn_info.num_pmkids = 1;
|
rsn_info.num_pmkids = 1;
|
||||||
rsn_info.pmkids = hs->pmk_r1_name;
|
rsn_info.pmkids = hs->pmk_r1_name;
|
||||||
|
|
||||||
/* Always set OCVC false for FT-over-DS */
|
/* Always set OCVC false for FT for now */
|
||||||
if (ft->over_ds)
|
|
||||||
rsn_info.ocvc = false;
|
rsn_info.ocvc = false;
|
||||||
|
|
||||||
rsne = alloca(256);
|
rsne = alloca(256);
|
||||||
|
@ -306,7 +333,7 @@ static int ft_tx_reassociate(struct ft_sm *ft)
|
||||||
iov_elems += 1;
|
iov_elems += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ft->tx_assoc(iov, iov_elems, ft->user_data);
|
return tx_assoc(ifindex, freq, prev_bssid, iov, iov_elems);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -348,7 +375,7 @@ static bool ft_verify_rsne(const uint8_t *rsne, const uint8_t *pmk_r0_name,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ft_parse_ies(struct handshake_state *hs,
|
static int parse_ies(struct handshake_state *hs,
|
||||||
const uint8_t *authenticator_ie,
|
const uint8_t *authenticator_ie,
|
||||||
const uint8_t *ies, size_t ies_len,
|
const uint8_t *ies, size_t ies_len,
|
||||||
const uint8_t **mde_out,
|
const uint8_t **mde_out,
|
||||||
|
@ -480,7 +507,7 @@ bool ft_over_ds_parse_action_ies(struct ft_ds_info *info,
|
||||||
const uint8_t *fte = NULL;
|
const uint8_t *fte = NULL;
|
||||||
bool is_rsn = hs->supplicant_ie != NULL;
|
bool is_rsn = hs->supplicant_ie != NULL;
|
||||||
|
|
||||||
if (ft_parse_ies(hs, info->authenticator_ie, ies, ies_len,
|
if (parse_ies(hs, info->authenticator_ie, ies, ies_len,
|
||||||
&mde, &fte) < 0)
|
&mde, &fte) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -512,7 +539,7 @@ static int ft_process_ies(struct handshake_state *hs, const uint8_t *ies,
|
||||||
if (!ies)
|
if (!ies)
|
||||||
goto ft_error;
|
goto ft_error;
|
||||||
|
|
||||||
if (ft_parse_ies(hs, hs->authenticator_ie, ies, ies_len,
|
if (parse_ies(hs, hs->authenticator_ie, ies, ies_len,
|
||||||
&mde, &fte) < 0)
|
&mde, &fte) < 0)
|
||||||
goto ft_error;
|
goto ft_error;
|
||||||
|
|
||||||
|
@ -654,11 +681,10 @@ auth_error:
|
||||||
return (int)status_code;
|
return (int)status_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame,
|
int __ft_rx_associate(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
|
||||||
size_t frame_len)
|
|
||||||
{
|
{
|
||||||
struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
|
struct netdev *netdev = netdev_find(ifindex);
|
||||||
struct handshake_state *hs = ft->hs;
|
struct handshake_state *hs = netdev_get_handshake(netdev);
|
||||||
uint32_t kck_len = handshake_state_get_kck_len(hs);
|
uint32_t kck_len = handshake_state_get_kck_len(hs);
|
||||||
const uint8_t *rsne = NULL;
|
const uint8_t *rsne = NULL;
|
||||||
const uint8_t *mde = NULL;
|
const uint8_t *mde = NULL;
|
||||||
|
@ -671,6 +697,9 @@ static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame,
|
||||||
&mde, &fte))
|
&mde, &fte))
|
||||||
return -EBADMSG;
|
return -EBADMSG;
|
||||||
|
|
||||||
|
if (out_status != 0)
|
||||||
|
return (int)out_status;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* During a transition in an RSN, check for an RSNE containing the
|
* During a transition in an RSN, check for an RSNE containing the
|
||||||
* PMK-R1-Name and the remaining fields same as in the advertised
|
* PMK-R1-Name and the remaining fields same as in the advertised
|
||||||
|
@ -785,17 +814,25 @@ static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame,
|
||||||
ft_info.igtk_ipn);
|
ft_info.igtk_ipn);
|
||||||
}
|
}
|
||||||
|
|
||||||
handshake_state_install_ptk(ft->hs);
|
handshake_state_install_ptk(hs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame,
|
||||||
|
size_t frame_len)
|
||||||
|
{
|
||||||
|
struct ft_sm *sm = l_container_of(ap, struct ft_sm, ap);
|
||||||
|
|
||||||
|
return __ft_rx_associate(sm->hs->ifindex, frame, frame_len);
|
||||||
|
}
|
||||||
|
|
||||||
static int ft_rx_oci(struct auth_proto *ap)
|
static int ft_rx_oci(struct auth_proto *ap)
|
||||||
{
|
{
|
||||||
struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
|
struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
|
||||||
|
|
||||||
return ft_tx_reassociate(ft);
|
return ft_tx_reassociate(ft->hs->ifindex, 0, ft->prev_bssid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ft_sm_free(struct auth_proto *ap)
|
static void ft_sm_free(struct auth_proto *ap)
|
||||||
|
@ -809,7 +846,7 @@ static bool ft_over_ds_start(struct auth_proto *ap)
|
||||||
{
|
{
|
||||||
struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
|
struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap);
|
||||||
|
|
||||||
return ft_tx_reassociate(ft) == 0;
|
return ft_tx_reassociate(ft->hs->ifindex, 0, ft->prev_bssid) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ft_build_authenticate_ies(struct handshake_state *hs, bool ocvc,
|
bool ft_build_authenticate_ies(struct handshake_state *hs, bool ocvc,
|
||||||
|
@ -924,6 +961,8 @@ struct auth_proto *ft_over_air_sm_new(struct handshake_state *hs,
|
||||||
ft->ap.free = ft_sm_free;
|
ft->ap.free = ft_sm_free;
|
||||||
ft->ap.rx_oci = ft_rx_oci;
|
ft->ap.rx_oci = ft_rx_oci;
|
||||||
|
|
||||||
|
memcpy(ft->prev_bssid, hs->aa, 6);
|
||||||
|
|
||||||
return &ft->ap;
|
return &ft->ap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -942,5 +981,253 @@ struct auth_proto *ft_over_ds_sm_new(struct handshake_state *hs,
|
||||||
ft->ap.start = ft_over_ds_start;
|
ft->ap.start = ft_over_ds_start;
|
||||||
ft->ap.free = ft_sm_free;
|
ft->ap.free = ft_sm_free;
|
||||||
|
|
||||||
|
memcpy(ft->prev_bssid, hs->aa, 6);
|
||||||
|
|
||||||
return &ft->ap;
|
return &ft->ap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __ft_set_tx_frame_func(ft_tx_frame_func_t func)
|
||||||
|
{
|
||||||
|
tx_frame = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ft_set_tx_associate_func(ft_tx_associate_func_t func)
|
||||||
|
{
|
||||||
|
tx_assoc = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ft_parse_ies(struct ft_info *info, struct handshake_state *hs,
|
||||||
|
const uint8_t *ies, size_t ies_len)
|
||||||
|
{
|
||||||
|
const uint8_t *mde = NULL;
|
||||||
|
const uint8_t *fte = NULL;
|
||||||
|
bool is_rsn = hs->supplicant_ie != NULL;
|
||||||
|
|
||||||
|
if (parse_ies(hs, info->authenticator_ie, ies, ies_len,
|
||||||
|
&mde, &fte) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!mde_equal(info->mde, mde))
|
||||||
|
goto ft_error;
|
||||||
|
|
||||||
|
if (is_rsn) {
|
||||||
|
if (!ft_parse_fte(hs, info->snonce, fte, &info->ft_info))
|
||||||
|
goto ft_error;
|
||||||
|
|
||||||
|
info->fte = l_memdup(fte, fte[1] + 2);
|
||||||
|
} else if (fte)
|
||||||
|
goto ft_error;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
ft_error:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ft_info *ft_info_find(uint32_t ifindex, const uint8_t *aa)
|
||||||
|
{
|
||||||
|
const struct l_queue_entry *e;
|
||||||
|
|
||||||
|
for (e = l_queue_get_entries(info_list); e; e = e->next) {
|
||||||
|
struct ft_info *info = e->data;
|
||||||
|
|
||||||
|
if (info->ifindex != ifindex)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (aa && memcmp(info->aa, aa, 6))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __ft_rx_action(uint32_t ifindex, const uint8_t *frame, size_t frame_len)
|
||||||
|
{
|
||||||
|
struct netdev *netdev = netdev_find(ifindex);
|
||||||
|
struct handshake_state *hs = netdev_get_handshake(netdev);
|
||||||
|
struct ft_info *info;
|
||||||
|
int ret;
|
||||||
|
const uint8_t *aa = NULL;
|
||||||
|
const uint8_t *spa = NULL;
|
||||||
|
const uint8_t *ies = NULL;
|
||||||
|
size_t ies_len = 0;
|
||||||
|
|
||||||
|
ret = ft_over_ds_parse_action_response(frame, frame_len, &spa, &aa,
|
||||||
|
&ies, &ies_len);
|
||||||
|
if (ret != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
info = ft_info_find(ifindex, aa);
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!ft_parse_ies(info, hs, ies, ies_len))
|
||||||
|
goto ft_error;
|
||||||
|
|
||||||
|
info->parsed = true;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
ft_error:
|
||||||
|
l_debug("FT-over-DS authenticate to "MAC" failed", MAC_STR(info->aa));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ft_info *ft_info_new(struct handshake_state *hs,
|
||||||
|
const struct scan_bss *target_bss)
|
||||||
|
{
|
||||||
|
struct ft_info *info = l_new(struct ft_info, 1);
|
||||||
|
|
||||||
|
info->ifindex = hs->ifindex;
|
||||||
|
memcpy(info->spa, hs->spa, 6);
|
||||||
|
memcpy(info->aa, target_bss->addr, 6);
|
||||||
|
memcpy(info->mde, target_bss->mde, sizeof(info->mde));
|
||||||
|
memcpy(info->prev_bssid, hs->aa, 6);
|
||||||
|
|
||||||
|
info->frequency = target_bss->frequency;
|
||||||
|
|
||||||
|
if (target_bss->rsne)
|
||||||
|
info->authenticator_ie = l_memdup(target_bss->rsne,
|
||||||
|
target_bss->rsne[1] + 2);
|
||||||
|
|
||||||
|
l_getrandom(info->snonce, 32);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ft_info_destroy(void *data)
|
||||||
|
{
|
||||||
|
struct ft_info *info = data;
|
||||||
|
|
||||||
|
if (info->fte)
|
||||||
|
l_free(info->fte);
|
||||||
|
|
||||||
|
if (info->authenticator_ie)
|
||||||
|
l_free(info->authenticator_ie);
|
||||||
|
|
||||||
|
l_free(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ft_prepare_handshake(struct ft_info *info,
|
||||||
|
struct handshake_state *hs)
|
||||||
|
{
|
||||||
|
if (!hs->supplicant_ie)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(hs->snonce, info->snonce, sizeof(hs->snonce));
|
||||||
|
|
||||||
|
handshake_state_set_fte(hs, info->fte);
|
||||||
|
|
||||||
|
handshake_state_set_anonce(hs, info->ft_info.anonce);
|
||||||
|
|
||||||
|
handshake_state_set_kh_ids(hs, info->ft_info.r0khid,
|
||||||
|
info->ft_info.r0khid_len,
|
||||||
|
info->ft_info.r1khid);
|
||||||
|
|
||||||
|
handshake_state_derive_ptk(hs);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft_action(uint32_t ifindex, uint32_t freq, const struct scan_bss *target)
|
||||||
|
{
|
||||||
|
struct netdev *netdev = netdev_find(ifindex);
|
||||||
|
struct handshake_state *hs = netdev_get_handshake(netdev);
|
||||||
|
struct ft_info *info;
|
||||||
|
uint8_t ft_req[14];
|
||||||
|
struct iovec iov[5];
|
||||||
|
uint8_t ies[512];
|
||||||
|
size_t len;
|
||||||
|
int ret = -EINVAL;
|
||||||
|
|
||||||
|
info = ft_info_new(hs, target);
|
||||||
|
|
||||||
|
ft_req[0] = 6; /* FT category */
|
||||||
|
ft_req[1] = 1; /* FT Request action */
|
||||||
|
memcpy(ft_req + 2, info->spa, 6);
|
||||||
|
memcpy(ft_req + 8, info->aa, 6);
|
||||||
|
|
||||||
|
if (!ft_build_authenticate_ies(hs, hs->supplicant_ocvc, info->snonce,
|
||||||
|
ies, &len))
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
iov[0].iov_base = ft_req;
|
||||||
|
iov[0].iov_len = sizeof(ft_req);
|
||||||
|
|
||||||
|
iov[1].iov_base = ies;
|
||||||
|
iov[1].iov_len = len;
|
||||||
|
|
||||||
|
ret = tx_frame(hs->ifindex, 0x00d0, freq, hs->aa, iov, 2);
|
||||||
|
if (ret < 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
l_queue_push_tail(info_list, info);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
l_free(info);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ft_associate(uint32_t ifindex, const uint8_t *addr)
|
||||||
|
{
|
||||||
|
struct netdev *netdev = netdev_find(ifindex);
|
||||||
|
struct handshake_state *hs = netdev_get_handshake(netdev);
|
||||||
|
struct ft_info *info;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Since FT-over-DS is done early, before the time of roaming, it
|
||||||
|
* may end up that a completely new BSS is the best candidate and
|
||||||
|
* we haven't yet authenticated. We could actually authenticate
|
||||||
|
* at this point, but for now just assume the caller will choose
|
||||||
|
* a different BSS.
|
||||||
|
*/
|
||||||
|
info = ft_info_find(ifindex, addr);
|
||||||
|
if (!info)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
ft_prepare_handshake(info, hs);
|
||||||
|
|
||||||
|
ret = ft_tx_reassociate(ifindex, info->frequency, info->prev_bssid);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
uint32_t ifindex = L_PTR_TO_UINT(user_data);
|
||||||
|
|
||||||
|
if (info->ifindex != ifindex)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ft_info_destroy(info);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ft_clear_authentications(uint32_t ifindex)
|
||||||
|
{
|
||||||
|
l_queue_foreach_remove(info_list, remove_ifindex,
|
||||||
|
L_UINT_TO_PTR(ifindex));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ft_init(void)
|
||||||
|
{
|
||||||
|
info_list = l_queue_new();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ft_exit(void)
|
||||||
|
{
|
||||||
|
if (!l_queue_isempty(info_list))
|
||||||
|
l_warn("stale FT info objects found!");
|
||||||
|
|
||||||
|
l_queue_destroy(info_list, ft_info_destroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
IWD_MODULE(ft, ft_init, ft_exit);
|
||||||
|
|
22
src/ft.h
22
src/ft.h
|
@ -21,11 +21,19 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct handshake_state;
|
struct handshake_state;
|
||||||
|
struct scan_bss;
|
||||||
|
|
||||||
|
typedef int (*ft_tx_frame_func_t)(uint32_t ifindex, uint16_t frame_type,
|
||||||
|
uint32_t frequency,
|
||||||
|
const uint8_t *dest, struct iovec *iov,
|
||||||
|
size_t iov_len);
|
||||||
|
|
||||||
typedef void (*ft_tx_authenticate_func_t)(struct iovec *iov, size_t iov_len,
|
typedef void (*ft_tx_authenticate_func_t)(struct iovec *iov, size_t iov_len,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
typedef int (*ft_tx_associate_func_t)(struct iovec *ie_iov, size_t iov_len,
|
|
||||||
void *user_data);
|
typedef int (*ft_tx_associate_func_t)(uint32_t ifindex, uint32_t freq,
|
||||||
|
const uint8_t *prev_bssid,
|
||||||
|
struct iovec *ie_iov, size_t iov_len);
|
||||||
typedef int (*ft_get_oci)(void *user_data);
|
typedef int (*ft_get_oci)(void *user_data);
|
||||||
|
|
||||||
typedef void (*ft_ds_free_func_t)(void *user_data);
|
typedef void (*ft_ds_free_func_t)(void *user_data);
|
||||||
|
@ -71,3 +79,13 @@ struct auth_proto *ft_over_ds_sm_new(struct handshake_state *hs,
|
||||||
|
|
||||||
bool ft_over_ds_prepare_handshake(struct ft_ds_info *info,
|
bool ft_over_ds_prepare_handshake(struct ft_ds_info *info,
|
||||||
struct handshake_state *hs);
|
struct handshake_state *hs);
|
||||||
|
|
||||||
|
void __ft_set_tx_frame_func(ft_tx_frame_func_t func);
|
||||||
|
void __ft_set_tx_associate_func(ft_tx_associate_func_t func);
|
||||||
|
int __ft_rx_associate(uint32_t ifindex, const uint8_t *frame,
|
||||||
|
size_t frame_len);
|
||||||
|
void __ft_rx_action(uint32_t ifindex, const uint8_t *frame, size_t frame_len);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
29
src/netdev.c
29
src/netdev.c
|
@ -4422,11 +4422,11 @@ restore_snonce:
|
||||||
MMPDU_STATUS_CODE_UNSPECIFIED);
|
MMPDU_STATUS_CODE_UNSPECIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int netdev_ft_tx_associate(struct iovec *ft_iov, size_t n_ft_iov,
|
static int netdev_ft_tx_associate(uint32_t ifindex, uint32_t freq,
|
||||||
void *user_data)
|
const uint8_t *prev_bssid,
|
||||||
|
struct iovec *ft_iov, size_t n_ft_iov)
|
||||||
{
|
{
|
||||||
struct netdev *netdev = user_data;
|
struct netdev *netdev = netdev_find(ifindex);
|
||||||
struct auth_proto *ap = netdev->ap;
|
|
||||||
struct handshake_state *hs = netdev->handshake;
|
struct handshake_state *hs = netdev->handshake;
|
||||||
struct l_genl_msg *msg;
|
struct l_genl_msg *msg;
|
||||||
struct iovec iov[64];
|
struct iovec iov[64];
|
||||||
|
@ -4447,7 +4447,7 @@ static int netdev_ft_tx_associate(struct iovec *ft_iov, size_t n_ft_iov,
|
||||||
mpdu_sort_ies(subtype, iov, c_iov);
|
mpdu_sort_ies(subtype, iov, c_iov);
|
||||||
|
|
||||||
l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
|
l_genl_msg_append_attr(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
|
||||||
ap->prev_bssid);
|
prev_bssid);
|
||||||
l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, c_iov);
|
l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, c_iov);
|
||||||
|
|
||||||
netdev->connect_cmd_id = l_genl_family_send(nl80211, msg,
|
netdev->connect_cmd_id = l_genl_family_send(nl80211, msg,
|
||||||
|
@ -4659,17 +4659,15 @@ int netdev_fast_transition(struct netdev *netdev,
|
||||||
l_get_le16(target_bss->mde))
|
l_get_le16(target_bss->mde))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
prepare_ft(netdev, target_bss);
|
|
||||||
|
|
||||||
handshake_state_new_snonce(netdev->handshake);
|
|
||||||
|
|
||||||
netdev->connect_cb = cb;
|
netdev->connect_cb = cb;
|
||||||
|
|
||||||
netdev->ap = ft_over_air_sm_new(netdev->handshake,
|
netdev->ap = ft_over_air_sm_new(netdev->handshake,
|
||||||
netdev_ft_tx_authenticate,
|
netdev_ft_tx_authenticate,
|
||||||
netdev_ft_tx_associate,
|
netdev_ft_tx_associate,
|
||||||
netdev_get_oci, netdev);
|
netdev_get_oci, netdev);
|
||||||
memcpy(netdev->ap->prev_bssid, orig_bss->addr, ETH_ALEN);
|
prepare_ft(netdev, target_bss);
|
||||||
|
|
||||||
|
handshake_state_new_snonce(netdev->handshake);
|
||||||
|
|
||||||
wiphy_radio_work_insert(netdev->wiphy, &netdev->work,
|
wiphy_radio_work_insert(netdev->wiphy, &netdev->work,
|
||||||
WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
|
WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
|
||||||
|
@ -4701,16 +4699,14 @@ int netdev_fast_transition_over_ds(struct netdev *netdev,
|
||||||
if (!info || !info->parsed)
|
if (!info || !info->parsed)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
prepare_ft(netdev, target_bss);
|
|
||||||
|
|
||||||
ft_over_ds_prepare_handshake(&info->super, netdev->handshake);
|
|
||||||
|
|
||||||
netdev->connect_cb = cb;
|
netdev->connect_cb = cb;
|
||||||
|
|
||||||
netdev->ap = ft_over_ds_sm_new(netdev->handshake,
|
netdev->ap = ft_over_ds_sm_new(netdev->handshake,
|
||||||
netdev_ft_tx_associate,
|
netdev_ft_tx_associate,
|
||||||
netdev);
|
netdev);
|
||||||
memcpy(netdev->ap->prev_bssid, orig_bss->addr, ETH_ALEN);
|
prepare_ft(netdev, target_bss);
|
||||||
|
|
||||||
|
ft_over_ds_prepare_handshake(&info->super, netdev->handshake);
|
||||||
|
|
||||||
wiphy_radio_work_insert(netdev->wiphy, &netdev->work,
|
wiphy_radio_work_insert(netdev->wiphy, &netdev->work,
|
||||||
WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
|
WIPHY_WORK_PRIORITY_CONNECT, &ft_work_ops);
|
||||||
|
@ -6656,6 +6652,8 @@ static int netdev_init(void)
|
||||||
__eapol_set_tx_packet_func(netdev_control_port_frame);
|
__eapol_set_tx_packet_func(netdev_control_port_frame);
|
||||||
__eapol_set_install_pmk_func(netdev_set_pmk);
|
__eapol_set_install_pmk_func(netdev_set_pmk);
|
||||||
|
|
||||||
|
__ft_set_tx_associate_func(netdev_ft_tx_associate);
|
||||||
|
|
||||||
unicast_watch = l_genl_add_unicast_watch(genl, NL80211_GENL_NAME,
|
unicast_watch = l_genl_add_unicast_watch(genl, NL80211_GENL_NAME,
|
||||||
netdev_unicast_notify,
|
netdev_unicast_notify,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
@ -6720,3 +6718,4 @@ IWD_MODULE(netdev, netdev_init, netdev_exit);
|
||||||
IWD_MODULE_DEPENDS(netdev, eapol);
|
IWD_MODULE_DEPENDS(netdev, eapol);
|
||||||
IWD_MODULE_DEPENDS(netdev, frame_xchg);
|
IWD_MODULE_DEPENDS(netdev, frame_xchg);
|
||||||
IWD_MODULE_DEPENDS(netdev, wiphy);
|
IWD_MODULE_DEPENDS(netdev, wiphy);
|
||||||
|
IWD_MODULE_DEPENDS(netdev, ft);
|
||||||
|
|
Loading…
Reference in New Issue