]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Set default scan IEs to the driver (QCA vendor extension)
authorvamsi krishna <vamsin@qti.qualcomm.com>
Tue, 19 Jul 2016 07:11:15 +0000 (12:41 +0530)
committerJouni Malinen <j@w1.fi>
Tue, 2 Aug 2016 18:21:52 +0000 (21:21 +0300)
This makes wpa_supplicant set default scan IEs to the driver (if the
vendor command is supported). The driver can use these IEs in the scan
requests initiated by the driver itself. Also the driver can merge these
IEs into further scan requests that it receives, in case if the scan
request doesn't carry any of the IEs sent in this command.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/drivers/driver.h
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211.h
src/drivers/driver_nl80211_capa.c
src/drivers/driver_nl80211_scan.c
wpa_supplicant/driver_i.h
wpa_supplicant/mbo.c
wpa_supplicant/scan.c
wpa_supplicant/scan.h
wpa_supplicant/wpa_supplicant.c

index a85ed325888768941301f7152a5e73cf5ac60451..cf49847774184e09917a395cb097542bdca6c112 100644 (file)
@@ -3603,6 +3603,23 @@ struct wpa_driver_ops {
         * Returns: 0 on success or -1 on failure
         */
        int (*p2p_lo_stop)(void *priv);
+
+       /**
+        * set_default_scan_ies - Set default scan IEs
+        * @priv: Private driver interface data
+        * @ies: Scan default IEs buffer
+        * @ies_len: Length of IEs in bytes
+        * Returns: 0 on success or -1 on failure
+        *
+        * The driver can use these by default when there are no scan IEs coming
+        * in the subsequent scan requests. Also in case of one or more of IEs
+        * given in set_default_scan_ies() are missing in the subsequent scan
+        * request, the driver should merge the missing scan IEs in the scan
+        * request from the IEs set by set_default_scan_ies() in the Probe
+        * Request frames sent.
+        */
+       int (*set_default_scan_ies)(void *priv, const u8 *ies, size_t ies_len);
+
 };
 
 
index ae40f427b0d67cdb32800d125b3fb21c9d3496ac..7743bd521fb5f7d929bd3d695763be181d09e574 100644 (file)
@@ -9469,6 +9469,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .set_prob_oper_freq = nl80211_set_prob_oper_freq,
        .p2p_lo_start = nl80211_p2p_lo_start,
        .p2p_lo_stop = nl80211_p2p_lo_stop,
+       .set_default_scan_ies = nl80211_set_default_scan_ies,
 #endif /* CONFIG_DRIVER_NL80211_QCA */
        .configure_data_frame_filters = nl80211_configure_data_frame_filters,
        .get_ext_capab = nl80211_get_ext_capab,
index 283dfd99b432abd0325c2eb640db5a03df4ace9a..d0ec48c9f9734d0548e5f9cb2cd06d5be7fb46d6 100644 (file)
@@ -159,6 +159,7 @@ struct wpa_driver_nl80211_data {
        unsigned int set_prob_oper_freq:1;
        unsigned int scan_vendor_cmd_avail:1;
        unsigned int connect_reassoc:1;
+       unsigned int set_wifi_conf_vendor_cmd_avail:1;
 
        u64 vendor_scan_cookie;
        u64 remain_on_chan_cookie;
@@ -301,5 +302,6 @@ void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv);
 int wpa_driver_nl80211_abort_scan(void *priv);
 int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
                                   struct wpa_driver_scan_params *params);
+int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);
 
 #endif /* DRIVER_NL80211_H */
index 1134886adb07646157879b393e93669399a467d5..df10c21dc09c7e144230ffda5d7c97c87c559240 100644 (file)
@@ -709,6 +709,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
                                case QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN:
                                        drv->scan_vendor_cmd_avail = 1;
                                        break;
+                               case QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION:
+                                       drv->set_wifi_conf_vendor_cmd_avail = 1;
+                                       break;
 #endif /* CONFIG_DRIVER_NL80211_QCA */
                                }
                        }
index c0898914624c911bd1ec0f0aa10a30d6fed1d37b..c115b6b31b7dc4b1f5ae9e5b82289e7a6926be41 100644 (file)
@@ -1070,4 +1070,54 @@ fail:
        return ret;
 }
 
+
+/**
+ * nl80211_set_default_scan_ies - Set the scan default IEs to the driver
+ * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
+ * @ies: Pointer to IEs buffer
+ * @ies_len: Length of IEs in bytes
+ * Returns: 0 on success, -1 on failure
+ */
+int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len)
+{
+       struct i802_bss *bss = priv;
+       struct wpa_driver_nl80211_data *drv = bss->drv;
+       struct nl_msg *msg = NULL;
+       struct nlattr *attr;
+       int ret = -1;
+
+       if (!drv->set_wifi_conf_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_SET_WIFI_CONFIGURATION))
+               goto fail;
+
+       attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+       if (attr == NULL)
+               goto fail;
+
+       wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan default IEs", ies, ies_len);
+       if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES,
+                   ies_len, ies))
+               goto fail;
+
+       nla_nest_end(msg, attr);
+
+       ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+       msg = NULL;
+       if (ret) {
+               wpa_printf(MSG_ERROR,
+                          "nl80211: Set scan default IEs failed: ret=%d (%s)",
+                          ret, strerror(-ret));
+               goto fail;
+       }
+
+fail:
+       nlmsg_free(msg);
+       return ret;
+}
+
 #endif /* CONFIG_DRIVER_NL80211_QCA */
index 396a0dc20103c95f20272acece08f1594fe15263..7a16b7aa39c1163863179ed3d5b3912ea4b5c4cd 100644 (file)
@@ -969,4 +969,12 @@ static inline int wpa_drv_p2p_lo_stop(struct wpa_supplicant *wpa_s)
        return wpa_s->driver->p2p_lo_stop(wpa_s->drv_priv);
 }
 
+static inline int wpa_drv_set_default_scan_ies(struct wpa_supplicant *wpa_s,
+                                              const u8 *ies, size_t len)
+{
+       if (!wpa_s->driver->set_default_scan_ies)
+               return -1;
+       return wpa_s->driver->set_default_scan_ies(wpa_s->drv_priv, ies, len);
+}
+
 #endif /* DRIVER_I_H */
index 5b5c3e65ff32f35cc50a90171dc347c3f529f31c..91667b07bb1590f84efcc83310dde976a00b07a0 100644 (file)
@@ -18,6 +18,7 @@
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
 #include "bss.h"
+#include "scan.h"
 
 /* type + length + oui + oui type */
 #define MBO_IE_HEADER 6
@@ -810,4 +811,5 @@ void wpas_mbo_update_cell_capa(struct wpa_supplicant *wpa_s, u8 mbo_cell_capa)
        cell_capa[6] = mbo_cell_capa;
 
        wpas_mbo_send_wnm_notification(wpa_s, cell_capa, 7);
+       wpa_supplicant_set_default_scan_ies(wpa_s);
 }
index 119da28d00b4cd3469718e4ad45128603290251c..371c16a3e5c0b897e09d79028bba24da18050170 100644 (file)
@@ -426,6 +426,39 @@ static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s,
 #endif /* CONFIG_INTERWORKING */
 
 
+void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
+{
+       struct wpabuf *default_ies = NULL;
+       u8 ext_capab[18];
+       int ext_capab_len;
+       enum wpa_driver_if_type type = WPA_IF_STATION;
+
+#ifdef CONFIG_P2P
+       if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
+               type = WPA_IF_P2P_CLIENT;
+#endif /* CONFIG_P2P */
+
+       wpa_drv_get_ext_capa(wpa_s, type);
+
+       ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
+                                            sizeof(ext_capab));
+       if (ext_capab_len > 0 &&
+           wpabuf_resize(&default_ies, ext_capab_len) == 0)
+               wpabuf_put_data(default_ies, ext_capab, ext_capab_len);
+
+#ifdef CONFIG_MBO
+       /* Send cellular capabilities for potential MBO STAs */
+       if (wpabuf_resize(&default_ies, 9) == 0)
+               wpas_mbo_scan_ie(wpa_s, default_ies);
+#endif /* CONFIG_MBO */
+
+       if (default_ies)
+               wpa_drv_set_default_scan_ies(wpa_s, wpabuf_head(default_ies),
+                                            wpabuf_len(default_ies));
+       wpabuf_free(default_ies);
+}
+
+
 static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
 {
        struct wpabuf *extra_ie = NULL;
index 9f8d04e76c96152f372acfdf14fadfef0957420f..b2bb386b1ffa60e151a45c17682d400713fcb504 100644 (file)
@@ -56,5 +56,6 @@ void filter_scan_res(struct wpa_supplicant *wpa_s,
 void scan_snr(struct wpa_scan_res *res);
 void scan_est_throughput(struct wpa_supplicant *wpa_s,
                         struct wpa_scan_res *res);
+void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s);
 
 #endif /* SCAN_H */
index 7ed7efa4a141afa6f67124ce085af9d6c3374450..91e3a918bcfc79cfc858da5824c46ed74c15cc62 100644 (file)
@@ -4875,6 +4875,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
        wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
 #endif /* CONFIG_MBO */
 
+       wpa_supplicant_set_default_scan_ies(wpa_s);
+
        return 0;
 }