]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add mesh_group_{add,remove} control interface commands
authorJavier Lopez <jlopex@gmail.com>
Mon, 1 Sep 2014 04:23:33 +0000 (00:23 -0400)
committerJouni Malinen <j@w1.fi>
Sun, 16 Nov 2014 17:43:11 +0000 (19:43 +0200)
Parse MESH_GROUP_ADD/REMOVE commands on ctrl interface and call
wpa_supplicant routines. These commands are used to start or
join and leave a mesh network.

The mesh id is given in the configuration file, therefore there is
no need to scan before joining a mesh network. We reuse the
connect_without_scan construct used by P2P for that same purpose.

Signed-off-by: Javier Cardona <javier@cozybit.com>
Signed-off-by: Javier Lopez <jlopex@gmail.com>
src/common/wpa_ctrl.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/wpa_cli.c
wpa_supplicant/wpa_supplicant.c

index af1e77686c9b22b78fe96ac0648d00933020a959..a91cc38fda78d8a1a9d82329c936711dd1d8ca02 100644 (file)
@@ -121,6 +121,8 @@ extern "C" {
 #define WPS_EVENT_ER_SET_SEL_REG "WPS-ER-AP-SET-SEL-REG "
 
 /* MESH events */
+#define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
+#define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED "
 #define MESH_PEER_CONNECTED "MESH-PEER-CONNECTED "
 #define MESH_PEER_DISCONNECTED "MESH-PEER-DISCONNECTED "
 
index 1c4844ce3de36ac817c0bbddd371540f6d37970a..b7eeb14cbadb3ce3237813073884f6ea5f96e482 100644 (file)
@@ -2365,6 +2365,77 @@ static int wpa_supplicant_ctrl_iface_scan_results(
 }
 
 
+#ifdef CONFIG_MESH
+
+static int wpa_supplicant_ctrl_iface_mesh_group_add(
+       struct wpa_supplicant *wpa_s, char *cmd)
+{
+       int id;
+       struct wpa_ssid *ssid;
+
+       id = atoi(cmd);
+       wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_ADD id=%d", id);
+
+       ssid = wpa_config_get_network(wpa_s->conf, id);
+       if (ssid == NULL) {
+               wpa_printf(MSG_DEBUG,
+                          "CTRL_IFACE: Could not find network id=%d", id);
+               return -1;
+       }
+       if (ssid->mode != WPAS_MODE_MESH) {
+               wpa_printf(MSG_DEBUG,
+                          "CTRL_IFACE: Cannot use MESH_GROUP_ADD on a non mesh network");
+               return -1;
+       }
+
+       /*
+        * TODO: If necessary write our own group_add function,
+        * for now we can reuse select_network
+        */
+       wpa_supplicant_select_network(wpa_s, ssid);
+
+       return 0;
+}
+
+
+static int wpa_supplicant_ctrl_iface_mesh_group_remove(
+       struct wpa_supplicant *wpa_s, char *cmd)
+{
+       if (!cmd) {
+               wpa_printf(MSG_ERROR,
+                          "CTRL_IFACE: MESH_GROUP_REMOVE ifname cannot be empty");
+               return -1;
+       }
+
+       /*
+        * TODO: Support a multiple mesh and other iface type combinations
+        */
+       if (os_strcmp(cmd, wpa_s->ifname) != 0) {
+               wpa_printf(MSG_DEBUG,
+                          "CTRL_IFACE: MESH_GROUP_REMOVE unknown interface name: %s",
+                          cmd);
+               return -1;
+       }
+
+       wpa_printf(MSG_DEBUG, "CTRL_IFACE: MESH_GROUP_REMOVE ifname=%s", cmd);
+
+       wpa_s->reassociate = 0;
+       wpa_s->disconnected = 1;
+       wpa_supplicant_cancel_sched_scan(wpa_s);
+       wpa_supplicant_cancel_scan(wpa_s);
+
+       /*
+        * TODO: If necessary write our own group_remove function,
+        * for now we can reuse deauthenticate
+        */
+       wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+
+       return 0;
+}
+
+#endif /* CONFIG_MESH */
+
+
 static int wpa_supplicant_ctrl_iface_select_network(
        struct wpa_supplicant *wpa_s, char *cmd)
 {
@@ -6904,6 +6975,15 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
                        reply_len = -1;
 #endif /* CONFIG_IBSS_RSN */
+#ifdef CONFIG_MESH
+       } else if (os_strncmp(buf, "MESH_GROUP_ADD ", 15) == 0) {
+               if (wpa_supplicant_ctrl_iface_mesh_group_add(wpa_s, buf + 15))
+                       reply_len = -1;
+       } else if (os_strncmp(buf, "MESH_GROUP_REMOVE ", 18) == 0) {
+               if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
+                                                               buf + 18))
+                       reply_len = -1;
+#endif /* CONFIG_MESH */
 #ifdef CONFIG_P2P
        } else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
                if (p2p_ctrl_find(wpa_s, buf + 9))
index 2bb3b65831acccc8a65f985efca929dcb3087f8b..5a3d1f69ef0c9a9e3f0a0b3fa88b86419ed43996 100644 (file)
@@ -1752,6 +1752,24 @@ static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
 }
 
 
+#ifdef CONFIG_MESH
+
+static int wpa_cli_cmd_mesh_group_add(struct wpa_ctrl *ctrl, int argc,
+                                     char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "MESH_GROUP_ADD", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_mesh_group_remove(struct wpa_ctrl *ctrl, int argc,
+                                        char *argv[])
+{
+       return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
+}
+
+#endif /* CONFIG_MESH */
+
+
 #ifdef CONFIG_P2P
 
 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
@@ -2781,6 +2799,14 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
          cli_cmd_flag_none,
          "<addr> = roam to the specified BSS" },
+#ifdef CONFIG_MESH
+       { "mesh_group_add", wpa_cli_cmd_mesh_group_add, NULL,
+         cli_cmd_flag_none,
+         "<network id> = join a mesh network (disable others)" },
+       { "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
+         cli_cmd_flag_none,
+         "<ifname> = Remove mesh group interface" },
+#endif /* CONFIG_MESH */
 #ifdef CONFIG_P2P
        { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
          cli_cmd_flag_none,
index 7e761e71ab3c9d769ee3dea94565df7ac3fdfeb9..695004856eae1a5ae21920d74da61abb60f33996 100644 (file)
@@ -52,6 +52,7 @@
 #include "hs20_supplicant.h"
 #include "wnm_sta.h"
 #include "wpas_kay.h"
+#include "mesh.h"
 
 const char *wpa_supplicant_version =
 "wpa_supplicant v" VERSION_STR "\n"
@@ -1532,6 +1533,31 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                return;
        }
 
+       if (ssid->mode == WPAS_MODE_MESH) {
+#ifdef CONFIG_MESH
+               if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) {
+                       wpa_msg(wpa_s, MSG_INFO,
+                               "Driver does not support mesh mode");
+                       return;
+               }
+               if (bss)
+                       ssid->frequency = bss->freq;
+               if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
+                       wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
+                       return;
+               }
+               wpa_s->current_bss = bss;
+               wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_STARTED
+                            "ssid=\"%s\" id=%d",
+                            wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
+                            ssid->id);
+#else /* CONFIG_MESH */
+               wpa_msg(wpa_s, MSG_ERROR,
+                       "mesh mode support not included in the build");
+#endif /* CONFIG_MESH */
+               return;
+       }
+
 #ifdef CONFIG_TDLS
        if (bss)
                wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
@@ -1879,8 +1905,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
                params.fixed_bssid = 1;
        }
 
-       if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
-           params.freq.freq == 0) {
+       /* Initial frequency for IBSS/mesh */
+       if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
+           ssid->frequency > 0 && params.freq.freq == 0) {
                enum hostapd_hw_mode hw_mode;
                u8 channel;
 
@@ -2143,6 +2170,14 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
        wpa_tdls_teardown_peers(wpa_s->wpa);
 #endif /* CONFIG_TDLS */
 
+#ifdef CONFIG_MESH
+       if (wpa_s->ifmsh) {
+               wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
+                            wpa_s->ifname);
+               wpa_supplicant_leave_mesh(wpa_s);
+       }
+#endif /* CONFIG_MESH */
+
        if (addr) {
                wpa_drv_deauthenticate(wpa_s, addr, reason_code);
                os_memset(&event, 0, sizeof(event));
@@ -2308,8 +2343,12 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
        if (ssid) {
                wpa_s->current_ssid = ssid;
                eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
+               wpa_s->connect_without_scan =
+                       (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL;
+       } else {
+               wpa_s->connect_without_scan = NULL;
        }
-       wpa_s->connect_without_scan = NULL;
+
        wpa_s->disconnected = 0;
        wpa_s->reassociate = 1;
 
@@ -3928,6 +3967,13 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
                wpa_s->ctrl_iface = NULL;
        }
 
+#ifdef CONFIG_MESH
+       if (wpa_s->ifmsh) {
+               wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
+               wpa_s->ifmsh = NULL;
+       }
+#endif /* CONFIG_MESH */
+
        if (wpa_s->conf != NULL) {
                wpa_config_free(wpa_s->conf);
                wpa_s->conf = NULL;