]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
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 19a4d8d5c97465a4eb29adb4349e39684f28b6a0..aa2778b7c66b96b6370111c8d52428d6c78675d9 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 d43a17266a6d68af8a1a95b11f344a3f2fbecded..8782ba83bf6ef2d6fe95e9bba17228b36e392a0b 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 8e17b9692440f71b407907e3061b18daa51ff8c3..162a0b82884bcb972210e3b505da24c01391036c 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 49ae1ccdb6c62e5d7a6d338b64bbcc1adfae3c52..ba53451294a628ec69d066cf8873f13c06e4bea0 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);