nl80211: Use process_bss_event() for the nl_connect handler
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 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 frame 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@intel.com>
This commit is contained in:
parent
f7835ac163
commit
ab89291928
3 changed files with 39 additions and 34 deletions
|
@ -531,6 +531,22 @@ 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,
|
||||||
|
int set_owner)
|
||||||
|
{
|
||||||
|
struct nl_sock *nl_connect = get_connect_handle(bss);
|
||||||
|
|
||||||
|
if (nl_connect)
|
||||||
|
return send_and_recv_msgs_owner(drv, msg, nl_connect, set_owner,
|
||||||
|
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)
|
struct nl_sock * get_connect_handle(struct i802_bss *bss)
|
||||||
{
|
{
|
||||||
if ((bss->drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) ||
|
if ((bss->drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) ||
|
||||||
|
@ -3542,10 +3558,11 @@ static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params,
|
||||||
int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
|
int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
|
||||||
const u8 *addr, int cmd, u16 reason_code,
|
const u8 *addr, int cmd, u16 reason_code,
|
||||||
int local_state_change,
|
int local_state_change,
|
||||||
struct nl_sock *nl_connect)
|
struct i802_bss *bss)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
|
struct nl_sock *nl_connect = get_connect_handle(bss);
|
||||||
|
|
||||||
if (!(msg = nl80211_drv_msg(drv, 0, cmd)) ||
|
if (!(msg = nl80211_drv_msg(drv, 0, cmd)) ||
|
||||||
nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code) ||
|
nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code) ||
|
||||||
|
@ -3557,8 +3574,8 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nl_connect)
|
if (nl_connect)
|
||||||
ret = send_and_recv(drv->global, nl_connect, msg, NULL, NULL,
|
ret = send_and_recv(drv->global, nl_connect, msg,
|
||||||
NULL, NULL);
|
process_bss_event, bss, NULL, NULL);
|
||||||
else
|
else
|
||||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -3572,7 +3589,7 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
|
||||||
|
|
||||||
static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
|
static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
|
||||||
u16 reason_code,
|
u16 reason_code,
|
||||||
struct nl_sock *nl_connect)
|
struct i802_bss *bss)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int drv_associated = drv->associated;
|
int drv_associated = drv->associated;
|
||||||
|
@ -3581,7 +3598,7 @@ static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
|
||||||
nl80211_mark_disconnected(drv);
|
nl80211_mark_disconnected(drv);
|
||||||
/* Disconnect command doesn't need BSSID - it uses cached value */
|
/* Disconnect command doesn't need BSSID - it uses cached value */
|
||||||
ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
|
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
|
* For locally generated disconnect, supplicant already generates a
|
||||||
* DEAUTH event, so ignore the event from NL80211.
|
* DEAUTH event, so ignore the event from NL80211.
|
||||||
|
@ -3604,14 +3621,13 @@ static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
|
||||||
return nl80211_leave_ibss(drv, 1);
|
return nl80211_leave_ibss(drv, 1);
|
||||||
}
|
}
|
||||||
if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
|
if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
|
||||||
return wpa_driver_nl80211_disconnect(drv, reason_code,
|
return wpa_driver_nl80211_disconnect(drv, reason_code, bss);
|
||||||
get_connect_handle(bss));
|
|
||||||
}
|
}
|
||||||
wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
|
wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
|
||||||
__func__, MAC2STR(addr), reason_code);
|
__func__, MAC2STR(addr), reason_code);
|
||||||
nl80211_mark_disconnected(drv);
|
nl80211_mark_disconnected(drv);
|
||||||
ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
|
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
|
* For locally generated deauthenticate, supplicant already generates a
|
||||||
* DEAUTH event, so ignore the event from NL80211.
|
* DEAUTH event, so ignore the event from NL80211.
|
||||||
|
@ -4760,8 +4776,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
|
||||||
goto fail;
|
goto fail;
|
||||||
#endif /* CONFIG_FILS */
|
#endif /* CONFIG_FILS */
|
||||||
|
|
||||||
ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1,
|
ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
|
||||||
NULL, NULL, NULL, NULL);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
|
wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
|
||||||
ret, strerror(-ret));
|
ret, strerror(-ret));
|
||||||
|
@ -5815,9 +5830,7 @@ static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS);
|
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS);
|
||||||
ret = send_and_recv_msgs_owner(drv, msg,
|
ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1);
|
||||||
get_connect_handle(drv->first_bss), 1,
|
|
||||||
NULL, NULL, NULL, NULL);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
|
wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
|
||||||
"(%s)", ret, strerror(-ret));
|
"(%s)", ret, strerror(-ret));
|
||||||
|
@ -5949,9 +5962,7 @@ retry:
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ret = send_and_recv_msgs_owner(drv, msg,
|
ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1);
|
||||||
get_connect_handle(drv->first_bss), 1,
|
|
||||||
NULL, NULL, NULL, NULL);
|
|
||||||
msg = NULL;
|
msg = NULL;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
|
wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
|
||||||
|
@ -6287,7 +6298,7 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
|
||||||
static int wpa_driver_nl80211_try_connect(
|
static int wpa_driver_nl80211_try_connect(
|
||||||
struct wpa_driver_nl80211_data *drv,
|
struct wpa_driver_nl80211_data *drv,
|
||||||
struct wpa_driver_associate_params *params,
|
struct wpa_driver_associate_params *params,
|
||||||
struct nl_sock *nl_connect)
|
struct i802_bss *bss)
|
||||||
{
|
{
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
enum nl80211_auth_type type;
|
enum nl80211_auth_type type;
|
||||||
|
@ -6359,8 +6370,7 @@ skip_auth_type:
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ret = send_and_recv_msgs_owner(drv, msg, nl_connect, 1, NULL,
|
ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
|
||||||
NULL, NULL, NULL);
|
|
||||||
msg = NULL;
|
msg = NULL;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
|
wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
|
||||||
|
@ -6384,7 +6394,7 @@ fail:
|
||||||
static int wpa_driver_nl80211_connect(
|
static int wpa_driver_nl80211_connect(
|
||||||
struct wpa_driver_nl80211_data *drv,
|
struct wpa_driver_nl80211_data *drv,
|
||||||
struct wpa_driver_associate_params *params,
|
struct wpa_driver_associate_params *params,
|
||||||
struct nl_sock *nl_connect)
|
struct i802_bss *bss)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -6394,7 +6404,7 @@ static int wpa_driver_nl80211_connect(
|
||||||
else
|
else
|
||||||
os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
|
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) {
|
if (ret == -EALREADY) {
|
||||||
/*
|
/*
|
||||||
* cfg80211 does not currently accept new connections if
|
* cfg80211 does not currently accept new connections if
|
||||||
|
@ -6405,9 +6415,9 @@ static int wpa_driver_nl80211_connect(
|
||||||
"disconnecting before reassociation "
|
"disconnecting before reassociation "
|
||||||
"attempt");
|
"attempt");
|
||||||
if (wpa_driver_nl80211_disconnect(
|
if (wpa_driver_nl80211_disconnect(
|
||||||
drv, WLAN_REASON_PREV_AUTH_NOT_VALID, nl_connect))
|
drv, WLAN_REASON_PREV_AUTH_NOT_VALID, bss))
|
||||||
return -1;
|
return -1;
|
||||||
ret = wpa_driver_nl80211_try_connect(drv, params, nl_connect);
|
ret = wpa_driver_nl80211_try_connect(drv, params, bss);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -6441,8 +6451,7 @@ static int wpa_driver_nl80211_associate(
|
||||||
else
|
else
|
||||||
bss->use_nl_connect = 0;
|
bss->use_nl_connect = 0;
|
||||||
|
|
||||||
return wpa_driver_nl80211_connect(drv, params,
|
return wpa_driver_nl80211_connect(drv, params, bss);
|
||||||
get_connect_handle(bss));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nl80211_mark_disconnected(drv);
|
nl80211_mark_disconnected(drv);
|
||||||
|
@ -6477,9 +6486,7 @@ static int wpa_driver_nl80211_associate(
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = send_and_recv_msgs_owner(drv, msg,
|
ret = send_and_recv_msgs_connect_handle(drv, msg, drv->first_bss, 1);
|
||||||
get_connect_handle(drv->first_bss), 1,
|
|
||||||
NULL, NULL, NULL, NULL);
|
|
||||||
msg = NULL;
|
msg = NULL;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG,
|
wpa_dbg(drv->ctx, MSG_DEBUG,
|
||||||
|
@ -10462,8 +10469,7 @@ static int nl80211_join_mesh(struct i802_bss *bss,
|
||||||
if (nl80211_put_mesh_config(msg, ¶ms->conf) < 0)
|
if (nl80211_put_mesh_config(msg, ¶ms->conf) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1,
|
ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
|
||||||
NULL, NULL, NULL, NULL);
|
|
||||||
msg = NULL;
|
msg = NULL;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)",
|
wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)",
|
||||||
|
@ -10520,8 +10526,7 @@ static int wpa_driver_nl80211_leave_mesh(void *priv)
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex);
|
wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex);
|
||||||
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH);
|
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH);
|
||||||
ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 0,
|
ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 0);
|
||||||
NULL, NULL, NULL, NULL);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)",
|
wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)",
|
||||||
ret, strerror(-ret));
|
ret, strerror(-ret));
|
||||||
|
|
|
@ -274,7 +274,7 @@ int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
|
||||||
int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
|
int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
|
||||||
const u8 *addr, int cmd, u16 reason_code,
|
const u8 *addr, int cmd, u16 reason_code,
|
||||||
int local_state_change,
|
int local_state_change,
|
||||||
struct nl_sock *nl_connect);
|
struct i802_bss *bss);
|
||||||
|
|
||||||
int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv);
|
int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv);
|
||||||
void nl80211_remove_monitor_interface(struct wpa_driver_nl80211_data *drv);
|
void nl80211_remove_monitor_interface(struct wpa_driver_nl80211_data *drv);
|
||||||
|
|
|
@ -870,7 +870,7 @@ static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv,
|
||||||
wpa_driver_nl80211_mlme(drv, addr,
|
wpa_driver_nl80211_mlme(drv, addr,
|
||||||
NL80211_CMD_DEAUTHENTICATE,
|
NL80211_CMD_DEAUTHENTICATE,
|
||||||
WLAN_REASON_PREV_AUTH_NOT_VALID, 1,
|
WLAN_REASON_PREV_AUTH_NOT_VALID, 1,
|
||||||
get_connect_handle(drv->first_bss));
|
drv->first_bss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue