summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiří Klimeš <jklimes@redhat.com>2015-09-30 17:05:40 +0200
committerJiří Klimeš <jklimes@redhat.com>2015-10-01 12:08:14 +0200
commiteff10c60e007745e52b0f00dbc9ef08323f9a92f (patch)
tree6c2090fd06faafec12401dd4395546a7bde78605
parent192b92bb0e83c4ced7e9e0f4e1ca16367b103417 (diff)
downloadNetworkManager-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.c60
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 ();