[PATCH] nl80211: use the process_bss_event for the nl_connect handler
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Thu Jan 21 10:40:34 EST 2021
From: Avraham Stern <avraham.stern at intel.com>
The nl_connect is initialized with the process_bss_event() handler.
However, it is used several times with the default valid handler.
As a result, if a message that is only valid for the
process_bss_event() is received while the default handler is used, it
will be dropped.
This has been observed in a case where during the 4 way handshake, a
beacon is received on the AP side, which triggers a beacon update,
just before receiving the next EAPOL.
When send_and_recv_msgs_owner() is called for sending the
NL80211_CMD_SET_BEACON command, the NL80211_CMD_CONTROL_PORT_FRAME
event is already pending.
As a result, it is received with the default handler, which drops it.
Since the EAPOL frame is dropped, the connection attempt fails.
Fix it by using the process_bss_event() handler when the nl_connect
handler is used.
Signed-off-by: Avraham Stern <avraham.stern at intel.com>
---
src/drivers/driver_nl80211.c | 75 +++++++++++++++----------------
src/drivers/driver_nl80211.h | 2 +-
src/drivers/driver_nl80211_scan.c | 2 +-
3 files changed, 38 insertions(+), 41 deletions(-)
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 13ecd11d3f..3a78380172 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -530,6 +530,21 @@ static int send_and_recv_msgs_owner(struct wpa_driver_nl80211_data *drv,
}
+static int
+send_and_recv_msgs_connect_handle(struct wpa_driver_nl80211_data *drv,
+ struct nl_msg *msg, struct i802_bss *bss)
+{
+ struct nl_sock *nl_connect = get_connect_handle(bss);
+
+ if (nl_connect)
+ return send_and_recv_msgs_owner(drv, msg, nl_connect, 1,
+ process_bss_event, bss, NULL,
+ NULL);
+ else
+ return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
+}
+
+
struct nl_sock * get_connect_handle(struct i802_bss *bss)
{
if ((bss->drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) ||
@@ -3515,10 +3530,11 @@ static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params,
int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
const u8 *addr, int cmd, u16 reason_code,
int local_state_change,
- struct nl_sock *nl_connect)
+ struct i802_bss *bss)
{
int ret;
struct nl_msg *msg;
+ struct nl_sock *nl_connect = get_connect_handle(bss);
if (!(msg = nl80211_drv_msg(drv, 0, cmd)) ||
nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code) ||
@@ -3530,8 +3546,8 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
}
if (nl_connect)
- ret = send_and_recv(drv->global, nl_connect, msg, NULL, NULL,
- NULL, NULL);
+ ret = send_and_recv(drv->global, nl_connect, msg,
+ process_bss_event, bss, NULL, NULL);
else
ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
if (ret) {
@@ -3545,7 +3561,7 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
u16 reason_code,
- struct nl_sock *nl_connect)
+ struct i802_bss *bss)
{
int ret;
int drv_associated = drv->associated;
@@ -3554,7 +3570,7 @@ static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
nl80211_mark_disconnected(drv);
/* Disconnect command doesn't need BSSID - it uses cached value */
ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
- reason_code, 0, nl_connect);
+ reason_code, 0, bss);
/*
* For locally generated disconnect, supplicant already generates a
* DEAUTH event, so ignore the event from NL80211.
@@ -3577,14 +3593,13 @@ static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
return nl80211_leave_ibss(drv, 1);
}
if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
- return wpa_driver_nl80211_disconnect(drv, reason_code,
- get_connect_handle(bss));
+ return wpa_driver_nl80211_disconnect(drv, reason_code, bss);
}
wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
__func__, MAC2STR(addr), reason_code);
nl80211_mark_disconnected(drv);
ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
- reason_code, 0, get_connect_handle(bss));
+ reason_code, 0, bss);
/*
* For locally generated deauthenticate, supplicant already generates a
* DEAUTH event, so ignore the event from NL80211.
@@ -4604,15 +4619,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
}
#endif /* CONFIG_IEEE80211AX */
-#ifdef CONFIG_SAE
- if (((params->key_mgmt_suites & WPA_KEY_MGMT_SAE) ||
- (params->key_mgmt_suites & WPA_KEY_MGMT_FT_SAE)) &&
- nl80211_put_sae_pwe(msg, params->sae_pwe) < 0)
- goto fail;
-#endif /* CONFIG_SAE */
-
- ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1,
- NULL, NULL, NULL, NULL);
+ ret = send_and_recv_msgs_connect_handle(drv, msg, bss);
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
ret, strerror(-ret));
@@ -5652,9 +5659,7 @@ static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
int ret;
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS);
- ret = send_and_recv_msgs_owner(drv, msg,
- get_connect_handle(drv->first_bss), 1,
- NULL, NULL, NULL, NULL);
+ ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss);
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
"(%s)", ret, strerror(-ret));
@@ -5786,9 +5791,7 @@ retry:
if (ret < 0)
goto fail;
- ret = send_and_recv_msgs_owner(drv, msg,
- get_connect_handle(drv->first_bss), 1,
- NULL, NULL, NULL, NULL);
+ ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss);
msg = NULL;
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
@@ -6124,7 +6127,7 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
static int wpa_driver_nl80211_try_connect(
struct wpa_driver_nl80211_data *drv,
struct wpa_driver_associate_params *params,
- struct nl_sock *nl_connect)
+ struct i802_bss *bss)
{
struct nl_msg *msg;
enum nl80211_auth_type type;
@@ -6196,8 +6199,7 @@ skip_auth_type:
if (ret)
goto fail;
- ret = send_and_recv_msgs_owner(drv, msg, nl_connect, 1, NULL,
- (void *) -1, NULL, NULL);
+ ret = send_and_recv_msgs_connect_handle(drv, msg, bss);
msg = NULL;
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
@@ -6221,7 +6223,7 @@ fail:
static int wpa_driver_nl80211_connect(
struct wpa_driver_nl80211_data *drv,
struct wpa_driver_associate_params *params,
- struct nl_sock *nl_connect)
+ struct i802_bss *bss)
{
int ret;
@@ -6231,7 +6233,7 @@ static int wpa_driver_nl80211_connect(
else
os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
- ret = wpa_driver_nl80211_try_connect(drv, params, nl_connect);
+ ret = wpa_driver_nl80211_try_connect(drv, params, bss);
if (ret == -EALREADY) {
/*
* cfg80211 does not currently accept new connections if
@@ -6242,9 +6244,9 @@ static int wpa_driver_nl80211_connect(
"disconnecting before reassociation "
"attempt");
if (wpa_driver_nl80211_disconnect(
- drv, WLAN_REASON_PREV_AUTH_NOT_VALID, nl_connect))
+ drv, WLAN_REASON_PREV_AUTH_NOT_VALID, bss))
return -1;
- ret = wpa_driver_nl80211_try_connect(drv, params, nl_connect);
+ ret = wpa_driver_nl80211_try_connect(drv, params, bss);
}
return ret;
}
@@ -6278,8 +6280,7 @@ static int wpa_driver_nl80211_associate(
else
bss->use_nl_connect = 0;
- return wpa_driver_nl80211_connect(drv, params,
- get_connect_handle(bss));
+ return wpa_driver_nl80211_connect(drv, params, bss);
}
nl80211_mark_disconnected(drv);
@@ -6314,9 +6315,7 @@ static int wpa_driver_nl80211_associate(
goto fail;
}
- ret = send_and_recv_msgs_owner(drv, msg,
- get_connect_handle(drv->first_bss), 1,
- NULL, NULL, NULL, NULL);
+ ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss);
msg = NULL;
if (ret) {
wpa_dbg(drv->ctx, MSG_DEBUG,
@@ -10299,8 +10298,7 @@ static int nl80211_join_mesh(struct i802_bss *bss,
if (nl80211_put_mesh_config(msg, ¶ms->conf) < 0)
goto fail;
- ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1,
- NULL, NULL, NULL, NULL);
+ ret = send_and_recv_msgs_connect_handle(drv, msg, bss);
msg = NULL;
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)",
@@ -10357,8 +10355,7 @@ static int wpa_driver_nl80211_leave_mesh(void *priv)
wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex);
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH);
- ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 0,
- NULL, NULL, NULL, NULL);
+ ret = send_and_recv_msgs_connect_handle(drv, msg, bss);
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)",
ret, strerror(-ret));
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 7b9be1f3a9..924064fd76 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -270,7 +270,7 @@ int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
const u8 *addr, int cmd, u16 reason_code,
int local_state_change,
- struct nl_sock *nl_connect);
+ struct i802_bss *bss);
int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv);
void nl80211_remove_monitor_interface(struct wpa_driver_nl80211_data *drv);
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 233175d19b..1316084805 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -870,7 +870,7 @@ static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv,
wpa_driver_nl80211_mlme(drv, addr,
NL80211_CMD_DEAUTHENTICATE,
WLAN_REASON_PREV_AUTH_NOT_VALID, 1,
- get_connect_handle(drv->first_bss));
+ drv->first_bss);
}
}
--
2.28.0
More information about the Hostap
mailing list