diff options
Diffstat (limited to 'drivers/net/wireless/libertas/scan.c')
-rw-r--r-- | drivers/net/wireless/libertas/scan.c | 101 |
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 | |||
55 | static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, | 60 | static 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: | |||
741 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, | 745 | int 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: | |||
939 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | 944 | int 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)); |