3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-10-04 18:38:48 +02:00

wsc: Optionally disconnect before starting EAP-WSC

If the device is currently connected, we will initiate a disconnection
(or wait for the disconnection to complete) prior to starting the
WSC-EAP association.
This commit is contained in:
Denis Kenzior 2016-09-22 16:29:19 -05:00
parent 9a63ab6712
commit 9c2d61db2c

View File

@ -56,6 +56,8 @@ struct wsc {
size_t wsc_ies_size; size_t wsc_ies_size;
struct l_timeout *walk_timer; struct l_timeout *walk_timer;
uint32_t scan_id; uint32_t scan_id;
struct scan_bss *target;
uint32_t device_state_watch;
struct { struct {
char ssid[33]; char ssid[33];
enum security security; enum security security;
@ -361,10 +363,13 @@ static inline enum wsc_rf_band freq_to_rf_band(uint32_t freq)
return WSC_RF_BAND_2_4_GHZ; return WSC_RF_BAND_2_4_GHZ;
} }
static void wsc_connect(struct wsc *wsc, struct scan_bss *bss) static void wsc_connect(struct wsc *wsc)
{ {
struct eapol_sm *sm = eapol_sm_new(); struct eapol_sm *sm = eapol_sm_new();
struct l_settings *settings = l_settings_new(); struct l_settings *settings = l_settings_new();
struct scan_bss *bss = wsc->target;
wsc->target = NULL;
eapol_sm_set_authenticator_address(sm, bss->addr); eapol_sm_set_authenticator_address(sm, bss->addr);
eapol_sm_set_supplicant_address(sm, device_get_address(wsc->device)); eapol_sm_set_supplicant_address(sm, device_get_address(wsc->device));
@ -399,6 +404,57 @@ static void wsc_connect(struct wsc *wsc, struct scan_bss *bss)
dbus_pending_reply(&wsc->pending, dbus_error_failed(wsc->pending)); dbus_pending_reply(&wsc->pending, dbus_error_failed(wsc->pending));
} }
static void device_state_watch(enum device_state state, void *userdata)
{
struct wsc *wsc = userdata;
if (state != DEVICE_STATE_DISCONNECTED)
return;
l_debug("%p", wsc);
device_remove_state_watch(wsc->device, wsc->device_state_watch);
wsc->device_state_watch = 0;
wsc_connect(wsc);
}
static void wsc_check_can_connect(struct wsc *wsc, struct scan_bss *target)
{
l_debug("%p", wsc);
/*
* For now we assign the targe pointer directly, since we should not
* be triggering any more scans while disconnecting / connecting
*/
wsc->target = target;
device_set_autoconnect(wsc->device, false);
switch (device_get_state(wsc->device)) {
case DEVICE_STATE_DISCONNECTED:
wsc_connect(wsc);
return;
case DEVICE_STATE_CONNECTING:
case DEVICE_STATE_CONNECTED:
if (device_disconnect(wsc->device) < 0)
goto error;
/* fall through */
case DEVICE_STATE_DISCONNECTING:
wsc->device_state_watch =
device_add_state_watch(wsc->device, device_state_watch,
wsc, NULL);
return;
case DEVICE_STATE_AUTOCONNECT:
case DEVICE_STATE_OFF:
l_warn("wsc_check_can_connect: invalid device state");
break;
}
error:
wsc->target = NULL;
dbus_pending_reply(&wsc->pending, dbus_error_failed(wsc->pending));
}
static void wsc_cancel_scan(struct wsc *wsc) static void wsc_cancel_scan(struct wsc *wsc)
{ {
l_free(wsc->wsc_ies); l_free(wsc->wsc_ies);
@ -527,7 +583,7 @@ static bool scan_results(uint32_t wiphy_id, uint32_t ifindex,
l_debug("Found AP to connect to: %s", l_debug("Found AP to connect to: %s",
util_address_to_string(target->addr)); util_address_to_string(target->addr));
wsc_connect(wsc, target); wsc_check_can_connect(wsc, target);
return true; return true;
@ -627,6 +683,13 @@ static struct l_dbus_message *wsc_cancel(struct l_dbus *dbus,
return dbus_error_not_available(message); return dbus_error_not_available(message);
wsc_cancel_scan(wsc); wsc_cancel_scan(wsc);
if (wsc->device_state_watch) {
device_remove_state_watch(wsc->device, wsc->device_state_watch);
wsc->device_state_watch = 0;
wsc->target = NULL;
}
dbus_pending_reply(&wsc->pending, dbus_error_aborted(wsc->pending)); dbus_pending_reply(&wsc->pending, dbus_error_aborted(wsc->pending));
reply = l_dbus_message_new_method_return(message); reply = l_dbus_message_new_method_return(message);
@ -649,6 +712,12 @@ static void wsc_free(void *userdata)
wsc_cancel_scan(wsc); wsc_cancel_scan(wsc);
if (wsc->device_state_watch) {
device_remove_state_watch(wsc->device, wsc->device_state_watch);
wsc->device_state_watch = 0;
wsc->target = NULL;
}
if (wsc->pending) if (wsc->pending)
dbus_pending_reply(&wsc->pending, dbus_pending_reply(&wsc->pending,
dbus_error_not_available(wsc->pending)); dbus_error_not_available(wsc->pending));