From 86d4f806da8ca21a1dcb777494da2307d76127cf Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 10 Apr 2010 22:56:55 +0300 Subject: [PATCH] Add ctrl_iface command for triggering a roam to a specific BSS 'wpa_cli roam ' can now be used to test roaming within an ESS (e.g., for FT over-the-air). This command will bypass a new scan and will select the BSS based on the specified BSSID. It is responsibility of the caller to make sure that the target AP is in the BSS table. This can be done, e.g., by running a scan before the roam command, if needed. --- wpa_supplicant/ctrl_iface.c | 43 +++++++++++++++++++++++++++++++ wpa_supplicant/events.c | 6 ++--- wpa_supplicant/wpa_cli.c | 23 +++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 3 +++ 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 19a4d8d5c..aa2778b7c 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -1648,6 +1648,46 @@ static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) } +static int wpa_supplicant_ctrl_iface_roam(struct wpa_supplicant *wpa_s, + char *addr) +{ + u8 bssid[ETH_ALEN]; + struct wpa_bss *bss; + struct wpa_ssid *ssid = wpa_s->current_ssid; + + if (hwaddr_aton(addr, bssid)) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: invalid " + "address '%s'", addr); + return -1; + } + + wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM " MACSTR, MAC2STR(bssid)); + + bss = wpa_bss_get_bssid(wpa_s, bssid); + if (!bss) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: Target AP not found " + "from BSS table"); + return -1; + } + + /* + * TODO: Find best network configuration block from configuration to + * allow roaming to other networks + */ + + if (!ssid) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE ROAM: No network " + "configuration known for the target AP"); + return -1; + } + + wpa_s->reassociate = 1; + wpa_supplicant_connect(wpa_s, bss, ssid); + + return 0; +} + + char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, char *buf, size_t *resp_len) { @@ -1853,6 +1893,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, wpas_notify_resume(wpa_s->global); } else if (os_strcmp(buf, "DROP_SA") == 0) { wpa_supplicant_ctrl_iface_drop_sa(wpa_s); + } else if (os_strncmp(buf, "ROAM ", 5) == 0) { + if (wpa_supplicant_ctrl_iface_roam(wpa_s, buf + 5)) + reply_len = -1; } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index d43a17266..8782ba83b 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -720,9 +720,9 @@ static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s, } -static void wpa_supplicant_connect(struct wpa_supplicant *wpa_s, - struct wpa_bss *selected, - struct wpa_ssid *ssid) +void wpa_supplicant_connect(struct wpa_supplicant *wpa_s, + struct wpa_bss *selected, + struct wpa_ssid *ssid) { if (wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) { wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 8e17b9692..162a0b828 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -1440,6 +1440,26 @@ static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[]) } +static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[128]; + int res; + + if (argc != 1) { + printf("Invalid ROAM command: needs one argument " + "(target AP's BSSID)\n"); + return -1; + } + + res = os_snprintf(cmd, sizeof(cmd), "ROAM %s", argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long ROAM command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} + + enum wpa_cli_cmd_flags { cli_cmd_flag_none = 0x00, cli_cmd_flag_sensitive = 0x01 @@ -1640,6 +1660,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { "= notification of resume/thaw" }, { "drop_sa", wpa_cli_cmd_drop_sa, cli_cmd_flag_none, "= drop SA without deauth/disassoc (test command)" }, + { "roam", wpa_cli_cmd_roam, + cli_cmd_flag_none, + " = roam to the specified BSS" }, { NULL, NULL, cli_cmd_flag_none, NULL } }; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 49ae1ccdb..ba5345129 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -488,6 +488,9 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, /* events.c */ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s); +void wpa_supplicant_connect(struct wpa_supplicant *wpa_s, + struct wpa_bss *selected, + struct wpa_ssid *ssid); /* eap_register.c */ int eap_register_methods(void);