aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/driver.h5
-rw-r--r--src/drivers/driver_nl80211.c11
-rw-r--r--src/drivers/driver_nl80211.h7
-rw-r--r--src/drivers/driver_nl80211_event.c64
-rw-r--r--src/drivers/driver_nl80211_scan.c2
5 files changed, 71 insertions, 18 deletions
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 5f3c6ffd..31cb23f1 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -4387,6 +4387,9 @@ union wpa_event_data {
* @ssids: Scanned SSIDs (%NULL or zero-length SSID indicates wildcard
* SSID)
* @num_ssids: Number of entries in ssids array
+ * @external_scan: Whether the scan info is for an external scan
+ * @nl_scan_event: 1 if the source of this scan event is a normal scan,
+ * 0 if the source of the scan event is a vendor scan
*/
struct scan_info {
int aborted;
@@ -4394,6 +4397,8 @@ union wpa_event_data {
size_t num_freqs;
struct wpa_driver_scan_ssid ssids[WPAS_MAX_SCAN_SSIDS];
size_t num_ssids;
+ int external_scan;
+ int nl_scan_event;
} scan_info;
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 9d7d7e57..ded7950f 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -7260,6 +7260,17 @@ static int driver_nl80211_scan2(void *priv,
struct wpa_driver_scan_params *params)
{
struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+
+ /*
+ * Do a vendor specific scan if possible. If only_new_results is
+ * set, do a normal scan since a kernel (cfg80211) BSS cache flush
+ * cannot be achieved through a vendor scan. The below condition may
+ * need to be modified if new scan flags are added in the future whose
+ * functionality can only be achieved through a normal scan.
+ */
+ if (drv->scan_vendor_cmd_avail && !params->only_new_results)
+ return wpa_driver_nl80211_vendor_scan(bss, params);
return wpa_driver_nl80211_scan(bss, params);
}
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index d1cbaeff..e2df8b43 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -187,6 +187,13 @@ struct wpa_driver_nl80211_data {
int auth_wep_tx_keyidx;
int auth_local_state_change;
int auth_p2p;
+
+ /*
+ * Tells whether the last scan issued from wpa_supplicant was a normal
+ * scan (NL80211_CMD_TRIGGER_SCAN) or a vendor scan
+ * (NL80211_CMD_VENDOR). 0 if no pending scan request.
+ */
+ int last_scan_cmd;
};
struct nl_msg;
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 647280c8..5f2811ce 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -968,7 +968,7 @@ static void mlme_event_ft_event(struct wpa_driver_nl80211_data *drv,
static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
- struct nlattr *tb[])
+ struct nlattr *tb[], int external_scan)
{
union wpa_event_data event;
struct nlattr *nl;
@@ -978,7 +978,7 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
int freqs[MAX_REPORT_FREQS];
int num_freqs = 0;
- if (drv->scan_for_auth) {
+ if (!external_scan && drv->scan_for_auth) {
drv->scan_for_auth = 0;
wpa_printf(MSG_DEBUG, "nl80211: Scan results for missing "
"cfg80211 BSS entry");
@@ -989,6 +989,8 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
os_memset(&event, 0, sizeof(event));
info = &event.scan_info;
info->aborted = aborted;
+ info->external_scan = external_scan;
+ info->nl_scan_event = 1;
if (tb[NL80211_ATTR_SCAN_SSIDS]) {
nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) {
@@ -1691,6 +1693,8 @@ static void qca_nl80211_scan_trigger_event(struct wpa_driver_nl80211_data *drv,
{
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1];
u64 cookie = 0;
+ union wpa_event_data event;
+ struct scan_info *info;
if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SCAN_MAX,
(struct nlattr *) data, len, NULL) ||
@@ -1703,13 +1707,20 @@ static void qca_nl80211_scan_trigger_event(struct wpa_driver_nl80211_data *drv,
return;
}
+ /* Cookie match, own scan */
+ os_memset(&event, 0, sizeof(event));
+ info = &event.scan_info;
+ info->external_scan = 0;
+ info->nl_scan_event = 0;
+
drv->scan_state = SCAN_STARTED;
- wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
+ wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, &event);
}
static void send_vendor_scan_event(struct wpa_driver_nl80211_data *drv,
- int aborted, struct nlattr *tb[])
+ int aborted, struct nlattr *tb[],
+ int external_scan)
{
union wpa_event_data event;
struct nlattr *nl;
@@ -1721,6 +1732,7 @@ static void send_vendor_scan_event(struct wpa_driver_nl80211_data *drv,
os_memset(&event, 0, sizeof(event));
info = &event.scan_info;
info->aborted = aborted;
+ info->external_scan = external_scan;
if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS]) {
nla_for_each_nested(nl,
@@ -1774,6 +1786,7 @@ static void qca_nl80211_scan_done_event(struct wpa_driver_nl80211_data *drv,
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1];
u64 cookie = 0;
enum scan_status status;
+ int external_scan;
if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SCAN_MAX,
(struct nlattr *) data, len, NULL) ||
@@ -1788,7 +1801,9 @@ static void qca_nl80211_scan_done_event(struct wpa_driver_nl80211_data *drv,
cookie = nla_get_u64(tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]);
if (cookie != drv->vendor_scan_cookie) {
/* Event from an external scan, get scan results */
+ external_scan = 1;
} else {
+ external_scan = 0;
if (status == VENDOR_SCAN_STATUS_NEW_RESULTS)
drv->scan_state = SCAN_COMPLETED;
else
@@ -1797,9 +1812,11 @@ static void qca_nl80211_scan_done_event(struct wpa_driver_nl80211_data *drv,
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
drv->ctx);
drv->vendor_scan_cookie = 0;
+ drv->last_scan_cmd = 0;
}
- send_vendor_scan_event(drv, (status == VENDOR_SCAN_STATUS_ABORTED), tb);
+ send_vendor_scan_event(drv, (status == VENDOR_SCAN_STATUS_ABORTED), tb,
+ external_scan);
}
@@ -1954,6 +1971,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
{
struct wpa_driver_nl80211_data *drv = bss->drv;
union wpa_event_data data;
+ int external_scan_event = 0;
wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s",
cmd, nl80211_command_to_string(cmd), bss->ifname);
@@ -2006,28 +2024,38 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
case NL80211_CMD_NEW_SCAN_RESULTS:
wpa_dbg(drv->ctx, MSG_DEBUG,
"nl80211: New scan results available");
- drv->scan_state = SCAN_COMPLETED;
drv->scan_complete_events = 1;
- eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
- drv->ctx);
- send_scan_event(drv, 0, tb);
+ if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
+ drv->scan_state = SCAN_COMPLETED;
+ eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
+ drv, drv->ctx);
+ drv->last_scan_cmd = 0;
+ } else {
+ external_scan_event = 1;
+ }
+ send_scan_event(drv, 0, tb, external_scan_event);
break;
case NL80211_CMD_SCHED_SCAN_RESULTS:
wpa_dbg(drv->ctx, MSG_DEBUG,
"nl80211: New sched scan results available");
drv->scan_state = SCHED_SCAN_RESULTS;
- send_scan_event(drv, 0, tb);
+ send_scan_event(drv, 0, tb, 0);
break;
case NL80211_CMD_SCAN_ABORTED:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
- drv->scan_state = SCAN_ABORTED;
- /*
- * Need to indicate that scan results are available in order
- * not to make wpa_supplicant stop its scanning.
- */
- eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
- drv->ctx);
- send_scan_event(drv, 1, tb);
+ if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
+ drv->scan_state = SCAN_ABORTED;
+ /*
+ * Need to indicate that scan results are available in
+ * order not to make wpa_supplicant stop its scanning.
+ */
+ eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
+ drv, drv->ctx);
+ drv->last_scan_cmd = 0;
+ } else {
+ external_scan_event = 1;
+ }
+ send_scan_event(drv, 1, tb, external_scan_event);
break;
case NL80211_CMD_AUTHENTICATE:
case NL80211_CMD_ASSOCIATE:
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 99e12e74..a8ce7ea8 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -295,6 +295,7 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
drv, drv->ctx);
+ drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN;
fail:
nlmsg_free(msg);
@@ -979,6 +980,7 @@ int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
eloop_register_timeout(30, 0, wpa_driver_nl80211_scan_timeout,
drv, drv->ctx);
+ drv->last_scan_cmd = NL80211_CMD_VENDOR;
fail:
nlmsg_free(msg);