diff options
author | Helmut Schaa <helmut.schaa@googlemail.com> | 2009-03-09 10:47:08 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-16 18:09:38 -0400 |
commit | af88b9078d4aa31d667d2d82601ede9cae3bac37 (patch) | |
tree | afd9528736ecaf17eb1628be08abead2fee699f7 /net/mac80211 | |
parent | 8830cb678b13004ab54f606345769f1e74e378c6 (diff) |
mac80211: handle failed scan requests in STA mode
If cfg80211 requests a scan it awaits either a return code != 0 from
the scan function or the cfg80211_scan_done to be called. In case of
a STA mac80211's scan function ever returns 0 and queues the scan request.
If ieee80211_sta_work is executed and ieee80211_start_scan fails for
some reason cfg80211_scan_done will never be called but cfg80211 still
thinks the scan was triggered successfully and will refuse any future
scan requests due to drv->scan_req not being cleaned up.
If a scan is triggered from within the MLME a similar problem appears. If
ieee80211_start_scan returns an error, local->scan_req will not be reset
and mac80211 will refuse any future scan requests.
Hence, in both cases call ieee80211_scan_failed (which notifies cfg80211
and resets local->scan_req) if ieee80211_start_scan returns an error.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 14 | ||||
-rw-r--r-- | net/mac80211/scan.c | 12 |
3 files changed, 25 insertions, 2 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ecbc8e0cb3e7..fbb91f1aebb2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -972,6 +972,7 @@ int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, | |||
972 | char *ie, size_t len); | 972 | char *ie, size_t len); |
973 | 973 | ||
974 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); | 974 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); |
975 | void ieee80211_scan_failed(struct ieee80211_local *local); | ||
975 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | 976 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, |
976 | struct cfg80211_scan_request *req); | 977 | struct cfg80211_scan_request *req); |
977 | struct ieee80211_bss * | 978 | struct ieee80211_bss * |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index eeb6da8505c6..841b8450b3de 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1720,7 +1720,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) | |||
1720 | local->int_scan_req.ssids[0].ssid_len = 0; | 1720 | local->int_scan_req.ssids[0].ssid_len = 0; |
1721 | else | 1721 | else |
1722 | local->int_scan_req.ssids[0].ssid_len = ifmgd->ssid_len; | 1722 | local->int_scan_req.ssids[0].ssid_len = ifmgd->ssid_len; |
1723 | ieee80211_start_scan(sdata, &local->int_scan_req); | 1723 | |
1724 | if (ieee80211_start_scan(sdata, &local->int_scan_req)) | ||
1725 | ieee80211_scan_failed(local); | ||
1726 | |||
1724 | ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE; | 1727 | ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE; |
1725 | set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); | 1728 | set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); |
1726 | } else { | 1729 | } else { |
@@ -1757,7 +1760,14 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
1757 | ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE && | 1760 | ifmgd->state != IEEE80211_STA_MLME_AUTHENTICATE && |
1758 | ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE && | 1761 | ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE && |
1759 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) { | 1762 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) { |
1760 | ieee80211_start_scan(sdata, local->scan_req); | 1763 | /* |
1764 | * The call to ieee80211_start_scan can fail but ieee80211_request_scan | ||
1765 | * (which queued ieee80211_sta_work) did not return an error. Thus, call | ||
1766 | * ieee80211_scan_failed here if ieee80211_start_scan fails in order to | ||
1767 | * notify the scan requester. | ||
1768 | */ | ||
1769 | if (ieee80211_start_scan(sdata, local->scan_req)) | ||
1770 | ieee80211_scan_failed(local); | ||
1761 | return; | 1771 | return; |
1762 | } | 1772 | } |
1763 | 1773 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 0e81e1633a66..5030a3c87509 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -202,6 +202,18 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
202 | return RX_QUEUED; | 202 | return RX_QUEUED; |
203 | } | 203 | } |
204 | 204 | ||
205 | void ieee80211_scan_failed(struct ieee80211_local *local) | ||
206 | { | ||
207 | if (WARN_ON(!local->scan_req)) | ||
208 | return; | ||
209 | |||
210 | /* notify cfg80211 about the failed scan */ | ||
211 | if (local->scan_req != &local->int_scan_req) | ||
212 | cfg80211_scan_done(local->scan_req, true); | ||
213 | |||
214 | local->scan_req = NULL; | ||
215 | } | ||
216 | |||
205 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 217 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) |
206 | { | 218 | { |
207 | struct ieee80211_local *local = hw_to_local(hw); | 219 | struct ieee80211_local *local = hw_to_local(hw); |