Merge "DO NOT MERGE - Merge RQ3A.210605.005"
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 6a2de1f..1a5f899 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -464,6 +464,13 @@
event.assoc_info.fils_pmkid = nla_data(fils_pmkid);
wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
+
+ /* Avoid a race condition by stopping to ignore any following
+ * disconnection events now that the driver has indicated it is
+ * connected since that connection could have been triggered by a roam
+ * operation that happened in parallel with the disconnection request.
+ */
+ drv->ignore_next_local_disconnect = 0;
}
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index 3994ec0..05fd593 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -595,14 +595,12 @@
goto out;
}
+ dev = p2p_get_device(p2p, sa);
if (!dev) {
- dev = p2p_get_device(p2p, sa);
- if (!dev) {
- p2p_dbg(p2p,
- "Provision Discovery device not found "
- MACSTR, MAC2STR(sa));
- goto out;
- }
+ p2p_dbg(p2p,
+ "Provision Discovery device not found "
+ MACSTR, MAC2STR(sa));
+ goto out;
}
} else if (msg.wfd_subelems) {
wpabuf_free(dev->info.wfd_subelems);
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index e1d9824..173be09 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -4305,6 +4305,7 @@
config->disassoc_imminent_rssi_threshold =
DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD;
config->oce = DEFAULT_OCE_SUPPORT;
+ config->btm_offload = DEFAULT_BTM_OFFLOAD;
#endif /* CONFIG_MBO */
if (ctrl_interface)
@@ -5048,6 +5049,7 @@
MBO_CELL_CAPA_NOT_SUPPORTED), 0 },
{ INT_RANGE(disassoc_imminent_rssi_threshold, -120, 0), 0 },
{ INT_RANGE(oce, 0, 3), 0 },
+ { INT_RANGE(btm_offload, 0, 1), CFG_CHANGED_DISABLE_BTM_NOTIFY },
#endif /* CONFIG_MBO */
{ INT(gas_address3), 0 },
{ INT_RANGE(ftm_responder, 0, 1), 0 },
@@ -5065,6 +5067,7 @@
{ INT_RANGE(disable_btm, 0, 1), CFG_CHANGED_DISABLE_BTM },
{ INT_RANGE(extended_key_id, 0, 1), 0 },
#endif /* CONFIG_WNM */
+ { INT_RANGE(wowlan_disconnect_on_deinit, 0, 1), 0},
};
#undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 0ca27cb..712e871 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -45,6 +45,7 @@
#define DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD -75
#define DEFAULT_OCE_SUPPORT OCE_STA
#define DEFAULT_EXTENDED_KEY_ID 0
+#define DEFAULT_BTM_OFFLOAD 0
#include "config_ssid.h"
#include "wps/wps.h"
@@ -376,6 +377,7 @@
#define CFG_CHANGED_SCHED_SCAN_PLANS BIT(17)
#define CFG_CHANGED_WOWLAN_TRIGGERS BIT(18)
#define CFG_CHANGED_DISABLE_BTM BIT(19)
+#define CFG_CHANGED_DISABLE_BTM_NOTIFY BIT(20)
/**
* struct wpa_config - wpa_supplicant configuration data
@@ -1447,6 +1449,14 @@
* - Set BIT(1) to enable OCE in STA-CFON mode
*/
unsigned int oce;
+
+ /**
+ * btm_offload - Set where to perform roaming logic
+ * - Set to 0 to handle fully roaming logic in supplicant
+ * - Set to 1 to skip roaming logic in supplicant for firmware roaming
+ * just parse BTM frame and notify framework
+ */
+ int btm_offload;
#endif /* CONFIG_MBO */
/**
@@ -1590,6 +1600,15 @@
* 1 = use Extended Key ID when possible
*/
int extended_key_id;
+
+ /**
+ * wowlan_disconnect_on_deinit - Trigger disconnect on wpa_supplicant
+ * interface deinit even if the driver has enabled WoWLAN.
+ *
+ * 0 = Do not disconnect
+ * 1 = Trigger disconnection
+ */
+ int wowlan_disconnect_on_deinit;
};
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 52e1372..5faed4e 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1607,6 +1607,9 @@
if (config->extended_key_id != DEFAULT_EXTENDED_KEY_ID)
fprintf(f, "extended_key_id=%d\n",
config->extended_key_id);
+ if (config->wowlan_disconnect_on_deinit)
+ fprintf(f, "wowlan_disconnect_on_deinit=%d\n",
+ config->wowlan_disconnect_on_deinit);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/ctrl_iface.h b/wpa_supplicant/ctrl_iface.h
index 510668d..a408288 100644
--- a/wpa_supplicant/ctrl_iface.h
+++ b/wpa_supplicant/ctrl_iface.h
@@ -70,14 +70,17 @@
/**
* wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface
+ * @wpa_s: Pointer to wpa_supplicant data
* @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
*
* Deinitialize the control interface that was initialized with
- * wpa_supplicant_ctrl_iface_init().
+ * wpa_supplicant_ctrl_iface_init() and any data related to the wpa_s instance.
+ * @priv may be %NULL if the control interface has not yet been initialized.
*
* Required to be implemented in each control interface backend.
*/
-void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv);
+void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
+ struct ctrl_iface_priv *priv);
/**
* wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor
diff --git a/wpa_supplicant/ctrl_iface_named_pipe.c b/wpa_supplicant/ctrl_iface_named_pipe.c
index 79ff787..bddc041 100644
--- a/wpa_supplicant/ctrl_iface_named_pipe.c
+++ b/wpa_supplicant/ctrl_iface_named_pipe.c
@@ -462,8 +462,11 @@
}
-void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
+void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
+ struct ctrl_iface_priv *priv)
{
+ if (!priv)
+ return;
while (priv->ctrl_dst)
ctrl_close_pipe(priv->ctrl_dst);
if (priv->sec_attr_set)
diff --git a/wpa_supplicant/ctrl_iface_udp.c b/wpa_supplicant/ctrl_iface_udp.c
index 1512080..1cbf7fa 100644
--- a/wpa_supplicant/ctrl_iface_udp.c
+++ b/wpa_supplicant/ctrl_iface_udp.c
@@ -490,8 +490,12 @@
}
-void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
+void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
+ struct ctrl_iface_priv *priv)
{
+ if (!priv)
+ return;
+
if (priv->sock > -1) {
eloop_unregister_read_sock(priv->sock);
if (priv->ctrl_dst) {
diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c
index 953fd2c..639573d 100644
--- a/wpa_supplicant/ctrl_iface_unix.c
+++ b/wpa_supplicant/ctrl_iface_unix.c
@@ -800,12 +800,52 @@
}
-void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
+static void
+wpas_global_ctrl_iface_flush_queued_msg(struct wpa_global *global,
+ struct wpa_supplicant *wpa_s)
+{
+ struct ctrl_iface_global_priv *gpriv;
+ struct ctrl_iface_msg *msg, *prev_msg;
+ unsigned int count = 0;
+
+ if (!global || !global->ctrl_iface)
+ return;
+
+ gpriv = global->ctrl_iface;
+ dl_list_for_each_safe(msg, prev_msg, &gpriv->msg_queue,
+ struct ctrl_iface_msg, list) {
+ if (msg->wpa_s == wpa_s) {
+ count++;
+ dl_list_del(&msg->list);
+ os_free(msg);
+ }
+ }
+
+ if (count) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: Dropped %u pending message(s) for interface that is being removed",
+ count);
+ }
+}
+
+
+void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
+ struct ctrl_iface_priv *priv)
{
struct wpa_ctrl_dst *dst, *prev;
struct ctrl_iface_msg *msg, *prev_msg;
struct ctrl_iface_global_priv *gpriv;
+ if (!priv) {
+ /* Control interface has not yet been initialized, so there is
+ * nothing to deinitialize here. However, there might be a
+ * pending message for this interface, so get rid of any such
+ * entry before completing interface removal. */
+ wpas_global_ctrl_iface_flush_queued_msg(wpa_s->global, wpa_s);
+ eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, wpa_s, NULL);
+ return;
+ }
+
if (priv->sock > -1) {
char *fname;
char *buf, *dir = NULL;
@@ -877,6 +917,7 @@
}
}
}
+ wpas_global_ctrl_iface_flush_queued_msg(wpa_s->global, wpa_s);
eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, priv->wpa_s, NULL);
os_free(priv);
}
diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
index 9f69736..11eee98 100644
--- a/wpa_supplicant/eapol_test.c
+++ b/wpa_supplicant/eapol_test.c
@@ -674,10 +674,8 @@
os_free(e->radius_conf);
e->radius_conf = NULL;
scard_deinit(wpa_s->scard);
- if (wpa_s->ctrl_iface) {
- wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
- wpa_s->ctrl_iface = NULL;
- }
+ wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
+ wpa_s->ctrl_iface = NULL;
ext_password_deinit(wpa_s->ext_pw);
wpa_s->ext_pw = NULL;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 7b68ebe..096fd02 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -4586,6 +4586,11 @@
break;
}
#endif /* CONFIG_TESTING_OPTIONS */
+ if (wpa_s->disconnected) {
+ wpa_printf(MSG_INFO,
+ "Ignore unexpected EVENT_ASSOC in disconnected state");
+ break;
+ }
wpa_supplicant_event_assoc(wpa_s, data);
wpa_s->assoc_status_code = WLAN_STATUS_SUCCESS;
if (data &&
diff --git a/wpa_supplicant/preauth_test.c b/wpa_supplicant/preauth_test.c
index 4a8f4ff..dc955b8 100644
--- a/wpa_supplicant/preauth_test.c
+++ b/wpa_supplicant/preauth_test.c
@@ -192,10 +192,8 @@
pmksa_candidate_free(wpa_s->wpa);
wpa_sm_deinit(wpa_s->wpa);
scard_deinit(wpa_s->scard);
- if (wpa_s->ctrl_iface) {
- wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
- wpa_s->ctrl_iface = NULL;
- }
+ wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
+ wpa_s->ctrl_iface = NULL;
wpa_config_free(wpa_s->conf);
}
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 2e09102..ac04383 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -1451,6 +1451,22 @@
wpa_s->wnm_dissoc_timer * beacon_int * 128 / 125, url);
}
+#ifdef CONFIG_MBO
+ vendor = get_ie(pos, end - pos, WLAN_EID_VENDOR_SPECIFIC);
+ if (vendor) {
+ wpas_mbo_ie_trans_req(wpa_s, vendor + 2, vendor[1]);
+ if (wpa_s->conf->btm_offload) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "WNM: Notify BSS Transition Management Request frame status");
+ wpa_s->bss_tm_status = WNM_BSS_TM_ACCEPT;
+ wpas_notify_bss_tm_status(wpa_s);
+ /* since it could be referenced in the scan result logic, initialize it */
+ wpa_s->wnm_mbo_trans_reason_present = 0;
+ return;
+ }
+ }
+#endif /* CONFIG_MBO */
+
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
wpa_msg(wpa_s, MSG_INFO, "WNM: Disassociation Imminent - "
"Disassociation Timer %u", wpa_s->wnm_dissoc_timer);
@@ -1462,12 +1478,6 @@
}
}
-#ifdef CONFIG_MBO
- vendor = get_ie(pos, end - pos, WLAN_EID_VENDOR_SPECIFIC);
- if (vendor)
- wpas_mbo_ie_trans_req(wpa_s, vendor + 2, vendor[1]);
-#endif /* CONFIG_MBO */
-
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED) {
unsigned int valid_ms;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index a01a4e5..f928fdb 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1137,8 +1137,8 @@
os_strcmp(conf->ctrl_interface,
wpa_s->conf->ctrl_interface) != 0);
- if (reconf_ctrl && wpa_s->ctrl_iface) {
- wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
+ if (reconf_ctrl) {
+ wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
wpa_s->ctrl_iface = NULL;
}
@@ -6493,8 +6493,12 @@
wpa_s->disconnected = 1;
if (wpa_s->drv_priv) {
- /* Don't deauthenticate if WoWLAN is enabled */
- if (!wpa_drv_get_wowlan(wpa_s)) {
+ /*
+ * Don't deauthenticate if WoWLAN is enabled and not explicitly
+ * been configured to disconnect.
+ */
+ if (!wpa_drv_get_wowlan(wpa_s) ||
+ wpa_s->conf->wowlan_disconnect_on_deinit) {
wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
@@ -6532,10 +6536,8 @@
if (terminate)
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
- if (wpa_s->ctrl_iface) {
- wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
- wpa_s->ctrl_iface = NULL;
- }
+ wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
+ wpa_s->ctrl_iface = NULL;
#ifdef CONFIG_MESH
if (wpa_s->ifmsh) {
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 3b90567..f5194be 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -1584,6 +1584,12 @@
# Set to 1 to disable BSS transition management
#disable_btm=0
+# This value is used to set where to perform roaming logic
+# Set to 0 to handle roaming logic fully in supplicant
+# Set to 1 to skip roaming logic in supplicant and handle it in firmware
+# In supplicant, just parse BTM frame and notify framework
+#btm_offload=0
+
# Enable EDMG capability in STA/AP mode, default value is false
#enable_edmg=1
diff --git a/wpa_supplicant/wpa_supplicant_template.conf b/wpa_supplicant/wpa_supplicant_template.conf
index fce7e5e..552477d 100644
--- a/wpa_supplicant/wpa_supplicant_template.conf
+++ b/wpa_supplicant/wpa_supplicant_template.conf
@@ -6,3 +6,4 @@
pmf=1
p2p_add_cli_chan=1
oce=1
+wowlan_disconnect_on_deinit=1