]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Test functionality to override driver reported signal levels
authorJouni Malinen <j@w1.fi>
Thu, 2 Jan 2020 18:29:24 +0000 (20:29 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 2 Jan 2020 18:34:39 +0000 (20:34 +0200)
"SET driver_signal_override <BSSID> [<si_signal< <si_avg_signal>
<si_avg_beacon_signal> <si_noise> <scan_level>]" command can now be used
to request wpa_supplicant to override driver reported signal levels for
signal_poll and scan results. This can be used to test roaming behavior.

Signed-off-by: Jouni Malinen <j@w1.fi>
wpa_supplicant/ctrl_iface.c
wpa_supplicant/driver_i.h
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 46c96accdfb87b29a5a0f882683bff64ab1b1048..339d8198c49cf10d60f16f402a6e2681982876c8 100644 (file)
@@ -419,6 +419,64 @@ static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s,
 }
 
 
+#ifdef CONFIG_TESTING_OPTIONS
+static int wpas_ctrl_iface_set_dso(struct wpa_supplicant *wpa_s,
+                                  const char *val)
+{
+       u8 bssid[ETH_ALEN];
+       const char *pos = val;
+       struct driver_signal_override *dso = NULL, *tmp, parsed;
+
+       if (hwaddr_aton(pos, bssid))
+               return -1;
+       pos = os_strchr(pos, ' ');
+
+       dl_list_for_each(tmp, &wpa_s->drv_signal_override,
+                        struct driver_signal_override, list) {
+               if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
+                       dso = tmp;
+                       break;
+               }
+       }
+
+       if (!pos) {
+               /* Remove existing entry */
+               if (dso) {
+                       dl_list_del(&dso->list);
+                       os_free(dso);
+               }
+               return 0;
+       }
+       pos++;
+
+       /* Update an existing entry or add a new one */
+       os_memset(&parsed, 0, sizeof(parsed));
+       if (sscanf(pos, "%d %d %d %d %d",
+                  &parsed.si_current_signal,
+                  &parsed.si_avg_signal,
+                  &parsed.si_avg_beacon_signal,
+                  &parsed.si_current_noise,
+                  &parsed.scan_level) != 5)
+               return -1;
+
+       if (!dso) {
+               dso = os_zalloc(sizeof(*dso));
+               if (!dso)
+                       return -1;
+               os_memcpy(dso->bssid, bssid, ETH_ALEN);
+               dl_list_add(&wpa_s->drv_signal_override, &dso->list);
+       }
+       dso->si_current_signal = parsed.si_current_signal;
+       dso->si_avg_signal = parsed.si_avg_signal;
+       dso->si_avg_beacon_signal = parsed.si_avg_beacon_signal;
+       dso->si_current_noise = parsed.si_current_noise;
+       dso->scan_level = parsed.scan_level;
+
+       return 0;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
                                         char *cmd)
 {
@@ -713,6 +771,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
                        wpa_s->sae_commit_override = NULL;
                else
                        wpa_s->sae_commit_override = wpabuf_parse_bin(value);
+       } else if (os_strcasecmp(cmd, "driver_signal_override") == 0) {
+               ret = wpas_ctrl_iface_set_dso(wpa_s, value);
 #ifdef CONFIG_DPP
        } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
                os_free(wpa_s->dpp_config_obj_override);
@@ -8104,6 +8164,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
        wpa_s->rsnxe_override_assoc = NULL;
        wpabuf_free(wpa_s->rsnxe_override_eapol);
        wpa_s->rsnxe_override_eapol = NULL;
+       wpas_clear_driver_signal_override(wpa_s);
 #ifdef CONFIG_DPP
        os_free(wpa_s->dpp_config_obj_override);
        wpa_s->dpp_config_obj_override = NULL;
index 31643a858c510dfa6c8945a75536a1d0d040ee38..8743d566858797c19e050b77ab44647be7f366ad 100644 (file)
@@ -124,13 +124,8 @@ static inline int wpa_drv_stop_sched_scan(struct wpa_supplicant *wpa_s)
        return -1;
 }
 
-static inline struct wpa_scan_results * wpa_drv_get_scan_results2(
-       struct wpa_supplicant *wpa_s)
-{
-       if (wpa_s->driver->get_scan_results2)
-               return wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
-       return NULL;
-}
+struct wpa_scan_results *
+wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s);
 
 static inline int wpa_drv_get_bssid(struct wpa_supplicant *wpa_s, u8 *bssid)
 {
@@ -494,13 +489,8 @@ static inline int wpa_drv_signal_monitor(struct wpa_supplicant *wpa_s,
        return -1;
 }
 
-static inline int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
-                                     struct wpa_signal_info *si)
-{
-       if (wpa_s->driver->signal_poll)
-               return wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
-       return -1;
-}
+int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
+                       struct wpa_signal_info *si);
 
 static inline int wpa_drv_channel_info(struct wpa_supplicant *wpa_s,
                                       struct wpa_channel_info *ci)
index 08e70e57ac5c658567273100819e177a5b615dc5..0a9e37c3b01cd530d86d810d0763eb343cf80cb0 100644 (file)
@@ -487,6 +487,20 @@ void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
 }
 
 
+#ifdef CONFIG_TESTING_OPTIONS
+void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
+{
+       struct driver_signal_override *dso;
+
+       while ((dso = dl_list_first(&wpa_s->drv_signal_override,
+                                   struct driver_signal_override, list))) {
+               dl_list_del(&dso->list);
+               os_free(dso);
+       }
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
 static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
 {
        int i;
@@ -516,6 +530,7 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
        wpa_s->rsnxe_override_assoc = NULL;
        wpabuf_free(wpa_s->rsnxe_override_eapol);
        wpa_s->rsnxe_override_eapol = NULL;
+       wpas_clear_driver_signal_override(wpa_s);
 #endif /* CONFIG_TESTING_OPTIONS */
 
        if (wpa_s->conf != NULL) {
@@ -4802,6 +4817,9 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent)
 
        dl_list_init(&wpa_s->bss_tmp_disallowed);
        dl_list_init(&wpa_s->fils_hlp_req);
+#ifdef CONFIG_TESTING_OPTIONS
+       dl_list_init(&wpa_s->drv_signal_override);
+#endif /* CONFIG_TESTING_OPTIONS */
 
        return wpa_s;
 }
@@ -7884,3 +7902,87 @@ int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
 
        return 0;
 }
+
+
+int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
+                       struct wpa_signal_info *si)
+{
+       int res;
+
+       if (!wpa_s->driver->signal_poll)
+               return -1;
+
+       res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
+
+#ifdef CONFIG_TESTING_OPTIONS
+       if (res == 0) {
+               struct driver_signal_override *dso;
+
+               dl_list_for_each(dso, &wpa_s->drv_signal_override,
+                                struct driver_signal_override, list) {
+                       if (os_memcmp(wpa_s->bssid, dso->bssid,
+                                     ETH_ALEN) != 0)
+                               continue;
+                       wpa_printf(MSG_DEBUG,
+                                  "Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
+                                  si->current_signal,
+                                  dso->si_current_signal,
+                                  si->avg_signal,
+                                  dso->si_avg_signal,
+                                  si->avg_beacon_signal,
+                                  dso->si_avg_beacon_signal,
+                                  si->current_noise,
+                                  dso->si_current_noise);
+                       si->current_signal = dso->si_current_signal;
+                       si->avg_signal = dso->si_avg_signal;
+                       si->avg_beacon_signal = dso->si_avg_beacon_signal;
+                       si->current_noise = dso->si_current_noise;
+                       break;
+               }
+       }
+#endif /* CONFIG_TESTING_OPTIONS */
+
+       return res;
+}
+
+
+struct wpa_scan_results *
+wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
+{
+       struct wpa_scan_results *scan_res;
+#ifdef CONFIG_TESTING_OPTIONS
+       size_t idx;
+#endif /* CONFIG_TESTING_OPTIONS */
+
+       if (!wpa_s->driver->get_scan_results2)
+               return NULL;
+
+       scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
+
+#ifdef CONFIG_TESTING_OPTIONS
+       for (idx = 0; scan_res && idx < scan_res->num; idx++) {
+               struct driver_signal_override *dso;
+               struct wpa_scan_res *res = scan_res->res[idx];
+
+               dl_list_for_each(dso, &wpa_s->drv_signal_override,
+                                struct driver_signal_override, list) {
+                       if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
+                               continue;
+                       wpa_printf(MSG_DEBUG,
+                                  "Override driver scan signal level %d->%d for "
+                                  MACSTR,
+                                  res->level, dso->scan_level,
+                                  MAC2STR(res->bssid));
+                       res->flags |= WPA_SCAN_QUAL_INVALID;
+                       if (dso->scan_level < 0)
+                               res->flags |= WPA_SCAN_LEVEL_DBM;
+                       else
+                               res->flags &= ~WPA_SCAN_LEVEL_DBM;
+                       res->level = dso->scan_level;
+                       break;
+               }
+       }
+#endif /* CONFIG_TESTING_OPTIONS */
+
+       return scan_res;
+}
index 422f2cb2470f796e543daf3400430f68b46e1529..b8313f935fec6a9a0fc295eab449ee45a507a650 100644 (file)
@@ -480,6 +480,16 @@ struct fils_hlp_req {
        struct wpabuf *pkt;
 };
 
+struct driver_signal_override {
+       struct dl_list list;
+       u8 bssid[ETH_ALEN];
+       int si_current_signal;
+       int si_avg_signal;
+       int si_avg_beacon_signal;
+       int si_current_noise;
+       int scan_level;
+};
+
 /**
  * struct wpa_supplicant - Internal data for wpa_supplicant interface
  *
@@ -1132,6 +1142,7 @@ struct wpa_supplicant {
        int *extra_sae_rejected_groups;
        struct wpabuf *rsnxe_override_assoc;
        struct wpabuf *rsnxe_override_eapol;
+       struct dl_list drv_signal_override;
 #endif /* CONFIG_TESTING_OPTIONS */
 
        struct wmm_ac_assoc_data *wmm_ac_assoc_info;
@@ -1570,4 +1581,6 @@ int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
 int wpa_is_fils_supported(struct wpa_supplicant *wpa_s);
 int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s);
 
+void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s);
+
 #endif /* WPA_SUPPLICANT_I_H */