Add ctrl_iface command for triggering a roam to a specific BSS
authorJouni Malinen <j@w1.fi>
Sat, 10 Apr 2010 19:56:55 +0000 (22:56 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 10 Apr 2010 19:56:55 +0000 (22:56 +0300)
'wpa_cli roam <bssid>' 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
wpa_supplicant/events.c
wpa_supplicant/wpa_cli.c
wpa_supplicant/wpa_supplicant_i.h

index 19a4d8d..aa2778b 100644 (file)
@@ -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;
index d43a172..8782ba8 100644 (file)
@@ -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
index 8e17b96..162a0b8 100644 (file)
@@ -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,
+         "<addr> = roam to the specified BSS" },
        { NULL, NULL, cli_cmd_flag_none, NULL }
 };
 
index 49ae1cc..ba53451 100644 (file)
@@ -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);