Add mesh_group_{add,remove} control interface commands
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>
This commit is contained in:
parent
798b318223
commit
603a3f34c4
4 changed files with 157 additions and 3 deletions
|
@ -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 "
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue