[PATCH v2 2/2] nl80211: use the process_bss_event for the nl_connect handler
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Wed Feb 17 05:14:33 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 | 68 ++++++++++++++++---------------
src/drivers/driver_nl80211.h | 2 +-
src/drivers/driver_nl80211_scan.c | 2 +-
3 files changed, 38 insertions(+), 34 deletions(-)
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 6fb085446f..d8a911a6a4 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) ||
@@ -3541,10 +3556,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) ||
@@ -3556,8 +3572,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) {
@@ -3571,7 +3587,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;
@@ -3580,7 +3596,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.
@@ -3603,14 +3619,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.
@@ -4759,8 +4774,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
goto fail;
#endif /* CONFIG_FILS */
- 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));
@@ -5814,9 +5828,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));
@@ -5948,9 +5960,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)",
@@ -6286,7 +6296,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;
@@ -6358,8 +6368,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 "
@@ -6383,7 +6392,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;
@@ -6393,7 +6402,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
@@ -6404,9 +6413,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;
}
@@ -6440,8 +6449,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);
@@ -6476,9 +6484,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,
@@ -10461,8 +10467,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)",
@@ -10519,8 +10524,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 940d82c87b..7b0caa2782 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -272,7 +272,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