include $(TOPDIR)/rules.mk
PKG_NAME:=hostapd
-PKG_RELEASE:=1
+PKG_RELEASE:=2
PKG_SOURCE_URL:=http://w1.fi/hostap.git
PKG_SOURCE_PROTO:=git
--- /dev/null
+From c05ace7510ead96e72b97ce47b33f7b5865d6d36 Mon Sep 17 00:00:00 2001
+From: Peter Oh <peter.oh@bowerswilkins.com>
+Date: Mon, 27 Aug 2018 14:28:38 -0700
+Subject: [PATCH 1/7] mesh: use setup completion callback to complete mesh join
+
+mesh join function is the last function to be called during
+mesh join process, but it's been called a bit earlier than
+it's supposed to be, so that some mesh parameter values
+such as VHT capabilities not applied correct when mesh join
+is in process.
+Moreover current design of mesh join that is called directly
+after mesh initialization isn't suitable for DFS channels to use,
+since mesh join process should be paused until DFS CAC is
+done and resumed after it's done.
+The callback will be called by hostapd_setup_interface_complete_sync.
+There is possiblity that completing mesh init fails, so add error
+handle codes.
+
+Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
+Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
+---
+ src/ap/hostapd.c | 11 ++++++++++-
+ wpa_supplicant/mesh.c | 13 +++++++------
+ 2 files changed, 17 insertions(+), 7 deletions(-)
+
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -434,6 +434,8 @@ static void hostapd_free_hapd_data(struc
+ #ifdef CONFIG_MESH
+ wpabuf_free(hapd->mesh_pending_auth);
+ hapd->mesh_pending_auth = NULL;
++ /* handling setup failure is already done */
++ hapd->setup_complete_cb = NULL;
+ #endif /* CONFIG_MESH */
+
+ hostapd_clean_rrm(hapd);
+@@ -2145,6 +2147,13 @@ dfs_offload:
+ if (hapd->setup_complete_cb)
+ hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);
+
++#ifdef CONFIG_MESH
++ if (delay_apply_cfg && !iface->mconf) {
++ wpa_printf(MSG_ERROR, "Error while completing mesh init");
++ goto fail;
++ }
++#endif /* CONFIG_MESH */
++
+ wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
+ iface->bss[0]->conf->iface);
+ if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
+@@ -2288,7 +2297,7 @@ int hostapd_setup_interface(struct hosta
+ ret = setup_interface(iface);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
+- iface->bss[0]->conf->iface);
++ iface->conf ? iface->conf->bss[0]->iface : "N/A");
+ return -1;
+ }
+
+--- a/wpa_supplicant/mesh.c
++++ b/wpa_supplicant/mesh.c
+@@ -194,8 +194,9 @@ static int wpas_mesh_init_rsn(struct wpa
+ }
+
+
+-static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
++static void wpas_mesh_complete_cb(void *ctx)
+ {
++ struct wpa_supplicant *wpa_s = ctx;
+ struct hostapd_iface *ifmsh = wpa_s->ifmsh;
+ struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params;
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+@@ -204,7 +205,7 @@ static int wpas_mesh_complete(struct wpa
+ if (!params || !ssid || !ifmsh) {
+ wpa_printf(MSG_ERROR, "mesh: %s called without active mesh",
+ __func__);
+- return -1;
++ return;
+ }
+
+ if (ifmsh->mconf->security != MESH_CONF_SEC_NONE &&
+@@ -213,7 +214,7 @@ static int wpas_mesh_complete(struct wpa
+ "mesh: RSN initialization failed - deinit mesh");
+ wpa_supplicant_mesh_deinit(wpa_s);
+ wpa_drv_leave_mesh(wpa_s);
+- return -1;
++ return;
+ }
+
+ if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
+@@ -239,8 +240,6 @@ static int wpas_mesh_complete(struct wpa
+
+ if (!ret)
+ wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+-
+- return ret;
+ }
+
+
+@@ -267,6 +266,7 @@ static int wpa_supplicant_mesh_init(stru
+ if (!ifmsh)
+ return -ENOMEM;
+
++ ifmsh->owner = wpa_s;
+ ifmsh->drv_flags = wpa_s->drv_flags;
+ ifmsh->drv_flags2 = wpa_s->drv_flags2;
+ ifmsh->num_bss = 1;
+@@ -285,6 +285,8 @@ static int wpa_supplicant_mesh_init(stru
+ bss->drv_priv = wpa_s->drv_priv;
+ bss->iface = ifmsh;
+ bss->mesh_sta_free_cb = mesh_mpm_free_sta;
++ bss->setup_complete_cb = wpas_mesh_complete_cb;
++ bss->setup_complete_cb_ctx = wpa_s;
+ frequency = ssid->frequency;
+ if (frequency != freq->freq &&
+ frequency == freq->freq + freq->sec_channel_offset * 20) {
+@@ -526,7 +528,6 @@ int wpa_supplicant_join_mesh(struct wpa_
+ goto out;
+ }
+
+- ret = wpas_mesh_complete(wpa_s);
+ out:
+ return ret;
+ }
--- /dev/null
+From c56f18380d1d404a2abc0ea5373d294508ef1e54 Mon Sep 17 00:00:00 2001
+From: Peter Oh <peter.oh@bowerswilkins.com>
+Date: Mon, 27 Aug 2018 14:28:41 -0700
+Subject: [PATCH 2/7] mesh: update ssid->frequency as pri/sec channel switch
+
+ssid->frequency is one of variables used to gets channel
+number from given frequency. Leave it as unchanged when
+pri/sec channel switched will cause picking up wrong
+channel number after applying secondary channel offset
+for HT40 and leads failing interface bring-up.
+
+Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
+---
+ wpa_supplicant/mesh.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/wpa_supplicant/mesh.c
++++ b/wpa_supplicant/mesh.c
+@@ -292,6 +292,7 @@ static int wpa_supplicant_mesh_init(stru
+ frequency == freq->freq + freq->sec_channel_offset * 20) {
+ wpa_printf(MSG_DEBUG, "mesh: pri/sec channels switched");
+ frequency = freq->freq;
++ ssid->frequency = frequency;
+ }
+ wpa_s->assoc_freq = frequency;
+ wpa_s->current_ssid = ssid;
--- /dev/null
+From 593602b7f14be5c2695979639764b1c50f01bbec Mon Sep 17 00:00:00 2001
+From: Peter Oh <peter.oh@bowerswilkins.com>
+Date: Mon, 27 Aug 2018 14:28:49 -0700
+Subject: [PATCH 7/7] mesh: inform kernel driver DFS handler in userspace
+
+NL80211_ATTR_HANDLE_DFS is required by kerenel space
+to enable DFS channels that indicates DFS handler
+resides in userspace.
+
+Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
+---
+ src/drivers/driver.h | 1 +
+ src/drivers/driver_nl80211.c | 3 +++
+ wpa_supplicant/mesh.c | 1 +
+ 3 files changed, 5 insertions(+)
+
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1542,6 +1542,7 @@ struct wpa_driver_mesh_join_params {
+ #define WPA_DRIVER_MESH_FLAG_SAE_AUTH 0x00000004
+ #define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008
+ unsigned int flags;
++ u8 handle_dfs;
+ };
+
+ struct wpa_driver_set_key_params {
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -10038,6 +10038,9 @@ static int nl80211_join_mesh(struct i802
+
+ wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags);
+
++ if (params->handle_dfs)
++ if (nla_put_flag(msg, NL80211_ATTR_HANDLE_DFS))
++ goto fail;
+ container = nla_nest_start(msg, NL80211_ATTR_MESH_SETUP);
+ if (!container)
+ goto fail;
+--- a/wpa_supplicant/mesh.c
++++ b/wpa_supplicant/mesh.c
+@@ -314,6 +314,7 @@ static int wpa_supplicant_mesh_init(stru
+ conf->country[0] = wpa_s->conf->country[0];
+ conf->country[1] = wpa_s->conf->country[1];
+ conf->country[2] = ' ';
++ wpa_s->mesh_params->handle_dfs = 1;
+ }
+
+ bss->iconf = conf;
--- /dev/null
+From 2564184440d9d6041d11a8c7d50b31368634c3bd Mon Sep 17 00:00:00 2001
+From: Peter Oh <peter.oh@bowerswilkins.com>
+Date: Mon, 27 Aug 2018 14:28:40 -0700
+Subject: [PATCH] mesh: Apply channel attributes before setup interface
+
+This helps mesh interface initialization with correct channel
+parameters.
+
+Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
+---
+ wpa_supplicant/mesh.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/wpa_supplicant/mesh.c
++++ b/wpa_supplicant/mesh.c
+@@ -253,7 +253,7 @@ static int wpa_supplicant_mesh_init(stru
+ struct mesh_conf *mconf;
+ int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 };
+ int rate_len;
+- int frequency;
++ int frequency, saved_freq;
+
+ if (!wpa_s->conf->user_mpm) {
+ /* not much for us to do here */
+@@ -391,6 +391,13 @@ static int wpa_supplicant_mesh_init(stru
+ conf->basic_rates[rate_len] = -1;
+ }
+
++ /* Handle pri/sec switch frequency within AP configuration parameter
++ * generation without changing the stored network profile in the end. */
++ saved_freq = ssid->frequency;
++ ssid->frequency = frequency;
++ wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
++ ssid->frequency = saved_freq;
++
+ if (wpa_drv_init_mesh(wpa_s)) {
+ wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
+ return -1;
+@@ -402,8 +409,6 @@ static int wpa_supplicant_mesh_init(stru
+ return -1;
+ }
+
+- wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
+-
+ return 0;
+ out_free:
+ wpa_supplicant_mesh_deinit(wpa_s);
--- /dev/null
+From 89fa0d75fb1be82330258082ed3d7fd452eb6076 Mon Sep 17 00:00:00 2001
+From: Peter Oh <peter.oh@bowerswilkins.com>
+Date: Mon, 27 Aug 2018 14:28:45 -0700
+Subject: [PATCH 3/7] mesh: Allow DFS channels to be selected if dfs is enabled
+
+Note: DFS is assumed to be usable if a country code has been set
+
+Signed-off-by: Benjamin Berg <benjamin@sipsolutions.net>
+Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
+---
+ wpa_supplicant/wpa_supplicant.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+--- a/wpa_supplicant/wpa_supplicant.c
++++ b/wpa_supplicant/wpa_supplicant.c
+@@ -2345,6 +2345,8 @@ void ibss_mesh_setup_freq(struct wpa_sup
+ int chwidth, seg0, seg1;
+ u32 vht_caps = 0;
+ int is_24ghz;
++ int dfs_enabled = wpa_s->conf->country[0] &&
++ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_RADAR);
+
+ freq->freq = ssid->frequency;
+
+@@ -2432,8 +2434,11 @@ void ibss_mesh_setup_freq(struct wpa_sup
+ return;
+
+ /* Check primary channel flags */
+- if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
++ if (pri_chan->flag & HOSTAPD_CHAN_DISABLED)
+ return;
++ if (pri_chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
++ if (!dfs_enabled)
++ return;
+
+ freq->channel = pri_chan->chan;
+
+@@ -2466,8 +2471,11 @@ void ibss_mesh_setup_freq(struct wpa_sup
+ return;
+
+ /* Check secondary channel flags */
+- if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
++ if (sec_chan->flag & HOSTAPD_CHAN_DISABLED)
+ return;
++ if (sec_chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
++ if (!dfs_enabled)
++ return;
+
+ if (ht40 == -1) {
+ if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
+@@ -2560,8 +2568,11 @@ skip_ht40:
+ return;
+
+ /* Back to HT configuration if channel not usable */
+- if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
++ if (chan->flag & HOSTAPD_CHAN_DISABLED)
+ return;
++ if (chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
++ if (!dfs_enabled)
++ return;
+ }
+
+ chwidth = CHANWIDTH_80MHZ;
+@@ -2581,10 +2592,11 @@ skip_ht40:
+ if (!chan)
+ continue;
+
+- if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+- HOSTAPD_CHAN_NO_IR |
+- HOSTAPD_CHAN_RADAR))
++ if (chan->flag & HOSTAPD_CHAN_DISABLED)
+ continue;
++ if (chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
++ if (!dfs_enabled)
++ continue;
+
+ /* Found a suitable second segment for 80+80 */
+ chwidth = CHANWIDTH_80P80MHZ;
--- /dev/null
+From 4f4a9b9e2e61fba334a21dadea749e4b440f42e6 Mon Sep 17 00:00:00 2001
+From: Peter Oh <peter.oh@bowerswilkins.com>
+Date: Mon, 27 Aug 2018 14:28:48 -0700
+Subject: [PATCH 6/7] mesh: don't allow pri/sec channel switch
+
+This limitation isn't backed by standard, but it is known that
+mesh doesn't have capability to handle 20/40 coex change in
+current implementation and it will not able to establish
+PLINK when channel switch between primary and secondary happens.
+
+Since it's unknown when we will have the implementation of handling
+20/40 coex change for mesh, it'd better to avoid them from happening
+until standard based implementation is introduced.
+
+Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
+---
+ wpa_supplicant/mesh.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/wpa_supplicant/mesh.c
++++ b/wpa_supplicant/mesh.c
+@@ -391,6 +391,7 @@ static int wpa_supplicant_mesh_init(stru
+ conf->basic_rates[rate_len] = -1;
+ }
+
++ conf->no_pri_sec_switch = 1;
+ /* Handle pri/sec switch frequency within AP configuration parameter
+ * generation without changing the stored network profile in the end. */
+ saved_freq = ssid->frequency;
--- /dev/null
+From 71e9c65a7c8af90a5fd11072062b596421316452 Mon Sep 17 00:00:00 2001
+From: Peter Oh <peter.oh@bowerswilkins.com>
+Date: Mon, 27 Aug 2018 14:28:46 -0700
+Subject: [PATCH 4/7] mesh: do not set offchanok on DFS channels in non-ETSI
+
+mac80211 does not allow mgmt tx to use off channel on
+DFS channels in non-ETSI domain, because it will invalidate
+CAC result on current operating channel.
+(mac80211 commit: 34373d12f3cbb74960a73431138ef619d857996f)
+Hence don't set offchanok for mgmt tx in case of DFS channels
+in non-ETSI.
+
+Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
+---
+ src/drivers/driver_nl80211.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -7788,6 +7788,10 @@ static int wpa_driver_nl80211_send_actio
+ u8 *buf;
+ struct ieee80211_hdr *hdr;
+ int offchanok = 1;
++ struct hostapd_hw_modes *modes;
++ int i;
++ u16 num_modes, flags;
++ u8 dfs_domain;
+
+ if (is_ap_interface(drv->nlmode) && (int) freq == bss->freq &&
+ bss->beacon_set)
+@@ -7816,6 +7820,21 @@ static int wpa_driver_nl80211_send_actio
+ os_memset(bss->rand_addr, 0, ETH_ALEN);
+ }
+
++ if (is_mesh_interface(drv->nlmode)) {
++ modes = nl80211_get_hw_feature_data(bss, &num_modes,
++ &flags, &dfs_domain);
++ if (dfs_domain != HOSTAPD_DFS_REGION_ETSI &&
++ ieee80211_is_dfs(bss->freq, modes, num_modes))
++ offchanok = 0;
++ if (modes) {
++ for (i = 0; i < num_modes; i++) {
++ os_free(modes[i].channels);
++ os_free(modes[i].rates);
++ }
++ os_free(modes);
++ }
++ }
++
+ if (is_ap_interface(drv->nlmode) &&
+ (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
+ (int) freq == bss->freq || drv->device_ap_sme ||
--- /dev/null
+From 5913d6e2a741683e7c747c046f72ca790bbe1337 Mon Sep 17 00:00:00 2001
+From: Peter Oh <peter.oh@bowerswilkins.com>
+Date: Mon, 27 Aug 2018 14:28:47 -0700
+Subject: [PATCH 5/7] mesh: fix channel switch error during CAC
+
+Mesh interface has used its channel parameters that configured
+during its initialization even after channel switched due to
+DFS radar detection during CAC which caused channel switch error.
+This change fixes the error by updating its channel parameters
+when channel's been changed from initial one.
+
+Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
+---
+ wpa_supplicant/mesh.c | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+--- a/wpa_supplicant/mesh.c
++++ b/wpa_supplicant/mesh.c
+@@ -13,6 +13,7 @@
+ #include "utils/uuid.h"
+ #include "common/ieee802_11_defs.h"
+ #include "common/wpa_ctrl.h"
++#include "common/hw_features_common.h"
+ #include "ap/sta_info.h"
+ #include "ap/hostapd.h"
+ #include "ap/ieee802_11.h"
+@@ -208,6 +209,34 @@ static void wpas_mesh_complete_cb(void *
+ return;
+ }
+
++ /*
++ * inspect if channel's been changed since initialized.
++ * i.e. DFS radar detection
++ */
++ if (ifmsh->freq != params->freq.freq) {
++ wpa_s->assoc_freq = ifmsh->freq;
++ ssid->frequency = ifmsh->freq;
++ if (hostapd_set_freq_params(¶ms->freq,
++ ifmsh->conf->hw_mode,
++ ifmsh->freq,
++ ifmsh->conf->channel,
++ ifmsh->conf->enable_edmg,
++ ifmsh->conf->edmg_channel,
++ ifmsh->conf->ieee80211n,
++ ifmsh->conf->ieee80211ac,
++ ifmsh->conf->ieee80211ax,
++ ifmsh->conf->secondary_channel,
++ hostapd_get_oper_chwidth(ifmsh->conf),
++ hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
++ hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
++ ifmsh->current_mode->vht_capab,
++ &ifmsh->current_mode->he_capab[IEEE80211_MODE_AP])) {
++ wpa_printf(MSG_ERROR, "Error updating mesh frequency params.");
++ wpa_supplicant_mesh_deinit(wpa_s);
++ return;
++ }
++ }
++
+ if (ifmsh->mconf->security != MESH_CONF_SEC_NONE &&
+ wpas_mesh_init_rsn(wpa_s)) {
+ wpa_printf(MSG_ERROR,
--- /dev/null
+From 90fe6429624fc48bc0e5d2d7eeecb7498708b5e3 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Wed, 18 Apr 2018 19:24:31 +0200
+Subject: [PATCH 18/18] mesh: make forwarding configurable
+
+Allow mesh_fwding to be specified in a mesh bss config, pass that
+to the driver (only nl80211 implemented for now) and announce
+forwarding capability accordingly.
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+---
+ src/ap/ap_config.h | 2 ++
+ src/drivers/driver.h | 2 ++
+ src/drivers/driver_nl80211.c | 3 +++
+ wpa_supplicant/config.c | 4 ++++
+ wpa_supplicant/config.h | 9 +++++++++
+ wpa_supplicant/config_file.c | 4 ++++
+ wpa_supplicant/config_ssid.h | 5 +++++
+ wpa_supplicant/mesh.c | 6 ++++++
+ wpa_supplicant/mesh_mpm.c | 4 ++--
+ wpa_supplicant/wpa_supplicant.conf | 3 +++
+ 10 files changed, 40 insertions(+), 2 deletions(-)
+
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -51,6 +51,7 @@ struct mesh_conf {
+ int dot11MeshRetryTimeout; /* msec */
+ int dot11MeshConfirmTimeout; /* msec */
+ int dot11MeshHoldingTimeout; /* msec */
++ int mesh_fwding;
+ };
+
+ #define MAX_STA_COUNT 2007
+@@ -691,6 +692,7 @@ struct hostapd_bss_config {
+
+ #define MESH_ENABLED BIT(0)
+ int mesh;
++ int mesh_fwding;
+
+ u8 radio_measurements[RRM_CAPABILITIES_IE_LEN];
+
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1515,6 +1515,7 @@ struct wpa_driver_mesh_bss_params {
+ #define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS 0x00000004
+ #define WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE 0x00000008
+ #define WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD 0x00000010
++#define WPA_DRIVER_MESH_CONF_FLAG_FORWARDING 0x00000020
+ /*
+ * TODO: Other mesh configuration parameters would go here.
+ * See NL80211_MESHCONF_* for all the mesh config parameters.
+@@ -1524,6 +1525,7 @@ struct wpa_driver_mesh_bss_params {
+ int peer_link_timeout;
+ int max_peer_links;
+ int rssi_threshold;
++ int forwarding;
+ u16 ht_opmode;
+ };
+
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -10006,6 +10006,9 @@ static int nl80211_put_mesh_config(struc
+ if (((params->flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) &&
+ nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
+ params->auto_plinks)) ||
++ ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_FORWARDING) &&
++ nla_put_u8(msg, NL80211_MESHCONF_FORWARDING,
++ params->forwarding)) ||
+ ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS) &&
+ nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
+ params->max_peer_links)) ||
+--- a/wpa_supplicant/config.c
++++ b/wpa_supplicant/config.c
+@@ -2473,6 +2473,7 @@ static const struct parse_data ssid_fiel
+ #ifdef CONFIG_MESH
+ { INT_RANGE(mode, 0, 5) },
+ { INT_RANGE(no_auto_peer, 0, 1) },
++ { INT_RANGE(mesh_fwding, 0, 1) },
+ { INT_RANGE(mesh_rssi_threshold, -255, 1) },
+ #else /* CONFIG_MESH */
+ { INT_RANGE(mode, 0, 4) },
+@@ -3046,6 +3047,7 @@ void wpa_config_set_network_defaults(str
+ ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT;
+ ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT;
+ ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT;
++ ssid->mesh_fwding = DEFAULT_MESH_FWDING;
+ ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD;
+ #endif /* CONFIG_MESH */
+ #ifdef CONFIG_HT_OVERRIDES
+@@ -4273,6 +4275,7 @@ struct wpa_config * wpa_config_alloc_emp
+ config->user_mpm = DEFAULT_USER_MPM;
+ config->max_peer_links = DEFAULT_MAX_PEER_LINKS;
+ config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY;
++ config->mesh_fwding = DEFAULT_MESH_FWDING;
+ config->dot11RSNASAERetransPeriod =
+ DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD;
+ config->fast_reauth = DEFAULT_FAST_REAUTH;
+@@ -4911,6 +4914,7 @@ static const struct global_parse_data gl
+ { INT(user_mpm), 0 },
+ { INT_RANGE(max_peer_links, 0, 255), 0 },
+ { INT(mesh_max_inactivity), 0 },
++ { INT_RANGE(mesh_fwding, 0, 1), 0 },
+ { INT(dot11RSNASAERetransPeriod), 0 },
+ #endif /* CONFIG_MESH */
+ { INT(disable_scan_offload), 0 },
+--- a/wpa_supplicant/config.h
++++ b/wpa_supplicant/config.h
+@@ -18,6 +18,7 @@
+ #define DEFAULT_USER_MPM 1
+ #define DEFAULT_MAX_PEER_LINKS 99
+ #define DEFAULT_MESH_MAX_INACTIVITY 300
++#define DEFAULT_MESH_FWDING 1
+ /*
+ * The default dot11RSNASAERetransPeriod is defined as 40 ms in the standard,
+ * but use 1000 ms in practice to avoid issues on low power CPUs.
+@@ -1351,6 +1352,14 @@ struct wpa_config {
+ int mesh_max_inactivity;
+
+ /**
++ * mesh_fwding - Mesh network layer-2 forwarding
++ *
++ * This controls whether to enable layer-2 forwarding.
++ * By default: 1: enabled
++ */
++ int mesh_fwding;
++
++ /**
+ * dot11RSNASAERetransPeriod - Timeout to retransmit SAE Auth frame
+ *
+ * This timeout value is used in mesh STA to retransmit
+--- a/wpa_supplicant/config_file.c
++++ b/wpa_supplicant/config_file.c
+@@ -866,6 +866,7 @@ static void wpa_config_write_network(FIL
+ #endif /* IEEE8021X_EAPOL */
+ INT(mode);
+ INT(no_auto_peer);
++ INT(mesh_fwding);
+ INT(frequency);
+ INT(enable_edmg);
+ INT(edmg_channel);
+@@ -1526,6 +1527,9 @@ static void wpa_config_write_global(FILE
+ fprintf(f, "mesh_max_inactivity=%d\n",
+ config->mesh_max_inactivity);
+
++ if (config->mesh_fwding != DEFAULT_MESH_FWDING)
++ fprintf(f, "mesh_fwding=%d\n", config->mesh_fwding);
++
+ if (config->dot11RSNASAERetransPeriod !=
+ DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD)
+ fprintf(f, "dot11RSNASAERetransPeriod=%d\n",
+--- a/wpa_supplicant/config_ssid.h
++++ b/wpa_supplicant/config_ssid.h
+@@ -540,6 +540,11 @@ struct wpa_ssid {
+ int dot11MeshConfirmTimeout; /* msec */
+ int dot11MeshHoldingTimeout; /* msec */
+
++ /**
++ * Mesh network layer-2 forwarding
++ */
++ int mesh_fwding;
++
+ int ht;
+ int ht40;
+
+--- a/wpa_supplicant/mesh.c
++++ b/wpa_supplicant/mesh.c
+@@ -130,6 +130,7 @@ static struct mesh_conf * mesh_config_cr
+ conf->mesh_cc_id = 0;
+ conf->mesh_sp_id = MESH_SYNC_METHOD_NEIGHBOR_OFFSET;
+ conf->mesh_auth_id = (conf->security & MESH_CONF_SEC_AUTH) ? 1 : 0;
++ conf->mesh_fwding = ssid->mesh_fwding;
+ conf->dot11MeshMaxRetries = ssid->dot11MeshMaxRetries;
+ conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout;
+ conf->dot11MeshConfirmTimeout = ssid->dot11MeshConfirmTimeout;
+@@ -335,6 +336,7 @@ static int wpa_supplicant_mesh_init(stru
+ bss->conf->start_disabled = 1;
+ bss->conf->mesh = MESH_ENABLED;
+ bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
++ bss->conf->mesh_fwding = wpa_s->conf->mesh_fwding;
+
+ if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes,
+ wpa_s->hw.num_modes) && wpa_s->conf->country[0]) {
+@@ -556,6 +558,10 @@ int wpa_supplicant_join_mesh(struct wpa_
+ }
+ params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
+
++ /* always explicitely set forwarding to on or off for now */
++ params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_FORWARDING;
++ params->conf.forwarding = ssid->mesh_fwding;
++
+ os_free(wpa_s->mesh_params);
+ wpa_s->mesh_params = params;
+ if (wpa_supplicant_mesh_init(wpa_s, ssid, ¶ms->freq)) {
+--- a/wpa_supplicant/mesh_mpm.c
++++ b/wpa_supplicant/mesh_mpm.c
+@@ -303,9 +303,9 @@ static void mesh_mpm_send_plink_action(s
+ info = (bss->num_plinks > 63 ? 63 : bss->num_plinks) << 1;
+ /* TODO: Add Connected to Mesh Gate/AS subfields */
+ wpabuf_put_u8(buf, info);
+- /* always forwarding & accepting plinks for now */
++ /* set forwarding & always accepting plinks for now */
+ wpabuf_put_u8(buf, MESH_CAP_ACCEPT_ADDITIONAL_PEER |
+- MESH_CAP_FORWARDING);
++ (conf->mesh_fwding ? MESH_CAP_FORWARDING : 0));
+ } else { /* Peer closing frame */
+ /* IE: Mesh ID */
+ wpabuf_put_u8(buf, WLAN_EID_MESH_ID);
+--- a/wpa_supplicant/wpa_supplicant.conf
++++ b/wpa_supplicant/wpa_supplicant.conf
+@@ -150,6 +150,9 @@ ap_scan=1
+ # This timeout value is used in mesh STA to clean up inactive stations.
+ #mesh_max_inactivity=300
+
++# Enable 802.11s layer-2 routing and forwarding
++#mesh_fwding=1
++
+ # cert_in_cb - Whether to include a peer certificate dump in events
+ # This controls whether peer certificates for authentication server and
+ # its certificate chain are included in EAP peer certificate events. This is
LIBS += $(DRV_AP_LIBS)
ifdef CONFIG_L2_PACKET
-@@ -1294,6 +1300,12 @@ install: $(addprefix $(DESTDIR)$(BINDIR)
+@@ -1300,6 +1306,12 @@ install: $(addprefix $(DESTDIR)$(BINDIR)
BCHECK=../src/drivers/build.hostapd
hostapd: $(BCHECK) $(OBJS)
$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
@$(E) " LD " $@
-@@ -1335,6 +1347,12 @@ ifeq ($(CONFIG_TLS), linux)
+@@ -1341,6 +1353,12 @@ ifeq ($(CONFIG_TLS), linux)
HOBJS += ../src/crypto/crypto_linux.o
endif
ifndef CONFIG_NO_GITVER
# Add VERSION_STR postfix for builds from a git repository
-@@ -359,7 +360,9 @@ endif
+@@ -365,7 +366,9 @@ endif
ifdef CONFIG_IBSS_RSN
NEED_RSN_AUTHENTICATOR=y
CFLAGS += -DCONFIG_IBSS_RSN
OBJS += ibss_rsn.o
endif
-@@ -880,6 +883,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS
+@@ -886,6 +889,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS
CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS
LIBS += -ldl -rdynamic
endif
endif
ifdef CONFIG_AP
-@@ -887,9 +894,11 @@ NEED_EAP_COMMON=y
+@@ -893,9 +900,11 @@ NEED_EAP_COMMON=y
NEED_RSN_AUTHENTICATOR=y
CFLAGS += -DCONFIG_AP
OBJS += ap.o
OBJS += ../src/ap/hostapd.o
OBJS += ../src/ap/wpa_auth_glue.o
OBJS += ../src/ap/utils.o
-@@ -969,6 +978,12 @@ endif
+@@ -975,6 +984,12 @@ endif
ifdef CONFIG_HS20
OBJS += ../src/ap/hs20.o
endif
endif
ifdef CONFIG_MBO
-@@ -977,7 +992,9 @@ CFLAGS += -DCONFIG_MBO
+@@ -983,7 +998,9 @@ CFLAGS += -DCONFIG_MBO
endif
ifdef NEED_RSN_AUTHENTICATOR
NEED_AES_WRAP=y
OBJS += ../src/ap/wpa_auth.o
OBJS += ../src/ap/wpa_auth_ie.o
-@@ -1887,6 +1904,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv)
+@@ -1893,6 +1910,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv)
$(OBJS_c) $(OBJS_t) $(OBJS_t2) $(OBJS) $(BCHECK) $(EXTRA_progs): .config
wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)
$(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
@$(E) " LD " $@
-@@ -1987,6 +2010,12 @@ endif
+@@ -1993,6 +2016,12 @@ endif
$(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@
@$(E) " sed" $<
wpa_cli.exe: wpa_cli
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
-@@ -5865,8 +5865,8 @@ union wpa_event_data {
+@@ -5879,8 +5879,8 @@ union wpa_event_data {
* Driver wrapper code should call this function whenever an event is received
* from the driver.
*/
/**
* wpa_supplicant_event_global - Report a driver event for wpa_supplicant
-@@ -5878,7 +5878,7 @@ void wpa_supplicant_event(void *ctx, enu
+@@ -5892,7 +5892,7 @@ void wpa_supplicant_event(void *ctx, enu
* Same as wpa_supplicant_event(), but we search for the interface in
* wpa_global.
*/
os_memset(&global, 0, sizeof(global));
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
-@@ -4499,8 +4499,8 @@ static void wpas_event_unprot_beacon(str
+@@ -4500,8 +4500,8 @@ static void wpas_event_unprot_beacon(str
}
{
struct wpa_supplicant *wpa_s = ctx;
int resched;
-@@ -5313,7 +5313,7 @@ void wpa_supplicant_event(void *ctx, enu
+@@ -5319,7 +5319,7 @@ void wpa_supplicant_event(void *ctx, enu
}
struct wpa_supplicant *wpa_s;
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
-@@ -6571,7 +6571,6 @@ struct wpa_interface * wpa_supplicant_ma
+@@ -6593,7 +6593,6 @@ struct wpa_interface * wpa_supplicant_ma
return NULL;
}
/**
* wpa_supplicant_match_existing - Match existing interfaces
* @global: Pointer to global data from wpa_supplicant_init()
-@@ -6608,6 +6607,11 @@ static int wpa_supplicant_match_existing
+@@ -6630,6 +6629,11 @@ static int wpa_supplicant_match_existing
#endif /* CONFIG_MATCH_IFACE */
/**
* wpa_supplicant_add_iface - Add a new network interface
-@@ -6864,6 +6868,8 @@ struct wpa_global * wpa_supplicant_init(
+@@ -6886,6 +6890,8 @@ struct wpa_global * wpa_supplicant_init(
#ifndef CONFIG_NO_WPA_MSG
wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
#endif /* CONFIG_NO_WPA_MSG */
#ifdef CONFIG_WPS
static int gen_uuid(const char *txt_addr)
-@@ -680,6 +685,8 @@ int main(int argc, char *argv[])
+@@ -684,6 +689,8 @@ int main(int argc, char *argv[])
return -1;
#endif /* CONFIG_DPP */
} else if (os_strcmp(buf, "ht_capab") == 0) {
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
-@@ -972,6 +972,8 @@ struct hostapd_config {
+@@ -974,6 +974,8 @@ struct hostapd_config {
int ht_op_mode_fixed;
u16 ht_capab;
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
-@@ -2477,6 +2477,7 @@ static const struct parse_data ssid_fiel
+@@ -2478,6 +2478,7 @@ static const struct parse_data ssid_fiel
#else /* CONFIG_MESH */
{ INT_RANGE(mode, 0, 4) },
#endif /* CONFIG_MESH */
INT(mode);
INT(no_auto_peer);
+ INT(noscan);
+ INT(mesh_fwding);
INT(frequency);
INT(enable_edmg);
- INT(edmg_channel);
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
-@@ -333,6 +333,8 @@ static int wpa_supplicant_mesh_init(stru
+@@ -368,6 +368,8 @@ static int wpa_supplicant_mesh_init(stru
frequency);
goto out_free;
}
if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && ssid->vht) {
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
-@@ -2331,12 +2331,12 @@ void ibss_mesh_setup_freq(struct wpa_sup
+@@ -2334,12 +2334,12 @@ void ibss_mesh_setup_freq(struct wpa_sup
int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
enum hostapd_hw_mode hw_mode;
struct hostapd_hw_modes *mode = NULL;
unsigned int j, k;
struct hostapd_freq_params vht_freq;
int chwidth, seg0, seg1;
-@@ -2416,7 +2416,7 @@ void ibss_mesh_setup_freq(struct wpa_sup
+@@ -2421,7 +2421,7 @@ void ibss_mesh_setup_freq(struct wpa_sup
#endif /* CONFIG_HE_OVERRIDES */
/* Setup higher BW only for 5 GHz */
for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
-@@ -960,6 +960,8 @@ struct wpa_ssid {
+@@ -965,6 +965,8 @@ struct wpa_ssid {
*/
int no_auto_peer;
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
-@@ -4926,7 +4926,7 @@ wpa_supplicant_alloc(struct wpa_supplica
+@@ -4948,7 +4948,7 @@ wpa_supplicant_alloc(struct wpa_supplica
if (wpa_s == NULL)
return NULL;
wpa_s->scan_req = INITIAL_SCAN_REQ;
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -4639,7 +4639,7 @@ static int nl80211_set_channel(struct i8
+@@ -4645,7 +4645,7 @@ static int nl80211_set_channel(struct i8
freq->freq, freq->ht_enabled, freq->vht_enabled, freq->he_enabled,
freq->bandwidth, freq->center_freq1, freq->center_freq2);
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
-@@ -112,6 +112,28 @@ static void hostapd_reload_bss(struct ho
+@@ -114,6 +114,28 @@ static void hostapd_reload_bss(struct ho
#endif /* CONFIG_NO_RADIUS */
ssid = &hapd->conf->ssid;
if (!ssid->wpa_psk_set && ssid->wpa_psk && !ssid->wpa_psk->next &&
ssid->wpa_passphrase_set && ssid->wpa_passphrase) {
/*
-@@ -213,6 +235,7 @@ int hostapd_reload_config(struct hostapd
+@@ -215,6 +237,7 @@ int hostapd_reload_config(struct hostapd
struct hostapd_data *hapd = iface->bss[0];
struct hostapd_config *newconf, *oldconf;
size_t j;
if (iface->config_fname == NULL) {
/* Only in-memory config in use - assume it has been updated */
-@@ -263,24 +286,20 @@ int hostapd_reload_config(struct hostapd
+@@ -265,24 +288,20 @@ int hostapd_reload_config(struct hostapd
}
iface->conf = newconf;
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -2778,10 +2778,15 @@ static int wpa_driver_nl80211_del_beacon
+@@ -2787,10 +2787,15 @@ static int wpa_driver_nl80211_del_beacon
struct nl_msg *msg;
struct wpa_driver_nl80211_data *drv = bss->drv;
return send_and_recv_msgs(drv, msg, NULL, NULL);
}
-@@ -5250,7 +5255,7 @@ static void nl80211_teardown_ap(struct i
+@@ -5260,7 +5265,7 @@ static void nl80211_teardown_ap(struct i
nl80211_mgmt_unsubscribe(bss, "AP teardown");
nl80211_put_wiphy_data_ap(bss);
}
-@@ -7631,8 +7636,6 @@ static int wpa_driver_nl80211_if_remove(
+@@ -7678,8 +7683,6 @@ static int wpa_driver_nl80211_if_remove(
} else {
wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
nl80211_teardown_ap(bss);
nl80211_destroy_bss(bss);
if (!bss->added_if)
i802_set_iface_flags(bss, 0);
-@@ -8006,7 +8009,6 @@ static int wpa_driver_nl80211_deinit_ap(
+@@ -8073,7 +8076,6 @@ static int wpa_driver_nl80211_deinit_ap(
if (!is_ap_interface(drv->nlmode))
return -1;
wpa_driver_nl80211_del_beacon(bss);
/*
* If the P2P GO interface was dynamically added, then it is
-@@ -8026,7 +8028,6 @@ static int wpa_driver_nl80211_stop_ap(vo
+@@ -8093,7 +8095,6 @@ static int wpa_driver_nl80211_stop_ap(vo
if (!is_ap_interface(drv->nlmode))
return -1;
wpa_driver_nl80211_del_beacon(bss);
#ifdef NEED_AP_MLME
static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
-@@ -3499,6 +3556,8 @@ static int hostapd_ctrl_iface_receive_pr
+@@ -3527,6 +3584,8 @@ static int hostapd_ctrl_iface_receive_pr
} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
reply_size);
wpa_s->new_connection = 1;
wpa_drv_set_operstate(wpa_s, 0);
#ifndef IEEE8021X_EAPOL
-@@ -2222,6 +2274,8 @@ void wpa_supplicant_associate(struct wpa
+@@ -2225,6 +2277,8 @@ void wpa_supplicant_associate(struct wpa
wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
ssid->id);
wpas_notify_mesh_group_started(wpa_s, ssid);
#else /* CONFIG_MESH */
wpa_msg(wpa_s, MSG_ERROR,
"mesh mode support not included in the build");
-@@ -6184,6 +6238,16 @@ static int wpa_supplicant_init_iface(str
+@@ -6206,6 +6260,16 @@ static int wpa_supplicant_init_iface(str
sizeof(wpa_s->bridge_ifname));
}
/* RSNA Supplicant Key Management - INITIALIZE */
eapol_sm_notify_portEnabled(wpa_s->eapol, false);
eapol_sm_notify_portValid(wpa_s->eapol, false);
-@@ -6517,6 +6581,11 @@ static void wpa_supplicant_deinit_iface(
+@@ -6539,6 +6603,11 @@ static void wpa_supplicant_deinit_iface(
if (terminate)
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
-@@ -2665,6 +2665,11 @@ static int hostapd_ctrl_iface_chan_switc
+@@ -2693,6 +2693,11 @@ static int hostapd_ctrl_iface_chan_switc
return 0;
}
/* Save CHAN_SWITCH VHT config */
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
-@@ -1460,11 +1460,6 @@ int ieee802_11_set_beacon(struct hostapd
+@@ -1468,11 +1468,6 @@ int ieee802_11_set_beacon(struct hostapd
struct wpabuf *beacon, *proberesp, *assocresp;
int res, ret = -1;
if (ieee802_11_build_ap_params(hapd, ¶ms) < 0)
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
-@@ -4499,6 +4499,60 @@ static void wpas_event_unprot_beacon(str
+@@ -4500,6 +4500,60 @@ static void wpas_event_unprot_beacon(str
}
void supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
{
-@@ -4801,8 +4855,10 @@ void supplicant_event(void *ctx, enum wp
+@@ -4802,8 +4856,10 @@ void supplicant_event(void *ctx, enum wp
channel_width_to_string(data->ch_switch.ch_width),
data->ch_switch.cf1,
data->ch_switch.cf2);
wpa_s->current_ssid->frequency = data->ch_switch.freq;
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
-@@ -5669,6 +5669,7 @@ union wpa_event_data {
+@@ -5683,6 +5683,7 @@ union wpa_event_data {
/**
* struct ch_switch
* @freq: Frequency of new channel in MHz
* @ht_enabled: Whether this is an HT channel
* @ch_offset: Secondary channel offset
-@@ -5677,6 +5678,7 @@ union wpa_event_data {
+@@ -5691,6 +5692,7 @@ union wpa_event_data {
* @cf2: Center frequency 2
*/
struct ch_switch {
if (finished)
bss->freq = data.ch_switch.freq;
-@@ -2689,6 +2691,7 @@ static void do_process_drv_event(struct
+@@ -2686,6 +2688,7 @@ static void do_process_drv_event(struct
tb[NL80211_ATTR_CHANNEL_WIDTH],
tb[NL80211_ATTR_CENTER_FREQ1],
tb[NL80211_ATTR_CENTER_FREQ2],
0);
break;
case NL80211_CMD_CH_SWITCH_NOTIFY:
-@@ -2699,6 +2702,7 @@ static void do_process_drv_event(struct
+@@ -2696,6 +2699,7 @@ static void do_process_drv_event(struct
tb[NL80211_ATTR_CHANNEL_WIDTH],
tb[NL80211_ATTR_CENTER_FREQ1],
tb[NL80211_ATTR_CENTER_FREQ2],
else
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
-@@ -3323,6 +3323,7 @@ static int hostapd_ctrl_iface_receive_pr
+@@ -3351,6 +3351,7 @@ static int hostapd_ctrl_iface_receive_pr
reply_size);
} else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
reply_len = hostapd_drv_status(hapd, reply, reply_size);
} else if (os_strcmp(buf, "MIB") == 0) {
reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
if (reply_len >= 0) {
-@@ -3364,6 +3365,7 @@ static int hostapd_ctrl_iface_receive_pr
+@@ -3392,6 +3393,7 @@ static int hostapd_ctrl_iface_receive_pr
} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
reply_size);
reply_len = -1;
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
-@@ -942,6 +942,9 @@ ifdef CONFIG_FILS
+@@ -948,6 +948,9 @@ ifdef CONFIG_FILS
OBJS += ../src/ap/fils_hlp.o
endif
ifdef CONFIG_CTRL_IFACE
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
-@@ -2257,7 +2257,7 @@ static int wpa_supplicant_ctrl_iface_sta
+@@ -2261,7 +2261,7 @@ static int wpa_supplicant_ctrl_iface_sta
pos += ret;
}
if (wpa_s->ap_iface) {
pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
end - pos,
-@@ -10172,6 +10172,7 @@ char * wpa_supplicant_ctrl_iface_process
+@@ -10243,6 +10243,7 @@ char * wpa_supplicant_ctrl_iface_process
reply_len = -1;
} else if (os_strncmp(buf, "NOTE ", 5) == 0) {
wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
} else if (os_strcmp(buf, "MIB") == 0) {
reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
if (reply_len >= 0) {
-@@ -10184,6 +10185,7 @@ char * wpa_supplicant_ctrl_iface_process
+@@ -10255,6 +10256,7 @@ char * wpa_supplicant_ctrl_iface_process
reply_size - reply_len);
#endif /* CONFIG_MACSEC */
}
} else if (os_strncmp(buf, "STATUS", 6) == 0) {
reply_len = wpa_supplicant_ctrl_iface_status(
wpa_s, buf + 6, reply, reply_size);
-@@ -10668,6 +10670,7 @@ char * wpa_supplicant_ctrl_iface_process
+@@ -10739,6 +10741,7 @@ char * wpa_supplicant_ctrl_iface_process
reply_len = wpa_supplicant_ctrl_iface_bss(
wpa_s, buf + 4, reply, reply_size);
#ifdef CONFIG_AP
} else if (os_strcmp(buf, "STA-FIRST") == 0) {
reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
} else if (os_strncmp(buf, "STA ", 4) == 0) {
-@@ -10676,12 +10679,15 @@ char * wpa_supplicant_ctrl_iface_process
+@@ -10747,12 +10750,15 @@ char * wpa_supplicant_ctrl_iface_process
} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
reply_size);
static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
-@@ -4351,6 +4351,7 @@ static const char * wpa_bool_txt(int val
+@@ -4391,6 +4391,7 @@ static const char * wpa_bool_txt(int val
return val ? "TRUE" : "FALSE";
}
#define RSN_SUITE "%02x-%02x-%02x-%d"
#define RSN_SUITE_ARG(s) \
-@@ -4501,7 +4502,7 @@ int wpa_get_mib_sta(struct wpa_state_mac
+@@ -4541,7 +4542,7 @@ int wpa_get_mib_sta(struct wpa_state_mac
return len;
}
{
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
-@@ -2680,6 +2680,8 @@ static u32 wpa_key_mgmt_suite(struct wpa
+@@ -2717,6 +2717,8 @@ static u32 wpa_key_mgmt_suite(struct wpa
}
#define RSN_SUITE "%02x-%02x-%02x-%d"
#define RSN_SUITE_ARG(s) \
((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
-@@ -2761,6 +2763,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch
+@@ -2798,6 +2800,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch
return (int) len;
}
#include "crypto/random.h"
#include "crypto/tls.h"
#include "common/version.h"
-@@ -688,7 +689,7 @@ int main(int argc, char *argv[])
+@@ -692,7 +693,7 @@ int main(int argc, char *argv[])
wpa_supplicant_event = hostapd_wpa_event;
wpa_supplicant_event_global = hostapd_wpa_event_global;
for (;;) {
if (c < 0)
break;
switch (c) {
-@@ -725,6 +726,8 @@ int main(int argc, char *argv[])
+@@ -729,6 +730,8 @@ int main(int argc, char *argv[])
break;
#endif /* CONFIG_DEBUG_LINUX_TRACING */
case 'v':
/* Helper macros for network block parser */
#ifdef OFFSET
-@@ -2551,6 +2643,8 @@ static const struct parse_data ssid_fiel
+@@ -2552,6 +2644,8 @@ static const struct parse_data ssid_fiel
{ INT(ap_max_inactivity) },
{ INT(dtim_period) },
{ INT(beacon_int) },
#define DEFAULT_EAP_WORKAROUND ((unsigned int) -1)
-@@ -832,6 +834,9 @@ struct wpa_ssid {
+@@ -837,6 +839,9 @@ struct wpa_ssid {
*/
void *parent_cred;
* macsec_policy - Determines the policy for MACsec secure session
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
-@@ -3615,6 +3615,12 @@ static void wpas_start_assoc_cb(struct w
+@@ -3637,6 +3637,12 @@ static void wpas_start_assoc_cb(struct w
params.beacon_int = ssid->beacon_int;
else
params.beacon_int = wpa_s->conf->beacon_int;
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -5573,7 +5573,7 @@ static int wpa_driver_nl80211_ibss(struc
+@@ -5583,7 +5583,7 @@ static int wpa_driver_nl80211_ibss(struc
struct wpa_driver_associate_params *params)
{
struct nl_msg *msg;
int count = 0;
wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
-@@ -5600,6 +5600,37 @@ retry:
+@@ -5610,6 +5610,37 @@ retry:
nl80211_put_beacon_int(msg, params->beacon_int))
goto fail;
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
-@@ -1546,6 +1546,7 @@ struct wpa_driver_mesh_join_params {
- #define WPA_DRIVER_MESH_FLAG_SAE_AUTH 0x00000004
+@@ -1549,6 +1549,7 @@ struct wpa_driver_mesh_join_params {
#define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008
unsigned int flags;
+ u8 handle_dfs;
+ int mcast_rate;
};
struct wpa_driver_set_key_params {
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -9959,6 +9959,18 @@ static int nl80211_put_mesh_id(struct nl
+@@ -10026,6 +10026,18 @@ static int nl80211_put_mesh_id(struct nl
}
static int nl80211_put_mesh_config(struct nl_msg *msg,
struct wpa_driver_mesh_bss_params *params)
{
-@@ -10017,6 +10029,7 @@ static int nl80211_join_mesh(struct i802
+@@ -10087,6 +10099,7 @@ static int nl80211_join_mesh(struct i802
nl80211_put_basic_rates(msg, params->basic_rates) ||
nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) ||
nl80211_put_beacon_int(msg, params->beacon_int) ||
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
-@@ -460,6 +460,7 @@ int wpa_supplicant_join_mesh(struct wpa_
+@@ -501,6 +501,7 @@ int wpa_supplicant_join_mesh(struct wpa_
params->meshid = ssid->ssid;
params->meshid_len = ssid->ssid_len;
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
-@@ -2402,11 +2402,13 @@ void ibss_mesh_setup_freq(struct wpa_sup
+@@ -2407,11 +2407,13 @@ void ibss_mesh_setup_freq(struct wpa_sup
for (j = 0; j < wpa_s->last_scan_res_used; j++) {
struct wpa_bss *bss = wpa_s->last_scan_res[j];
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
-@@ -1310,14 +1310,14 @@ hostapd_multi.a: $(BCHECK) $(OBJS)
+@@ -1316,14 +1316,14 @@ hostapd_multi.a: $(BCHECK) $(OBJS)
@$(AR) cr $@ hostapd_multi.o $(OBJS)
hostapd: $(BCHECK) $(OBJS)
NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS)
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
-@@ -1920,23 +1920,23 @@ wpa_supplicant_multi.a: .config $(BCHECK
+@@ -1926,23 +1926,23 @@ wpa_supplicant_multi.a: .config $(BCHECK
@$(AR) cr $@ wpa_supplicant_multi.o $(OBJS)
wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)
int interface_added; /* virtual interface added for this BSS */
unsigned int started:1;
unsigned int disabled:1;
-@@ -588,6 +590,7 @@ hostapd_alloc_bss_data(struct hostapd_if
+@@ -603,6 +605,7 @@ hostapd_alloc_bss_data(struct hostapd_if
struct hostapd_bss_config *bss);
int hostapd_setup_interface(struct hostapd_iface *iface);
int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
struct hostapd_iface * hostapd_alloc_iface(void);
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
-@@ -391,6 +391,7 @@ static void hostapd_free_hapd_data(struc
+@@ -395,6 +395,7 @@ static void hostapd_free_hapd_data(struc
hapd->beacon_set_done = 0;
wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
accounting_deinit(hapd);
hostapd_deinit_wpa(hapd);
vlan_deinit(hapd);
-@@ -1392,6 +1393,8 @@ static int hostapd_setup_bss(struct host
+@@ -1413,6 +1414,8 @@ static int hostapd_setup_bss(struct host
if (hapd->driver && hapd->driver->set_operstate)
hapd->driver->set_operstate(hapd->drv_priv, 1);
return 0;
}
-@@ -1967,6 +1970,7 @@ static int hostapd_setup_interface_compl
+@@ -1988,6 +1991,7 @@ static int hostapd_setup_interface_compl
if (err)
goto fail;
wpa_printf(MSG_DEBUG, "Completing interface initialization");
if (iface->freq) {
#ifdef NEED_AP_MLME
-@@ -2157,6 +2161,7 @@ dfs_offload:
+@@ -2185,6 +2189,7 @@ dfs_offload:
fail:
wpa_printf(MSG_ERROR, "Interface initialization failed");
hostapd_set_state(iface, HAPD_IFACE_DISABLED);
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
#ifdef CONFIG_FST
-@@ -2630,6 +2635,7 @@ void hostapd_interface_deinit_free(struc
+@@ -2658,6 +2663,7 @@ void hostapd_interface_deinit_free(struc
(unsigned int) iface->conf->num_bss);
driver = iface->bss[0]->driver;
drv_priv = iface->bss[0]->drv_priv;
if (res == HOSTAPD_ACL_PENDING)
return;
-@@ -4078,7 +4090,7 @@ static void handle_assoc(struct hostapd_
+@@ -4087,7 +4099,7 @@ static void handle_assoc(struct hostapd_
int resp = WLAN_STATUS_SUCCESS;
u16 reply_res;
const u8 *pos;
struct sta_info *sta;
u8 *tmp = NULL;
#ifdef CONFIG_FILS
-@@ -4291,6 +4303,11 @@ static void handle_assoc(struct hostapd_
+@@ -4300,6 +4312,11 @@ static void handle_assoc(struct hostapd_
left = res;
}
#endif /* CONFIG_FILS */
/* followed by SSID and Supported rates; and HT capabilities if 802.11n
* is used */
-@@ -4455,6 +4472,14 @@ static void handle_assoc(struct hostapd_
+@@ -4464,6 +4481,14 @@ static void handle_assoc(struct hostapd_
pos, left, rssi, omit_rsnxe);
os_free(tmp);
/*
* Remove the station in case tranmission of a success response fails
* (the STA was added associated to the driver) or if the station was
-@@ -4482,6 +4507,7 @@ static void handle_disassoc(struct hosta
+@@ -4491,6 +4516,7 @@ static void handle_disassoc(struct hosta
wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
MAC2STR(mgmt->sa),
le_to_host16(mgmt->u.disassoc.reason_code));
sta = ap_get_sta(hapd, mgmt->sa);
if (sta == NULL) {
-@@ -4548,6 +4574,8 @@ static void handle_deauth(struct hostapd
+@@ -4557,6 +4583,8 @@ static void handle_deauth(struct hostapd
" reason_code=%d",
MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
-@@ -810,6 +810,12 @@ void handle_probe_req(struct hostapd_dat
+@@ -814,6 +814,12 @@ void handle_probe_req(struct hostapd_dat
u16 csa_offs[2];
size_t csa_offs_len;
struct radius_sta rad_info;
if (len < IEEE80211_HDRLEN)
return;
-@@ -992,6 +998,12 @@ void handle_probe_req(struct hostapd_dat
+@@ -996,6 +1002,12 @@ void handle_probe_req(struct hostapd_dat
}
#endif /* CONFIG_P2P */
wpabuf_free(sta->p2p_ie);
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
-@@ -423,6 +423,7 @@ void ap_handle_timer(void *eloop_ctx, vo
+@@ -424,6 +424,7 @@ void ap_handle_timer(void *eloop_ctx, vo
HOSTAPD_LEVEL_INFO, "deauthenticated due to "
"local deauth request");
ap_free_sta(hapd, sta);
return;
}
-@@ -578,6 +579,7 @@ skip_poll:
+@@ -579,6 +580,7 @@ skip_poll:
hapd, sta,
WLAN_REASON_PREV_AUTH_NOT_VALID);
ap_free_sta(hapd, sta);
break;
}
}
-@@ -1293,6 +1295,7 @@ void ap_sta_set_authorized(struct hostap
+@@ -1294,6 +1296,7 @@ void ap_sta_set_authorized(struct hostap
buf, ip_addr, keyid_buf);
} else {
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
ifdef CONFIG_CODE_COVERAGE
CFLAGS += -O0 -fprofile-arcs -ftest-coverage
LIBS += -lgcov
-@@ -877,6 +883,9 @@ OBJS += ../src/pae/ieee802_1x_secy_ops.o
+@@ -883,6 +889,9 @@ OBJS += ../src/pae/ieee802_1x_secy_ops.o
ifdef CONFIG_AP
OBJS += ../src/ap/wpa_auth_kay.o
endif
ifdef CONFIG_IEEE8021X_EAPOL
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
-@@ -6771,6 +6771,8 @@ struct wpa_supplicant * wpa_supplicant_a
+@@ -6793,6 +6793,8 @@ struct wpa_supplicant * wpa_supplicant_a
}
#endif /* CONFIG_P2P */
return wpa_s;
}
-@@ -6797,6 +6799,8 @@ int wpa_supplicant_remove_iface(struct w
+@@ -6819,6 +6821,8 @@ int wpa_supplicant_remove_iface(struct w
struct wpa_supplicant *parent = wpa_s->parent;
#endif /* CONFIG_MESH */
/* Remove interface from the global list of interfaces */
prev = global->ifaces;
if (prev == wpa_s) {
-@@ -7100,8 +7104,12 @@ int wpa_supplicant_run(struct wpa_global
+@@ -7122,8 +7126,12 @@ int wpa_supplicant_run(struct wpa_global
eloop_register_signal_terminate(wpa_supplicant_terminate, global);
eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
#ifndef WPS_PIN_SCAN_IGNORE_SEL_REG
-@@ -388,6 +389,8 @@ static int wpa_supplicant_wps_cred(void
+@@ -392,6 +393,8 @@ static int wpa_supplicant_wps_cred(void
wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
cred->cred_attr, cred->cred_attr_len);
--- a/hostapd/main.c
+++ b/hostapd/main.c
-@@ -892,6 +892,7 @@ int main(int argc, char *argv[])
+@@ -896,6 +896,7 @@ int main(int argc, char *argv[])
}
hostapd_global_ctrl_iface_init(&interfaces);
if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
wpa_printf(MSG_ERROR, "Failed to start eloop");
-@@ -901,6 +902,7 @@ int main(int argc, char *argv[])
+@@ -905,6 +906,7 @@ int main(int argc, char *argv[])
ret = 0;
out:
os_free(conf->basic_rates);
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
-@@ -859,6 +859,7 @@ struct hostapd_bss_config {
+@@ -861,6 +861,7 @@ struct hostapd_bss_config {
*/
u8 mka_psk_set;
#endif /* CONFIG_MACSEC */
};
/**
-@@ -1050,6 +1051,7 @@ struct hostapd_config {
+@@ -1052,6 +1053,7 @@ struct hostapd_config {
unsigned int airtime_update_interval;
#define AIRTIME_MODE_MAX (__AIRTIME_MODE_MAX - 1)
#endif /* CONFIG_AIRTIME_POLICY */
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
-@@ -216,6 +216,10 @@ static int hostapd_iface_conf_changed(st
+@@ -218,6 +218,10 @@ static int hostapd_iface_conf_changed(st
{
size_t i;
if (newconf->num_bss != oldconf->num_bss)
return 1;
-@@ -229,7 +233,7 @@ static int hostapd_iface_conf_changed(st
+@@ -231,7 +235,7 @@ static int hostapd_iface_conf_changed(st
}
{
struct hapd_interfaces *interfaces = iface->interfaces;
struct hostapd_data *hapd = iface->bss[0];
-@@ -252,13 +256,16 @@ int hostapd_reload_config(struct hostapd
+@@ -254,13 +258,16 @@ int hostapd_reload_config(struct hostapd
if (newconf == NULL)
return -1;
wpa_printf(MSG_DEBUG,
"Configuration changes include interface/BSS modification - force full disable+enable sequence");
fname = os_strdup(iface->config_fname);
-@@ -283,6 +290,24 @@ int hostapd_reload_config(struct hostapd
+@@ -285,6 +292,24 @@ int hostapd_reload_config(struct hostapd
wpa_printf(MSG_ERROR,
"Failed to enable interface on config reload");
return res;
+ * items (e.g., open/close sockets, etc.) */
+ radius_client_flush(iface->bss[j]->radius, 0);
+#endif /* CONFIG_NO_RADIUS */
-+ wpa_printf(MSG_INFO, "bss %d changed", j);
++ wpa_printf(MSG_INFO, "bss %zu changed", j);
+ }
+ }
}
iface->conf = newconf;
-@@ -299,6 +324,12 @@ int hostapd_reload_config(struct hostapd
+@@ -301,6 +326,12 @@ int hostapd_reload_config(struct hostapd
for (j = 0; j < iface->num_bss; j++) {
hapd = iface->bss[j];
hapd->iconf = newconf;
hapd->conf = newconf->bss[j];
hostapd_reload_bss(hapd);
-@@ -2329,6 +2360,10 @@ hostapd_alloc_bss_data(struct hostapd_if
+@@ -2355,6 +2386,10 @@ hostapd_alloc_bss_data(struct hostapd_if
hapd->iconf = conf;
hapd->conf = bss;
hapd->iface = hapd_iface;
int interface_added; /* virtual interface added for this BSS */
unsigned int started:1;
unsigned int disabled:1;
-@@ -582,7 +583,7 @@ struct hostapd_iface {
+@@ -597,7 +598,7 @@ struct hostapd_iface {
int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
int (*cb)(struct hostapd_iface *iface,
void *ctx), void *ctx);
hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -4486,6 +4486,9 @@ static int wpa_driver_nl80211_set_ap(voi
+@@ -4492,6 +4492,9 @@ static int wpa_driver_nl80211_set_ap(voi
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
ret, strerror(-ret));