summaryrefslogtreecommitdiff
authorDan Williams <dcbw@redhat.com>2010-07-15 07:00:42 (GMT)
committer Dan Williams <dcbw@redhat.com>2010-07-15 07:00:42 (GMT)
commit4880cc68b2e1a6580f30318c660c2f669b8f5708 (patch) (side-by-side diff)
tree80eb2fafd773e3d5c92846b25e71a7f4fa598c69
parent72399bfa2cab6de881518b4b473c5b2a76f058b8 (diff)
downloadNetworkManager-4880cc68b2e1a6580f30318c660c2f669b8f5708.zip
NetworkManager-4880cc68b2e1a6580f30318c660c2f669b8f5708.tar.gz
wifi: work around wl.o frequency reporting for active AP matching
Some proprietary drivers (wl.o) report tuned frequency (like when scanning) instead of the associated AP's frequency. This is a great example of how WEXT is underspecified. We use frequency to find the active AP in the scan list because some configurations use the same SSID/BSSID on the 2GHz and 5GHz bands simultaneously, and we need to make sure we get the right AP in the right band. This configuration is uncommon though, and the frequency check penalizes closed drivers we can't fix. Because we're not total dicks, ignore the frequency condition if the associated BSSID/SSID exists only in one band since that's most likely the AP we want.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/nm-device-wifi.c48
1 files changed, 44 insertions, 4 deletions
diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c
index dc76dc2..895d4d1 100644
--- a/src/nm-device-wifi.c
+++ b/src/nm-device-wifi.c
@@ -829,6 +829,11 @@ get_active_ap (NMDeviceWifi *self,
const GByteArray *ssid;
GSList *iter;
int i = 0;
+ NMAccessPoint *match_nofreq = NULL;
+ gboolean found_a_band = FALSE;
+ gboolean found_bg_band = FALSE;
+ NM80211Mode devmode;
+ guint32 devfreq;
nm_device_wifi_get_bssid (self, &bssid);
nm_log_dbg (LOGD_WIFI, "(%s): active BSSID: %02x:%02x:%02x:%02x:%02x:%02x",
@@ -847,6 +852,9 @@ get_active_ap (NMDeviceWifi *self,
ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)",
ssid ? "'" : "");
+ devmode = nm_device_wifi_get_mode (self);
+ devfreq = nm_device_wifi_get_frequency (self);
+
/* When matching hidden APs, do a second pass that ignores the SSID check,
* because NM might not yet know the SSID of the hidden AP in the scan list
* and therefore it won't get matched the first time around.
@@ -859,8 +867,8 @@ get_active_ap (NMDeviceWifi *self,
NMAccessPoint *ap = NM_AP (iter->data);
const struct ether_addr *ap_bssid = nm_ap_get_address (ap);
const GByteArray *ap_ssid = nm_ap_get_ssid (ap);
- NM80211Mode devmode, apmode;
- guint32 devfreq, apfreq;
+ NM80211Mode apmode;
+ guint32 apfreq;
nm_log_dbg (LOGD_WIFI, " AP: %s%s%s %02x:%02x:%02x:%02x:%02x:%02x",
ap_ssid ? "'" : "",
@@ -885,7 +893,6 @@ get_active_ap (NMDeviceWifi *self,
continue;
}
- devmode = nm_device_wifi_get_mode (self);
apmode = nm_ap_get_mode (ap);
if (devmode != apmode) {
nm_log_dbg (LOGD_WIFI, " mode mismatch (device %d, ap %d)",
@@ -893,11 +900,18 @@ get_active_ap (NMDeviceWifi *self,
continue;
}
- devfreq = nm_device_wifi_get_frequency (self);
apfreq = nm_ap_get_freq (ap);
if (devfreq != apfreq) {
nm_log_dbg (LOGD_WIFI, " frequency mismatch (device %u, ap %u)",
devfreq, apfreq);
+
+ if (match_nofreq == NULL)
+ match_nofreq = ap;
+
+ if (apfreq > 4000)
+ found_a_band = TRUE;
+ else if (apfreq > 2000)
+ found_bg_band = TRUE;
continue;
}
@@ -907,6 +921,32 @@ get_active_ap (NMDeviceWifi *self,
}
}
+ /* Some proprietary drivers (wl.o) report tuned frequency (like when
+ * scanning) instead of the associated AP's frequency. This is a great
+ * example of how WEXT is underspecified. We use frequency to find the
+ * active AP in the scan list because some configurations use the same
+ * SSID/BSSID on the 2GHz and 5GHz bands simultaneously, and we need to
+ * make sure we get the right AP in the right band. This configuration
+ * is uncommon though, and the frequency check penalizes closed drivers we
+ * can't fix. Because we're not total dicks, ignore the frequency condition
+ * if the associated BSSID/SSID exists only in one band since that's most
+ * likely the AP we want.
+ */
+ if (match_nofreq && (found_a_band != found_bg_band)) {
+ const struct ether_addr *ap_bssid = nm_ap_get_address (match_nofreq);
+ const GByteArray *ap_ssid = nm_ap_get_ssid (match_nofreq);
+
+ nm_log_dbg (LOGD_WIFI, " matched %s%s%s %02x:%02x:%02x:%02x:%02x:%02x",
+ ap_ssid ? "'" : "",
+ ap_ssid ? nm_utils_escape_ssid (ap_ssid->data, ap_ssid->len) : "(none)",
+ ap_ssid ? "'" : "",
+ ap_bssid->ether_addr_octet[0], ap_bssid->ether_addr_octet[1],
+ ap_bssid->ether_addr_octet[2], ap_bssid->ether_addr_octet[3],
+ ap_bssid->ether_addr_octet[4], ap_bssid->ether_addr_octet[5]);
+
+ return match_nofreq;
+ }
+
nm_log_dbg (LOGD_WIFI, " No matching AP found.");
return NULL;
}