diff options
author | Dan Williams <dcbw@redhat.com> | 2010-07-15 00:00:42 -0700 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2010-07-15 00:00:42 -0700 |
commit | 4880cc68b2e1a6580f30318c660c2f669b8f5708 (patch) | |
tree | 80eb2fafd773e3d5c92846b25e71a7f4fa598c69 | |
parent | 72399bfa2cab6de881518b4b473c5b2a76f058b8 (diff) |
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.
-rw-r--r-- | src/nm-device-wifi.c | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index dc76dc29db..895d4d1765 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; } |