summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-04-29 10:50:13 +0200
committerThomas Haller <thaller@redhat.com>2020-04-29 11:27:49 +0200
commit46c41aac454aa1727b8205c38417e70e1b5acebf (patch)
tree834b9159c42c98e37d3dfa75d423539751a30f0e
parente62678c55e41766742ec0254ac70955cf017e97f (diff)
downloadNetworkManager-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.c20
-rw-r--r--src/supplicant/nm-supplicant-interface.c62
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;
}
/*****************************************************************************/