Browse Source

mesh: Add MESH_PEER_ADD command

This allows a mesh peer connection to be initiated manually in
no_auto_peer mesh networks.

Signed-off-by: Natsuki Itaya <Natsuki.Itaya@jp.sony.com>
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
Masashi Honma 9 years ago
parent
commit
2604edbfbd

+ 15 - 0
wpa_supplicant/ctrl_iface.c

@@ -2739,6 +2739,18 @@ static int wpa_supplicant_ctrl_iface_mesh_peer_remove(
 	return wpas_mesh_peer_remove(wpa_s, addr);
 	return wpas_mesh_peer_remove(wpa_s, addr);
 }
 }
 
 
+
+static int wpa_supplicant_ctrl_iface_mesh_peer_add(
+	struct wpa_supplicant *wpa_s, char *cmd)
+{
+	u8 addr[ETH_ALEN];
+
+	if (hwaddr_aton(cmd, addr))
+		return -1;
+
+	return wpas_mesh_peer_add(wpa_s, addr);
+}
+
 #endif /* CONFIG_MESH */
 #endif /* CONFIG_MESH */
 
 
 
 
@@ -8587,6 +8599,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 	} else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
 	} else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
 		if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
 		if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
 			reply_len = -1;
 			reply_len = -1;
+	} else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) {
+		if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14))
+			reply_len = -1;
 #endif /* CONFIG_MESH */
 #endif /* CONFIG_MESH */
 #ifdef CONFIG_P2P
 #ifdef CONFIG_P2P
 	} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
 	} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {

+ 6 - 0
wpa_supplicant/mesh.c

@@ -603,3 +603,9 @@ int wpas_mesh_peer_remove(struct wpa_supplicant *wpa_s, const u8 *addr)
 {
 {
 	return mesh_mpm_close_peer(wpa_s, addr);
 	return mesh_mpm_close_peer(wpa_s, addr);
 }
 }
+
+
+int wpas_mesh_peer_add(struct wpa_supplicant *wpa_s, const u8 *addr)
+{
+	return mesh_mpm_connect_peer(wpa_s, addr);
+}

+ 1 - 0
wpa_supplicant/mesh.h

@@ -19,6 +19,7 @@ int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
 int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname,
 int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname,
 			    size_t len);
 			    size_t len);
 int wpas_mesh_peer_remove(struct wpa_supplicant *wpa_s, const u8 *addr);
 int wpas_mesh_peer_remove(struct wpa_supplicant *wpa_s, const u8 *addr);
+int wpas_mesh_peer_add(struct wpa_supplicant *wpa_s, const u8 *addr);
 
 
 #ifdef CONFIG_MESH
 #ifdef CONFIG_MESH
 
 

+ 44 - 0
wpa_supplicant/mesh_mpm.c

@@ -512,6 +512,50 @@ int mesh_mpm_close_peer(struct wpa_supplicant *wpa_s, const u8 *addr)
 }
 }
 
 
 
 
+int mesh_mpm_connect_peer(struct wpa_supplicant *wpa_s, const u8 *addr)
+{
+	struct wpa_ssid *ssid = wpa_s->current_ssid;
+	struct hostapd_data *hapd;
+	struct sta_info *sta;
+	struct mesh_conf *conf;
+
+	if (!wpa_s->ifmsh) {
+		wpa_msg(wpa_s, MSG_INFO, "Mesh is not prepared yet");
+		return -1;
+	}
+
+	if (!ssid || !ssid->no_auto_peer) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"This command is available only with no_auto_peer mesh network");
+		return -1;
+	}
+
+	hapd = wpa_s->ifmsh->bss[0];
+	conf = wpa_s->ifmsh->mconf;
+
+	sta = ap_get_sta(hapd, addr);
+	if (!sta) {
+		wpa_msg(wpa_s, MSG_INFO, "No such mesh peer");
+		return -1;
+	}
+
+	if ((PLINK_OPEN_SENT <= sta->plink_state &&
+	    sta->plink_state <= PLINK_ESTAB) ||
+	    (sta->sae && sta->sae->state > SAE_NOTHING)) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"Specified peer is connecting/connected");
+		return -1;
+	}
+
+	if (conf->security == MESH_CONF_SEC_NONE)
+		mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
+	else
+		mesh_rsn_auth_sae_sta(wpa_s, sta);
+
+	return 0;
+}
+
+
 void mesh_mpm_deinit(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh)
 void mesh_mpm_deinit(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh)
 {
 {
 	struct hostapd_data *hapd = ifmsh->bss[0];
 	struct hostapd_data *hapd = ifmsh->bss[0];

+ 1 - 0
wpa_supplicant/mesh_mpm.h

@@ -19,6 +19,7 @@ void wpa_mesh_set_plink_state(struct wpa_supplicant *wpa_s,
 			      struct sta_info *sta,
 			      struct sta_info *sta,
 			      enum mesh_plink_state state);
 			      enum mesh_plink_state state);
 int mesh_mpm_close_peer(struct wpa_supplicant *wpa_s, const u8 *addr);
 int mesh_mpm_close_peer(struct wpa_supplicant *wpa_s, const u8 *addr);
+int mesh_mpm_connect_peer(struct wpa_supplicant *wpa_s, const u8 *addr);
 
 
 #ifdef CONFIG_MESH
 #ifdef CONFIG_MESH
 
 

+ 10 - 0
wpa_supplicant/wpa_cli.c

@@ -2049,6 +2049,13 @@ static int wpa_cli_cmd_mesh_peer_remove(struct wpa_ctrl *ctrl, int argc,
 	return wpa_cli_cmd(ctrl, "MESH_PEER_REMOVE", 1, argc, argv);
 	return wpa_cli_cmd(ctrl, "MESH_PEER_REMOVE", 1, argc, argv);
 }
 }
 
 
+
+static int wpa_cli_cmd_mesh_peer_add(struct wpa_ctrl *ctrl, int argc,
+				     char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "MESH_PEER_ADD", 1, argc, argv);
+}
+
 #endif /* CONFIG_MESH */
 #endif /* CONFIG_MESH */
 
 
 
 
@@ -3220,6 +3227,9 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
 	{ "mesh_peer_remove", wpa_cli_cmd_mesh_peer_remove, NULL,
 	{ "mesh_peer_remove", wpa_cli_cmd_mesh_peer_remove, NULL,
 	  cli_cmd_flag_none,
 	  cli_cmd_flag_none,
 	  "<addr> = Remove a mesh peer" },
 	  "<addr> = Remove a mesh peer" },
+	{ "mesh_peer_add", wpa_cli_cmd_mesh_peer_add, NULL,
+	  cli_cmd_flag_none,
+	  "<addr> = Add a mesh peer" },
 #endif /* CONFIG_MESH */
 #endif /* CONFIG_MESH */
 #ifdef CONFIG_P2P
 #ifdef CONFIG_P2P
 	{ "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
 	{ "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,