mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-01-03 10:32:33 +01:00
station/netdev: handle rekeying based on driver features
A new driver extended feature bit was added signifying if the driver supports PTK replacement/rekeying. During a connect, netdev checks for the driver feature and sets the handshakes 'no_rekey' flag accordingly. At some point the AP will decide to rekey which is handled inside eapol. If no_rekey is unset we rekey as normal and the connection remains open. If we have set no_rekey eapol will emit HANDSHAKE_EVENT_REKEY_FAILED, which is now caught inside station. If this happens our only choice is to fully disconnect and reconnect.
This commit is contained in:
parent
8edaa23f8a
commit
a2354f88a6
@ -2748,6 +2748,10 @@ static int netdev_connect_common(struct netdev *netdev,
|
|||||||
handshake_state_set_authenticator_address(hs, bss->addr);
|
handshake_state_set_authenticator_address(hs, bss->addr);
|
||||||
handshake_state_set_supplicant_address(hs, netdev->addr);
|
handshake_state_set_supplicant_address(hs, netdev->addr);
|
||||||
|
|
||||||
|
if (!wiphy_has_ext_feature(netdev->wiphy,
|
||||||
|
NL80211_EXT_FEATURE_CAN_REPLACE_PTK0))
|
||||||
|
handshake_state_set_no_rekey(hs, true);
|
||||||
|
|
||||||
if (netdev->sae_sm)
|
if (netdev->sae_sm)
|
||||||
sae_start(netdev->sae_sm);
|
sae_start(netdev->sae_sm);
|
||||||
else if (netdev->owe)
|
else if (netdev->owe)
|
||||||
|
@ -377,6 +377,8 @@ void station_set_scan_results(struct station *station, struct l_queue *bss_list,
|
|||||||
l_queue_destroy(old_bss_list, bss_free);
|
l_queue_destroy(old_bss_list, bss_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void station_reconnect(struct station *station);
|
||||||
|
|
||||||
static void station_handshake_event(struct handshake_state *hs,
|
static void station_handshake_event(struct handshake_state *hs,
|
||||||
enum handshake_event event,
|
enum handshake_event event,
|
||||||
void *event_data, void *user_data)
|
void *event_data, void *user_data)
|
||||||
@ -397,8 +399,11 @@ static void station_handshake_event(struct handshake_state *hs,
|
|||||||
case HANDSHAKE_EVENT_FAILED:
|
case HANDSHAKE_EVENT_FAILED:
|
||||||
netdev_handshake_failed(hs, l_get_u16(event_data));
|
netdev_handshake_failed(hs, l_get_u16(event_data));
|
||||||
break;
|
break;
|
||||||
case HANDSHAKE_EVENT_SETTING_KEYS_FAILED:
|
case HANDSHAKE_EVENT_REKEY_FAILED:
|
||||||
|
station_reconnect(station);
|
||||||
|
break;
|
||||||
case HANDSHAKE_EVENT_COMPLETE:
|
case HANDSHAKE_EVENT_COMPLETE:
|
||||||
|
case HANDSHAKE_EVENT_SETTING_KEYS_FAILED:
|
||||||
/*
|
/*
|
||||||
* currently we dont care about any other events. The
|
* currently we dont care about any other events. The
|
||||||
* netdev_connect_cb will notify us when the connection is
|
* netdev_connect_cb will notify us when the connection is
|
||||||
@ -1811,6 +1816,42 @@ static struct l_dbus_message *station_dbus_connect_hidden_network(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void station_disconnect_reconnect_cb(struct netdev *netdev, bool success,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct station *station = user_data;
|
||||||
|
struct handshake_state *hs;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
hs = station_handshake_setup(station, station->connected_network,
|
||||||
|
station->connected_bss);
|
||||||
|
if (!hs)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
r = netdev_connect(station->netdev, station->connected_bss, hs,
|
||||||
|
station_netdev_event, station_connect_cb,
|
||||||
|
station);
|
||||||
|
if (r < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
station_disconnect(station);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void station_reconnect(struct station *station)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Rather than doing 4 or so state changes, lets just go into
|
||||||
|
* roaming for the duration of this reconnect.
|
||||||
|
*/
|
||||||
|
station_enter_state(station, STATION_STATE_ROAMING);
|
||||||
|
|
||||||
|
netdev_disconnect(station->netdev, station_disconnect_reconnect_cb,
|
||||||
|
station);
|
||||||
|
}
|
||||||
|
|
||||||
static void station_disconnect_cb(struct netdev *netdev, bool success,
|
static void station_disconnect_cb(struct netdev *netdev, bool success,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user