aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.c195
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c16
-rw-r--r--drivers/net/wireless/iwmc3200wifi/wext.c320
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
308int 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
309int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) 328int 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
522static 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
552static 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
568static 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
602static 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
625static 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
682static 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
503static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, 695static 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
37static 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
50static int iwm_wext_siwfreq(struct net_device *dev, 30static 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
66static int iwm_wext_giwfreq(struct net_device *dev, 44static 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
81static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, 60static 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
137static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info, 75static 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
159static int iwm_wext_siwessid(struct net_device *dev, 90static 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
196static int iwm_wext_giwessid(struct net_device *dev, 106static 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
218static 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
229static 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
241static 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
263static 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
292static 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
322static 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
365static 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
372static const iw_handler iwm_handlers[] = 122static 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[] =
432const struct iw_handler_def iwm_iw_handler_def = { 182const 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