diff options
author | Jiří Klimeš <jklimes@redhat.com> | 2015-09-30 17:05:40 +0200 |
---|---|---|
committer | Jiří Klimeš <jklimes@redhat.com> | 2015-10-01 12:08:14 +0200 |
commit | eff10c60e007745e52b0f00dbc9ef08323f9a92f (patch) | |
tree | 6c2090fd06faafec12401dd4395546a7bde78605 | |
parent | 192b92bb0e83c4ced7e9e0f4e1ca16367b103417 (diff) | |
download | NetworkManager-eff10c60e007745e52b0f00dbc9ef08323f9a92f.tar.gz |
wifi: emit NEW_BSS on ScanDone to update APs in Wi-Fi device (rh #1267327)
When a Wi-Fi is switched to AP mode, NMDeviceWifi forgets the AP scan list.
Later, when the device goes back to normal managed mode, the device was not
able to acquire the AP list again (for a long time), because the list is only
populated when a new BSS is signalled. And that could take very long or never
happen as the supplicant would have to lost the BSS and announce it later.
Fix the problem by announcing known BSSs as a response to ScanDone signal.
Testcase:
$ nmcli con add type wifi ifname wlan0 con-name my-wifi-ap autoconnect off ssid MYSSID
$ nmcli con modify my-wifi-ap wifi.mode ap ipv4.method shared
$ nmcli con up my-wifi-ap
$ nmcli con down my-wifi-ap
$ nmcli device wifi list
https://bugzilla.redhat.com/show_bug.cgi?id=1267327
-rw-r--r-- | src/supplicant-manager/nm-supplicant-interface.c | 60 |
1 files changed, 45 insertions, 15 deletions
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index 7d33db465b..ff58fa5536 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -128,16 +128,36 @@ bss_props_changed_cb (GDBusProxy *proxy, changed_properties); } +static GVariant * +_get_bss_proxy_properties (NMSupplicantInterface *self, GDBusProxy *proxy) +{ + gs_strfreev char **properties = NULL; + GVariantBuilder builder; + char **iter; + + iter = properties = g_dbus_proxy_get_cached_property_names (proxy); + if (!iter) + return NULL; + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + while (*iter) { + GVariant *copy = g_dbus_proxy_get_cached_property (proxy, *iter); + + g_variant_builder_add (&builder, "{sv}", *iter++, copy); + g_variant_unref (copy); + } + + return g_variant_builder_end (&builder); +} + +#define BSS_PROXY_INITED "bss-proxy-inited" + static void on_bss_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data) { NMSupplicantInterface *self; - NMSupplicantInterfacePrivate *priv; gs_free_error GError *error = NULL; - gs_strfreev char **properties = NULL; gs_unref_variant GVariant *props = NULL; - GVariantBuilder builder; - char **iter; if (!g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error)) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { @@ -149,19 +169,12 @@ on_bss_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_da } self = NM_SUPPLICANT_INTERFACE (user_data); - priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); - - iter = properties = g_dbus_proxy_get_cached_property_names (proxy); - while (iter && *iter) { - GVariant *copy = g_dbus_proxy_get_cached_property (proxy, *iter); + props = _get_bss_proxy_properties (self, proxy); + if (!props) + return; - g_variant_builder_add (&builder, "{sv}", *iter++, copy); - g_variant_unref (copy); - } + g_object_set_data (G_OBJECT (proxy), BSS_PROXY_INITED, GUINT_TO_POINTER (TRUE)); - props = g_variant_builder_end (&builder); g_signal_emit (self, signals[NEW_BSS], 0, g_dbus_proxy_get_object_path (proxy), g_variant_ref_sink (props)); @@ -508,11 +521,28 @@ signal_cb (GDBusProxy *proxy, gboolean success; if (MATCH_SIGNAL (signal, "ScanDone", args, G_VARIANT_TYPE ("(b)"))) { + GVariant *props; + GHashTableIter iter; + char *bss_path; + GDBusProxy *bss_proxy; + /* Cache last scan completed time */ priv->last_scan = nm_utils_get_monotonic_timestamp_s (); g_variant_get (args, "(b)", &success); g_signal_emit (self, signals[SCAN_DONE], 0, success); + + /* Emit NEW_BSS so that wifi device has the APs (in case it removed them) */ + g_hash_table_iter_init (&iter, priv->bss_proxies); + while (g_hash_table_iter_next (&iter, (gpointer) &bss_path, (gpointer) &bss_proxy)) { + props = _get_bss_proxy_properties (self, bss_proxy); + if (props && g_object_get_data (G_OBJECT (bss_proxy), BSS_PROXY_INITED) != NULL) { + g_signal_emit (self, signals[NEW_BSS], 0, + bss_path, + g_variant_ref_sink (props)); + g_variant_unref (props); + } + } } else if (MATCH_SIGNAL (signal, "BSSAdded", args, G_VARIANT_TYPE ("(oa{sv})"))) { if (priv->scanning) priv->last_scan = nm_utils_get_monotonic_timestamp_s (); |