hostap-driver 0.4.7 -- scan bug ( managed mode )
espy at pepper.com
Thu Apr 6 19:06:33 EDT 2006
I think I've uncovered a bug with way the hostap-driver returns scan
I'm currently running v0.4.7 of the hostap-driver in managed mode on the
Pepper Pad which has a CF-based WiFi card ( STA fw = 1.8.4 ). The Pad
also uses wpa_supplicant, but from my analysis, it doesn't appear to be
There are two potential scenarios. The first I discovered yesterday
when I put my Pepper Pad to sleep ( ie. suspend mode ) and drove into
Cambridge, MA ( in a lovely Spring snowstorm I might add ) to meet a
friend for lunch.
When I woke my Pad, it tried to connect to one of the APs we have here
in the office! I took a look at one of our logs and noticed that the
scan results from wpa_supplicant included all of the APs in our office!
So after getting back, I ran thru some tests and stared at the driver
code for awhile and I think I've found the problem.
The function prism2_translate_scan() in hostap_ioctl.c builds the scan
response returned to user-land. It uses two sources to build the response:
- 'last_scan_results' - an array populated with the scan results from
the prism firmware response to a SCAN or HOSTSCAN command
- 'bss_list' - this list is built dynamically by the driver whenever it
receives a beacon or probe frame.
APs added to the bss_list are expired every so often based upon a
last_update attribute. The problem is that the expire_bss() function is
only called by the function that parses incoming beacon or probe frames
( hostap_rx_sta_beacon() ). If none are received, the entries in the
list don't seem to ever expire. More on this later...
The last piece of the puzzle is how the function prism2_translate_scan()
First, it walks thru the bss_list and sets the include attribute of each
bss to 0.
Next, it walks thru the last_scan_results list. For each entry, it
checks to see if the entry is also in the bss_list. If it is, it adds
the bss entry to the response via a call to __prism2_translate_scan()
and sets its include flag to 1.
Finally, it walks thru the bss_list and adds any entries that have not
already been added ( ie. include == 0 ).
It appears ( based upon comments ) that this last logic was done to
circumvent the fact that the Prism firmware will only return a maximum
of 32 APs in it's scan results.
So, this bug can occur whenever a device running the hostap-driver in
managed mode has a populated bss_list and moves out of range of any
access points ( ie. no beacons or probes frames are received ). In our
case, this can easily be accomplished by putting the Pepper Pad to sleep
and waking it in an area that has no Wi-Fi traffic.
I think the proper fix is twofold:
1. On a suspend, clear the bss_list ( ie. via a new function
2. Call hostap_expire_bss() from prism2_translate_scan() - this takes
care of the case where someone has moved outside of the range of any
access point traffic before the entries in the list have expired. One
possible scenario is getting into an elevator that moves out of range of
any Wi-Fi traffic.
I'll followup this post with the actual patch. The one thing I'm a bit
unsure about is whether or not I'm using the correct spinlock calls in
Also FYI, the patch includes a previous patch that we've been running
with for quite some time that grabs the channel number out of local_info
if needed. If the AP the JOIN is for isn't found in the
last_scan_results, then the JOIN is sent to the firmware with channel=0.
This was causing the firmware to behave unpredictably ( eg. the rate
would sometimes drop to 1Mbps and never go back up and scanning would
break association ).
More information about the HostAP