[PATCH 1/2] mesh: Enable DFS for mesh network

Masashi Honma masashi.honma at gmail.com
Sun Apr 9 19:55:46 PDT 2017


Signed-off-by: Masashi Honma <masashi.honma at gmail.com>
---
 src/ap/ap_config.h              |   1 +
 src/ap/dfs.c                    |  27 ++++--
 src/ap/hostapd.c                |   7 ++
 tests/hwsim/test_wpas_mesh.py   |  12 +--
 wpa_supplicant/ap.c             |  42 ++++++---
 wpa_supplicant/mesh.c           | 184 ++++++++++++++++++++++------------------
 wpa_supplicant/mesh.h           |   2 +-
 wpa_supplicant/wpa_supplicant.c |   8 +-
 8 files changed, 170 insertions(+), 113 deletions(-)

diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 989b071..0513dd9 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -49,6 +49,7 @@ struct mesh_conf {
 	int dot11MeshRetryTimeout; /* msec */
 	int dot11MeshConfirmTimeout; /* msec */
 	int dot11MeshHoldingTimeout; /* msec */
+	int (*join_mesh)(void *priv);
 };
 
 #define MAX_STA_COUNT 2007
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 2957201..30cb99f 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -637,6 +637,17 @@ static unsigned int dfs_get_cac_time(struct hostapd_iface *iface,
 }
 
 
+static void *get_message_ctx(struct hostapd_iface *iface)
+{
+#ifdef CONFIG_MESH
+	if (iface->mconf)
+		return iface->owner;
+#endif /* CONFIG_MESH */
+
+	return iface->bss[0]->msg_ctx;
+}
+
+
 /*
  * Main DFS handler
  * 1 - continue channel/ap setup
@@ -719,7 +730,7 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
 	/* Finally start CAC */
 	hostapd_set_state(iface, HAPD_IFACE_DFS);
 	wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq);
-	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
+	wpa_msg(get_message_ctx(iface), MSG_INFO, DFS_EVENT_CAC_START
 		"freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds",
 		iface->freq,
 		iface->conf->channel, iface->conf->secondary_channel,
@@ -768,7 +779,7 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
 			     int ht_enabled, int chan_offset, int chan_width,
 			     int cf1, int cf2)
 {
-	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED
+	wpa_msg(get_message_ctx(iface), MSG_INFO, DFS_EVENT_CAC_COMPLETED
 		"success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
 		success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
 
@@ -810,7 +821,7 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq,
 				int ht_enabled, int chan_offset, int chan_width,
 				int cf1, int cf2)
 {
-	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_PRE_CAC_EXPIRED
+	wpa_msg(get_message_ctx(iface), MSG_INFO, DFS_EVENT_PRE_CAC_EXPIRED
 		"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
 		freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
 
@@ -848,7 +859,7 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
 
 	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
 		   channel->chan);
-	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
+	wpa_msg(get_message_ctx(iface), MSG_INFO, DFS_EVENT_NEW_CHANNEL
 		"freq=%d chan=%d sec_chan=%d", channel->freq,
 		channel->chan, secondary_channel);
 
@@ -928,7 +939,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
 
 	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
 		   channel->chan);
-	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
+	wpa_msg(get_message_ctx(iface), MSG_INFO, DFS_EVENT_NEW_CHANNEL
 		"freq=%d chan=%d sec_chan=%d", channel->freq,
 		channel->chan, secondary_channel);
 
@@ -990,7 +1001,7 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
 {
 	int res;
 
-	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_RADAR_DETECTED
+	wpa_msg(get_message_ctx(iface), MSG_INFO, DFS_EVENT_RADAR_DETECTED
 		"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
 		freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
 
@@ -1021,7 +1032,7 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
 			     int ht_enabled, int chan_offset, int chan_width,
 			     int cf1, int cf2)
 {
-	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NOP_FINISHED
+	wpa_msg(get_message_ctx(iface), MSG_INFO, DFS_EVENT_NOP_FINISHED
 		"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
 		freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
 
@@ -1071,7 +1082,7 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
 			  int ht_enabled, int chan_offset, int chan_width,
 			  int cf1, int cf2)
 {
-	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
+	wpa_msg(get_message_ctx(iface), MSG_INFO, DFS_EVENT_CAC_START
 		"freq=%d chan=%d chan_offset=%d width=%d seg0=%d "
 		"seg1=%d cac_time=%ds",
 		freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2, 60);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 01215aa..27f5d7f 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1821,6 +1821,13 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
 		return res_dfs_offload;
 	}
 
+#ifdef CONFIG_MESH
+	if (iface->mconf && iface->mconf->join_mesh(iface->owner) < 0) {
+		wpa_msg(iface->owner, MSG_ERROR, "Could not join mesh");
+		goto fail;
+	}
+#endif /* CONFIG_MESH */
+
 #ifdef NEED_AP_MLME
 dfs_offload:
 #endif /* NEED_AP_MLME */
diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py
index f632ffd..469fe01 100644
--- a/tests/hwsim/test_wpas_mesh.py
+++ b/tests/hwsim/test_wpas_mesh.py
@@ -1573,7 +1573,7 @@ def test_mesh_oom(dev, apdev):
                 raise
             logger.info("Ignore no-oom for i=%d" % i)
 
-    with alloc_fail(dev[0], 4, "=wpa_supplicant_mesh_init"):
+    with alloc_fail(dev[0], 3, "=wpa_supplicant_mesh_init"):
         id = add_mesh_secure_net(dev[0])
         dev[0].mesh_group_add(id)
         ev = dev[0].wait_event(["Failed to init mesh"])
@@ -1636,7 +1636,7 @@ def test_mesh_drv_fail(dev, apdev):
     dev[0].dump_monitor()
     with fail_test(dev[0], 1, "wpa_driver_nl80211_init_mesh"):
         add_open_mesh_network(dev[0])
-        ev = dev[0].wait_event(["Could not join mesh"])
+        ev = dev[0].wait_event(["Failed to init mesh"])
         if ev is None:
             raise Exception("Join failure not reported")
 
@@ -1772,15 +1772,15 @@ def test_mesh_invalid_frequency(dev, apdev):
     check_mesh_support(dev[0])
     add_open_mesh_network(dev[0], freq=None)
     ev = dev[0].wait_event(["MESH-GROUP-STARTED",
-                            "Could not join mesh"])
-    if ev is None or "Could not join mesh" not in ev:
+                            "Failed to init mesh"])
+    if ev is None or "Failed to init mesh" not in ev:
         raise Exception("Mesh join failure not reported")
     dev[0].request("REMOVE_NETWORK all")
 
     add_open_mesh_network(dev[0], freq="2413")
     ev = dev[0].wait_event(["MESH-GROUP-STARTED",
-                            "Could not join mesh"])
-    if ev is None or "Could not join mesh" not in ev:
+                            "Failed to init mesh"])
+    if ev is None or "Failed to init mesh" not in ev:
         raise Exception("Mesh join failure not reported")
 
 def test_mesh_default_beacon_int(dev, apdev):
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 3fc8e94..720cd98 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -1497,13 +1497,35 @@ int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd)
 
 
 #ifdef NEED_AP_MLME
+static int event_handling_required(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_MESH
+	if (wpa_s->ifmsh)
+		return 1;
+#endif /* CONFIG_MESH */
+
+	return wpa_s->ap_iface && wpa_s->ap_iface->bss[0];
+}
+
+
+static struct hostapd_iface *get_hapd_iface(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_MESH
+	if (wpa_s->ifmsh)
+		return wpa_s->ifmsh;
+#endif /* CONFIG_MESH */
+
+	return wpa_s->ap_iface;
+}
+
+
 void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
 				   struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+	if (!event_handling_required(wpa_s))
 		return;
 	wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
-	hostapd_dfs_radar_detected(wpa_s->ap_iface, radar->freq,
+	hostapd_dfs_radar_detected(get_hapd_iface(wpa_s), radar->freq,
 				   radar->ht_enabled, radar->chan_offset,
 				   radar->chan_width,
 				   radar->cf1, radar->cf2);
@@ -1513,10 +1535,10 @@ void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
 void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
 				struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+	if (!event_handling_required(wpa_s))
 		return;
 	wpa_printf(MSG_DEBUG, "DFS CAC started on %d MHz", radar->freq);
-	hostapd_dfs_start_cac(wpa_s->ap_iface, radar->freq,
+	hostapd_dfs_start_cac(get_hapd_iface(wpa_s), radar->freq,
 			      radar->ht_enabled, radar->chan_offset,
 			      radar->chan_width, radar->cf1, radar->cf2);
 }
@@ -1525,10 +1547,10 @@ void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
 void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
 				 struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+	if (!event_handling_required(wpa_s))
 		return;
 	wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
-	hostapd_dfs_complete_cac(wpa_s->ap_iface, 1, radar->freq,
+	hostapd_dfs_complete_cac(get_hapd_iface(wpa_s), 1, radar->freq,
 				 radar->ht_enabled, radar->chan_offset,
 				 radar->chan_width, radar->cf1, radar->cf2);
 }
@@ -1537,10 +1559,10 @@ void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
 void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
 				struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+	if (!event_handling_required(wpa_s))
 		return;
 	wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
-	hostapd_dfs_complete_cac(wpa_s->ap_iface, 0, radar->freq,
+	hostapd_dfs_complete_cac(get_hapd_iface(wpa_s), 0, radar->freq,
 				 radar->ht_enabled, radar->chan_offset,
 				 radar->chan_width, radar->cf1, radar->cf2);
 }
@@ -1549,10 +1571,10 @@ void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
 void wpas_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
 				     struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+	if (!event_handling_required(wpa_s))
 		return;
 	wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
-	hostapd_dfs_nop_finished(wpa_s->ap_iface, radar->freq,
+	hostapd_dfs_nop_finished(get_hapd_iface(wpa_s), radar->freq,
 				 radar->ht_enabled, radar->chan_offset,
 				 radar->chan_width, radar->cf1, radar->cf2);
 }
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 01b657e..02323ae 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -26,6 +26,7 @@
 #include "mesh_rsn.h"
 #include "mesh.h"
 
+static int wpa_supplicant_join_mesh(void *priv);
 
 static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s)
 {
@@ -124,6 +125,7 @@ static struct mesh_conf * mesh_config_create(struct wpa_supplicant *wpa_s,
 	conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout;
 	conf->dot11MeshConfirmTimeout = ssid->dot11MeshConfirmTimeout;
 	conf->dot11MeshHoldingTimeout = ssid->dot11MeshHoldingTimeout;
+	conf->join_mesh = wpa_supplicant_join_mesh;
 
 	return conf;
 }
@@ -147,20 +149,55 @@ static void wpas_mesh_copy_groups(struct hostapd_data *bss,
 }
 
 
-static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
-				    struct wpa_ssid *ssid,
-				    struct hostapd_freq_params *freq)
+static void wpa_supplicant_mesh_freq_init(struct wpa_supplicant *wpa_s,
+					  struct wpa_ssid *ssid,
+					  struct hostapd_freq_params *freq)
+{
+	os_memset(freq, 0, sizeof(*freq));
+	ibss_mesh_setup_freq(wpa_s, ssid, freq);
+	if (freq->ht_enabled && freq->sec_channel_offset)
+		ssid->ht40 = freq->sec_channel_offset;
+	if (freq->vht_enabled) {
+		ssid->vht = 1;
+		switch (freq->bandwidth) {
+		case 80:
+			if (freq->center_freq2) {
+				ssid->max_oper_chwidth = VHT_CHANWIDTH_80P80MHZ;
+				ssid->vht_center_freq2 = freq->center_freq2;
+			} else {
+				ssid->max_oper_chwidth = VHT_CHANWIDTH_80MHZ;
+			}
+			break;
+		case 160:
+			ssid->max_oper_chwidth = VHT_CHANWIDTH_160MHZ;
+			break;
+		default:
+			ssid->max_oper_chwidth = VHT_CHANWIDTH_USE_HT;
+			break;
+		}
+	}
+}
+
+
+int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
+			     struct wpa_ssid *ssid)
 {
 	struct hostapd_iface *ifmsh;
 	struct hostapd_data *bss;
 	struct hostapd_config *conf;
 	struct mesh_conf *mconf;
+	struct hostapd_freq_params freq;
 	int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 };
-	static int default_groups[] = { 19, 20, 21, 25, 26, -1 };
-	size_t len;
 	int rate_len;
 	int frequency;
 
+	if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency)
+		return -EINVAL;
+
+	wpa_supplicant_mesh_deinit(wpa_s);
+
+	wpa_supplicant_mesh_freq_init(wpa_s, ssid, &freq);
+
 	if (!wpa_s->conf->user_mpm) {
 		/* not much for us to do here */
 		wpa_msg(wpa_s, MSG_WARNING,
@@ -172,6 +209,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
 	if (!ifmsh)
 		return -ENOMEM;
 
+	ifmsh->owner = wpa_s;
 	ifmsh->drv_flags = wpa_s->drv_flags;
 	ifmsh->num_bss = 1;
 	ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss,
@@ -189,10 +227,10 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
 	bss->iface = ifmsh;
 	bss->mesh_sta_free_cb = mesh_mpm_free_sta;
 	frequency = ssid->frequency;
-	if (frequency != freq->freq &&
-	    frequency == freq->freq + freq->sec_channel_offset * 20) {
+	if (frequency != freq.freq &&
+	    frequency == freq.freq + freq.sec_channel_offset * 20) {
 		wpa_printf(MSG_DEBUG, "mesh: pri/sec channels switched");
-		frequency = freq->freq;
+		frequency = freq.freq;
 	}
 	wpa_s->assoc_freq = frequency;
 	wpa_s->current_ssid = ssid;
@@ -226,6 +264,15 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
 			   frequency);
 		goto out_free;
 	}
+
+	if (ieee80211_is_dfs(ssid->frequency) && wpa_s->conf->country[0]) {
+		conf->ieee80211h = 1;
+		conf->ieee80211d = 1;
+		conf->country[0] = wpa_s->conf->country[0];
+		conf->country[1] = wpa_s->conf->country[1];
+		conf->country[2] = ' ';
+	}
+
 	if (ssid->ht40)
 		conf->secondary_channel = ssid->ht40;
 	if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && ssid->vht) {
@@ -279,45 +326,15 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
 		conf->basic_rates[rate_len] = -1;
 	}
 
-	if (hostapd_setup_interface(ifmsh)) {
-		wpa_printf(MSG_ERROR,
-			   "Failed to initialize hostapd interface for mesh");
-		return -1;
-	}
-
 	if (wpa_drv_init_mesh(wpa_s)) {
 		wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
 		return -1;
 	}
 
-	if (mconf->security != MESH_CONF_SEC_NONE) {
-		if (ssid->passphrase == NULL) {
-			wpa_printf(MSG_ERROR,
-				   "mesh: Passphrase for SAE not configured");
-			goto out_free;
-		}
-
-		bss->conf->wpa = ssid->proto;
-		bss->conf->wpa_key_mgmt = ssid->key_mgmt;
-
-		if (wpa_s->conf->sae_groups &&
-		    wpa_s->conf->sae_groups[0] > 0) {
-			wpas_mesh_copy_groups(bss, wpa_s);
-		} else {
-			bss->conf->sae_groups =
-				os_memdup(default_groups,
-					  sizeof(default_groups));
-			if (!bss->conf->sae_groups)
-				goto out_free;
-		}
-
-		len = os_strlen(ssid->passphrase);
-		bss->conf->ssid.wpa_passphrase =
-			dup_binstr(ssid->passphrase, len);
-
-		wpa_s->mesh_rsn = mesh_rsn_auth_init(wpa_s, mconf);
-		if (!wpa_s->mesh_rsn)
-			goto out_free;
+	if (hostapd_setup_interface(ifmsh)) {
+		wpa_printf(MSG_ERROR,
+			   "Failed to initialize hostapd interface for mesh");
+		return -1;
 	}
 
 	wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
@@ -359,19 +376,13 @@ void wpa_supplicant_mesh_add_scan_ie(struct wpa_supplicant *wpa_s,
 }
 
 
-int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
-			     struct wpa_ssid *ssid)
+static int wpa_supplicant_join_mesh(void *priv)
 {
+	struct wpa_supplicant *wpa_s = priv;
 	struct wpa_driver_mesh_join_params params;
+	struct wpa_ssid *ssid = wpa_s->last_ssid;
 	int ret = 0;
 
-	if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency) {
-		ret = -ENOENT;
-		goto out;
-	}
-
-	wpa_supplicant_mesh_deinit(wpa_s);
-
 	wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
 	wpa_s->group_cipher = WPA_CIPHER_NONE;
 	wpa_s->mgmt_group_cipher = 0;
@@ -379,31 +390,9 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
 	os_memset(&params, 0, sizeof(params));
 	params.meshid = ssid->ssid;
 	params.meshid_len = ssid->ssid_len;
-	ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
+	wpa_supplicant_mesh_freq_init(wpa_s, ssid, &params.freq);
 	wpa_s->mesh_ht_enabled = !!params.freq.ht_enabled;
 	wpa_s->mesh_vht_enabled = !!params.freq.vht_enabled;
-	if (params.freq.ht_enabled && params.freq.sec_channel_offset)
-		ssid->ht40 = params.freq.sec_channel_offset;
-	if (wpa_s->mesh_vht_enabled) {
-		ssid->vht = 1;
-		switch (params.freq.bandwidth) {
-		case 80:
-			if (params.freq.center_freq2) {
-				ssid->max_oper_chwidth = VHT_CHANWIDTH_80P80MHZ;
-				ssid->vht_center_freq2 =
-					params.freq.center_freq2;
-			} else {
-				ssid->max_oper_chwidth = VHT_CHANWIDTH_80MHZ;
-			}
-			break;
-		case 160:
-			ssid->max_oper_chwidth = VHT_CHANWIDTH_160MHZ;
-			break;
-		default:
-			ssid->max_oper_chwidth = VHT_CHANWIDTH_USE_HT;
-			break;
-		}
-	}
 	if (ssid->beacon_int > 0)
 		params.beacon_int = ssid->beacon_int;
 	else if (wpa_s->conf->beacon_int > 0)
@@ -429,14 +418,41 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
 	}
 	params.conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
 
-	if (wpa_supplicant_mesh_init(wpa_s, ssid, &params.freq)) {
-		wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh");
-		wpa_drv_leave_mesh(wpa_s);
-		ret = -1;
-		goto out;
-	}
-
 	if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
+		struct hostapd_iface *ifmsh = wpa_s->ifmsh;
+		struct hostapd_data *bss = ifmsh->bss[0];
+		struct mesh_conf *mconf = ifmsh->mconf;
+		static int default_groups[] = { 19, 20, 21, 25, 26, -1 };
+		size_t len;
+
+		if (ssid->passphrase == NULL) {
+			wpa_printf(MSG_ERROR,
+				   "mesh: Passphrase for SAE not configured");
+			return -1;
+		}
+
+		bss->conf->wpa = ssid->proto;
+		bss->conf->wpa_key_mgmt = ssid->key_mgmt;
+
+		if (wpa_s->conf->sae_groups &&
+		    wpa_s->conf->sae_groups[0] > 0) {
+			wpas_mesh_copy_groups(bss, wpa_s);
+		} else {
+			bss->conf->sae_groups =
+				os_memdup(default_groups,
+					  sizeof(default_groups));
+			if (!bss->conf->sae_groups)
+				return -1;
+		}
+
+		len = os_strlen(ssid->passphrase);
+		bss->conf->ssid.wpa_passphrase =
+			dup_binstr(ssid->passphrase, len);
+
+		wpa_s->mesh_rsn = mesh_rsn_auth_init(wpa_s, mconf);
+		if (!wpa_s->mesh_rsn)
+			return -1;
+
 		wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher;
 		wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher;
 		wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher;
@@ -459,10 +475,12 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
 	/* hostapd sets the interface down until we associate */
 	wpa_drv_set_operstate(wpa_s, 1);
 
-	if (!ret)
+	if (!ret) {
 		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+		wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
+			wpa_ssid_txt(ssid->ssid, ssid->ssid_len), ssid->id);
+	}
 
-out:
 	return ret;
 }
 
diff --git a/wpa_supplicant/mesh.h b/wpa_supplicant/mesh.h
index 7317083..4ff23f2 100644
--- a/wpa_supplicant/mesh.h
+++ b/wpa_supplicant/mesh.h
@@ -9,7 +9,7 @@
 #ifndef MESH_H
 #define MESH_H
 
-int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
+int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
 			     struct wpa_ssid *ssid);
 int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 498820a..6c6d1c3 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1806,14 +1806,12 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
 		}
 		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");
+		if (wpa_supplicant_mesh_init(wpa_s, ssid)) {
+			wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh");
+			wpa_drv_leave_mesh(wpa_s);
 			return;
 		}
 		wpa_s->current_bss = bss;
-		wpa_msg(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");
-- 
2.7.4




More information about the Hostap mailing list