summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2015-04-20 10:18:32 -0500
committerDan Williams <dcbw@redhat.com>2015-05-06 15:14:06 -0500
commite482f853f65d7959e2856d386d1fc55fe999bdf9 (patch)
tree3e46e2cf9e9d726de25f69b1b7881f02c3f00b3b
parent910c62d8c7ee052db4cdc992350c36ed5d8bd138 (diff)
downloadNetworkManager-e482f853f65d7959e2856d386d1fc55fe999bdf9.tar.gz
wifi: remove supplicant-forgotten current AP from list on disconnect
NM never removes the current AP from the AP list, to prevent NM from indicating that it's connected, but to nothing. But the supplicant can remove that AP from its list at any time (out of range, turned off, etc), leading to a priv->current_ap that is no longer known to the supplicant but still exists in the NM AP list. Since the supplicant has forgotten it, NM will never receive a removal signal for it. To ensure that a supplicant-forgotten priv->current_ap is removed from the NM AP list when priv->current_ap is cleared or changed, mark any AP removed by the supplicant as 'fake'. It will then always be removed in set_current_ap() and not linger in the AP list forever like a zombie.
-rw-r--r--src/devices/wifi/nm-device-wifi.c19
-rw-r--r--src/devices/wifi/nm-wifi-ap.c3
2 files changed, 17 insertions, 5 deletions
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 1922f9424f..cc4db66628 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -1600,11 +1600,20 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface,
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
ap = get_ap_by_supplicant_path (self, object_path);
- if (ap && ap != priv->current_ap) {
- nm_ap_dump (ap, "removed ", nm_device_get_iface (NM_DEVICE (self)));
- emit_ap_added_removed (self, ACCESS_POINT_REMOVED, ap, TRUE);
- g_hash_table_remove (priv->aps, nm_ap_get_dbus_path (ap));
- schedule_ap_list_dump (self);
+ if (ap) {
+ if (ap == priv->current_ap) {
+ /* The current AP cannot be removed (to prevent NM indicating that
+ * it is connected, but to nothing), but it must be removed later
+ * when the current AP is changed or cleared. Set 'fake' to
+ * indicate that this AP is now unknown to the supplicant.
+ */
+ nm_ap_set_fake (ap, TRUE);
+ } else {
+ nm_ap_dump (ap, "removed ", nm_device_get_iface (NM_DEVICE (self)));
+ emit_ap_added_removed (self, ACCESS_POINT_REMOVED, ap, TRUE);
+ g_hash_table_remove (priv->aps, nm_ap_get_dbus_path (ap));
+ schedule_ap_list_dump (self);
+ }
}
}
diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c
index 5068e66e96..c4dad39a2e 100644
--- a/src/devices/wifi/nm-wifi-ap.c
+++ b/src/devices/wifi/nm-wifi-ap.c
@@ -388,6 +388,7 @@ nm_ap_update_from_properties (NMAccessPoint *ap,
const char *supplicant_path,
GVariant *properties)
{
+ NMAccessPointPrivate *priv;
char *addr;
const guint8 *bytes;
GVariant *v;
@@ -399,6 +400,7 @@ nm_ap_update_from_properties (NMAccessPoint *ap,
g_return_if_fail (ap != NULL);
g_return_if_fail (properties != NULL);
+ priv = NM_AP_GET_PRIVATE (ap);
g_object_freeze_notify (G_OBJECT (ap));
@@ -475,6 +477,7 @@ nm_ap_update_from_properties (NMAccessPoint *ap,
nm_ap_set_supplicant_path (ap, supplicant_path);
nm_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ());
+ priv->fake = FALSE;
g_object_thaw_notify (G_OBJECT (ap));
}