diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 7ef88712c..98c4b6554 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -5963,6 +5963,14 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = -1; else wpas_request_connection(wpa_s); + } else if (os_strcmp(buf, "REATTACH") == 0) { + if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED || + !wpa_s->current_ssid) + reply_len = -1; + else { + wpa_s->reattach = 1; + wpas_request_connection(wpa_s); + } } else if (os_strcmp(buf, "RECONNECT") == 0) { if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) reply_len = -1; diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index f40d4219e..5e02956b4 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -2462,6 +2462,12 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { END_ARGS } }, + { "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) &wpas_dbus_handler_reattach, + { + END_ARGS + } + }, { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, (WPADBusMethodHandler) &wpas_dbus_handler_remove_network, { diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index bfb33d5d2..5466d16cd 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -1486,6 +1486,29 @@ DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message, } +/** + * wpas_dbus_handler_reattach - Reattach to current AP + * @message: Pointer to incoming dbus message + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: NotConnected DBus error message if not connected + * or NULL otherwise. + * + * Handler function for "Reattach" method call of network interface. + */ +DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + if (wpa_s->current_ssid != NULL) { + wpa_s->reattach = 1; + wpas_request_connection(wpa_s); + return NULL; + } + + return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED, + "This interface is not connected"); +} + + /** * wpas_dbus_handler_remove_network - Remove a configured network * @message: Pointer to incoming dbus message diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h index c0669445e..461970d3f 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/wpa_supplicant/dbus/dbus_new_handlers.h @@ -101,6 +101,9 @@ DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message, DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message, struct wpa_supplicant *wpa_s); +DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message, + struct wpa_supplicant *wpa_s); + DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message, struct wpa_supplicant *wpa_s); diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 8e35fcc3c..1d8e8a609 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -665,6 +665,36 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) * wildcard SSID. */ ssid = NULL; + } else if (wpa_s->reattach && wpa_s->current_ssid != NULL) { + /* + * Perform single-channel single-SSID scan for + * reassociate-to-same-BSS operation. + */ + /* Setup SSID */ + ssid = wpa_s->current_ssid; + wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", + ssid->ssid, ssid->ssid_len); + params.ssids[0].ssid = ssid->ssid; + params.ssids[0].ssid_len = ssid->ssid_len; + params.num_ssids = 1; + + /* + * Allocate memory for frequency array, allocate one extra + * slot for the zero-terminator. + */ + params.freqs = os_malloc(sizeof(int) * 2); + if (params.freqs == NULL) { + wpa_dbg(wpa_s, MSG_ERROR, "Memory allocation failed"); + return; + } + params.freqs[0] = wpa_s->assoc_freq; + params.freqs[1] = 0; + + /* + * Reset the reattach flag so that we fall back to full scan if + * this scan fails. + */ + wpa_s->reattach = 0; } else { struct wpa_ssid *start = ssid, *tssid; int freqs_set = 0; diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 63ea1df93..2a9ab7fe0 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -676,6 +676,12 @@ static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc, } +static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + return wpa_ctrl_command(ctrl, "REATTACH"); +} + + static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -2510,6 +2516,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { { "reassociate", wpa_cli_cmd_reassociate, NULL, cli_cmd_flag_none, "= force reassociation" }, + { "reattach", wpa_cli_cmd_reattach, NULL, + cli_cmd_flag_none, + "= force reassociation back to the same BSS" }, { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss, cli_cmd_flag_none, " = force preauthentication" }, diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index fd162d725..739b11f70 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -594,6 +594,7 @@ struct wpa_supplicant { u8 pending_eapol_rx_src[ETH_ALEN]; unsigned int last_eapol_matches_bssid:1; unsigned int eap_expected_failure:1; + unsigned int reattach:1; /* reassociation to the same BSS requested */ struct ibss_rsn *ibss_rsn;