mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 21:22:37 +01:00
wsc: Refactor to separate station-specific code
Split the interface-specific logic from the core WSC logic. The core WSC code is the part that we can re-use between P2P and station and doesn't include the D-Bus code, scanning for the target BSS or the attempt to make a station mode connection.
This commit is contained in:
parent
a716f46573
commit
25708fbb5c
141
src/wsc.c
141
src/wsc.c
@ -65,6 +65,11 @@ struct wsc {
|
|||||||
struct wsc_credentials_info creds[3];
|
struct wsc_credentials_info creds[3];
|
||||||
uint32_t n_creds;
|
uint32_t n_creds;
|
||||||
struct l_settings *eap_settings;
|
struct l_settings *eap_settings;
|
||||||
|
char *pin;
|
||||||
|
|
||||||
|
wsc_done_cb_t done_cb;
|
||||||
|
void *done_data;
|
||||||
|
uint16_t config_method;
|
||||||
|
|
||||||
bool wsc_association : 1;
|
bool wsc_association : 1;
|
||||||
};
|
};
|
||||||
@ -153,15 +158,12 @@ static void wsc_try_credentials(struct wsc *wsc)
|
|||||||
l_dbus_message_unref(wsc->pending);
|
l_dbus_message_unref(wsc->pending);
|
||||||
wsc->pending = NULL;
|
wsc->pending = NULL;
|
||||||
|
|
||||||
goto done;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbus_pending_reply(&wsc->pending,
|
dbus_pending_reply(&wsc->pending,
|
||||||
wsc_error_not_reachable(wsc->pending));
|
wsc_error_not_reachable(wsc->pending));
|
||||||
station_set_autoconnect(wsc->station, true);
|
station_set_autoconnect(wsc->station, true);
|
||||||
done:
|
|
||||||
memset(wsc->creds, 0, sizeof(wsc->creds));
|
|
||||||
wsc->n_creds = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wsc_store_credentials(struct wsc *wsc)
|
static void wsc_store_credentials(struct wsc *wsc)
|
||||||
@ -217,6 +219,22 @@ static void wsc_disconnect_cb(struct netdev *netdev, bool success,
|
|||||||
station_set_autoconnect(wsc->station, true);
|
station_set_autoconnect(wsc->station, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wsc_connect_cleanup(struct wsc *wsc)
|
||||||
|
{
|
||||||
|
wsc->wsc_association = false;
|
||||||
|
|
||||||
|
l_settings_free(wsc->eap_settings);
|
||||||
|
wsc->eap_settings = NULL;
|
||||||
|
|
||||||
|
if (wsc->pin) {
|
||||||
|
explicit_bzero(wsc->pin, strlen(wsc->pin));
|
||||||
|
l_free(wsc->pin);
|
||||||
|
wsc->pin = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsc->target = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void wsc_connect_cb(struct netdev *netdev, enum netdev_result result,
|
static void wsc_connect_cb(struct netdev *netdev, enum netdev_result result,
|
||||||
void *event_data, void *user_data)
|
void *event_data, void *user_data)
|
||||||
{
|
{
|
||||||
@ -224,33 +242,38 @@ static void wsc_connect_cb(struct netdev *netdev, enum netdev_result result,
|
|||||||
|
|
||||||
l_debug("%d, result: %d", netdev_get_ifindex(wsc->netdev), result);
|
l_debug("%d, result: %d", netdev_get_ifindex(wsc->netdev), result);
|
||||||
|
|
||||||
wsc->wsc_association = false;
|
wsc_connect_cleanup(wsc);
|
||||||
|
|
||||||
l_settings_free(wsc->eap_settings);
|
|
||||||
wsc->eap_settings = NULL;
|
|
||||||
|
|
||||||
if (result == NETDEV_RESULT_HANDSHAKE_FAILED && wsc->n_creds > 0) {
|
if (result == NETDEV_RESULT_HANDSHAKE_FAILED && wsc->n_creds > 0) {
|
||||||
wsc_store_credentials(wsc);
|
struct wsc_credentials_info creds[L_ARRAY_SIZE(wsc->creds)];
|
||||||
wsc_try_credentials(wsc);
|
uint32_t n_creds = wsc->n_creds;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Once we call done_cb, the state is assumed to be wiped,
|
||||||
|
* so use a temporary array for creds here
|
||||||
|
*/
|
||||||
|
memcpy(creds, wsc->creds, sizeof(creds));
|
||||||
|
explicit_bzero(wsc->creds, sizeof(creds));
|
||||||
|
wsc->n_creds = 0;
|
||||||
|
wsc->done_cb(0, creds, n_creds, wsc->done_data);
|
||||||
|
explicit_bzero(creds, sizeof(creds));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case NETDEV_RESULT_ABORTED:
|
case NETDEV_RESULT_ABORTED:
|
||||||
dbus_pending_reply(&wsc->pending,
|
wsc->done_cb(-ECANCELED, NULL, 0, wsc->done_data);
|
||||||
dbus_error_aborted(wsc->pending));
|
|
||||||
return;
|
return;
|
||||||
case NETDEV_RESULT_HANDSHAKE_FAILED:
|
case NETDEV_RESULT_HANDSHAKE_FAILED:
|
||||||
dbus_pending_reply(&wsc->pending,
|
wsc->done_cb(-ENOKEY, NULL, 0, wsc->done_data);
|
||||||
wsc_error_no_credentials(wsc->pending));
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dbus_pending_reply(&wsc->pending,
|
wsc->done_cb(-EIO, NULL, 0, wsc->done_data);
|
||||||
dbus_error_failed(wsc->pending));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
station_set_autoconnect(wsc->station, true);
|
if (wsc->station)
|
||||||
|
station_set_autoconnect(wsc->station, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wsc_credential_obtained(struct wsc *wsc,
|
static void wsc_credential_obtained(struct wsc *wsc,
|
||||||
@ -460,22 +483,18 @@ static void wsc_connect(struct wsc *wsc)
|
|||||||
l_settings_set_string(settings, "WSC", "EnrolleeMAC",
|
l_settings_set_string(settings, "WSC", "EnrolleeMAC",
|
||||||
util_address_to_string(netdev_get_address(wsc->netdev)));
|
util_address_to_string(netdev_get_address(wsc->netdev)));
|
||||||
|
|
||||||
if (!strcmp(l_dbus_message_get_member(wsc->pending), "StartPin")) {
|
if (wsc->config_method == WSC_CONFIGURATION_METHOD_KEYPAD) {
|
||||||
const char *pin;
|
enum wsc_device_password_id dpid;
|
||||||
|
|
||||||
if (l_dbus_message_get_arguments(wsc->pending, "s", &pin)) {
|
if (strlen(wsc->pin) == 4 ||
|
||||||
enum wsc_device_password_id dpid;
|
wsc_pin_is_checksum_valid(wsc->pin))
|
||||||
|
dpid = WSC_DEVICE_PASSWORD_ID_DEFAULT;
|
||||||
|
else
|
||||||
|
dpid = WSC_DEVICE_PASSWORD_ID_USER_SPECIFIED;
|
||||||
|
|
||||||
if (strlen(pin) == 4 || wsc_pin_is_checksum_valid(pin))
|
l_settings_set_uint(settings, "WSC", "DevicePasswordId", dpid);
|
||||||
dpid = WSC_DEVICE_PASSWORD_ID_DEFAULT;
|
l_settings_set_string(settings, "WSC", "DevicePassword",
|
||||||
else
|
wsc->pin);
|
||||||
dpid = WSC_DEVICE_PASSWORD_ID_USER_SPECIFIED;
|
|
||||||
|
|
||||||
l_settings_set_uint(settings, "WSC",
|
|
||||||
"DevicePasswordId", dpid);
|
|
||||||
l_settings_set_string(settings, "WSC",
|
|
||||||
"DevicePassword", pin);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handshake_state_set_event_func(hs, wsc_handshake_event, wsc);
|
handshake_state_set_event_func(hs, wsc_handshake_event, wsc);
|
||||||
@ -511,8 +530,41 @@ static void wsc_connect(struct wsc *wsc)
|
|||||||
return;
|
return;
|
||||||
error:
|
error:
|
||||||
handshake_state_free(hs);
|
handshake_state_free(hs);
|
||||||
dbus_pending_reply(&wsc->pending,
|
wsc_connect_cleanup(wsc);
|
||||||
dbus_error_failed(wsc->pending));
|
wsc->done_cb(r, NULL, 0, wsc->done_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done callback for when WSC is triggered by DBus methods */
|
||||||
|
static void wsc_dbus_done_cb(int err, struct wsc_credentials_info *creds,
|
||||||
|
unsigned int n_creds, void *user_data)
|
||||||
|
{
|
||||||
|
struct wsc *wsc = user_data;
|
||||||
|
|
||||||
|
l_debug("err=%i", err);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case -ECANCELED:
|
||||||
|
dbus_pending_reply(&wsc->pending,
|
||||||
|
dbus_error_aborted(wsc->pending));
|
||||||
|
return;
|
||||||
|
case -ENOKEY:
|
||||||
|
dbus_pending_reply(&wsc->pending,
|
||||||
|
wsc_error_no_credentials(wsc->pending));
|
||||||
|
return;
|
||||||
|
case -EBUSY:
|
||||||
|
dbus_pending_reply(&wsc->pending,
|
||||||
|
dbus_error_busy(wsc->pending));
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
dbus_pending_reply(&wsc->pending,
|
||||||
|
dbus_error_failed(wsc->pending));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsc_store_credentials(wsc);
|
||||||
|
wsc_try_credentials(wsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void station_state_watch(enum station_state state, void *userdata)
|
static void station_state_watch(enum station_state state, void *userdata)
|
||||||
@ -541,6 +593,22 @@ static void wsc_check_can_connect(struct wsc *wsc, struct scan_bss *target)
|
|||||||
wsc->target = target;
|
wsc->target = target;
|
||||||
station_set_autoconnect(wsc->station, false);
|
station_set_autoconnect(wsc->station, false);
|
||||||
|
|
||||||
|
if (!strcmp(l_dbus_message_get_member(wsc->pending), "StartPin")) {
|
||||||
|
char *pin;
|
||||||
|
|
||||||
|
wsc->config_method = WSC_CONFIGURATION_METHOD_KEYPAD;
|
||||||
|
|
||||||
|
if (!l_dbus_message_get_arguments(wsc->pending, "s", &pin))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
wsc->pin = l_strdup(pin);
|
||||||
|
} else
|
||||||
|
wsc->config_method =
|
||||||
|
WSC_CONFIGURATION_METHOD_VIRTUAL_PUSH_BUTTON;
|
||||||
|
|
||||||
|
wsc->done_cb = wsc_dbus_done_cb;
|
||||||
|
wsc->done_data = wsc;
|
||||||
|
|
||||||
switch (station_get_state(wsc->station)) {
|
switch (station_get_state(wsc->station)) {
|
||||||
case STATION_STATE_DISCONNECTED:
|
case STATION_STATE_DISCONNECTED:
|
||||||
wsc_connect(wsc);
|
wsc_connect(wsc);
|
||||||
@ -564,7 +632,7 @@ static void wsc_check_can_connect(struct wsc *wsc, struct scan_bss *target)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
error:
|
error:
|
||||||
wsc->target = NULL;
|
wsc_connect_cleanup(wsc);
|
||||||
dbus_pending_reply(&wsc->pending, dbus_error_failed(wsc->pending));
|
dbus_pending_reply(&wsc->pending, dbus_error_failed(wsc->pending));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1074,12 +1142,12 @@ static void wsc_free(void *userdata)
|
|||||||
struct wsc *wsc = userdata;
|
struct wsc *wsc = userdata;
|
||||||
|
|
||||||
wsc_cancel_scan(wsc);
|
wsc_cancel_scan(wsc);
|
||||||
|
wsc_connect_cleanup(wsc);
|
||||||
|
|
||||||
if (wsc->station_state_watch) {
|
if (wsc->station_state_watch) {
|
||||||
station_remove_state_watch(wsc->station,
|
station_remove_state_watch(wsc->station,
|
||||||
wsc->station_state_watch);
|
wsc->station_state_watch);
|
||||||
wsc->station_state_watch = 0;
|
wsc->station_state_watch = 0;
|
||||||
wsc->target = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wsc->pending)
|
if (wsc->pending)
|
||||||
@ -1090,9 +1158,6 @@ static void wsc_free(void *userdata)
|
|||||||
dbus_pending_reply(&wsc->pending_cancel,
|
dbus_pending_reply(&wsc->pending_cancel,
|
||||||
dbus_error_aborted(wsc->pending_cancel));
|
dbus_error_aborted(wsc->pending_cancel));
|
||||||
|
|
||||||
if (wsc->eap_settings)
|
|
||||||
l_settings_free(wsc->eap_settings);
|
|
||||||
|
|
||||||
l_free(wsc);
|
l_free(wsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user