diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 63b3fa0f0..38156c32a 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -405,6 +405,41 @@ static void nl80211_nlmsg_clear(struct nl_msg *msg) } +static int send_event_marker(struct wpa_driver_nl80211_data *drv) +{ + struct nl_sock *handle; + struct nl_msg *msg; + struct nlmsghdr *hdr; + int res = 0; + int err = -NLE_NOMEM; + + msg = nlmsg_alloc(); + if (!msg) + goto out; + + /* We only care about the returned sequence number for matching. */ + if (!nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_PROTOCOL_FEATURES)) + goto out; + + handle = (void *) (((intptr_t) drv->global->nl_event) ^ + ELOOP_SOCKET_INVALID); + + err = nl_send_auto_complete(handle, msg); + if (err < 0) + goto out; + + hdr = nlmsg_hdr(msg); + res = hdr->nlmsg_seq; + +out: + nlmsg_free(msg); + if (err) + wpa_printf(MSG_INFO, "nl80211: %s failed: %s", + __func__, nl_geterror(err)); + return res; +} + + static int send_and_recv(struct nl80211_global *global, struct nl_sock *nl_handle, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), @@ -3736,7 +3771,6 @@ static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv, struct i802_bss *bss) { int ret; - int drv_associated = drv->associated; wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code); nl80211_mark_disconnected(drv); @@ -3747,7 +3781,8 @@ static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv, * For locally generated disconnect, supplicant already generates a * DEAUTH event, so ignore the event from NL80211. */ - drv->ignore_next_local_disconnect = drv_associated && (ret == 0); + if (ret == 0) + drv->ignore_next_local_disconnect = send_event_marker(drv); return ret; } @@ -3758,7 +3793,6 @@ static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss, { struct wpa_driver_nl80211_data *drv = bss->drv; int ret; - int drv_associated = drv->associated; if (drv->nlmode == NL80211_IFTYPE_ADHOC) { nl80211_mark_disconnected(drv); @@ -3776,7 +3810,8 @@ static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss, * For locally generated deauthenticate, supplicant already generates a * DEAUTH event, so ignore the event from NL80211. */ - drv->ignore_next_local_deauth = drv_associated && (ret == 0); + if (ret == 0) + drv->ignore_next_local_deauth = send_event_marker(drv); return ret; } @@ -10811,9 +10846,9 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen) drv->retry_auth ? "retry_auth=1\n" : "", drv->use_monitor ? "use_monitor=1\n" : "", drv->ignore_next_local_disconnect ? - "ignore_next_local_disconnect=1\n" : "", + "ignore_next_local_disconnect\n" : "", drv->ignore_next_local_deauth ? - "ignore_next_local_deauth=1\n" : ""); + "ignore_next_local_deauth\n" : ""); if (os_snprintf_error(end - pos, res)) return pos - buf; pos += res; diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index aee8c4512..d41973993 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -165,8 +165,6 @@ struct wpa_driver_nl80211_data { unsigned int scan_for_auth:1; unsigned int retry_auth:1; unsigned int use_monitor:1; - unsigned int ignore_next_local_disconnect:1; - unsigned int ignore_next_local_deauth:1; unsigned int hostapd:1; unsigned int start_mode_sta:1; unsigned int start_iface_up:1; @@ -203,6 +201,9 @@ struct wpa_driver_nl80211_data { unsigned int puncturing:1; unsigned int qca_ap_allowed_freqs:1; + u32 ignore_next_local_disconnect; + u32 ignore_next_local_deauth; + u64 vendor_scan_cookie; u64 remain_on_chan_cookie; u64 send_frame_cookie; diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index b3daf546f..4f477ea5a 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -4066,6 +4066,30 @@ int process_global_event(struct nl_msg *msg, void *arg) int wdev_id_set = 0; int wiphy_idx_set = 0; + /* Event marker, all prior events have been processed */ + if (gnlh->cmd == NL80211_CMD_GET_PROTOCOL_FEATURES) { + u32 seq = nlmsg_hdr(msg)->nlmsg_seq; + + dl_list_for_each_safe(drv, tmp, &global->interfaces, + struct wpa_driver_nl80211_data, list) { + if (drv->ignore_next_local_deauth > 0 && + drv->ignore_next_local_deauth <= seq) { + wpa_printf(MSG_DEBUG, + "nl80211: No DEAUTHENTICATE event was ignored"); + drv->ignore_next_local_deauth = 0; + } + + if (drv->ignore_next_local_disconnect > 0 && + drv->ignore_next_local_disconnect <= seq) { + wpa_printf(MSG_DEBUG, + "nl80211: No DISCONNECT event was ignored"); + drv->ignore_next_local_disconnect = 0; + } + } + + return NL_SKIP; + } + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);