3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-22 14:49:24 +01:00

netdev: hook in RX for FT-Action/Authentication/Association

This forwards Action, Authentication and Association frames to
ft.c via their new hooks in netdev.

Note that this will break FT-over-Air temporarily since the
auth-proto still is in use.
This commit is contained in:
James Prestwood 2022-09-27 12:47:25 -07:00 committed by Denis Kenzior
parent e12f198255
commit 8833a7377e

View File

@ -3205,13 +3205,15 @@ static void netdev_associate_event(struct l_genl_msg *msg,
const uint8_t *frame = NULL; const uint8_t *frame = NULL;
uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED; uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED;
int ret; int ret;
const struct mmpdu_header *hdr;
const struct mmpdu_association_response *assoc;
l_debug(""); l_debug("");
if (!netdev->connected || netdev->aborting) if (!netdev->connected || netdev->aborting)
return; return;
if (!netdev->ap) { if (!netdev->ap && !netdev->in_ft) {
netdev->associated = true; netdev->associated = true;
netdev->in_reassoc = false; netdev->in_reassoc = false;
return; return;
@ -3251,61 +3253,59 @@ static void netdev_associate_event(struct l_genl_msg *msg,
if (L_WARN_ON(!frame)) if (L_WARN_ON(!frame))
goto assoc_failed; goto assoc_failed;
if (netdev->ap) { hdr = mpdu_validate(frame, frame_len);
const struct mmpdu_header *hdr; if (L_WARN_ON(!hdr))
const struct mmpdu_association_response *assoc; goto assoc_failed;
hdr = mpdu_validate(frame, frame_len); assoc = mmpdu_body(hdr);
if (L_WARN_ON(!hdr)) status_code = L_CPU_TO_LE16(assoc->status_code);
goto assoc_failed;
assoc = mmpdu_body(hdr); if (netdev->ap)
status_code = L_CPU_TO_LE16(assoc->status_code); ret = auth_proto_rx_associate(netdev->ap, frame,
frame_len);
ret = auth_proto_rx_associate(netdev->ap, frame, frame_len); else
if (ret == 0) { ret = __ft_rx_associate(netdev->index, frame,
bool fils = !!(netdev->handshake->akm_suite & frame_len);
(IE_RSN_AKM_SUITE_FILS_SHA256 | if (ret == 0) {
IE_RSN_AKM_SUITE_FILS_SHA384 | bool fils = !!(netdev->handshake->akm_suite &
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384 | (IE_RSN_AKM_SUITE_FILS_SHA256 |
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256)); IE_RSN_AKM_SUITE_FILS_SHA384 |
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384 |
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256));
if (netdev->ap) {
auth_proto_free(netdev->ap); auth_proto_free(netdev->ap);
netdev->ap = NULL; netdev->ap = NULL;
}
netdev->sm = eapol_sm_new(netdev->handshake); netdev->sm = eapol_sm_new(netdev->handshake);
eapol_register(netdev->sm); eapol_register(netdev->sm);
/* Just in case this was a retry */ /* Just in case this was a retry */
netdev->ignore_connect_event = false; netdev->ignore_connect_event = false;
/* /*
* If in FT and/or FILS we don't force an initial 4-way * If in FT and/or FILS we don't force an initial 4-way
* handshake and instead just keep the EAPoL state * handshake and instead just keep the EAPoL state
* machine for the rekeys. * machine for the rekeys.
*/ */
if (netdev->in_ft || fils) if (netdev->in_ft || fils)
eapol_sm_set_require_handshake(netdev->sm, eapol_sm_set_require_handshake(netdev->sm,
false); false);
netdev->in_ft = false; netdev->in_ft = false;
netdev->in_reassoc = false; netdev->in_reassoc = false;
netdev->associated = true; netdev->associated = true;
return; return;
} else if (ret == -EAGAIN) { } else if (ret == -EAGAIN) {
/* /*
* Here to support OWE retries. OWE will retry * Here to support OWE retries. OWE will retry
* internally, but a connect event will still be emitted * internally, but a connect event will still be emitted
*/ */
netdev->ignore_connect_event = true; netdev->ignore_connect_event = true;
return; return;
} else if (ret > 0) } else if (ret > 0)
status_code = (uint16_t)ret; status_code = (uint16_t)ret;
goto assoc_failed;
}
return;
assoc_failed: assoc_failed:
netdev->result = NETDEV_RESULT_ASSOCIATION_FAILED; netdev->result = NETDEV_RESULT_ASSOCIATION_FAILED;
@ -4591,49 +4591,25 @@ static void netdev_ft_response_frame_event(const struct mmpdu_header *hdr,
int rssi, void *user_data) int rssi, void *user_data)
{ {
struct netdev *netdev = user_data; struct netdev *netdev = user_data;
struct netdev_ft_over_ds_info *info;
int ret;
uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED;
const uint8_t *aa;
const uint8_t *spa;
const uint8_t *ies;
size_t ies_len;
struct ft_ds_finder finder;
if (!netdev->connected) if (!netdev->connected)
return; return;
ret = ft_over_ds_parse_action_response(body, body_len, &spa, &aa, __ft_rx_action(netdev->index, (const uint8_t *)hdr,
&ies, &ies_len); mmpdu_header_len(hdr) + body_len);
if (ret < 0) }
static void netdev_ft_auth_response_frame_event(const struct mmpdu_header *hdr,
const void *body, size_t body_len,
int rssi, void *user_data)
{
struct netdev *netdev = user_data;
if (!netdev->connected)
return; return;
finder.spa = spa; __ft_rx_authenticate(netdev->index, (const uint8_t *)hdr,
finder.aa = aa; mmpdu_header_len(hdr) + body_len);
info = l_queue_find(netdev->ft_ds_list, match_ft_ds_info, &finder);
if (!info)
return;
/* Lookup successful, now check the status code */
if (ret > 0) {
status_code = (uint16_t)ret;
goto ft_error;
}
if (!ft_over_ds_parse_action_ies(&info->super, netdev->handshake,
ies, ies_len))
goto ft_error;
info->parsed = true;
return;
ft_error:
l_debug("FT-over-DS to "MAC" failed (%d)", MAC_STR(info->super.aa),
status_code);
netdev_ft_over_ds_auth_failed(info, status_code);
} }
static void netdev_qos_map_frame_event(const struct mmpdu_header *hdr, static void netdev_qos_map_frame_event(const struct mmpdu_header *hdr,
@ -5859,6 +5835,7 @@ static void netdev_add_station_frame_watches(struct netdev *netdev)
static const uint8_t action_sa_query_resp_prefix[2] = { 0x08, 0x01 }; static const uint8_t action_sa_query_resp_prefix[2] = { 0x08, 0x01 };
static const uint8_t action_sa_query_req_prefix[2] = { 0x08, 0x00 }; static const uint8_t action_sa_query_req_prefix[2] = { 0x08, 0x00 };
static const uint8_t action_ft_response_prefix[] = { 0x06, 0x02 }; static const uint8_t action_ft_response_prefix[] = { 0x06, 0x02 };
static const uint8_t auth_ft_response_prefix[] = { 0x02, 0x00 };
static const uint8_t action_qos_map_prefix[] = { 0x01, 0x04 }; static const uint8_t action_qos_map_prefix[] = { 0x01, 0x04 };
uint64_t wdev = netdev->wdev_id; uint64_t wdev = netdev->wdev_id;
@ -5879,6 +5856,10 @@ static void netdev_add_station_frame_watches(struct netdev *netdev)
sizeof(action_ft_response_prefix), sizeof(action_ft_response_prefix),
netdev_ft_response_frame_event, netdev, NULL); netdev_ft_response_frame_event, netdev, NULL);
frame_watch_add(wdev, 0, 0x00b0, auth_ft_response_prefix,
sizeof(auth_ft_response_prefix),
netdev_ft_auth_response_frame_event, netdev, NULL);
if (wiphy_supports_qos_set_map(netdev->wiphy)) if (wiphy_supports_qos_set_map(netdev->wiphy))
frame_watch_add(wdev, 0, 0x00d0, action_qos_map_prefix, frame_watch_add(wdev, 0, 0x00d0, action_qos_map_prefix,
sizeof(action_qos_map_prefix), sizeof(action_qos_map_prefix),