mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-04 19:10:17 +01:00
wifi: ensure user-created Ad-Hoc APs disappear when no longer used (bgo #569241)
Since NM doesn't scan while associated with an Ad-Hoc BSS (since scanning in adhoc mode makes most driver quite angry and doesn't work well anyway) the user-created BSS was never found in the scan list, and the 'fake' flag wasn't cleared. Thus the BSS stuck around in NM's scan list forever. Additionally, ensure that set_current_ap() maintains a reference to the old AP until after setting the new AP, just in case the same AP is being set again. Third, handle IBSS coalescing by always updating the current AP's address (if it's an Ad-Hoc AP) with the BSSID reported by the card. The joined Ad-Hoc networks' BSSID will change if the card coalesces with other stations in the same IBSS, which would make NM fail to find the currently joined network in the scan list, and lead to "roamed to (none)" messages and inability to find the current AP.
This commit is contained in:
parent
5b1fadb1ac
commit
df92606d61
1 changed files with 61 additions and 11 deletions
|
|
@ -837,20 +837,35 @@ get_active_ap (NMDeviceWifi *self,
|
|||
static void
|
||||
set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
NMDeviceWifiPrivate *priv;
|
||||
char *old_path = NULL;
|
||||
NMAccessPoint *old_ap;
|
||||
|
||||
g_return_if_fail (NM_IS_DEVICE_WIFI (self));
|
||||
|
||||
if (priv->current_ap) {
|
||||
old_path = g_strdup (nm_ap_get_dbus_path (priv->current_ap));
|
||||
g_object_unref (priv->current_ap);
|
||||
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
old_ap = priv->current_ap;
|
||||
|
||||
if (old_ap) {
|
||||
old_path = g_strdup (nm_ap_get_dbus_path (old_ap));
|
||||
priv->current_ap = NULL;
|
||||
}
|
||||
|
||||
if (new_ap)
|
||||
if (new_ap) {
|
||||
priv->current_ap = g_object_ref (new_ap);
|
||||
|
||||
/* Move the current AP to the front of the scan list. Since we
|
||||
* do a lot of searches looking for the current AP, it saves
|
||||
* time to have it in front.
|
||||
*/
|
||||
priv->ap_list = g_slist_remove (priv->ap_list, new_ap);
|
||||
priv->ap_list = g_slist_prepend (priv->ap_list, new_ap);
|
||||
}
|
||||
|
||||
/* Unref old AP here to ensure object lives if new_ap == old_ap */
|
||||
if (old_ap)
|
||||
g_object_unref (old_ap);
|
||||
|
||||
/* Only notify if it's really changed */
|
||||
if ( (!old_path && new_ap)
|
||||
|| (old_path && !new_ap)
|
||||
|
|
@ -867,6 +882,24 @@ periodic_update (NMDeviceWifi *self)
|
|||
NMAccessPoint *new_ap;
|
||||
guint32 new_rate;
|
||||
|
||||
/* In IBSS mode, most newer firmware/drivers do "BSS coalescing" where
|
||||
* multiple IBSS stations using the same SSID will eventually switch to
|
||||
* using the same BSSID to avoid network segmentation. When this happens,
|
||||
* the card's reported BSSID will change, but the the new BSS may not
|
||||
* be in the scan list, since scanning isn't done in ad-hoc mode for
|
||||
* various reasons. So pull the BSSID from the card and update the
|
||||
* current AP with it, if the current AP is adhoc.
|
||||
*/
|
||||
if (priv->current_ap && (nm_ap_get_mode (priv->current_ap) == NM_802_11_MODE_ADHOC)) {
|
||||
struct ether_addr bssid = { {0x0, 0x0, 0x0, 0x0, 0x0, 0x0} };
|
||||
|
||||
nm_device_wifi_get_bssid (self, &bssid);
|
||||
/* 0x02 is the first byte of IBSS BSSIDs */
|
||||
if ( (bssid.ether_addr_octet[0] == 0x02)
|
||||
&& nm_ethernet_address_is_valid (&bssid))
|
||||
nm_ap_set_address (priv->current_ap, &bssid);
|
||||
}
|
||||
|
||||
new_ap = get_active_ap (self, NULL, FALSE);
|
||||
if (new_ap)
|
||||
nm_device_wifi_update_signal_strength (self, new_ap);
|
||||
|
|
@ -1009,11 +1042,25 @@ real_take_down (NMDevice *dev)
|
|||
static void
|
||||
real_deactivate_quickly (NMDevice *dev)
|
||||
{
|
||||
NMDeviceWifi * self = NM_DEVICE_WIFI (dev);
|
||||
NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
NMAccessPoint *orig_ap;
|
||||
|
||||
cleanup_association_attempt (self, TRUE);
|
||||
|
||||
/* If the AP is 'fake', i.e. it wasn't actually found from
|
||||
* a scan but the user tried to connect to it manually (maybe it
|
||||
* was non-broadcasting or something) clear the 'fake' flag here,
|
||||
* becuase 'fake' APs should only live for as long as we're
|
||||
* connected to them. Fixes a bug where user-created Ad-Hoc APs
|
||||
* are never removed from the scan list, because scanning is
|
||||
* disabled while in Ad-Hoc mode (for stability), and thus the
|
||||
* AP culling never happens. (bgo #569241)
|
||||
*/
|
||||
orig_ap = nm_device_wifi_get_activation_ap (self);
|
||||
if (orig_ap && nm_ap_get_fake (orig_ap))
|
||||
nm_ap_set_fake (orig_ap, FALSE);
|
||||
|
||||
set_current_ap (self, NULL);
|
||||
priv->rate = 0;
|
||||
|
||||
|
|
@ -1958,7 +2005,7 @@ merge_scanned_ap (NMDeviceWifi *self,
|
|||
/* New entry in the list */
|
||||
// FIXME: figure out if reference counts are correct here for AP objects
|
||||
g_object_ref (merge_ap);
|
||||
priv->ap_list = g_slist_append (priv->ap_list, merge_ap);
|
||||
priv->ap_list = g_slist_prepend (priv->ap_list, merge_ap);
|
||||
nm_ap_export_to_dbus (merge_ap);
|
||||
g_signal_emit (self, signals[ACCESS_POINT_ADDED], 0, merge_ap);
|
||||
}
|
||||
|
|
@ -2842,7 +2889,7 @@ real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||
break;
|
||||
}
|
||||
|
||||
priv->ap_list = g_slist_append (priv->ap_list, ap);
|
||||
priv->ap_list = g_slist_prepend (priv->ap_list, ap);
|
||||
nm_ap_export_to_dbus (ap);
|
||||
g_signal_emit (self, signals[ACCESS_POINT_ADDED], 0, ap);
|
||||
}
|
||||
|
|
@ -3113,13 +3160,16 @@ activation_success_handler (NMDevice *dev)
|
|||
|
||||
ap = nm_device_wifi_get_activation_ap (self);
|
||||
|
||||
/* If the activate AP was fake, it probably won't have a BSSID at all.
|
||||
* But if activation was successful, the card will know the BSSID. Grab
|
||||
* the BSSID off the card and fill in the BSSID of the activation AP.
|
||||
/* If the AP isn't fake, it was found in the scan list and all its
|
||||
* details are known.
|
||||
*/
|
||||
if (!nm_ap_get_fake (ap))
|
||||
goto done;
|
||||
|
||||
/* If the activate AP was fake, it probably won't have a BSSID at all.
|
||||
* But if activation was successful, the card will know the BSSID. Grab
|
||||
* the BSSID off the card and fill in the BSSID of the activation AP.
|
||||
*/
|
||||
nm_device_wifi_get_bssid (self, &bssid);
|
||||
if (!nm_ethernet_address_is_valid (nm_ap_get_address (ap)))
|
||||
nm_ap_set_address (ap, &bssid);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue