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-02 09:45:15 +0200
commit956577a24640cb96f6255417073d52230c573ed4 (patch)
tree1fb4f8373abee176d7947ced0fd9075bc81af29c
parent984714333ffa3e23ee0e0c48e1244feb631362b2 (diff)
downloadNetworkManager-956577a24640cb96f6255417073d52230c573ed4.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.c61
1 files changed, 46 insertions, 15 deletions
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c
index 2e5d073fb1..38eaabcb43 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));
@@ -502,11 +515,29 @@ wpas_iface_scan_done (GDBusProxy *proxy,
{
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+ 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_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)) {
+ if (g_object_get_data (G_OBJECT (bss_proxy), BSS_PROXY_INITED)) {
+ props = _get_bss_proxy_properties (self, bss_proxy);
+ if (props) {
+ g_signal_emit (self, signals[NEW_BSS], 0,
+ bss_path,
+ g_variant_ref_sink (props));
+ g_variant_unref (props);
+ }
+ }
+ }
}
static void