aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas
diff options
context:
space:
mode:
authorHolger Schurig <hs4233@mail.mn-solutions.de>2008-04-02 10:27:42 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-08 16:44:40 -0400
commit245bf20f9c159f8d35befbc038997096b759459c (patch)
treeefa49f9090e2933689140d8725d1bbcbcafb7f8c /drivers/net/wireless/libertas
parent697900ac14528e985b66f471ecb81082fc00baa9 (diff)
libertas: move association code from scan.c into assoc.c
Besides code moving, I did the following changes: * made some functions static * removed some unneeded #include's * made patch checkpatch.pl clean Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de> Acked-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r--drivers/net/wireless/libertas/assoc.c352
-rw-r--r--drivers/net/wireless/libertas/dev.h41
-rw-r--r--drivers/net/wireless/libertas/main.c1
-rw-r--r--drivers/net/wireless/libertas/scan.c364
-rw-r--r--drivers/net/wireless/libertas/scan.h62
-rw-r--r--drivers/net/wireless/libertas/wext.c1
6 files changed, 397 insertions, 424 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index e794e93a2297..319b4f931a62 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -5,6 +5,7 @@
5#include "assoc.h" 5#include "assoc.h"
6#include "decl.h" 6#include "decl.h"
7#include "host.h" 7#include "host.h"
8#include "scan.h"
8#include "cmd.h" 9#include "cmd.h"
9 10
10 11
@@ -170,6 +171,272 @@ int lbs_stop_adhoc_network(struct lbs_private *priv)
170 0, CMD_OPTION_WAITFORRSP, 0, NULL); 171 0, CMD_OPTION_WAITFORRSP, 0, NULL);
171} 172}
172 173
174static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
175 struct bss_descriptor *match_bss)
176{
177 if (!secinfo->wep_enabled && !secinfo->WPAenabled
178 && !secinfo->WPA2enabled
179 && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
180 && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
181 && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
182 return 1;
183 else
184 return 0;
185}
186
187static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
188 struct bss_descriptor *match_bss)
189{
190 if (secinfo->wep_enabled && !secinfo->WPAenabled
191 && !secinfo->WPA2enabled
192 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
193 return 1;
194 else
195 return 0;
196}
197
198static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
199 struct bss_descriptor *match_bss)
200{
201 if (!secinfo->wep_enabled && secinfo->WPAenabled
202 && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
203 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
204 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
205 )
206 return 1;
207 else
208 return 0;
209}
210
211static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
212 struct bss_descriptor *match_bss)
213{
214 if (!secinfo->wep_enabled && secinfo->WPA2enabled &&
215 (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
216 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
217 (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
218 )
219 return 1;
220 else
221 return 0;
222}
223
224static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
225 struct bss_descriptor *match_bss)
226{
227 if (!secinfo->wep_enabled && !secinfo->WPAenabled
228 && !secinfo->WPA2enabled
229 && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
230 && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
231 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
232 return 1;
233 else
234 return 0;
235}
236
237/**
238 * @brief Check if a scanned network compatible with the driver settings
239 *
240 * WEP WPA WPA2 ad-hoc encrypt Network
241 * enabled enabled enabled AES mode privacy WPA WPA2 Compatible
242 * 0 0 0 0 NONE 0 0 0 yes No security
243 * 1 0 0 0 NONE 1 0 0 yes Static WEP
244 * 0 1 0 0 x 1x 1 x yes WPA
245 * 0 0 1 0 x 1x x 1 yes WPA2
246 * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
247 * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
248 *
249 *
250 * @param priv A pointer to struct lbs_private
251 * @param index Index in scantable to check against current driver settings
252 * @param mode Network mode: Infrastructure or IBSS
253 *
254 * @return Index in scantable, or error code if negative
255 */
256static int is_network_compatible(struct lbs_private *priv,
257 struct bss_descriptor *bss, uint8_t mode)
258{
259 int matched = 0;
260
261 lbs_deb_enter(LBS_DEB_SCAN);
262
263 if (bss->mode != mode)
264 goto done;
265
266 matched = match_bss_no_security(&priv->secinfo, bss);
267 if (matched)
268 goto done;
269 matched = match_bss_static_wep(&priv->secinfo, bss);
270 if (matched)
271 goto done;
272 matched = match_bss_wpa(&priv->secinfo, bss);
273 if (matched) {
274 lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x "
275 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
276 "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
277 priv->secinfo.wep_enabled ? "e" : "d",
278 priv->secinfo.WPAenabled ? "e" : "d",
279 priv->secinfo.WPA2enabled ? "e" : "d",
280 (bss->capability & WLAN_CAPABILITY_PRIVACY));
281 goto done;
282 }
283 matched = match_bss_wpa2(&priv->secinfo, bss);
284 if (matched) {
285 lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x "
286 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
287 "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
288 priv->secinfo.wep_enabled ? "e" : "d",
289 priv->secinfo.WPAenabled ? "e" : "d",
290 priv->secinfo.WPA2enabled ? "e" : "d",
291 (bss->capability & WLAN_CAPABILITY_PRIVACY));
292 goto done;
293 }
294 matched = match_bss_dynamic_wep(&priv->secinfo, bss);
295 if (matched) {
296 lbs_deb_scan("is_network_compatible() dynamic WEP: "
297 "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
298 bss->wpa_ie[0], bss->rsn_ie[0],
299 (bss->capability & WLAN_CAPABILITY_PRIVACY));
300 goto done;
301 }
302
303 /* bss security settings don't match those configured on card */
304 lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x "
305 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
306 bss->wpa_ie[0], bss->rsn_ie[0],
307 priv->secinfo.wep_enabled ? "e" : "d",
308 priv->secinfo.WPAenabled ? "e" : "d",
309 priv->secinfo.WPA2enabled ? "e" : "d",
310 (bss->capability & WLAN_CAPABILITY_PRIVACY));
311
312done:
313 lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
314 return matched;
315}
316
317/**
318 * @brief This function finds a specific compatible BSSID in the scan list
319 *
320 * Used in association code
321 *
322 * @param priv A pointer to struct lbs_private
323 * @param bssid BSSID to find in the scan list
324 * @param mode Network mode: Infrastructure or IBSS
325 *
326 * @return index in BSSID list, or error return code (< 0)
327 */
328static struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
329 uint8_t *bssid, uint8_t mode)
330{
331 struct bss_descriptor *iter_bss;
332 struct bss_descriptor *found_bss = NULL;
333
334 lbs_deb_enter(LBS_DEB_SCAN);
335
336 if (!bssid)
337 goto out;
338
339 lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN);
340
341 /* Look through the scan table for a compatible match. The loop will
342 * continue past a matched bssid that is not compatible in case there
343 * is an AP with multiple SSIDs assigned to the same BSSID
344 */
345 mutex_lock(&priv->lock);
346 list_for_each_entry(iter_bss, &priv->network_list, list) {
347 if (compare_ether_addr(iter_bss->bssid, bssid))
348 continue; /* bssid doesn't match */
349 switch (mode) {
350 case IW_MODE_INFRA:
351 case IW_MODE_ADHOC:
352 if (!is_network_compatible(priv, iter_bss, mode))
353 break;
354 found_bss = iter_bss;
355 break;
356 default:
357 found_bss = iter_bss;
358 break;
359 }
360 }
361 mutex_unlock(&priv->lock);
362
363out:
364 lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
365 return found_bss;
366}
367
368/**
369 * @brief This function finds ssid in ssid list.
370 *
371 * Used in association code
372 *
373 * @param priv A pointer to struct lbs_private
374 * @param ssid SSID to find in the list
375 * @param bssid BSSID to qualify the SSID selection (if provided)
376 * @param mode Network mode: Infrastructure or IBSS
377 *
378 * @return index in BSSID list
379 */
380static struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
381 uint8_t *ssid, uint8_t ssid_len,
382 uint8_t *bssid, uint8_t mode,
383 int channel)
384{
385 u32 bestrssi = 0;
386 struct bss_descriptor *iter_bss = NULL;
387 struct bss_descriptor *found_bss = NULL;
388 struct bss_descriptor *tmp_oldest = NULL;
389
390 lbs_deb_enter(LBS_DEB_SCAN);
391
392 mutex_lock(&priv->lock);
393
394 list_for_each_entry(iter_bss, &priv->network_list, list) {
395 if (!tmp_oldest ||
396 (iter_bss->last_scanned < tmp_oldest->last_scanned))
397 tmp_oldest = iter_bss;
398
399 if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
400 ssid, ssid_len) != 0)
401 continue; /* ssid doesn't match */
402 if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
403 continue; /* bssid doesn't match */
404 if ((channel > 0) && (iter_bss->channel != channel))
405 continue; /* channel doesn't match */
406
407 switch (mode) {
408 case IW_MODE_INFRA:
409 case IW_MODE_ADHOC:
410 if (!is_network_compatible(priv, iter_bss, mode))
411 break;
412
413 if (bssid) {
414 /* Found requested BSSID */
415 found_bss = iter_bss;
416 goto out;
417 }
418
419 if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
420 bestrssi = SCAN_RSSI(iter_bss->rssi);
421 found_bss = iter_bss;
422 }
423 break;
424 case IW_MODE_AUTO:
425 default:
426 if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
427 bestrssi = SCAN_RSSI(iter_bss->rssi);
428 found_bss = iter_bss;
429 }
430 break;
431 }
432 }
433
434out:
435 mutex_unlock(&priv->lock);
436 lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
437 return found_bss;
438}
439
173static int assoc_helper_essid(struct lbs_private *priv, 440static int assoc_helper_essid(struct lbs_private *priv,
174 struct assoc_request * assoc_req) 441 struct assoc_request * assoc_req)
175{ 442{
@@ -617,6 +884,91 @@ static int should_stop_adhoc(struct lbs_private *priv,
617} 884}
618 885
619 886
887/**
888 * @brief This function finds the best SSID in the Scan List
889 *
890 * Search the scan table for the best SSID that also matches the current
891 * adapter network preference (infrastructure or adhoc)
892 *
893 * @param priv A pointer to struct lbs_private
894 *
895 * @return index in BSSID list
896 */
897static struct bss_descriptor *lbs_find_best_ssid_in_list(
898 struct lbs_private *priv, uint8_t mode)
899{
900 uint8_t bestrssi = 0;
901 struct bss_descriptor *iter_bss;
902 struct bss_descriptor *best_bss = NULL;
903
904 lbs_deb_enter(LBS_DEB_SCAN);
905
906 mutex_lock(&priv->lock);
907
908 list_for_each_entry(iter_bss, &priv->network_list, list) {
909 switch (mode) {
910 case IW_MODE_INFRA:
911 case IW_MODE_ADHOC:
912 if (!is_network_compatible(priv, iter_bss, mode))
913 break;
914 if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
915 break;
916 bestrssi = SCAN_RSSI(iter_bss->rssi);
917 best_bss = iter_bss;
918 break;
919 case IW_MODE_AUTO:
920 default:
921 if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
922 break;
923 bestrssi = SCAN_RSSI(iter_bss->rssi);
924 best_bss = iter_bss;
925 break;
926 }
927 }
928
929 mutex_unlock(&priv->lock);
930 lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
931 return best_bss;
932}
933
934/**
935 * @brief Find the best AP
936 *
937 * Used from association worker.
938 *
939 * @param priv A pointer to struct lbs_private structure
940 * @param pSSID A pointer to AP's ssid
941 *
942 * @return 0--success, otherwise--fail
943 */
944static int lbs_find_best_network_ssid(struct lbs_private *priv,
945 uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode,
946 uint8_t *out_mode)
947{
948 int ret = -1;
949 struct bss_descriptor *found;
950
951 lbs_deb_enter(LBS_DEB_SCAN);
952
953 priv->scan_ssid_len = 0;
954 lbs_scan_networks(priv, 1);
955 if (priv->surpriseremoved)
956 goto out;
957
958 found = lbs_find_best_ssid_in_list(priv, preferred_mode);
959 if (found && (found->ssid_len > 0)) {
960 memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
961 *out_ssid_len = found->ssid_len;
962 *out_mode = found->mode;
963 ret = 0;
964 }
965
966out:
967 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
968 return ret;
969}
970
971
620void lbs_association_worker(struct work_struct *work) 972void lbs_association_worker(struct work_struct *work)
621{ 973{
622 struct lbs_private *priv = container_of(work, struct lbs_private, 974 struct lbs_private *priv = container_of(work, struct lbs_private,
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 3f3e7f6e68b3..1e6bae80396b 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -10,9 +10,10 @@
10#include <linux/wireless.h> 10#include <linux/wireless.h>
11#include <linux/ethtool.h> 11#include <linux/ethtool.h>
12#include <linux/debugfs.h> 12#include <linux/debugfs.h>
13#include <net/ieee80211.h>
13 14
14#include "defs.h" 15#include "defs.h"
15#include "scan.h" 16#include "hostcmd.h"
16 17
17extern struct ethtool_ops lbs_ethtool_ops; 18extern struct ethtool_ops lbs_ethtool_ops;
18 19
@@ -325,6 +326,44 @@ struct lbs_private {
325 326
326extern struct cmd_confirm_sleep confirm_sleep; 327extern struct cmd_confirm_sleep confirm_sleep;
327 328
329/**
330 * @brief Structure used to store information for each beacon/probe response
331 */
332struct bss_descriptor {
333 u8 bssid[ETH_ALEN];
334
335 u8 ssid[IW_ESSID_MAX_SIZE + 1];
336 u8 ssid_len;
337
338 u16 capability;
339 u32 rssi;
340 u32 channel;
341 u16 beaconperiod;
342 u32 atimwindow;
343
344 /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
345 u8 mode;
346
347 /* zero-terminated array of supported data rates */
348 u8 rates[MAX_RATES + 1];
349
350 unsigned long last_scanned;
351
352 union ieeetypes_phyparamset phyparamset;
353 union IEEEtypes_ssparamset ssparamset;
354
355 struct ieeetypes_countryinfofullset countryinfo;
356
357 u8 wpa_ie[MAX_WPA_IE_LEN];
358 size_t wpa_ie_len;
359 u8 rsn_ie[MAX_WPA_IE_LEN];
360 size_t rsn_ie_len;
361
362 u8 mesh;
363
364 struct list_head list;
365};
366
328/** Association request 367/** Association request
329 * 368 *
330 * Encapsulates all the options that describe a specific assocation request 369 * Encapsulates all the options that describe a specific assocation request
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 15c9cc8bab48..8f1122610974 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -19,6 +19,7 @@
19#include "dev.h" 19#include "dev.h"
20#include "wext.h" 20#include "wext.h"
21#include "debugfs.h" 21#include "debugfs.h"
22#include "scan.h"
22#include "assoc.h" 23#include "assoc.h"
23#include "cmd.h" 24#include "cmd.h"
24 25
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 1c7003d7de43..e72c97a0d6c1 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -4,22 +4,13 @@
4 * IOCTL handlers as well as command preperation and response routines 4 * IOCTL handlers as well as command preperation and response routines
5 * for sending scan commands to the firmware. 5 * for sending scan commands to the firmware.
6 */ 6 */
7#include <linux/ctype.h>
8#include <linux/if.h>
9#include <linux/netdevice.h>
10#include <linux/wireless.h>
11#include <linux/etherdevice.h> 7#include <linux/etherdevice.h>
12
13#include <net/ieee80211.h>
14#include <net/iw_handler.h>
15
16#include <asm/unaligned.h> 8#include <asm/unaligned.h>
17 9
18#include "host.h" 10#include "host.h"
19#include "decl.h" 11#include "decl.h"
20#include "dev.h" 12#include "dev.h"
21#include "scan.h" 13#include "scan.h"
22#include "assoc.h"
23#include "cmd.h" 14#include "cmd.h"
24 15
25//! Approximate amount of data needed to pass a scan result back to iwlist 16//! Approximate amount of data needed to pass a scan result back to iwlist
@@ -110,69 +101,6 @@ int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2,
110 return memcmp(ssid1, ssid2, ssid1_len); 101 return memcmp(ssid1, ssid2, ssid1_len);
111} 102}
112 103
113static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
114 struct bss_descriptor *match_bss)
115{
116 if (!secinfo->wep_enabled && !secinfo->WPAenabled
117 && !secinfo->WPA2enabled
118 && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
119 && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
120 && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
121 return 1;
122 else
123 return 0;
124}
125
126static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
127 struct bss_descriptor *match_bss)
128{
129 if (secinfo->wep_enabled && !secinfo->WPAenabled
130 && !secinfo->WPA2enabled
131 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
132 return 1;
133 else
134 return 0;
135}
136
137static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
138 struct bss_descriptor *match_bss)
139{
140 if (!secinfo->wep_enabled && secinfo->WPAenabled
141 && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
142 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
143 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
144 )
145 return 1;
146 else
147 return 0;
148}
149
150static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
151 struct bss_descriptor *match_bss)
152{
153 if (!secinfo->wep_enabled && secinfo->WPA2enabled
154 && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
155 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
156 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
157 )
158 return 1;
159 else
160 return 0;
161}
162
163static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
164 struct bss_descriptor *match_bss)
165{
166 if (!secinfo->wep_enabled && !secinfo->WPAenabled
167 && !secinfo->WPA2enabled
168 && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
169 && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
170 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
171 return 1;
172 else
173 return 0;
174}
175
176static inline int is_same_network(struct bss_descriptor *src, 104static inline int is_same_network(struct bss_descriptor *src,
177 struct bss_descriptor *dst) 105 struct bss_descriptor *dst)
178{ 106{
@@ -185,78 +113,6 @@ static inline int is_same_network(struct bss_descriptor *src,
185 !memcmp(src->ssid, dst->ssid, src->ssid_len)); 113 !memcmp(src->ssid, dst->ssid, src->ssid_len));
186} 114}
187 115
188/**
189 * @brief Check if a scanned network compatible with the driver settings
190 *
191 * WEP WPA WPA2 ad-hoc encrypt Network
192 * enabled enabled enabled AES mode privacy WPA WPA2 Compatible
193 * 0 0 0 0 NONE 0 0 0 yes No security
194 * 1 0 0 0 NONE 1 0 0 yes Static WEP
195 * 0 1 0 0 x 1x 1 x yes WPA
196 * 0 0 1 0 x 1x x 1 yes WPA2
197 * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
198 * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
199 *
200 *
201 * @param priv A pointer to struct lbs_private
202 * @param index Index in scantable to check against current driver settings
203 * @param mode Network mode: Infrastructure or IBSS
204 *
205 * @return Index in scantable, or error code if negative
206 */
207static int is_network_compatible(struct lbs_private *priv,
208 struct bss_descriptor *bss, uint8_t mode)
209{
210 int matched = 0;
211
212 lbs_deb_enter(LBS_DEB_SCAN);
213
214 if (bss->mode != mode)
215 goto done;
216
217 if ((matched = match_bss_no_security(&priv->secinfo, bss))) {
218 goto done;
219 } else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) {
220 goto done;
221 } else if ((matched = match_bss_wpa(&priv->secinfo, bss))) {
222 lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x "
223 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
224 "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
225 priv->secinfo.wep_enabled ? "e" : "d",
226 priv->secinfo.WPAenabled ? "e" : "d",
227 priv->secinfo.WPA2enabled ? "e" : "d",
228 (bss->capability & WLAN_CAPABILITY_PRIVACY));
229 goto done;
230 } else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) {
231 lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x "
232 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
233 "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
234 priv->secinfo.wep_enabled ? "e" : "d",
235 priv->secinfo.WPAenabled ? "e" : "d",
236 priv->secinfo.WPA2enabled ? "e" : "d",
237 (bss->capability & WLAN_CAPABILITY_PRIVACY));
238 goto done;
239 } else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) {
240 lbs_deb_scan("is_network_compatible() dynamic WEP: "
241 "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
242 bss->wpa_ie[0], bss->rsn_ie[0],
243 (bss->capability & WLAN_CAPABILITY_PRIVACY));
244 goto done;
245 }
246
247 /* bss security settings don't match those configured on card */
248 lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x "
249 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
250 bss->wpa_ie[0], bss->rsn_ie[0],
251 priv->secinfo.wep_enabled ? "e" : "d",
252 priv->secinfo.WPAenabled ? "e" : "d",
253 priv->secinfo.WPA2enabled ? "e" : "d",
254 (bss->capability & WLAN_CAPABILITY_PRIVACY));
255
256done:
257 lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
258 return matched;
259}
260 116
261 117
262 118
@@ -341,7 +197,6 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
341 return chanidx; 197 return chanidx;
342} 198}
343 199
344
345/* 200/*
346 * Add SSID TLV of the form: 201 * Add SSID TLV of the form:
347 * 202 *
@@ -359,7 +214,6 @@ static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
359 return sizeof(ssid_tlv->header) + priv->scan_ssid_len; 214 return sizeof(ssid_tlv->header) + priv->scan_ssid_len;
360} 215}
361 216
362
363/* 217/*
364 * Add CHANLIST TLV of the form 218 * Add CHANLIST TLV of the form
365 * 219 *
@@ -398,7 +252,6 @@ static int lbs_scan_add_chanlist_tlv(uint8_t *tlv,
398 return sizeof(chan_tlv->header) + size; 252 return sizeof(chan_tlv->header) + size;
399} 253}
400 254
401
402/* 255/*
403 * Add RATES TLV of the form 256 * Add RATES TLV of the form
404 * 257 *
@@ -433,7 +286,6 @@ static int lbs_scan_add_rates_tlv(uint8_t *tlv)
433 return sizeof(rate_tlv->header) + i; 286 return sizeof(rate_tlv->header) + i;
434} 287}
435 288
436
437/* 289/*
438 * Generate the CMD_802_11_SCAN command with the proper tlv 290 * Generate the CMD_802_11_SCAN command with the proper tlv
439 * for a bunch of channels. 291 * for a bunch of channels.
@@ -482,12 +334,9 @@ out:
482 return ret; 334 return ret;
483} 335}
484 336
485
486/** 337/**
487 * @brief Internal function used to start a scan based on an input config 338 * @brief Internal function used to start a scan based on an input config
488 * 339 *
489 * Also used from debugfs
490 *
491 * Use the input user scan configuration information when provided in 340 * Use the input user scan configuration information when provided in
492 * order to send the appropriate scan commands to firmware to populate or 341 * order to send the appropriate scan commands to firmware to populate or
493 * update the internal driver scan table 342 * update the internal driver scan table
@@ -497,7 +346,7 @@ out:
497 * 346 *
498 * @return 0 or < 0 if error 347 * @return 0 or < 0 if error
499 */ 348 */
500static int lbs_scan_networks(struct lbs_private *priv, int full_scan) 349int lbs_scan_networks(struct lbs_private *priv, int full_scan)
501{ 350{
502 int ret = -ENOMEM; 351 int ret = -ENOMEM;
503 struct chanscanparamset *chan_list; 352 struct chanscanparamset *chan_list;
@@ -627,9 +476,6 @@ out:
627 return ret; 476 return ret;
628} 477}
629 478
630
631
632
633void lbs_scan_worker(struct work_struct *work) 479void lbs_scan_worker(struct work_struct *work)
634{ 480{
635 struct lbs_private *priv = 481 struct lbs_private *priv =
@@ -881,214 +727,6 @@ done:
881} 727}
882 728
883/** 729/**
884 * @brief This function finds a specific compatible BSSID in the scan list
885 *
886 * Used in association code
887 *
888 * @param priv A pointer to struct lbs_private
889 * @param bssid BSSID to find in the scan list
890 * @param mode Network mode: Infrastructure or IBSS
891 *
892 * @return index in BSSID list, or error return code (< 0)
893 */
894struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
895 uint8_t *bssid, uint8_t mode)
896{
897 struct bss_descriptor *iter_bss;
898 struct bss_descriptor *found_bss = NULL;
899
900 lbs_deb_enter(LBS_DEB_SCAN);
901
902 if (!bssid)
903 goto out;
904
905 lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN);
906
907 /* Look through the scan table for a compatible match. The loop will
908 * continue past a matched bssid that is not compatible in case there
909 * is an AP with multiple SSIDs assigned to the same BSSID
910 */
911 mutex_lock(&priv->lock);
912 list_for_each_entry (iter_bss, &priv->network_list, list) {
913 if (compare_ether_addr(iter_bss->bssid, bssid))
914 continue; /* bssid doesn't match */
915 switch (mode) {
916 case IW_MODE_INFRA:
917 case IW_MODE_ADHOC:
918 if (!is_network_compatible(priv, iter_bss, mode))
919 break;
920 found_bss = iter_bss;
921 break;
922 default:
923 found_bss = iter_bss;
924 break;
925 }
926 }
927 mutex_unlock(&priv->lock);
928
929out:
930 lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
931 return found_bss;
932}
933
934/**
935 * @brief This function finds ssid in ssid list.
936 *
937 * Used in association code
938 *
939 * @param priv A pointer to struct lbs_private
940 * @param ssid SSID to find in the list
941 * @param bssid BSSID to qualify the SSID selection (if provided)
942 * @param mode Network mode: Infrastructure or IBSS
943 *
944 * @return index in BSSID list
945 */
946struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
947 uint8_t *ssid, uint8_t ssid_len,
948 uint8_t *bssid, uint8_t mode,
949 int channel)
950{
951 u32 bestrssi = 0;
952 struct bss_descriptor * iter_bss = NULL;
953 struct bss_descriptor * found_bss = NULL;
954 struct bss_descriptor * tmp_oldest = NULL;
955
956 lbs_deb_enter(LBS_DEB_SCAN);
957
958 mutex_lock(&priv->lock);
959
960 list_for_each_entry (iter_bss, &priv->network_list, list) {
961 if ( !tmp_oldest
962 || (iter_bss->last_scanned < tmp_oldest->last_scanned))
963 tmp_oldest = iter_bss;
964
965 if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
966 ssid, ssid_len) != 0)
967 continue; /* ssid doesn't match */
968 if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
969 continue; /* bssid doesn't match */
970 if ((channel > 0) && (iter_bss->channel != channel))
971 continue; /* channel doesn't match */
972
973 switch (mode) {
974 case IW_MODE_INFRA:
975 case IW_MODE_ADHOC:
976 if (!is_network_compatible(priv, iter_bss, mode))
977 break;
978
979 if (bssid) {
980 /* Found requested BSSID */
981 found_bss = iter_bss;
982 goto out;
983 }
984
985 if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
986 bestrssi = SCAN_RSSI(iter_bss->rssi);
987 found_bss = iter_bss;
988 }
989 break;
990 case IW_MODE_AUTO:
991 default:
992 if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
993 bestrssi = SCAN_RSSI(iter_bss->rssi);
994 found_bss = iter_bss;
995 }
996 break;
997 }
998 }
999
1000out:
1001 mutex_unlock(&priv->lock);
1002 lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
1003 return found_bss;
1004}
1005
1006/**
1007 * @brief This function finds the best SSID in the Scan List
1008 *
1009 * Search the scan table for the best SSID that also matches the current
1010 * adapter network preference (infrastructure or adhoc)
1011 *
1012 * @param priv A pointer to struct lbs_private
1013 *
1014 * @return index in BSSID list
1015 */
1016static struct bss_descriptor *lbs_find_best_ssid_in_list(struct lbs_private *priv,
1017 uint8_t mode)
1018{
1019 uint8_t bestrssi = 0;
1020 struct bss_descriptor *iter_bss;
1021 struct bss_descriptor *best_bss = NULL;
1022
1023 lbs_deb_enter(LBS_DEB_SCAN);
1024
1025 mutex_lock(&priv->lock);
1026
1027 list_for_each_entry (iter_bss, &priv->network_list, list) {
1028 switch (mode) {
1029 case IW_MODE_INFRA:
1030 case IW_MODE_ADHOC:
1031 if (!is_network_compatible(priv, iter_bss, mode))
1032 break;
1033 if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
1034 break;
1035 bestrssi = SCAN_RSSI(iter_bss->rssi);
1036 best_bss = iter_bss;
1037 break;
1038 case IW_MODE_AUTO:
1039 default:
1040 if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
1041 break;
1042 bestrssi = SCAN_RSSI(iter_bss->rssi);
1043 best_bss = iter_bss;
1044 break;
1045 }
1046 }
1047
1048 mutex_unlock(&priv->lock);
1049 lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
1050 return best_bss;
1051}
1052
1053/**
1054 * @brief Find the best AP
1055 *
1056 * Used from association worker.
1057 *
1058 * @param priv A pointer to struct lbs_private structure
1059 * @param pSSID A pointer to AP's ssid
1060 *
1061 * @return 0--success, otherwise--fail
1062 */
1063int lbs_find_best_network_ssid(struct lbs_private *priv, uint8_t *out_ssid,
1064 uint8_t *out_ssid_len, uint8_t preferred_mode,
1065 uint8_t *out_mode)
1066{
1067 int ret = -1;
1068 struct bss_descriptor *found;
1069
1070 lbs_deb_enter(LBS_DEB_SCAN);
1071
1072 priv->scan_ssid_len = 0;
1073 lbs_scan_networks(priv, 1);
1074 if (priv->surpriseremoved)
1075 goto out;
1076
1077 found = lbs_find_best_ssid_in_list(priv, preferred_mode);
1078 if (found && (found->ssid_len > 0)) {
1079 memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
1080 *out_ssid_len = found->ssid_len;
1081 *out_mode = found->mode;
1082 ret = 0;
1083 }
1084
1085out:
1086 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
1087 return ret;
1088}
1089
1090
1091/**
1092 * @brief Send a scan command for all available channels filtered on a spec 730 * @brief Send a scan command for all available channels filtered on a spec
1093 * 731 *
1094 * Used in association code and from debugfs 732 * Used in association code and from debugfs
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
index b50cf1415e04..9e07b0464a8e 100644
--- a/drivers/net/wireless/libertas/scan.h
+++ b/drivers/net/wireless/libertas/scan.h
@@ -7,73 +7,13 @@
7#ifndef _LBS_SCAN_H 7#ifndef _LBS_SCAN_H
8#define _LBS_SCAN_H 8#define _LBS_SCAN_H
9 9
10#include <net/ieee80211.h>
11#include "hostcmd.h"
12
13/** 10/**
14 * @brief Maximum number of channels that can be sent in a setuserscan ioctl 11 * @brief Maximum number of channels that can be sent in a setuserscan ioctl
15 */ 12 */
16#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50 13#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
17 14
18//! Infrastructure BSS scan type in cmd_ds_802_11_scan
19#define LBS_SCAN_BSS_TYPE_BSS 1
20
21//! Adhoc BSS scan type in cmd_ds_802_11_scan
22#define LBS_SCAN_BSS_TYPE_IBSS 2
23
24//! Adhoc or Infrastructure BSS scan type in cmd_ds_802_11_scan, no filter
25#define LBS_SCAN_BSS_TYPE_ANY 3
26
27/**
28 * @brief Structure used to store information for each beacon/probe response
29 */
30struct bss_descriptor {
31 u8 bssid[ETH_ALEN];
32
33 u8 ssid[IW_ESSID_MAX_SIZE + 1];
34 u8 ssid_len;
35
36 u16 capability;
37 u32 rssi;
38 u32 channel;
39 u16 beaconperiod;
40 u32 atimwindow;
41
42 /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
43 u8 mode;
44
45 /* zero-terminated array of supported data rates */
46 u8 rates[MAX_RATES + 1];
47
48 unsigned long last_scanned;
49
50 union ieeetypes_phyparamset phyparamset;
51 union IEEEtypes_ssparamset ssparamset;
52
53 struct ieeetypes_countryinfofullset countryinfo;
54
55 u8 wpa_ie[MAX_WPA_IE_LEN];
56 size_t wpa_ie_len;
57 u8 rsn_ie[MAX_WPA_IE_LEN];
58 size_t rsn_ie_len;
59
60 u8 mesh;
61
62 struct list_head list;
63};
64
65int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len); 15int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
66 16
67struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
68 u8 *ssid, u8 ssid_len, u8 *bssid, u8 mode,
69 int channel);
70
71struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
72 u8 *bssid, u8 mode);
73
74int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid,
75 u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode);
76
77int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, 17int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
78 u8 ssid_len); 18 u8 ssid_len);
79 19
@@ -82,6 +22,8 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
82int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, 22int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
83 union iwreq_data *wrqu, char *extra); 23 union iwreq_data *wrqu, char *extra);
84 24
25int lbs_scan_networks(struct lbs_private *priv, int full_scan);
26
85void lbs_scan_worker(struct work_struct *work); 27void lbs_scan_worker(struct work_struct *work);
86 28
87#endif 29#endif
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 375072130221..4ab5b8523ed9 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -17,6 +17,7 @@
17#include "defs.h" 17#include "defs.h"
18#include "dev.h" 18#include "dev.h"
19#include "wext.h" 19#include "wext.h"
20#include "scan.h"
20#include "assoc.h" 21#include "assoc.h"
21#include "cmd.h" 22#include "cmd.h"
22 23