aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/drivers/driver.h9
-rw-r--r--src/drivers/driver_nl80211.c62
-rw-r--r--src/drivers/driver_nl80211.h1
-rw-r--r--src/drivers/driver_nl80211_capa.c3
-rw-r--r--wpa_supplicant/driver_i.h10
-rw-r--r--wpa_supplicant/mbo.c3
-rw-r--r--wpa_supplicant/wpa_supplicant.c70
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h1
8 files changed, 139 insertions, 20 deletions
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index aee0cf6..455e7df 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -3966,6 +3966,15 @@ struct wpa_driver_ops {
* Returns: 0 on success, -1 on failure
*/
int (*ignore_assoc_disallow)(void *priv, int ignore_disallow);
+
+ /**
+ * set_bssid_blacklist - Set blacklist of BSSIDs to the driver
+ * @priv: Private driver interface data
+ * @num_bssid: Number of blacklist BSSIDs
+ * @bssids: List of blacklisted BSSIDs
+ */
+ int (*set_bssid_blacklist)(void *priv, unsigned int num_bssid,
+ const u8 *bssid);
};
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index d18cdeb..40889ce 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -8814,6 +8814,67 @@ static int nl80211_roaming(void *priv, int allowed, const u8 *bssid)
return send_and_recv_msgs(drv, msg, NULL, NULL);
}
+
+
+/* Reserved QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID value for wpa_supplicant */
+#define WPA_SUPPLICANT_CLIENT_ID 1
+
+static int nl80211_set_bssid_blacklist(void *priv, unsigned int num_bssid,
+ const u8 *bssid)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *params, *nlbssids, *attr;
+ unsigned int i;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Set blacklist BSSID (num=%u)",
+ num_bssid);
+
+ if (!drv->roam_vendor_cmd_avail)
+ return -1;
+
+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+ QCA_NL80211_VENDOR_SUBCMD_ROAM) ||
+ !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
+ QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID) ||
+ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID,
+ WPA_SUPPLICANT_CLIENT_ID) ||
+ nla_put_u32(msg,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID,
+ num_bssid))
+ goto fail;
+
+ nlbssids = nla_nest_start(
+ msg, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS);
+ if (!nlbssids)
+ goto fail;
+
+ for (i = 0; i < num_bssid; i++) {
+ attr = nla_nest_start(msg, i);
+ if (!attr)
+ goto fail;
+ if (nla_put(msg,
+ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID,
+ ETH_ALEN, &bssid[i * ETH_ALEN]))
+ goto fail;
+ wpa_printf(MSG_DEBUG, "nl80211: BSSID[%u]: " MACSTR, i,
+ MAC2STR(&bssid[i * ETH_ALEN]));
+ nla_nest_end(msg, attr);
+ }
+ nla_nest_end(msg, nlbssids);
+ nla_nest_end(msg, params);
+
+ return send_and_recv_msgs(drv, msg, NULL, NULL);
+
+fail:
+ nlmsg_free(msg);
+ return -1;
+}
+
#endif /* CONFIG_DRIVER_NL80211_QCA */
@@ -10282,6 +10343,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.get_bss_transition_status = nl80211_get_bss_transition_status,
.ignore_assoc_disallow = nl80211_ignore_assoc_disallow,
#endif /* CONFIG_MBO */
+ .set_bssid_blacklist = nl80211_set_bssid_blacklist,
#endif /* CONFIG_DRIVER_NL80211_QCA */
.configure_data_frame_filters = nl80211_configure_data_frame_filters,
.get_ext_capab = nl80211_get_ext_capab,
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 3eaccaa..23cf9db 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -163,6 +163,7 @@ struct wpa_driver_nl80211_data {
unsigned int set_wifi_conf_vendor_cmd_avail:1;
unsigned int he_capab_vendor_cmd_avail:1;
unsigned int fetch_bss_trans_status:1;
+ unsigned int roam_vendor_cmd_avail:1;
u64 vendor_scan_cookie;
u64 remain_on_chan_cookie;
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 3d747ce..c1423bd 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -752,6 +752,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
case QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS:
drv->fetch_bss_trans_status = 1;
break;
+ case QCA_NL80211_VENDOR_SUBCMD_ROAM:
+ drv->roam_vendor_cmd_avail = 1;
+ break;
#endif /* CONFIG_DRIVER_NL80211_QCA */
}
}
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index fa2296b..60628db 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -1007,4 +1007,14 @@ static inline int wpa_drv_ignore_assoc_disallow(struct wpa_supplicant *wpa_s,
return wpa_s->driver->ignore_assoc_disallow(wpa_s->drv_priv, val);
}
+static inline int wpa_drv_set_bssid_blacklist(struct wpa_supplicant *wpa_s,
+ unsigned int num_bssid,
+ const u8 *bssids)
+{
+ if (!wpa_s->driver->set_bssid_blacklist)
+ return -1;
+ return wpa_s->driver->set_bssid_blacklist(wpa_s->drv_priv, num_bssid,
+ bssids);
+}
+
#endif /* DRIVER_I_H */
diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c
index 138b405..4bf227d 100644
--- a/wpa_supplicant/mbo.c
+++ b/wpa_supplicant/mbo.c
@@ -432,6 +432,9 @@ void wpas_mbo_ie_trans_req(struct wpa_supplicant *wpa_s, const u8 *mbo_ie,
} else if (wpa_s->wnm_mode &
WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
disallowed_sec = WPA_GET_LE16(pos);
+ wpa_printf(MSG_DEBUG,
+ "MBO: Association retry delay: %u",
+ disallowed_sec);
} else {
wpa_printf(MSG_DEBUG,
"MBO: Association retry delay attribute not in disassoc imminent mode");
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index f599c7e..08168d3 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -114,6 +114,10 @@ const char *const wpa_supplicant_full_license5 =
"\n";
#endif /* CONFIG_NO_STDOUT_DEBUG */
+
+static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
+
+
/* Configure default/group WEP keys for static WEP */
int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
{
@@ -416,6 +420,7 @@ static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
struct wpa_bss_tmp_disallowed, list) {
+ eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
dl_list_del(&bss->list);
os_free(bss);
}
@@ -6706,18 +6711,56 @@ wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
}
+static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_bss_tmp_disallowed *tmp;
+ unsigned int num_bssid = 0;
+ u8 *bssids;
+ int ret;
+
+ bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN);
+ if (!bssids)
+ return -1;
+ dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid,
+ ETH_ALEN);
+ num_bssid++;
+ }
+ ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids);
+ os_free(bssids);
+ return ret;
+}
+
+
+static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx;
+
+ /* Make sure the bss is not already freed */
+ dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ if (bss == tmp) {
+ dl_list_del(&tmp->list);
+ os_free(tmp);
+ wpa_set_driver_tmp_disallow_list(wpa_s);
+ break;
+ }
+ }
+}
+
+
void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
unsigned int sec)
{
struct wpa_bss_tmp_disallowed *bss;
- struct os_reltime until;
-
- os_get_reltime(&until);
- until.sec += sec;
bss = wpas_get_disallowed_bss(wpa_s, bssid);
if (bss) {
- bss->disallowed_until = until;
+ eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss);
+ eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
+ wpa_s, bss);
return;
}
@@ -6728,27 +6771,20 @@ void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
return;
}
- bss->disallowed_until = until;
os_memcpy(bss->bssid, bssid, ETH_ALEN);
dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
+ wpa_set_driver_tmp_disallow_list(wpa_s);
+ eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout,
+ wpa_s, bss);
}
int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
{
struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
- struct os_reltime now, age;
-
- os_get_reltime(&now);
dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
struct wpa_bss_tmp_disallowed, list) {
- if (!os_reltime_before(&now, &tmp->disallowed_until)) {
- /* This BSS is not disallowed anymore */
- dl_list_del(&tmp->list);
- os_free(tmp);
- continue;
- }
if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
bss = tmp;
break;
@@ -6757,9 +6793,5 @@ int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
if (!bss)
return 0;
- os_reltime_sub(&bss->disallowed_until, &now, &age);
- wpa_printf(MSG_DEBUG,
- "BSS " MACSTR " disabled for %ld.%0ld seconds",
- MAC2STR(bss->bssid), age.sec, age.usec);
return 1;
}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 156f800..02acb56 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -447,7 +447,6 @@ struct icon_entry {
struct wpa_bss_tmp_disallowed {
struct dl_list list;
u8 bssid[ETH_ALEN];
- struct os_reltime disallowed_until;
};
struct beacon_rep_data {