diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 46c96accd..339d8198c 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -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; diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 31643a858..8743d5668 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -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) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 08e70e57a..0a9e37c3b 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -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; +} diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 422f2cb24..b8313f935 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -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 */