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 12:23:01 +0200
commitc9ae23af5e1fdf85e3fc34b29440b4de1d67a2ab (patch)
tree26de40a8b727f90ea93e2c60f432ef81297ac324
parente07fc217ecd7ac3afec4060ea8edffbca0ceac67 (diff)
downloadNetworkManager-c9ae23af5e1fdf85e3fc34b29440b4de1d67a2ab.tar.gz
wifi: don't limit active scans for SSIDs to 5
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;
}
/*****************************************************************************/