diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-07-29 05:23:49 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-04 16:43:24 -0400 |
commit | df7fc0f9735085bb617fff774bfd71465edb448c (patch) | |
tree | 2b47f3823a8aee6c13e86aa3dedc06bda9ebae38 /net/wireless/mlme.c | |
parent | 97af743207466ff8b477e14bfb7af0ba2c93375b (diff) |
cfg80211: keep track of current_bss for userspace SME
When a userspace SME is active, we're currently not
keeping track of the BSS properly for reporting the
current link and for internal use. Additionally, it
looks like there is a possible BSS leak in that the
BSS never gets removed from auth_bsses[]. To fix it,
pass the BSS struct to __cfg80211_connect_result in
this case.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/mlme.c')
-rw-r--r-- | net/wireless/mlme.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 097a87d7bae1..525e8e247b30 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -61,7 +61,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
61 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | 61 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; |
62 | u8 *ie = mgmt->u.assoc_resp.variable; | 62 | u8 *ie = mgmt->u.assoc_resp.variable; |
63 | int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); | 63 | int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); |
64 | bool done; | 64 | struct cfg80211_internal_bss *bss = NULL; |
65 | 65 | ||
66 | wdev_lock(wdev); | 66 | wdev_lock(wdev); |
67 | 67 | ||
@@ -69,22 +69,32 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
69 | 69 | ||
70 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); | 70 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); |
71 | 71 | ||
72 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, | ||
73 | status_code, | ||
74 | status_code == WLAN_STATUS_SUCCESS); | ||
75 | |||
76 | if (status_code == WLAN_STATUS_SUCCESS) { | 72 | if (status_code == WLAN_STATUS_SUCCESS) { |
77 | for (i = 0; wdev->current_bss && i < MAX_AUTH_BSSES; i++) { | 73 | for (i = 0; i < MAX_AUTH_BSSES; i++) { |
78 | if (wdev->auth_bsses[i] == wdev->current_bss) { | 74 | if (!wdev->auth_bsses[i]) |
79 | cfg80211_unhold_bss(wdev->auth_bsses[i]); | 75 | continue; |
80 | cfg80211_put_bss(&wdev->auth_bsses[i]->pub); | 76 | if (memcmp(wdev->auth_bsses[i]->pub.bssid, mgmt->bssid, |
77 | ETH_ALEN) == 0) { | ||
78 | bss = wdev->auth_bsses[i]; | ||
81 | wdev->auth_bsses[i] = NULL; | 79 | wdev->auth_bsses[i] = NULL; |
82 | done = true; | 80 | /* additional reference to drop hold */ |
81 | cfg80211_ref_bss(bss); | ||
83 | break; | 82 | break; |
84 | } | 83 | } |
85 | } | 84 | } |
86 | 85 | ||
87 | WARN_ON(!done); | 86 | WARN_ON(!bss); |
87 | } | ||
88 | |||
89 | /* this consumes one bss reference (unless bss is NULL) */ | ||
90 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, | ||
91 | status_code, | ||
92 | status_code == WLAN_STATUS_SUCCESS, | ||
93 | bss ? &bss->pub : NULL); | ||
94 | /* drop hold now, and also reference acquired above */ | ||
95 | if (bss) { | ||
96 | cfg80211_unhold_bss(bss); | ||
97 | cfg80211_put_bss(&bss->pub); | ||
88 | } | 98 | } |
89 | 99 | ||
90 | wdev_unlock(wdev); | 100 | wdev_unlock(wdev); |
@@ -144,7 +154,7 @@ static void __cfg80211_send_deauth(struct net_device *dev, | |||
144 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { | 154 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { |
145 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, | 155 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, |
146 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 156 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
147 | false); | 157 | false, NULL); |
148 | } | 158 | } |
149 | } | 159 | } |
150 | 160 | ||
@@ -241,7 +251,7 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | |||
241 | if (wdev->sme_state == CFG80211_SME_CONNECTING) | 251 | if (wdev->sme_state == CFG80211_SME_CONNECTING) |
242 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, | 252 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, |
243 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 253 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
244 | false); | 254 | false, NULL); |
245 | 255 | ||
246 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { | 256 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { |
247 | if (wdev->authtry_bsses[i] && | 257 | if (wdev->authtry_bsses[i] && |
@@ -275,7 +285,7 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) | |||
275 | if (wdev->sme_state == CFG80211_SME_CONNECTING) | 285 | if (wdev->sme_state == CFG80211_SME_CONNECTING) |
276 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, | 286 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, |
277 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 287 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
278 | false); | 288 | false, NULL); |
279 | 289 | ||
280 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { | 290 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { |
281 | if (wdev->auth_bsses[i] && | 291 | if (wdev->auth_bsses[i] && |