diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 145 |
1 files changed, 49 insertions, 96 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 29ac8e1a509e..c981604b71e6 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -19,33 +19,6 @@ | |||
19 | #include "rate.h" | 19 | #include "rate.h" |
20 | #include "mesh.h" | 20 | #include "mesh.h" |
21 | 21 | ||
22 | static bool nl80211_type_check(enum nl80211_iftype type) | ||
23 | { | ||
24 | switch (type) { | ||
25 | case NL80211_IFTYPE_ADHOC: | ||
26 | case NL80211_IFTYPE_STATION: | ||
27 | case NL80211_IFTYPE_MONITOR: | ||
28 | #ifdef CONFIG_MAC80211_MESH | ||
29 | case NL80211_IFTYPE_MESH_POINT: | ||
30 | #endif | ||
31 | case NL80211_IFTYPE_AP: | ||
32 | case NL80211_IFTYPE_AP_VLAN: | ||
33 | case NL80211_IFTYPE_WDS: | ||
34 | return true; | ||
35 | default: | ||
36 | return false; | ||
37 | } | ||
38 | } | ||
39 | |||
40 | static bool nl80211_params_check(enum nl80211_iftype type, | ||
41 | struct vif_params *params) | ||
42 | { | ||
43 | if (!nl80211_type_check(type)) | ||
44 | return false; | ||
45 | |||
46 | return true; | ||
47 | } | ||
48 | |||
49 | static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | 22 | static int ieee80211_add_iface(struct wiphy *wiphy, char *name, |
50 | enum nl80211_iftype type, u32 *flags, | 23 | enum nl80211_iftype type, u32 *flags, |
51 | struct vif_params *params) | 24 | struct vif_params *params) |
@@ -55,9 +28,6 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
55 | struct ieee80211_sub_if_data *sdata; | 28 | struct ieee80211_sub_if_data *sdata; |
56 | int err; | 29 | int err; |
57 | 30 | ||
58 | if (!nl80211_params_check(type, params)) | ||
59 | return -EINVAL; | ||
60 | |||
61 | err = ieee80211_if_add(local, name, &dev, type, params); | 31 | err = ieee80211_if_add(local, name, &dev, type, params); |
62 | if (err || type != NL80211_IFTYPE_MONITOR || !flags) | 32 | if (err || type != NL80211_IFTYPE_MONITOR || !flags) |
63 | return err; | 33 | return err; |
@@ -82,12 +52,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
82 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 52 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
83 | int ret; | 53 | int ret; |
84 | 54 | ||
85 | if (ieee80211_sdata_running(sdata)) | ||
86 | return -EBUSY; | ||
87 | |||
88 | if (!nl80211_params_check(type, params)) | ||
89 | return -EINVAL; | ||
90 | |||
91 | ret = ieee80211_if_change_type(sdata, type); | 55 | ret = ieee80211_if_change_type(sdata, type); |
92 | if (ret) | 56 | if (ret) |
93 | return ret; | 57 | return ret; |
@@ -114,44 +78,30 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
114 | u8 key_idx, const u8 *mac_addr, | 78 | u8 key_idx, const u8 *mac_addr, |
115 | struct key_params *params) | 79 | struct key_params *params) |
116 | { | 80 | { |
117 | struct ieee80211_sub_if_data *sdata; | 81 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
118 | struct sta_info *sta = NULL; | 82 | struct sta_info *sta = NULL; |
119 | enum ieee80211_key_alg alg; | ||
120 | struct ieee80211_key *key; | 83 | struct ieee80211_key *key; |
121 | int err; | 84 | int err; |
122 | 85 | ||
123 | if (!netif_running(dev)) | 86 | if (!ieee80211_sdata_running(sdata)) |
124 | return -ENETDOWN; | 87 | return -ENETDOWN; |
125 | 88 | ||
126 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 89 | /* reject WEP and TKIP keys if WEP failed to initialize */ |
127 | |||
128 | switch (params->cipher) { | 90 | switch (params->cipher) { |
129 | case WLAN_CIPHER_SUITE_WEP40: | 91 | case WLAN_CIPHER_SUITE_WEP40: |
130 | case WLAN_CIPHER_SUITE_WEP104: | ||
131 | alg = ALG_WEP; | ||
132 | break; | ||
133 | case WLAN_CIPHER_SUITE_TKIP: | 92 | case WLAN_CIPHER_SUITE_TKIP: |
134 | alg = ALG_TKIP; | 93 | case WLAN_CIPHER_SUITE_WEP104: |
135 | break; | 94 | if (IS_ERR(sdata->local->wep_tx_tfm)) |
136 | case WLAN_CIPHER_SUITE_CCMP: | 95 | return -EINVAL; |
137 | alg = ALG_CCMP; | ||
138 | break; | ||
139 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
140 | alg = ALG_AES_CMAC; | ||
141 | break; | 96 | break; |
142 | default: | 97 | default: |
143 | return -EINVAL; | 98 | break; |
144 | } | 99 | } |
145 | 100 | ||
146 | /* reject WEP and TKIP keys if WEP failed to initialize */ | 101 | key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, |
147 | if ((alg == ALG_WEP || alg == ALG_TKIP) && | 102 | params->key, params->seq_len, params->seq); |
148 | IS_ERR(sdata->local->wep_tx_tfm)) | 103 | if (IS_ERR(key)) |
149 | return -EINVAL; | 104 | return PTR_ERR(key); |
150 | |||
151 | key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key, | ||
152 | params->seq_len, params->seq); | ||
153 | if (!key) | ||
154 | return -ENOMEM; | ||
155 | 105 | ||
156 | mutex_lock(&sdata->local->sta_mtx); | 106 | mutex_lock(&sdata->local->sta_mtx); |
157 | 107 | ||
@@ -164,9 +114,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
164 | } | 114 | } |
165 | } | 115 | } |
166 | 116 | ||
167 | ieee80211_key_link(key, sdata, sta); | 117 | err = ieee80211_key_link(key, sdata, sta); |
118 | if (err) | ||
119 | ieee80211_key_free(sdata->local, key); | ||
168 | 120 | ||
169 | err = 0; | ||
170 | out_unlock: | 121 | out_unlock: |
171 | mutex_unlock(&sdata->local->sta_mtx); | 122 | mutex_unlock(&sdata->local->sta_mtx); |
172 | 123 | ||
@@ -247,10 +198,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
247 | 198 | ||
248 | memset(¶ms, 0, sizeof(params)); | 199 | memset(¶ms, 0, sizeof(params)); |
249 | 200 | ||
250 | switch (key->conf.alg) { | 201 | params.cipher = key->conf.cipher; |
251 | case ALG_TKIP: | ||
252 | params.cipher = WLAN_CIPHER_SUITE_TKIP; | ||
253 | 202 | ||
203 | switch (key->conf.cipher) { | ||
204 | case WLAN_CIPHER_SUITE_TKIP: | ||
254 | iv32 = key->u.tkip.tx.iv32; | 205 | iv32 = key->u.tkip.tx.iv32; |
255 | iv16 = key->u.tkip.tx.iv16; | 206 | iv16 = key->u.tkip.tx.iv16; |
256 | 207 | ||
@@ -268,8 +219,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
268 | params.seq = seq; | 219 | params.seq = seq; |
269 | params.seq_len = 6; | 220 | params.seq_len = 6; |
270 | break; | 221 | break; |
271 | case ALG_CCMP: | 222 | case WLAN_CIPHER_SUITE_CCMP: |
272 | params.cipher = WLAN_CIPHER_SUITE_CCMP; | ||
273 | seq[0] = key->u.ccmp.tx_pn[5]; | 223 | seq[0] = key->u.ccmp.tx_pn[5]; |
274 | seq[1] = key->u.ccmp.tx_pn[4]; | 224 | seq[1] = key->u.ccmp.tx_pn[4]; |
275 | seq[2] = key->u.ccmp.tx_pn[3]; | 225 | seq[2] = key->u.ccmp.tx_pn[3]; |
@@ -279,14 +229,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
279 | params.seq = seq; | 229 | params.seq = seq; |
280 | params.seq_len = 6; | 230 | params.seq_len = 6; |
281 | break; | 231 | break; |
282 | case ALG_WEP: | 232 | case WLAN_CIPHER_SUITE_AES_CMAC: |
283 | if (key->conf.keylen == 5) | ||
284 | params.cipher = WLAN_CIPHER_SUITE_WEP40; | ||
285 | else | ||
286 | params.cipher = WLAN_CIPHER_SUITE_WEP104; | ||
287 | break; | ||
288 | case ALG_AES_CMAC: | ||
289 | params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; | ||
290 | seq[0] = key->u.aes_cmac.tx_pn[5]; | 233 | seq[0] = key->u.aes_cmac.tx_pn[5]; |
291 | seq[1] = key->u.aes_cmac.tx_pn[4]; | 234 | seq[1] = key->u.aes_cmac.tx_pn[4]; |
292 | seq[2] = key->u.aes_cmac.tx_pn[3]; | 235 | seq[2] = key->u.aes_cmac.tx_pn[3]; |
@@ -634,6 +577,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
634 | struct sta_info *sta, | 577 | struct sta_info *sta, |
635 | struct station_parameters *params) | 578 | struct station_parameters *params) |
636 | { | 579 | { |
580 | unsigned long flags; | ||
637 | u32 rates; | 581 | u32 rates; |
638 | int i, j; | 582 | int i, j; |
639 | struct ieee80211_supported_band *sband; | 583 | struct ieee80211_supported_band *sband; |
@@ -642,7 +586,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
642 | 586 | ||
643 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 587 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
644 | 588 | ||
645 | spin_lock_bh(&sta->lock); | 589 | spin_lock_irqsave(&sta->flaglock, flags); |
646 | mask = params->sta_flags_mask; | 590 | mask = params->sta_flags_mask; |
647 | set = params->sta_flags_set; | 591 | set = params->sta_flags_set; |
648 | 592 | ||
@@ -669,7 +613,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
669 | if (set & BIT(NL80211_STA_FLAG_MFP)) | 613 | if (set & BIT(NL80211_STA_FLAG_MFP)) |
670 | sta->flags |= WLAN_STA_MFP; | 614 | sta->flags |= WLAN_STA_MFP; |
671 | } | 615 | } |
672 | spin_unlock_bh(&sta->lock); | 616 | spin_unlock_irqrestore(&sta->flaglock, flags); |
673 | 617 | ||
674 | /* | 618 | /* |
675 | * cfg80211 validates this (1-2007) and allows setting the AID | 619 | * cfg80211 validates this (1-2007) and allows setting the AID |
@@ -1143,9 +1087,9 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1143 | p.uapsd = false; | 1087 | p.uapsd = false; |
1144 | 1088 | ||
1145 | if (drv_conf_tx(local, params->queue, &p)) { | 1089 | if (drv_conf_tx(local, params->queue, &p)) { |
1146 | printk(KERN_DEBUG "%s: failed to set TX queue " | 1090 | wiphy_debug(local->hw.wiphy, |
1147 | "parameters for queue %d\n", | 1091 | "failed to set TX queue parameters for queue %d\n", |
1148 | wiphy_name(local->hw.wiphy), params->queue); | 1092 | params->queue); |
1149 | return -EINVAL; | 1093 | return -EINVAL; |
1150 | } | 1094 | } |
1151 | 1095 | ||
@@ -1207,15 +1151,26 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1207 | struct net_device *dev, | 1151 | struct net_device *dev, |
1208 | struct cfg80211_scan_request *req) | 1152 | struct cfg80211_scan_request *req) |
1209 | { | 1153 | { |
1210 | struct ieee80211_sub_if_data *sdata; | 1154 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1211 | |||
1212 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1213 | 1155 | ||
1214 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1156 | switch (ieee80211_vif_type_p2p(&sdata->vif)) { |
1215 | sdata->vif.type != NL80211_IFTYPE_ADHOC && | 1157 | case NL80211_IFTYPE_STATION: |
1216 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && | 1158 | case NL80211_IFTYPE_ADHOC: |
1217 | (sdata->vif.type != NL80211_IFTYPE_AP || sdata->u.ap.beacon)) | 1159 | case NL80211_IFTYPE_MESH_POINT: |
1160 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1161 | break; | ||
1162 | case NL80211_IFTYPE_P2P_GO: | ||
1163 | if (sdata->local->ops->hw_scan) | ||
1164 | break; | ||
1165 | /* FIXME: implement NoA while scanning in software */ | ||
1166 | return -EOPNOTSUPP; | ||
1167 | case NL80211_IFTYPE_AP: | ||
1168 | if (sdata->u.ap.beacon) | ||
1169 | return -EOPNOTSUPP; | ||
1170 | break; | ||
1171 | default: | ||
1218 | return -EOPNOTSUPP; | 1172 | return -EOPNOTSUPP; |
1173 | } | ||
1219 | 1174 | ||
1220 | return ieee80211_request_scan(sdata, req); | 1175 | return ieee80211_request_scan(sdata, req); |
1221 | } | 1176 | } |
@@ -1541,11 +1496,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
1541 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | 1496 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); |
1542 | } | 1497 | } |
1543 | 1498 | ||
1544 | static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | 1499 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, |
1545 | struct ieee80211_channel *chan, | 1500 | struct ieee80211_channel *chan, |
1546 | enum nl80211_channel_type channel_type, | 1501 | enum nl80211_channel_type channel_type, |
1547 | bool channel_type_valid, | 1502 | bool channel_type_valid, |
1548 | const u8 *buf, size_t len, u64 *cookie) | 1503 | const u8 *buf, size_t len, u64 *cookie) |
1549 | { | 1504 | { |
1550 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1505 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1551 | struct ieee80211_local *local = sdata->local; | 1506 | struct ieee80211_local *local = sdata->local; |
@@ -1575,8 +1530,6 @@ static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | |||
1575 | return -ENOLINK; | 1530 | return -ENOLINK; |
1576 | break; | 1531 | break; |
1577 | case NL80211_IFTYPE_STATION: | 1532 | case NL80211_IFTYPE_STATION: |
1578 | if (!(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED)) | ||
1579 | flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1580 | break; | 1533 | break; |
1581 | default: | 1534 | default: |
1582 | return -EOPNOTSUPP; | 1535 | return -EOPNOTSUPP; |
@@ -1647,6 +1600,6 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1647 | .set_bitrate_mask = ieee80211_set_bitrate_mask, | 1600 | .set_bitrate_mask = ieee80211_set_bitrate_mask, |
1648 | .remain_on_channel = ieee80211_remain_on_channel, | 1601 | .remain_on_channel = ieee80211_remain_on_channel, |
1649 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | 1602 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, |
1650 | .action = ieee80211_action, | 1603 | .mgmt_tx = ieee80211_mgmt_tx, |
1651 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, | 1604 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, |
1652 | }; | 1605 | }; |