diff options
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/cfg80211.c | 195 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/rx.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/wext.c | 320 |
3 files changed, 239 insertions, 292 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 0aa389564c71..ee4031764389 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c | |||
@@ -305,6 +305,25 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, | |||
305 | return iwm_reset_profile(iwm); | 305 | return iwm_reset_profile(iwm); |
306 | } | 306 | } |
307 | 307 | ||
308 | int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | ||
309 | u8 *mac, struct station_info *sinfo) | ||
310 | { | ||
311 | struct iwm_priv *iwm = ndev_to_iwm(ndev); | ||
312 | |||
313 | if (memcmp(mac, iwm->bssid, ETH_ALEN)) | ||
314 | return -ENOENT; | ||
315 | |||
316 | sinfo->filled |= STATION_INFO_TX_BITRATE; | ||
317 | sinfo->txrate.legacy = iwm->rate * 10; | ||
318 | |||
319 | if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { | ||
320 | sinfo->filled |= STATION_INFO_SIGNAL; | ||
321 | sinfo->signal = iwm->wstats.qual.level; | ||
322 | } | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
308 | 327 | ||
309 | int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) | 328 | int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) |
310 | { | 329 | { |
@@ -500,6 +519,179 @@ static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | |||
500 | return 0; | 519 | return 0; |
501 | } | 520 | } |
502 | 521 | ||
522 | static int iwm_set_auth_type(struct iwm_priv *iwm, | ||
523 | enum nl80211_auth_type sme_auth_type) | ||
524 | { | ||
525 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; | ||
526 | |||
527 | switch (sme_auth_type) { | ||
528 | case NL80211_AUTHTYPE_AUTOMATIC: | ||
529 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | ||
530 | IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n"); | ||
531 | *auth_type = UMAC_AUTH_TYPE_OPEN; | ||
532 | break; | ||
533 | case NL80211_AUTHTYPE_SHARED_KEY: | ||
534 | if (iwm->umac_profile->sec.flags & | ||
535 | (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) { | ||
536 | IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n"); | ||
537 | *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; | ||
538 | } else { | ||
539 | IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n"); | ||
540 | *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; | ||
541 | } | ||
542 | |||
543 | break; | ||
544 | default: | ||
545 | IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type); | ||
546 | return -ENOTSUPP; | ||
547 | } | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version) | ||
553 | { | ||
554 | if (!wpa_version) { | ||
555 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; | ||
556 | return 0; | ||
557 | } | ||
558 | |||
559 | if (wpa_version & NL80211_WPA_VERSION_2) | ||
560 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; | ||
561 | |||
562 | if (wpa_version & NL80211_WPA_VERSION_1) | ||
563 | iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK; | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast) | ||
569 | { | ||
570 | u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher : | ||
571 | &iwm->umac_profile->sec.mcast_cipher; | ||
572 | |||
573 | if (!cipher) { | ||
574 | *profile_cipher = UMAC_CIPHER_TYPE_NONE; | ||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | switch (cipher) { | ||
579 | case IW_AUTH_CIPHER_NONE: | ||
580 | *profile_cipher = UMAC_CIPHER_TYPE_NONE; | ||
581 | break; | ||
582 | case WLAN_CIPHER_SUITE_WEP40: | ||
583 | *profile_cipher = UMAC_CIPHER_TYPE_WEP_40; | ||
584 | break; | ||
585 | case WLAN_CIPHER_SUITE_WEP104: | ||
586 | *profile_cipher = UMAC_CIPHER_TYPE_WEP_104; | ||
587 | break; | ||
588 | case WLAN_CIPHER_SUITE_TKIP: | ||
589 | *profile_cipher = UMAC_CIPHER_TYPE_TKIP; | ||
590 | break; | ||
591 | case WLAN_CIPHER_SUITE_CCMP: | ||
592 | *profile_cipher = UMAC_CIPHER_TYPE_CCMP; | ||
593 | break; | ||
594 | default: | ||
595 | IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher); | ||
596 | return -ENOTSUPP; | ||
597 | } | ||
598 | |||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt) | ||
603 | { | ||
604 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; | ||
605 | |||
606 | IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); | ||
607 | |||
608 | if (key_mgt == WLAN_AKM_SUITE_8021X) | ||
609 | *auth_type = UMAC_AUTH_TYPE_8021X; | ||
610 | else if (key_mgt == WLAN_AKM_SUITE_PSK) { | ||
611 | if (iwm->umac_profile->sec.flags & | ||
612 | (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) | ||
613 | *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; | ||
614 | else | ||
615 | *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; | ||
616 | } else { | ||
617 | IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt); | ||
618 | return -EINVAL; | ||
619 | } | ||
620 | |||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | |||
625 | static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | ||
626 | struct cfg80211_connect_params *sme) | ||
627 | { | ||
628 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); | ||
629 | struct ieee80211_channel *chan = sme->channel; | ||
630 | int ret; | ||
631 | |||
632 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) | ||
633 | return -EIO; | ||
634 | |||
635 | if (!sme->ssid) | ||
636 | return -EINVAL; | ||
637 | |||
638 | if (chan) | ||
639 | iwm->channel = | ||
640 | ieee80211_frequency_to_channel(chan->center_freq); | ||
641 | |||
642 | iwm->umac_profile->ssid.ssid_len = sme->ssid_len; | ||
643 | memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len); | ||
644 | |||
645 | if (sme->bssid) { | ||
646 | IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid); | ||
647 | memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN); | ||
648 | iwm->umac_profile->bss_num = 1; | ||
649 | } else { | ||
650 | memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN); | ||
651 | iwm->umac_profile->bss_num = 0; | ||
652 | } | ||
653 | |||
654 | ret = iwm_set_auth_type(iwm, sme->auth_type); | ||
655 | if (ret < 0) | ||
656 | return ret; | ||
657 | |||
658 | ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions); | ||
659 | if (ret < 0) | ||
660 | return ret; | ||
661 | |||
662 | if (sme->crypto.n_ciphers_pairwise) { | ||
663 | ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0], | ||
664 | true); | ||
665 | if (ret < 0) | ||
666 | return ret; | ||
667 | } | ||
668 | |||
669 | ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false); | ||
670 | if (ret < 0) | ||
671 | return ret; | ||
672 | |||
673 | if (sme->crypto.n_akm_suites) { | ||
674 | ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]); | ||
675 | if (ret < 0) | ||
676 | return ret; | ||
677 | } | ||
678 | |||
679 | return iwm_send_mlme_profile(iwm); | ||
680 | } | ||
681 | |||
682 | static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, | ||
683 | u16 reason_code) | ||
684 | { | ||
685 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); | ||
686 | |||
687 | IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active); | ||
688 | |||
689 | if (iwm->umac_profile_active) | ||
690 | return iwm_invalidate_mlme_profile(iwm); | ||
691 | |||
692 | return 0; | ||
693 | } | ||
694 | |||
503 | static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, | 695 | static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, |
504 | enum tx_power_setting type, int dbm) | 696 | enum tx_power_setting type, int dbm) |
505 | { | 697 | { |
@@ -549,8 +741,11 @@ static struct cfg80211_ops iwm_cfg80211_ops = { | |||
549 | .get_key = iwm_cfg80211_get_key, | 741 | .get_key = iwm_cfg80211_get_key, |
550 | .del_key = iwm_cfg80211_del_key, | 742 | .del_key = iwm_cfg80211_del_key, |
551 | .set_default_key = iwm_cfg80211_set_default_key, | 743 | .set_default_key = iwm_cfg80211_set_default_key, |
744 | .get_station = iwm_cfg80211_get_station, | ||
552 | .scan = iwm_cfg80211_scan, | 745 | .scan = iwm_cfg80211_scan, |
553 | .set_wiphy_params = iwm_cfg80211_set_wiphy_params, | 746 | .set_wiphy_params = iwm_cfg80211_set_wiphy_params, |
747 | .connect = iwm_cfg80211_connect, | ||
748 | .disconnect = iwm_cfg80211_disconnect, | ||
554 | .join_ibss = iwm_cfg80211_join_ibss, | 749 | .join_ibss = iwm_cfg80211_join_ibss, |
555 | .leave_ibss = iwm_cfg80211_leave_ibss, | 750 | .leave_ibss = iwm_cfg80211_leave_ibss, |
556 | .set_tx_power = iwm_cfg80211_set_txpower, | 751 | .set_tx_power = iwm_cfg80211_set_txpower, |
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 218933b8800b..82b572a6fc0b 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -503,13 +503,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
503 | { | 503 | { |
504 | struct iwm_umac_notif_assoc_complete *complete = | 504 | struct iwm_umac_notif_assoc_complete *complete = |
505 | (struct iwm_umac_notif_assoc_complete *)buf; | 505 | (struct iwm_umac_notif_assoc_complete *)buf; |
506 | union iwreq_data wrqu; | ||
507 | 506 | ||
508 | IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n", | 507 | IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n", |
509 | complete->bssid, complete->status); | 508 | complete->bssid, complete->status); |
510 | 509 | ||
511 | memset(&wrqu, 0, sizeof(wrqu)); | ||
512 | |||
513 | clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status); | 510 | clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status); |
514 | 511 | ||
515 | switch (le32_to_cpu(complete->status)) { | 512 | switch (le32_to_cpu(complete->status)) { |
@@ -520,7 +517,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
520 | 517 | ||
521 | iwm_link_on(iwm); | 518 | iwm_link_on(iwm); |
522 | 519 | ||
523 | memcpy(wrqu.ap_addr.sa_data, complete->bssid, ETH_ALEN); | 520 | cfg80211_connect_result(iwm_to_ndev(iwm), |
521 | complete->bssid, | ||
522 | NULL, 0, NULL, 0, | ||
523 | WLAN_STATUS_SUCCESS, GFP_KERNEL); | ||
524 | break; | 524 | break; |
525 | case UMAC_ASSOC_COMPLETE_FAILURE: | 525 | case UMAC_ASSOC_COMPLETE_FAILURE: |
526 | clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); | 526 | clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); |
@@ -528,6 +528,11 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
528 | iwm->channel = 0; | 528 | iwm->channel = 0; |
529 | 529 | ||
530 | iwm_link_off(iwm); | 530 | iwm_link_off(iwm); |
531 | |||
532 | cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, | ||
533 | NULL, 0, NULL, 0, | ||
534 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
535 | GFP_KERNEL); | ||
531 | default: | 536 | default: |
532 | break; | 537 | break; |
533 | } | 538 | } |
@@ -537,9 +542,6 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
537 | return 0; | 542 | return 0; |
538 | } | 543 | } |
539 | 544 | ||
540 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
541 | wireless_send_event(iwm_to_ndev(iwm), SIOCGIWAP, &wrqu, NULL); | ||
542 | |||
543 | return 0; | 545 | return 0; |
544 | } | 546 | } |
545 | 547 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index 2e7eaf96cf93..c3c90d5963bf 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c | |||
@@ -21,31 +21,11 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/netdevice.h> | ||
26 | #include <linux/wireless.h> | 24 | #include <linux/wireless.h> |
27 | #include <linux/if_arp.h> | ||
28 | #include <linux/etherdevice.h> | ||
29 | #include <net/cfg80211.h> | 25 | #include <net/cfg80211.h> |
30 | #include <net/iw_handler.h> | ||
31 | 26 | ||
32 | #include "iwm.h" | 27 | #include "iwm.h" |
33 | #include "umac.h" | ||
34 | #include "commands.h" | 28 | #include "commands.h" |
35 | #include "debug.h" | ||
36 | |||
37 | static struct iw_statistics *iwm_get_wireless_stats(struct net_device *dev) | ||
38 | { | ||
39 | struct iwm_priv *iwm = ndev_to_iwm(dev); | ||
40 | struct iw_statistics *wstats = &iwm->wstats; | ||
41 | |||
42 | if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { | ||
43 | memset(wstats, 0, sizeof(struct iw_statistics)); | ||
44 | wstats->qual.updated = IW_QUAL_ALL_INVALID; | ||
45 | } | ||
46 | |||
47 | return wstats; | ||
48 | } | ||
49 | 29 | ||
50 | static int iwm_wext_siwfreq(struct net_device *dev, | 30 | static int iwm_wext_siwfreq(struct net_device *dev, |
51 | struct iw_request_info *info, | 31 | struct iw_request_info *info, |
@@ -53,14 +33,12 @@ static int iwm_wext_siwfreq(struct net_device *dev, | |||
53 | { | 33 | { |
54 | struct iwm_priv *iwm = ndev_to_iwm(dev); | 34 | struct iwm_priv *iwm = ndev_to_iwm(dev); |
55 | 35 | ||
56 | if (freq->flags == IW_FREQ_AUTO) | 36 | switch (iwm->conf.mode) { |
57 | return 0; | 37 | case UMAC_MODE_IBSS: |
58 | 38 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); | |
59 | /* frequency/channel can only be set in IBSS mode */ | 39 | default: |
60 | if (iwm->conf.mode != UMAC_MODE_IBSS) | ||
61 | return -EOPNOTSUPP; | 40 | return -EOPNOTSUPP; |
62 | 41 | } | |
63 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); | ||
64 | } | 42 | } |
65 | 43 | ||
66 | static int iwm_wext_giwfreq(struct net_device *dev, | 44 | static int iwm_wext_giwfreq(struct net_device *dev, |
@@ -69,69 +47,29 @@ static int iwm_wext_giwfreq(struct net_device *dev, | |||
69 | { | 47 | { |
70 | struct iwm_priv *iwm = ndev_to_iwm(dev); | 48 | struct iwm_priv *iwm = ndev_to_iwm(dev); |
71 | 49 | ||
72 | if (iwm->conf.mode == UMAC_MODE_IBSS) | 50 | switch (iwm->conf.mode) { |
51 | case UMAC_MODE_IBSS: | ||
73 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); | 52 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); |
74 | 53 | case UMAC_MODE_BSS: | |
75 | freq->e = 0; | 54 | return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); |
76 | freq->m = iwm->channel; | 55 | default: |
77 | 56 | return -EOPNOTSUPP; | |
78 | return 0; | 57 | } |
79 | } | 58 | } |
80 | 59 | ||
81 | static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, | 60 | static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, |
82 | struct sockaddr *ap_addr, char *extra) | 61 | struct sockaddr *ap_addr, char *extra) |
83 | { | 62 | { |
84 | struct iwm_priv *iwm = ndev_to_iwm(dev); | 63 | struct iwm_priv *iwm = ndev_to_iwm(dev); |
85 | int ret; | ||
86 | |||
87 | IWM_DBG_WEXT(iwm, DBG, "Set BSSID: %pM\n", ap_addr->sa_data); | ||
88 | 64 | ||
89 | if (iwm->conf.mode == UMAC_MODE_IBSS) | 65 | switch (iwm->conf.mode) { |
66 | case UMAC_MODE_IBSS: | ||
90 | return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); | 67 | return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); |
91 | 68 | case UMAC_MODE_BSS: | |
92 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) | 69 | return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); |
93 | return -EIO; | 70 | default: |
94 | 71 | return -EOPNOTSUPP; | |
95 | if (is_zero_ether_addr(ap_addr->sa_data) || | ||
96 | is_broadcast_ether_addr(ap_addr->sa_data)) { | ||
97 | IWM_DBG_WEXT(iwm, DBG, "clear mandatory bssid %pM\n", | ||
98 | iwm->umac_profile->bssid[0]); | ||
99 | memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN); | ||
100 | iwm->umac_profile->bss_num = 0; | ||
101 | } else { | ||
102 | IWM_DBG_WEXT(iwm, DBG, "add mandatory bssid %pM\n", | ||
103 | ap_addr->sa_data); | ||
104 | memcpy(&iwm->umac_profile->bssid[0], ap_addr->sa_data, | ||
105 | ETH_ALEN); | ||
106 | iwm->umac_profile->bss_num = 1; | ||
107 | } | ||
108 | |||
109 | if (iwm->umac_profile_active) { | ||
110 | int i; | ||
111 | |||
112 | if (!memcmp(&iwm->umac_profile->bssid[0], iwm->bssid, ETH_ALEN)) | ||
113 | return 0; | ||
114 | |||
115 | /* | ||
116 | * If we're clearing the BSSID, and we're associated, | ||
117 | * we have to clear the keys as they're no longer valid. | ||
118 | */ | ||
119 | if (is_zero_ether_addr(ap_addr->sa_data)) { | ||
120 | for (i = 0; i < IWM_NUM_KEYS; i++) | ||
121 | iwm->keys[i].key_len = 0; | ||
122 | } | ||
123 | |||
124 | ret = iwm_invalidate_mlme_profile(iwm); | ||
125 | if (ret < 0) { | ||
126 | IWM_ERR(iwm, "Couldn't invalidate profile\n"); | ||
127 | return ret; | ||
128 | } | ||
129 | } | 72 | } |
130 | |||
131 | if (iwm->umac_profile->ssid.ssid_len) | ||
132 | return iwm_send_mlme_profile(iwm); | ||
133 | |||
134 | return 0; | ||
135 | } | 73 | } |
136 | 74 | ||
137 | static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info, | 75 | static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info, |
@@ -143,17 +81,10 @@ static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info, | |||
143 | case UMAC_MODE_IBSS: | 81 | case UMAC_MODE_IBSS: |
144 | return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); | 82 | return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); |
145 | case UMAC_MODE_BSS: | 83 | case UMAC_MODE_BSS: |
146 | if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { | 84 | return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); |
147 | ap_addr->sa_family = ARPHRD_ETHER; | ||
148 | memcpy(&ap_addr->sa_data, iwm->bssid, ETH_ALEN); | ||
149 | } else | ||
150 | memset(&ap_addr->sa_data, 0, ETH_ALEN); | ||
151 | break; | ||
152 | default: | 85 | default: |
153 | return -EOPNOTSUPP; | 86 | return -EOPNOTSUPP; |
154 | } | 87 | } |
155 | |||
156 | return 0; | ||
157 | } | 88 | } |
158 | 89 | ||
159 | static int iwm_wext_siwessid(struct net_device *dev, | 90 | static int iwm_wext_siwessid(struct net_device *dev, |
@@ -161,36 +92,15 @@ static int iwm_wext_siwessid(struct net_device *dev, | |||
161 | struct iw_point *data, char *ssid) | 92 | struct iw_point *data, char *ssid) |
162 | { | 93 | { |
163 | struct iwm_priv *iwm = ndev_to_iwm(dev); | 94 | struct iwm_priv *iwm = ndev_to_iwm(dev); |
164 | size_t len = data->length; | ||
165 | int ret; | ||
166 | |||
167 | IWM_DBG_WEXT(iwm, DBG, "Set ESSID: >%s<\n", ssid); | ||
168 | 95 | ||
169 | if (iwm->conf.mode == UMAC_MODE_IBSS) | 96 | switch (iwm->conf.mode) { |
97 | case UMAC_MODE_IBSS: | ||
170 | return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); | 98 | return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); |
171 | 99 | case UMAC_MODE_BSS: | |
172 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) | 100 | return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); |
173 | return -EIO; | 101 | default: |
174 | 102 | return -EOPNOTSUPP; | |
175 | if (len > 0 && ssid[len - 1] == '\0') | ||
176 | len--; | ||
177 | |||
178 | if (iwm->umac_profile_active) { | ||
179 | if (iwm->umac_profile->ssid.ssid_len == len && | ||
180 | !memcmp(iwm->umac_profile->ssid.ssid, ssid, len)) | ||
181 | return 0; | ||
182 | |||
183 | ret = iwm_invalidate_mlme_profile(iwm); | ||
184 | if (ret < 0) { | ||
185 | IWM_ERR(iwm, "Couldn't invalidate profile\n"); | ||
186 | return ret; | ||
187 | } | ||
188 | } | 103 | } |
189 | |||
190 | iwm->umac_profile->ssid.ssid_len = len; | ||
191 | memcpy(iwm->umac_profile->ssid.ssid, ssid, len); | ||
192 | |||
193 | return iwm_send_mlme_profile(iwm); | ||
194 | } | 104 | } |
195 | 105 | ||
196 | static int iwm_wext_giwessid(struct net_device *dev, | 106 | static int iwm_wext_giwessid(struct net_device *dev, |
@@ -199,174 +109,14 @@ static int iwm_wext_giwessid(struct net_device *dev, | |||
199 | { | 109 | { |
200 | struct iwm_priv *iwm = ndev_to_iwm(dev); | 110 | struct iwm_priv *iwm = ndev_to_iwm(dev); |
201 | 111 | ||
202 | if (iwm->conf.mode == UMAC_MODE_IBSS) | 112 | switch (iwm->conf.mode) { |
113 | case UMAC_MODE_IBSS: | ||
203 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); | 114 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); |
204 | 115 | case UMAC_MODE_BSS: | |
205 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) | 116 | return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); |
206 | return -EIO; | ||
207 | |||
208 | data->length = iwm->umac_profile->ssid.ssid_len; | ||
209 | if (data->length) { | ||
210 | memcpy(ssid, iwm->umac_profile->ssid.ssid, data->length); | ||
211 | data->flags = 1; | ||
212 | } else | ||
213 | data->flags = 0; | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int iwm_wext_giwrate(struct net_device *dev, | ||
219 | struct iw_request_info *info, | ||
220 | struct iw_param *rate, char *extra) | ||
221 | { | ||
222 | struct iwm_priv *iwm = ndev_to_iwm(dev); | ||
223 | |||
224 | rate->value = iwm->rate * 1000000; | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version) | ||
230 | { | ||
231 | if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) | ||
232 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; | ||
233 | else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) | ||
234 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK; | ||
235 | else | ||
236 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt) | ||
242 | { | ||
243 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; | ||
244 | |||
245 | IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); | ||
246 | |||
247 | if (key_mgt == IW_AUTH_KEY_MGMT_802_1X) | ||
248 | *auth_type = UMAC_AUTH_TYPE_8021X; | ||
249 | else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) { | ||
250 | if (iwm->umac_profile->sec.flags & | ||
251 | (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) | ||
252 | *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; | ||
253 | else | ||
254 | *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; | ||
255 | } else { | ||
256 | IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt); | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static int iwm_set_cipher(struct iwm_priv *iwm, u8 cipher, u8 ucast) | ||
264 | { | ||
265 | u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher : | ||
266 | &iwm->umac_profile->sec.mcast_cipher; | ||
267 | |||
268 | switch (cipher) { | ||
269 | case IW_AUTH_CIPHER_NONE: | ||
270 | *profile_cipher = UMAC_CIPHER_TYPE_NONE; | ||
271 | break; | ||
272 | case IW_AUTH_CIPHER_WEP40: | ||
273 | *profile_cipher = UMAC_CIPHER_TYPE_WEP_40; | ||
274 | break; | ||
275 | case IW_AUTH_CIPHER_TKIP: | ||
276 | *profile_cipher = UMAC_CIPHER_TYPE_TKIP; | ||
277 | break; | ||
278 | case IW_AUTH_CIPHER_CCMP: | ||
279 | *profile_cipher = UMAC_CIPHER_TYPE_CCMP; | ||
280 | break; | ||
281 | case IW_AUTH_CIPHER_WEP104: | ||
282 | *profile_cipher = UMAC_CIPHER_TYPE_WEP_104; | ||
283 | break; | ||
284 | default: | ||
285 | IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher); | ||
286 | return -ENOTSUPP; | ||
287 | } | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg) | ||
293 | { | ||
294 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; | ||
295 | |||
296 | IWM_DBG_WEXT(iwm, DBG, "auth_alg: 0x%x\n", auth_alg); | ||
297 | |||
298 | switch (auth_alg) { | ||
299 | case IW_AUTH_ALG_OPEN_SYSTEM: | ||
300 | *auth_type = UMAC_AUTH_TYPE_OPEN; | ||
301 | break; | ||
302 | case IW_AUTH_ALG_SHARED_KEY: | ||
303 | if (iwm->umac_profile->sec.flags & | ||
304 | (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) { | ||
305 | if (*auth_type == UMAC_AUTH_TYPE_8021X) | ||
306 | return -EINVAL; | ||
307 | *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; | ||
308 | } else { | ||
309 | IWM_DBG_WEXT(iwm, DBG, "WEP shared key\n"); | ||
310 | *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; | ||
311 | } | ||
312 | break; | ||
313 | case IW_AUTH_ALG_LEAP: | ||
314 | default: | ||
315 | IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", auth_alg); | ||
316 | return -ENOTSUPP; | ||
317 | } | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static int iwm_wext_siwauth(struct net_device *dev, | ||
323 | struct iw_request_info *info, | ||
324 | struct iw_param *data, char *extra) | ||
325 | { | ||
326 | struct iwm_priv *iwm = ndev_to_iwm(dev); | ||
327 | int ret; | ||
328 | |||
329 | if ((data->flags) & | ||
330 | (IW_AUTH_WPA_VERSION | IW_AUTH_KEY_MGMT | | ||
331 | IW_AUTH_WPA_ENABLED | IW_AUTH_80211_AUTH_ALG)) { | ||
332 | /* We need to invalidate the current profile */ | ||
333 | if (iwm->umac_profile_active) { | ||
334 | ret = iwm_invalidate_mlme_profile(iwm); | ||
335 | if (ret < 0) { | ||
336 | IWM_ERR(iwm, "Couldn't invalidate profile\n"); | ||
337 | return ret; | ||
338 | } | ||
339 | } | ||
340 | } | ||
341 | |||
342 | switch (data->flags & IW_AUTH_INDEX) { | ||
343 | case IW_AUTH_WPA_VERSION: | ||
344 | return iwm_set_wpa_version(iwm, data->value); | ||
345 | break; | ||
346 | case IW_AUTH_CIPHER_PAIRWISE: | ||
347 | return iwm_set_cipher(iwm, data->value, 1); | ||
348 | break; | ||
349 | case IW_AUTH_CIPHER_GROUP: | ||
350 | return iwm_set_cipher(iwm, data->value, 0); | ||
351 | break; | ||
352 | case IW_AUTH_KEY_MGMT: | ||
353 | return iwm_set_key_mgt(iwm, data->value); | ||
354 | break; | ||
355 | case IW_AUTH_80211_AUTH_ALG: | ||
356 | return iwm_set_auth_alg(iwm, data->value); | ||
357 | break; | ||
358 | default: | 117 | default: |
359 | return -ENOTSUPP; | 118 | return -EOPNOTSUPP; |
360 | } | 119 | } |
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static int iwm_wext_giwauth(struct net_device *dev, | ||
366 | struct iw_request_info *info, | ||
367 | struct iw_param *data, char *extra) | ||
368 | { | ||
369 | return 0; | ||
370 | } | 120 | } |
371 | 121 | ||
372 | static const iw_handler iwm_handlers[] = | 122 | static const iw_handler iwm_handlers[] = |
@@ -404,7 +154,7 @@ static const iw_handler iwm_handlers[] = | |||
404 | (iw_handler) NULL, /* -- hole -- */ | 154 | (iw_handler) NULL, /* -- hole -- */ |
405 | (iw_handler) NULL, /* -- hole -- */ | 155 | (iw_handler) NULL, /* -- hole -- */ |
406 | (iw_handler) NULL, /* SIOCSIWRATE */ | 156 | (iw_handler) NULL, /* SIOCSIWRATE */ |
407 | (iw_handler) iwm_wext_giwrate, /* SIOCGIWRATE */ | 157 | (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */ |
408 | (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */ | 158 | (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */ |
409 | (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ | 159 | (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ |
410 | (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ | 160 | (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ |
@@ -419,10 +169,10 @@ static const iw_handler iwm_handlers[] = | |||
419 | (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ | 169 | (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ |
420 | (iw_handler) NULL, /* -- hole -- */ | 170 | (iw_handler) NULL, /* -- hole -- */ |
421 | (iw_handler) NULL, /* -- hole -- */ | 171 | (iw_handler) NULL, /* -- hole -- */ |
422 | (iw_handler) NULL, /* SIOCSIWGENIE */ | 172 | (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */ |
423 | (iw_handler) NULL, /* SIOCGIWGENIE */ | 173 | (iw_handler) NULL, /* SIOCGIWGENIE */ |
424 | (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */ | 174 | (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */ |
425 | (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */ | 175 | (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */ |
426 | (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ | 176 | (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ |
427 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ | 177 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ |
428 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | 178 | (iw_handler) NULL, /* SIOCSIWPMKSA */ |
@@ -432,6 +182,6 @@ static const iw_handler iwm_handlers[] = | |||
432 | const struct iw_handler_def iwm_iw_handler_def = { | 182 | const struct iw_handler_def iwm_iw_handler_def = { |
433 | .num_standard = ARRAY_SIZE(iwm_handlers), | 183 | .num_standard = ARRAY_SIZE(iwm_handlers), |
434 | .standard = (iw_handler *) iwm_handlers, | 184 | .standard = (iw_handler *) iwm_handlers, |
435 | .get_wireless_stats = iwm_get_wireless_stats, | 185 | .get_wireless_stats = cfg80211_wireless_stats, |
436 | }; | 186 | }; |
437 | 187 | ||