diff options
author | Thomas Haller <thaller@redhat.com> | 2020-04-29 10:50:13 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-04-29 11:27:49 +0200 |
commit | 46c41aac454aa1727b8205c38417e70e1b5acebf (patch) | |
tree | 834b9159c42c98e37d3dfa75d423539751a30f0e | |
parent | e62678c55e41766742ec0254ac70955cf017e97f (diff) | |
download | NetworkManager-th/wifi-scan.tar.gz |
wifi: don't limit active scans for SSIDs to 5th/wifi-scan
As far as NMSupplicantInterface is concerned, don't clamp the
max-scan-ssids to 5. We should track the real value that wpa_supplicant
announces, and it's up to the caller to provide fewer SSIDs.
In particular, we want to limit the number of hidden SSIDs that we
accept from connection profiles, but we don't want to limit the number
of active scans via `nmcli device wifi rescan ssid $SSID [...]`.
-rw-r--r-- | src/devices/wifi/nm-device-wifi.c | 20 | ||||
-rw-r--r-- | src/supplicant/nm-supplicant-interface.c | 62 |
2 files changed, 55 insertions, 27 deletions
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index e145a5c5f5..b9e71d94f1 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -1533,7 +1533,9 @@ _scan_request_ssids_build_hidden (NMDeviceWifi *self, gs_free NMSettingsConnection **connections = NULL; gs_unref_ptrarray GPtrArray *ssids = NULL; gs_unref_hashtable GHashTable *unique_ssids = NULL; - guint i, len; + guint connections_len; + guint n_hidden; + guint i; NM_SET_OUT (out_has_hidden_profiles, FALSE); @@ -1558,7 +1560,7 @@ _scan_request_ssids_build_hidden (NMDeviceWifi *self, } connections = nm_settings_get_connections_clone (nm_device_get_settings ((NMDevice *) self), - &len, + &connections_len, hidden_filter_func, NULL, NULL, @@ -1579,28 +1581,36 @@ _scan_request_ssids_build_hidden (NMDeviceWifi *self, } g_qsort_with_data (connections, - len, + connections_len, sizeof (NMSettingsConnection *), nm_settings_connection_cmp_timestamp_p_with_data, NULL); - for (i = 0; connections[i]; i++) { + n_hidden = 0; + for (i = 0; i < connections_len; i++) { NMSettingWireless *s_wifi; GBytes *ssid; if (ssids->len >= max_scan_ssids) break; + if (n_hidden > 4) { + /* we allow at most 4 hidden profiles to be actively scanned. The + * reason is speed and to not disclose too many SSIDs. */ + break; + } + s_wifi = nm_connection_get_setting_wireless (nm_settings_connection_get_connection (connections[i])); ssid = nm_setting_wireless_get_ssid (s_wifi); if (!g_hash_table_add (unique_ssids, ssid)) continue; - NM_SET_OUT (out_has_hidden_profiles, TRUE); g_ptr_array_add (ssids, g_bytes_ref (ssid)); + n_hidden++; } + NM_SET_OUT (out_has_hidden_profiles, n_hidden > 0); return g_steal_pointer (&ssids); } diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index 700563624a..1c7b9a4213 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -154,6 +154,9 @@ typedef struct _NMSupplicantInterfacePrivate { bool is_ready_main:1; bool is_ready_p2p_device:1; + bool prop_scan_active:1; + bool prop_scan_ssid:1; + } NMSupplicantInterfacePrivate; struct _NMSupplicantInterfaceClass { @@ -1167,10 +1170,11 @@ static void parse_capabilities (NMSupplicantInterface *self, GVariant *capabilities) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - gboolean have_active = FALSE; - gboolean have_ssid = FALSE; + const gboolean old_prop_scan_active = priv->prop_scan_active; + const gboolean old_prop_scan_ssid = priv->prop_scan_ssid; + const guint32 old_max_scan_ssids = priv->max_scan_ssids; gboolean have_ft = FALSE; - gint32 max_scan_ssids = -1; + gint32 max_scan_ssids; const char **array; nm_assert (capabilities && g_variant_is_of_type (capabilities, G_VARIANT_TYPE_VARDICT)); @@ -1195,28 +1199,37 @@ parse_capabilities (NMSupplicantInterface *self, GVariant *capabilities) } if (g_variant_lookup (capabilities, "Scan", "^a&s", &array)) { - if (g_strv_contains (array, "active")) - have_active = TRUE; - if (g_strv_contains (array, "ssid")) - have_ssid = TRUE; + const char **a; + + priv->prop_scan_active = FALSE; + priv->prop_scan_ssid = FALSE; + for (a = array; *a; a++) { + if (nm_streq (*a, "active")) + priv->prop_scan_active = TRUE; + else if (nm_streq (*a, "ssid")) + priv->prop_scan_ssid = TRUE; + } g_free (array); } if (g_variant_lookup (capabilities, "MaxScanSSID", "i", &max_scan_ssids)) { - /* We need active scan and SSID probe capabilities to care about MaxScanSSIDs */ - if ( max_scan_ssids > 0 - && have_active - && have_ssid) { - /* wpa_supplicant's NM_WPAS_MAX_SCAN_SSIDS value is 16, but for speed - * and to ensure we don't disclose too many SSIDs from the hidden - * list, we'll limit to 5. - */ - max_scan_ssids = CLAMP (max_scan_ssids, 0, 5); - if (max_scan_ssids != priv->max_scan_ssids) { - priv->max_scan_ssids = max_scan_ssids; - _LOGD ("supports %d scan SSIDs", priv->max_scan_ssids); - } - } + const gint32 WPAS_MAX_SCAN_SSIDS = 16; + + /* Even if supplicant claims that 20 SSIDs are supported, the Scan request + * still only accepts WPAS_MAX_SCAN_SSIDS SSIDs. Otherwise the D-Bus + * request will be rejected with "fi.w1.wpa_supplicant1.InvalidArgs" + * Body: ('Did not receive correct message arguments.', 'Too many ssids specified. Specify at most four') + * */ + priv->max_scan_ssids = CLAMP (max_scan_ssids, 0, WPAS_MAX_SCAN_SSIDS); + } + + if ( old_max_scan_ssids != priv->max_scan_ssids + || old_prop_scan_active != priv->prop_scan_active + || old_prop_scan_ssid != priv->prop_scan_ssid) { + _LOGD ("supports %u scan SSIDs (scan: %cactive %cssid)", + (guint32) priv->max_scan_ssids, + priv->prop_scan_active ? '+' : '-', + priv->prop_scan_ssid ? '+' : '-'); } } @@ -2514,9 +2527,14 @@ nm_supplicant_interface_get_ifname (NMSupplicantInterface *self) guint nm_supplicant_interface_get_max_scan_ssids (NMSupplicantInterface *self) { + NMSupplicantInterfacePrivate *priv; + g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), 0); - return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->max_scan_ssids; + priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + return priv->prop_scan_active && priv->prop_scan_ssid + ? priv->max_scan_ssids + : 0u; } /*****************************************************************************/ |