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_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)
|
||||
sae_start(netdev->sae_sm);
|
||||
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);
|
||||
}
|
||||
|
||||
static void station_reconnect(struct station *station);
|
||||
|
||||
static void station_handshake_event(struct handshake_state *hs,
|
||||
enum handshake_event event,
|
||||
void *event_data, void *user_data)
|
||||
@ -397,8 +399,11 @@ static void station_handshake_event(struct handshake_state *hs,
|
||||
case HANDSHAKE_EVENT_FAILED:
|
||||
netdev_handshake_failed(hs, l_get_u16(event_data));
|
||||
break;
|
||||
case HANDSHAKE_EVENT_SETTING_KEYS_FAILED:
|
||||
case HANDSHAKE_EVENT_REKEY_FAILED:
|
||||
station_reconnect(station);
|
||||
break;
|
||||
case HANDSHAKE_EVENT_COMPLETE:
|
||||
case HANDSHAKE_EVENT_SETTING_KEYS_FAILED:
|
||||
/*
|
||||
* currently we dont care about any other events. The
|
||||
* 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;
|
||||
}
|
||||
|
||||
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,
|
||||
void *user_data)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user