aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/scan.c')
-rw-r--r--drivers/net/wireless/libertas/scan.c101
1 files changed, 53 insertions, 48 deletions
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 22c4c6110521..93f74763a010 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -4,8 +4,11 @@
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/types.h>
7#include <linux/etherdevice.h> 8#include <linux/etherdevice.h>
9#include <linux/if_arp.h>
8#include <asm/unaligned.h> 10#include <asm/unaligned.h>
11#include <net/lib80211.h>
9 12
10#include "host.h" 13#include "host.h"
11#include "decl.h" 14#include "decl.h"
@@ -52,6 +55,8 @@
52//! Scan time specified in the channel TLV for each channel for active scans 55//! Scan time specified in the channel TLV for each channel for active scans
53#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 56#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100
54 57
58#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
59
55static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, 60static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
56 struct cmd_header *resp); 61 struct cmd_header *resp);
57 62
@@ -359,7 +364,7 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan)
359#ifdef CONFIG_LIBERTAS_DEBUG 364#ifdef CONFIG_LIBERTAS_DEBUG
360 struct bss_descriptor *iter; 365 struct bss_descriptor *iter;
361 int i = 0; 366 int i = 0;
362 DECLARE_MAC_BUF(mac); 367 DECLARE_SSID_BUF(ssid);
363#endif 368#endif
364 369
365 lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan); 370 lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan);
@@ -451,9 +456,9 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan)
451 mutex_lock(&priv->lock); 456 mutex_lock(&priv->lock);
452 lbs_deb_scan("scan table:\n"); 457 lbs_deb_scan("scan table:\n");
453 list_for_each_entry(iter, &priv->network_list, list) 458 list_for_each_entry(iter, &priv->network_list, list)
454 lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n", 459 lbs_deb_scan("%02d: BSSID %pM, RSSI %d, SSID '%s'\n",
455 i++, print_mac(mac, iter->bssid), iter->rssi, 460 i++, iter->bssid, iter->rssi,
456 escape_essid(iter->ssid, iter->ssid_len)); 461 print_ssid(ssid, iter->ssid, iter->ssid_len));
457 mutex_unlock(&priv->lock); 462 mutex_unlock(&priv->lock);
458#endif 463#endif
459 464
@@ -512,7 +517,7 @@ static int lbs_process_bss(struct bss_descriptor *bss,
512 struct ieeetypes_dsparamset *pDS; 517 struct ieeetypes_dsparamset *pDS;
513 struct ieeetypes_cfparamset *pCF; 518 struct ieeetypes_cfparamset *pCF;
514 struct ieeetypes_ibssparamset *pibss; 519 struct ieeetypes_ibssparamset *pibss;
515 DECLARE_MAC_BUF(mac); 520 DECLARE_SSID_BUF(ssid);
516 struct ieeetypes_countryinfoset *pcountryinfo; 521 struct ieeetypes_countryinfoset *pcountryinfo;
517 uint8_t *pos, *end, *p; 522 uint8_t *pos, *end, *p;
518 uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; 523 uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
@@ -544,7 +549,7 @@ static int lbs_process_bss(struct bss_descriptor *bss,
544 *bytesleft -= beaconsize; 549 *bytesleft -= beaconsize;
545 550
546 memcpy(bss->bssid, pos, ETH_ALEN); 551 memcpy(bss->bssid, pos, ETH_ALEN);
547 lbs_deb_scan("process_bss: BSSID %s\n", print_mac(mac, bss->bssid)); 552 lbs_deb_scan("process_bss: BSSID %pM\n", bss->bssid);
548 pos += ETH_ALEN; 553 pos += ETH_ALEN;
549 554
550 if ((end - pos) < 12) { 555 if ((end - pos) < 12) {
@@ -588,38 +593,36 @@ static int lbs_process_bss(struct bss_descriptor *bss,
588 593
589 /* process variable IE */ 594 /* process variable IE */
590 while (pos <= end - 2) { 595 while (pos <= end - 2) {
591 struct ieee80211_info_element * elem = (void *)pos; 596 if (pos + pos[1] > end) {
592
593 if (pos + elem->len > end) {
594 lbs_deb_scan("process_bss: error in processing IE, " 597 lbs_deb_scan("process_bss: error in processing IE, "
595 "bytes left < IE length\n"); 598 "bytes left < IE length\n");
596 break; 599 break;
597 } 600 }
598 601
599 switch (elem->id) { 602 switch (pos[0]) {
600 case MFIE_TYPE_SSID: 603 case WLAN_EID_SSID:
601 bss->ssid_len = min_t(int, 32, elem->len); 604 bss->ssid_len = min_t(int, IEEE80211_MAX_SSID_LEN, pos[1]);
602 memcpy(bss->ssid, elem->data, bss->ssid_len); 605 memcpy(bss->ssid, pos + 2, bss->ssid_len);
603 lbs_deb_scan("got SSID IE: '%s', len %u\n", 606 lbs_deb_scan("got SSID IE: '%s', len %u\n",
604 escape_essid(bss->ssid, bss->ssid_len), 607 print_ssid(ssid, bss->ssid, bss->ssid_len),
605 bss->ssid_len); 608 bss->ssid_len);
606 break; 609 break;
607 610
608 case MFIE_TYPE_RATES: 611 case WLAN_EID_SUPP_RATES:
609 n_basic_rates = min_t(uint8_t, MAX_RATES, elem->len); 612 n_basic_rates = min_t(uint8_t, MAX_RATES, pos[1]);
610 memcpy(bss->rates, elem->data, n_basic_rates); 613 memcpy(bss->rates, pos + 2, n_basic_rates);
611 got_basic_rates = 1; 614 got_basic_rates = 1;
612 lbs_deb_scan("got RATES IE\n"); 615 lbs_deb_scan("got RATES IE\n");
613 break; 616 break;
614 617
615 case MFIE_TYPE_FH_SET: 618 case WLAN_EID_FH_PARAMS:
616 pFH = (struct ieeetypes_fhparamset *) pos; 619 pFH = (struct ieeetypes_fhparamset *) pos;
617 memmove(&bss->phyparamset.fhparamset, pFH, 620 memmove(&bss->phyparamset.fhparamset, pFH,
618 sizeof(struct ieeetypes_fhparamset)); 621 sizeof(struct ieeetypes_fhparamset));
619 lbs_deb_scan("got FH IE\n"); 622 lbs_deb_scan("got FH IE\n");
620 break; 623 break;
621 624
622 case MFIE_TYPE_DS_SET: 625 case WLAN_EID_DS_PARAMS:
623 pDS = (struct ieeetypes_dsparamset *) pos; 626 pDS = (struct ieeetypes_dsparamset *) pos;
624 bss->channel = pDS->currentchan; 627 bss->channel = pDS->currentchan;
625 memcpy(&bss->phyparamset.dsparamset, pDS, 628 memcpy(&bss->phyparamset.dsparamset, pDS,
@@ -627,14 +630,14 @@ static int lbs_process_bss(struct bss_descriptor *bss,
627 lbs_deb_scan("got DS IE, channel %d\n", bss->channel); 630 lbs_deb_scan("got DS IE, channel %d\n", bss->channel);
628 break; 631 break;
629 632
630 case MFIE_TYPE_CF_SET: 633 case WLAN_EID_CF_PARAMS:
631 pCF = (struct ieeetypes_cfparamset *) pos; 634 pCF = (struct ieeetypes_cfparamset *) pos;
632 memcpy(&bss->ssparamset.cfparamset, pCF, 635 memcpy(&bss->ssparamset.cfparamset, pCF,
633 sizeof(struct ieeetypes_cfparamset)); 636 sizeof(struct ieeetypes_cfparamset));
634 lbs_deb_scan("got CF IE\n"); 637 lbs_deb_scan("got CF IE\n");
635 break; 638 break;
636 639
637 case MFIE_TYPE_IBSS_SET: 640 case WLAN_EID_IBSS_PARAMS:
638 pibss = (struct ieeetypes_ibssparamset *) pos; 641 pibss = (struct ieeetypes_ibssparamset *) pos;
639 bss->atimwindow = le16_to_cpu(pibss->atimwindow); 642 bss->atimwindow = le16_to_cpu(pibss->atimwindow);
640 memmove(&bss->ssparamset.ibssparamset, pibss, 643 memmove(&bss->ssparamset.ibssparamset, pibss,
@@ -642,7 +645,7 @@ static int lbs_process_bss(struct bss_descriptor *bss,
642 lbs_deb_scan("got IBSS IE\n"); 645 lbs_deb_scan("got IBSS IE\n");
643 break; 646 break;
644 647
645 case MFIE_TYPE_COUNTRY: 648 case WLAN_EID_COUNTRY:
646 pcountryinfo = (struct ieeetypes_countryinfoset *) pos; 649 pcountryinfo = (struct ieeetypes_countryinfoset *) pos;
647 lbs_deb_scan("got COUNTRY IE\n"); 650 lbs_deb_scan("got COUNTRY IE\n");
648 if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) 651 if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
@@ -659,7 +662,7 @@ static int lbs_process_bss(struct bss_descriptor *bss,
659 (int) (pcountryinfo->len + 2)); 662 (int) (pcountryinfo->len + 2));
660 break; 663 break;
661 664
662 case MFIE_TYPE_RATES_EX: 665 case WLAN_EID_EXT_SUPP_RATES:
663 /* only process extended supported rate if data rate is 666 /* only process extended supported rate if data rate is
664 * already found. Data rate IE should come before 667 * already found. Data rate IE should come before
665 * extended supported rate IE 668 * extended supported rate IE
@@ -670,50 +673,51 @@ static int lbs_process_bss(struct bss_descriptor *bss,
670 break; 673 break;
671 } 674 }
672 675
673 n_ex_rates = elem->len; 676 n_ex_rates = pos[1];
674 if (n_basic_rates + n_ex_rates > MAX_RATES) 677 if (n_basic_rates + n_ex_rates > MAX_RATES)
675 n_ex_rates = MAX_RATES - n_basic_rates; 678 n_ex_rates = MAX_RATES - n_basic_rates;
676 679
677 p = bss->rates + n_basic_rates; 680 p = bss->rates + n_basic_rates;
678 memcpy(p, elem->data, n_ex_rates); 681 memcpy(p, pos + 2, n_ex_rates);
679 break; 682 break;
680 683
681 case MFIE_TYPE_GENERIC: 684 case WLAN_EID_GENERIC:
682 if (elem->len >= 4 && 685 if (pos[1] >= 4 &&
683 elem->data[0] == 0x00 && elem->data[1] == 0x50 && 686 pos[2] == 0x00 && pos[3] == 0x50 &&
684 elem->data[2] == 0xf2 && elem->data[3] == 0x01) { 687 pos[4] == 0xf2 && pos[5] == 0x01) {
685 bss->wpa_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); 688 bss->wpa_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
686 memcpy(bss->wpa_ie, elem, bss->wpa_ie_len); 689 memcpy(bss->wpa_ie, pos, bss->wpa_ie_len);
687 lbs_deb_scan("got WPA IE\n"); 690 lbs_deb_scan("got WPA IE\n");
688 lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, elem->len); 691 lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie,
689 } else if (elem->len >= MARVELL_MESH_IE_LENGTH && 692 bss->wpa_ie_len);
690 elem->data[0] == 0x00 && elem->data[1] == 0x50 && 693 } else if (pos[1] >= MARVELL_MESH_IE_LENGTH &&
691 elem->data[2] == 0x43 && elem->data[3] == 0x04) { 694 pos[2] == 0x00 && pos[3] == 0x50 &&
695 pos[4] == 0x43 && pos[4] == 0x04) {
692 lbs_deb_scan("got mesh IE\n"); 696 lbs_deb_scan("got mesh IE\n");
693 bss->mesh = 1; 697 bss->mesh = 1;
694 } else { 698 } else {
695 lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n", 699 lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n",
696 elem->data[0], elem->data[1], 700 pos[2], pos[3],
697 elem->data[2], elem->data[3], 701 pos[4], pos[5],
698 elem->len); 702 pos[1]);
699 } 703 }
700 break; 704 break;
701 705
702 case MFIE_TYPE_RSN: 706 case WLAN_EID_RSN:
703 lbs_deb_scan("got RSN IE\n"); 707 lbs_deb_scan("got RSN IE\n");
704 bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); 708 bss->rsn_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
705 memcpy(bss->rsn_ie, elem, bss->rsn_ie_len); 709 memcpy(bss->rsn_ie, pos, bss->rsn_ie_len);
706 lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", 710 lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE",
707 bss->rsn_ie, elem->len); 711 bss->rsn_ie, bss->rsn_ie_len);
708 break; 712 break;
709 713
710 default: 714 default:
711 lbs_deb_scan("got IE 0x%04x, len %d\n", 715 lbs_deb_scan("got IE 0x%04x, len %d\n",
712 elem->id, elem->len); 716 pos[0], pos[1]);
713 break; 717 break;
714 } 718 }
715 719
716 pos += elem->len + 2; 720 pos += pos[1] + 2;
717 } 721 }
718 722
719 /* Timestamp */ 723 /* Timestamp */
@@ -741,10 +745,11 @@ done:
741int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, 745int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
742 uint8_t ssid_len) 746 uint8_t ssid_len)
743{ 747{
748 DECLARE_SSID_BUF(ssid_buf);
744 int ret = 0; 749 int ret = 0;
745 750
746 lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n", 751 lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
747 escape_essid(ssid, ssid_len)); 752 print_ssid(ssid_buf, ssid, ssid_len));
748 753
749 if (!ssid_len) 754 if (!ssid_len)
750 goto out; 755 goto out;
@@ -939,6 +944,7 @@ out:
939int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, 944int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
940 union iwreq_data *wrqu, char *extra) 945 union iwreq_data *wrqu, char *extra)
941{ 946{
947 DECLARE_SSID_BUF(ssid);
942 struct lbs_private *priv = dev->priv; 948 struct lbs_private *priv = dev->priv;
943 int ret = 0; 949 int ret = 0;
944 950
@@ -968,7 +974,7 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
968 priv->scan_ssid_len = req->essid_len; 974 priv->scan_ssid_len = req->essid_len;
969 memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len); 975 memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
970 lbs_deb_wext("set_scan, essid '%s'\n", 976 lbs_deb_wext("set_scan, essid '%s'\n",
971 escape_essid(priv->scan_ssid, priv->scan_ssid_len)); 977 print_ssid(ssid, priv->scan_ssid, priv->scan_ssid_len));
972 } else { 978 } else {
973 priv->scan_ssid_len = 0; 979 priv->scan_ssid_len = 0;
974 } 980 }
@@ -1151,7 +1157,6 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
1151 struct bss_descriptor new; 1157 struct bss_descriptor new;
1152 struct bss_descriptor *found = NULL; 1158 struct bss_descriptor *found = NULL;
1153 struct bss_descriptor *oldest = NULL; 1159 struct bss_descriptor *oldest = NULL;
1154 DECLARE_MAC_BUF(mac);
1155 1160
1156 /* Process the data fields and IEs returned for this BSS */ 1161 /* Process the data fields and IEs returned for this BSS */
1157 memset(&new, 0, sizeof (struct bss_descriptor)); 1162 memset(&new, 0, sizeof (struct bss_descriptor));
@@ -1190,7 +1195,7 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
1190 continue; 1195 continue;
1191 } 1196 }
1192 1197
1193 lbs_deb_scan("SCAN_RESP: BSSID %s\n", print_mac(mac, new.bssid)); 1198 lbs_deb_scan("SCAN_RESP: BSSID %pM\n", new.bssid);
1194 1199
1195 /* Copy the locally created newbssentry to the scan table */ 1200 /* Copy the locally created newbssentry to the scan table */
1196 memcpy(found, &new, offsetof(struct bss_descriptor, list)); 1201 memcpy(found, &new, offsetof(struct bss_descriptor, list));