From 3b4d3de16a7d045c26764a676f26219577493b6e Mon Sep 17 00:00:00 2001 From: Daniel Williams Date: Wed, 11 Jun 2008 11:01:48 +0000 Subject: [PATCH] - Fix 802.11a frequency bug - Always schedule specific SSID scans to help find hidden APs - Properly switch between modes on mac80211 drivers - Give adhoc connections more time to assocate --- ...0.6.3-dont-reschedule-specific-scans.patch | 163 ++++++++++++++++++ ....3-wext-dont-overwrite-BSS-frequency.patch | 35 ++++ ...3-wext-handle-mac80211-mode-switches.patch | 74 ++++++++ wpa_supplicant-assoc-timeout.patch | 2 +- wpa_supplicant.spec | 14 +- 5 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 wpa_supplicant-0.6.3-dont-reschedule-specific-scans.patch create mode 100644 wpa_supplicant-0.6.3-wext-dont-overwrite-BSS-frequency.patch create mode 100644 wpa_supplicant-0.6.3-wext-handle-mac80211-mode-switches.patch diff --git a/wpa_supplicant-0.6.3-dont-reschedule-specific-scans.patch b/wpa_supplicant-0.6.3-dont-reschedule-specific-scans.patch new file mode 100644 index 0000000..09d3b08 --- /dev/null +++ b/wpa_supplicant-0.6.3-dont-reschedule-specific-scans.patch @@ -0,0 +1,163 @@ +commit 7e1488494e0150ee7fdef83355266b5633c5c1b0 +Author: Dan Williams +Date: Tue Jun 3 11:37:48 2008 +0300 + + Do not continually reschedule specific scans to help finding hidden SSIDs + + In situations where the driver does background scanning and sends a + steady stream of scan results, wpa_supplicant would continually + reschedule the scan. This resulted in specific SSID scans never + happening for a hidden AP, and the supplicant never connecting to the AP + because it never got found. Instead, if there's an already scheduled + scan, and a request comes in to reschedule it, and there are enabled + scan_ssid=1 network blocks, let the scan happen anyway so the hidden + SSID has a chance to be found. + +diff --git a/src/utils/eloop.c b/src/utils/eloop.c +index f988e94..4edb2a7 100644 +--- a/src/utils/eloop.c ++++ b/src/utils/eloop.c +@@ -315,6 +315,25 @@ int eloop_cancel_timeout(eloop_timeout_handler handler, + } + + ++int eloop_is_timeout_registered(eloop_timeout_handler handler, ++ void *eloop_data, void *user_data) ++{ ++ struct eloop_timeout *tmp; ++ ++ tmp = eloop.timeout; ++ while (tmp != NULL) { ++ if (tmp->handler == handler && ++ tmp->eloop_data == eloop_data && ++ tmp->user_data == user_data) ++ return 1; ++ ++ tmp = tmp->next; ++ } ++ ++ return 0; ++} ++ ++ + #ifndef CONFIG_NATIVE_WINDOWS + static void eloop_handle_alarm(int sig) + { +diff --git a/src/utils/eloop.h b/src/utils/eloop.h +index 4dd2871..cf83f38 100644 +--- a/src/utils/eloop.h ++++ b/src/utils/eloop.h +@@ -207,6 +207,19 @@ int eloop_cancel_timeout(eloop_timeout_handler handler, + void *eloop_data, void *user_data); + + /** ++ * eloop_is_timeout_registered - Check if a timeout is already registered ++ * @handler: Matching callback function ++ * @eloop_data: Matching eloop_data ++ * @user_data: Matching user_data ++ * Returns: 1 if the timeout is registered, 0 if the timeout is not registered ++ * ++ * Determine if a matching timeout is registered ++ * with eloop_register_timeout(). ++ */ ++int eloop_is_timeout_registered(eloop_timeout_handler handler, ++ void *eloop_data, void *user_data); ++ ++/** + * eloop_register_signal - Register handler for signals + * @sig: Signal number (e.g., SIGHUP) + * @handler: Callback function to be called when the signal is received +diff --git a/src/utils/eloop_none.c b/src/utils/eloop_none.c +index 6943109..215030b 100644 +--- a/src/utils/eloop_none.c ++++ b/src/utils/eloop_none.c +@@ -197,6 +197,26 @@ int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx), + } + + ++int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx, ++ void *timeout_ctx), ++ void *eloop_data, void *user_data) ++{ ++ struct eloop_timeout *tmp; ++ ++ tmp = eloop.timeout; ++ while (tmp != NULL) { ++ if (tmp->handler == handler && ++ tmp->eloop_data == eloop_data && ++ tmp->user_data == user_data) ++ return 1; ++ ++ tmp = tmp->next; ++ } ++ ++ return 0; ++} ++ ++ + /* TODO: replace with suitable signal handler */ + #if 0 + static void eloop_handle_signal(int sig) +diff --git a/src/utils/eloop_win.c b/src/utils/eloop_win.c +index 73f0eaf..a1ccd94 100644 +--- a/src/utils/eloop_win.c ++++ b/src/utils/eloop_win.c +@@ -320,6 +320,25 @@ int eloop_cancel_timeout(eloop_timeout_handler handler, + } + + ++int eloop_is_timeout_registered(eloop_timeout_handler handler, ++ void *eloop_data, void *user_data) ++{ ++ struct eloop_timeout *tmp; ++ ++ tmp = eloop.timeout; ++ while (tmp != NULL) { ++ if (tmp->handler == handler && ++ tmp->eloop_data == eloop_data && ++ tmp->user_data == user_data) ++ return 1; ++ ++ tmp = tmp->next; ++ } ++ ++ return 0; ++} ++ ++ + /* TODO: replace with suitable signal handler */ + #if 0 + static void eloop_handle_signal(int sig) +diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c +index b046d90..c2549e2 100644 +--- a/wpa_supplicant/scan.c ++++ b/wpa_supplicant/scan.c +@@ -172,6 +172,28 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) + */ + void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) + { ++ /* If there's at least one network that should be specifically scanned ++ * then don't cancel the scan and reschedule. Some drivers do ++ * background scanning which generates frequent scan results, and that ++ * causes the specific SSID scan to get continually pushed back and ++ * never happen, which causes hidden APs to never get probe-scanned. ++ */ ++ if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) && ++ wpa_s->conf->ap_scan == 1) { ++ struct wpa_ssid *ssid = wpa_s->conf->ssid; ++ ++ while (ssid) { ++ if (!ssid->disabled && ssid->scan_ssid) ++ break; ++ ssid = ssid->next; ++ } ++ if (ssid) { ++ wpa_msg(wpa_s, MSG_DEBUG, "Not rescheduling scan to " ++ "ensure that specific SSID scans occur"); ++ return; ++ } ++ } ++ + wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec", + sec, usec); + eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); diff --git a/wpa_supplicant-0.6.3-wext-dont-overwrite-BSS-frequency.patch b/wpa_supplicant-0.6.3-wext-dont-overwrite-BSS-frequency.patch new file mode 100644 index 0000000..6970beb --- /dev/null +++ b/wpa_supplicant-0.6.3-wext-dont-overwrite-BSS-frequency.patch @@ -0,0 +1,35 @@ +commit 2e5a7b49a0a52ce36033e4839aae90e638746b6a +Author: Dan Williams +Date: Mon Jun 2 20:47:09 2008 +0300 + + wext: don't overwrite BSS frequency + + mac80211 sends _both_ channel and frequency in it's scan results, with + frequency first and channel second (it's since been fixed to send + channel first and frequency second to work around this issue). This + results in wpa_supplicant getting the right value when the frequency + comes, but overwriting the value with '0' when the channel comes because + wpa_supplicant can't handle 5GHz channel numbers. So if a valid + previous SIOCGIWFREQ event came in, don't try to overwrite it. + +diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c +index f9c86bb..efa88a8 100644 +--- a/src/drivers/driver_wext.c ++++ b/src/drivers/driver_wext.c +@@ -1294,8 +1294,15 @@ static void wext_get_scan_freq(struct iw_event *iwe, + /* + * Some drivers do not report frequency, but a channel. + * Try to map this to frequency by assuming they are using +- * IEEE 802.11b/g. ++ * IEEE 802.11b/g. But don't overwrite a previously parsed ++ * frequency if the driver sends both frequency and channel, ++ * since the driver may be sending an A-band channel that we ++ * don't handle here. + */ ++ ++ if (res->res.freq) ++ return; ++ + if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) { + res->res.freq = 2407 + 5 * iwe->u.freq.m; + return; diff --git a/wpa_supplicant-0.6.3-wext-handle-mac80211-mode-switches.patch b/wpa_supplicant-0.6.3-wext-handle-mac80211-mode-switches.patch new file mode 100644 index 0000000..b212963 --- /dev/null +++ b/wpa_supplicant-0.6.3-wext-handle-mac80211-mode-switches.patch @@ -0,0 +1,74 @@ +commit 59c9707863336c1255936c755d24c8eb1ed8db2f +Author: Dan Williams +Date: Wed Jun 4 20:55:57 2008 +0300 + + wext: handle mode switches correctly for mac80211 + + Since mac80211 requires that the device be !IFF_UP to change the mode + (and I think the old prism54 fullmac driver does too), do that. This + shouldn't harm fullmac devices since they can handle mode switches on + the fly and usually don't care about up/down that much. + +diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c +index 1226b94..c9d7399 100644 +--- a/src/drivers/driver_wext.c ++++ b/src/drivers/driver_wext.c +@@ -2151,17 +2151,54 @@ int wpa_driver_wext_set_mode(void *priv, int mode) + { + struct wpa_driver_wext_data *drv = priv; + struct iwreq iwr; +- int ret = 0; ++ int ret = -1, flags; ++ unsigned int new_mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA; + + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); +- iwr.u.mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA; ++ iwr.u.mode = new_mode; ++ if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) == 0) { ++ ret = 0; ++ goto done; ++ } + +- if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) { ++ if (errno != EBUSY) { + perror("ioctl[SIOCSIWMODE]"); +- ret = -1; ++ goto done; ++ } ++ ++ /* mac80211 doesn't allow mode changes while the device is up, so if ++ * the device isn't in the mode we're about to change to, take device ++ * down, try to set the mode again, and bring it back up. ++ */ ++ if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) { ++ perror("ioctl[SIOCGIWMODE]"); ++ goto done; ++ } ++ ++ if (iwr.u.mode == new_mode) { ++ ret = 0; ++ goto done; ++ } ++ ++ if (wpa_driver_wext_get_ifflags(drv, &flags) == 0) { ++ (void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP); ++ ++ /* Try to set the mode again while the interface is down */ ++ iwr.u.mode = new_mode; ++ if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) ++ perror("ioctl[SIOCSIWMODE]"); ++ else ++ ret = 0; ++ ++ /* Ignore return value of get_ifflags to ensure that the device ++ * is always up like it was before this function was called. ++ */ ++ (void) wpa_driver_wext_get_ifflags(drv, &flags); ++ (void) wpa_driver_wext_set_ifflags(drv, flags | IFF_UP); + } + ++done: + return ret; + } + diff --git a/wpa_supplicant-assoc-timeout.patch b/wpa_supplicant-assoc-timeout.patch index 9fb21f4..43baf71 100644 --- a/wpa_supplicant-assoc-timeout.patch +++ b/wpa_supplicant-assoc-timeout.patch @@ -8,7 +8,7 @@ + timeout = 15; else if (wpa_s->conf->ap_scan == 1) - timeout = 10; -+ timeout = 15; ++ timeout = 20; else timeout = 60; wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0); diff --git a/wpa_supplicant.spec b/wpa_supplicant.spec index 2e67dec..77c0293 100644 --- a/wpa_supplicant.spec +++ b/wpa_supplicant.spec @@ -2,7 +2,7 @@ Summary: WPA/WPA2/IEEE 802.1X Supplicant Name: wpa_supplicant Epoch: 1 Version: 0.6.3 -Release: 5%{?dist} +Release: 6%{?dist} License: BSD Group: System Environment/Base Source0: http://hostap.epitest.fi/releases/%{name}-%{version}.tar.gz @@ -20,6 +20,9 @@ Patch3: wpa_supplicant-0.5.7-flush-debug-output.patch Patch4: wpa_supplicant-0.5.7-use-IW_ENCODE_TEMP.patch Patch5: wpa_supplicant-0.5.10-dbus-service-file.patch Patch6: wpa_supplicant-0.6.3-fix-dbus-use-after-free.patch +Patch7: wpa_supplicant-0.6.3-wext-dont-overwrite-BSS-frequency.patch +Patch8: wpa_supplicant-0.6.3-dont-reschedule-specific-scans.patch +Patch9: wpa_supplicant-0.6.3-wext-handle-mac80211-mode-switches.patch URL: http://w1.fi/wpa_supplicant/ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -54,6 +57,9 @@ Graphical User Interface for wpa_supplicant written using QT3 %patch4 -p1 -b .use-IW_ENCODE_TEMP %patch5 -p1 -b .dbus-service-file %patch6 -p1 -b .use-after-free +%patch7 -p1 -b .bss-freq +%patch8 -p1 -b .ssid-scans +%patch9 -p1 -b .mac80211-mode %build pushd src @@ -147,6 +153,12 @@ fi %{_bindir}/wpa_gui %changelog +* Tue Jun 10 2008 Dan Williams - 1:0.6.3-6 +- Fix 802.11a frequency bug +- Always schedule specific SSID scans to help find hidden APs +- Properly switch between modes on mac80211 drivers +- Give adhoc connections more time to assocate + * Mon Mar 10 2008 Christopher Aillon - 1:0.6.3-5 - BuildRequires qt3-devel