diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 170 |
1 files changed, 167 insertions, 3 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9d4e4d846ec1..58693e52d458 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -133,6 +133,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
133 | case WLAN_CIPHER_SUITE_CCMP: | 133 | case WLAN_CIPHER_SUITE_CCMP: |
134 | alg = ALG_CCMP; | 134 | alg = ALG_CCMP; |
135 | break; | 135 | break; |
136 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
137 | alg = ALG_AES_CMAC; | ||
138 | break; | ||
136 | default: | 139 | default: |
137 | return -EINVAL; | 140 | return -EINVAL; |
138 | } | 141 | } |
@@ -275,6 +278,17 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
275 | else | 278 | else |
276 | params.cipher = WLAN_CIPHER_SUITE_WEP104; | 279 | params.cipher = WLAN_CIPHER_SUITE_WEP104; |
277 | break; | 280 | break; |
281 | case ALG_AES_CMAC: | ||
282 | params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; | ||
283 | seq[0] = key->u.aes_cmac.tx_pn[5]; | ||
284 | seq[1] = key->u.aes_cmac.tx_pn[4]; | ||
285 | seq[2] = key->u.aes_cmac.tx_pn[3]; | ||
286 | seq[3] = key->u.aes_cmac.tx_pn[2]; | ||
287 | seq[4] = key->u.aes_cmac.tx_pn[1]; | ||
288 | seq[5] = key->u.aes_cmac.tx_pn[0]; | ||
289 | params.seq = seq; | ||
290 | params.seq_len = 6; | ||
291 | break; | ||
278 | } | 292 | } |
279 | 293 | ||
280 | params.key = key->conf.key; | 294 | params.key = key->conf.key; |
@@ -304,6 +318,22 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, | |||
304 | return 0; | 318 | return 0; |
305 | } | 319 | } |
306 | 320 | ||
321 | static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, | ||
322 | struct net_device *dev, | ||
323 | u8 key_idx) | ||
324 | { | ||
325 | struct ieee80211_sub_if_data *sdata; | ||
326 | |||
327 | rcu_read_lock(); | ||
328 | |||
329 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
330 | ieee80211_set_default_mgmt_key(sdata, key_idx); | ||
331 | |||
332 | rcu_read_unlock(); | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
307 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 337 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) |
308 | { | 338 | { |
309 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 339 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -311,11 +341,15 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
311 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | 341 | sinfo->filled = STATION_INFO_INACTIVE_TIME | |
312 | STATION_INFO_RX_BYTES | | 342 | STATION_INFO_RX_BYTES | |
313 | STATION_INFO_TX_BYTES | | 343 | STATION_INFO_TX_BYTES | |
344 | STATION_INFO_RX_PACKETS | | ||
345 | STATION_INFO_TX_PACKETS | | ||
314 | STATION_INFO_TX_BITRATE; | 346 | STATION_INFO_TX_BITRATE; |
315 | 347 | ||
316 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 348 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
317 | sinfo->rx_bytes = sta->rx_bytes; | 349 | sinfo->rx_bytes = sta->rx_bytes; |
318 | sinfo->tx_bytes = sta->tx_bytes; | 350 | sinfo->tx_bytes = sta->tx_bytes; |
351 | sinfo->rx_packets = sta->rx_packets; | ||
352 | sinfo->tx_packets = sta->tx_packets; | ||
319 | 353 | ||
320 | if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { | 354 | if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { |
321 | sinfo->filled |= STATION_INFO_SIGNAL; | 355 | sinfo->filled |= STATION_INFO_SIGNAL; |
@@ -417,7 +451,8 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
417 | * This is a kludge. beacon interval should really be part | 451 | * This is a kludge. beacon interval should really be part |
418 | * of the beacon information. | 452 | * of the beacon information. |
419 | */ | 453 | */ |
420 | if (params->interval) { | 454 | if (params->interval && (sdata->local->hw.conf.beacon_int != |
455 | params->interval)) { | ||
421 | sdata->local->hw.conf.beacon_int = params->interval; | 456 | sdata->local->hw.conf.beacon_int = params->interval; |
422 | err = ieee80211_hw_config(sdata->local, | 457 | err = ieee80211_hw_config(sdata->local, |
423 | IEEE80211_CONF_CHANGE_BEACON_INTERVAL); | 458 | IEEE80211_CONF_CHANGE_BEACON_INTERVAL); |
@@ -493,7 +528,8 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
493 | 528 | ||
494 | kfree(old); | 529 | kfree(old); |
495 | 530 | ||
496 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 531 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | |
532 | IEEE80211_IFCC_BEACON_ENABLED); | ||
497 | } | 533 | } |
498 | 534 | ||
499 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | 535 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, |
@@ -553,7 +589,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
553 | synchronize_rcu(); | 589 | synchronize_rcu(); |
554 | kfree(old); | 590 | kfree(old); |
555 | 591 | ||
556 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 592 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); |
557 | } | 593 | } |
558 | 594 | ||
559 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ | 595 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ |
@@ -630,6 +666,10 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
630 | sta->flags &= ~WLAN_STA_WME; | 666 | sta->flags &= ~WLAN_STA_WME; |
631 | if (params->station_flags & STATION_FLAG_WME) | 667 | if (params->station_flags & STATION_FLAG_WME) |
632 | sta->flags |= WLAN_STA_WME; | 668 | sta->flags |= WLAN_STA_WME; |
669 | |||
670 | sta->flags &= ~WLAN_STA_MFP; | ||
671 | if (params->station_flags & STATION_FLAG_MFP) | ||
672 | sta->flags |= WLAN_STA_MFP; | ||
633 | spin_unlock_bh(&sta->lock); | 673 | spin_unlock_bh(&sta->lock); |
634 | } | 674 | } |
635 | 675 | ||
@@ -1141,6 +1181,125 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
1141 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 1181 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
1142 | } | 1182 | } |
1143 | 1183 | ||
1184 | static int set_mgmt_extra_ie_sta(struct ieee80211_sub_if_data *sdata, | ||
1185 | u8 subtype, u8 *ies, size_t ies_len) | ||
1186 | { | ||
1187 | struct ieee80211_local *local = sdata->local; | ||
1188 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1189 | |||
1190 | switch (subtype) { | ||
1191 | case IEEE80211_STYPE_PROBE_REQ >> 4: | ||
1192 | if (local->ops->hw_scan) | ||
1193 | break; | ||
1194 | kfree(ifmgd->ie_probereq); | ||
1195 | ifmgd->ie_probereq = ies; | ||
1196 | ifmgd->ie_probereq_len = ies_len; | ||
1197 | return 0; | ||
1198 | case IEEE80211_STYPE_PROBE_RESP >> 4: | ||
1199 | kfree(ifmgd->ie_proberesp); | ||
1200 | ifmgd->ie_proberesp = ies; | ||
1201 | ifmgd->ie_proberesp_len = ies_len; | ||
1202 | return 0; | ||
1203 | case IEEE80211_STYPE_AUTH >> 4: | ||
1204 | kfree(ifmgd->ie_auth); | ||
1205 | ifmgd->ie_auth = ies; | ||
1206 | ifmgd->ie_auth_len = ies_len; | ||
1207 | return 0; | ||
1208 | case IEEE80211_STYPE_ASSOC_REQ >> 4: | ||
1209 | kfree(ifmgd->ie_assocreq); | ||
1210 | ifmgd->ie_assocreq = ies; | ||
1211 | ifmgd->ie_assocreq_len = ies_len; | ||
1212 | return 0; | ||
1213 | case IEEE80211_STYPE_REASSOC_REQ >> 4: | ||
1214 | kfree(ifmgd->ie_reassocreq); | ||
1215 | ifmgd->ie_reassocreq = ies; | ||
1216 | ifmgd->ie_reassocreq_len = ies_len; | ||
1217 | return 0; | ||
1218 | case IEEE80211_STYPE_DEAUTH >> 4: | ||
1219 | kfree(ifmgd->ie_deauth); | ||
1220 | ifmgd->ie_deauth = ies; | ||
1221 | ifmgd->ie_deauth_len = ies_len; | ||
1222 | return 0; | ||
1223 | case IEEE80211_STYPE_DISASSOC >> 4: | ||
1224 | kfree(ifmgd->ie_disassoc); | ||
1225 | ifmgd->ie_disassoc = ies; | ||
1226 | ifmgd->ie_disassoc_len = ies_len; | ||
1227 | return 0; | ||
1228 | } | ||
1229 | |||
1230 | return -EOPNOTSUPP; | ||
1231 | } | ||
1232 | |||
1233 | static int ieee80211_set_mgmt_extra_ie(struct wiphy *wiphy, | ||
1234 | struct net_device *dev, | ||
1235 | struct mgmt_extra_ie_params *params) | ||
1236 | { | ||
1237 | struct ieee80211_sub_if_data *sdata; | ||
1238 | u8 *ies; | ||
1239 | size_t ies_len; | ||
1240 | int ret = -EOPNOTSUPP; | ||
1241 | |||
1242 | if (params->ies) { | ||
1243 | ies = kmemdup(params->ies, params->ies_len, GFP_KERNEL); | ||
1244 | if (ies == NULL) | ||
1245 | return -ENOMEM; | ||
1246 | ies_len = params->ies_len; | ||
1247 | } else { | ||
1248 | ies = NULL; | ||
1249 | ies_len = 0; | ||
1250 | } | ||
1251 | |||
1252 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1253 | |||
1254 | switch (sdata->vif.type) { | ||
1255 | case NL80211_IFTYPE_STATION: | ||
1256 | ret = set_mgmt_extra_ie_sta(sdata, params->subtype, | ||
1257 | ies, ies_len); | ||
1258 | break; | ||
1259 | default: | ||
1260 | ret = -EOPNOTSUPP; | ||
1261 | break; | ||
1262 | } | ||
1263 | |||
1264 | if (ret) | ||
1265 | kfree(ies); | ||
1266 | return ret; | ||
1267 | } | ||
1268 | |||
1269 | #ifdef CONFIG_PM | ||
1270 | static int ieee80211_suspend(struct wiphy *wiphy) | ||
1271 | { | ||
1272 | return __ieee80211_suspend(wiphy_priv(wiphy)); | ||
1273 | } | ||
1274 | |||
1275 | static int ieee80211_resume(struct wiphy *wiphy) | ||
1276 | { | ||
1277 | return __ieee80211_resume(wiphy_priv(wiphy)); | ||
1278 | } | ||
1279 | #else | ||
1280 | #define ieee80211_suspend NULL | ||
1281 | #define ieee80211_resume NULL | ||
1282 | #endif | ||
1283 | |||
1284 | static int ieee80211_scan(struct wiphy *wiphy, | ||
1285 | struct net_device *dev, | ||
1286 | struct cfg80211_scan_request *req) | ||
1287 | { | ||
1288 | struct ieee80211_sub_if_data *sdata; | ||
1289 | |||
1290 | if (!netif_running(dev)) | ||
1291 | return -ENETDOWN; | ||
1292 | |||
1293 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1294 | |||
1295 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
1296 | sdata->vif.type != NL80211_IFTYPE_ADHOC && | ||
1297 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
1298 | return -EOPNOTSUPP; | ||
1299 | |||
1300 | return ieee80211_request_scan(sdata, req); | ||
1301 | } | ||
1302 | |||
1144 | struct cfg80211_ops mac80211_config_ops = { | 1303 | struct cfg80211_ops mac80211_config_ops = { |
1145 | .add_virtual_intf = ieee80211_add_iface, | 1304 | .add_virtual_intf = ieee80211_add_iface, |
1146 | .del_virtual_intf = ieee80211_del_iface, | 1305 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1149,6 +1308,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1149 | .del_key = ieee80211_del_key, | 1308 | .del_key = ieee80211_del_key, |
1150 | .get_key = ieee80211_get_key, | 1309 | .get_key = ieee80211_get_key, |
1151 | .set_default_key = ieee80211_config_default_key, | 1310 | .set_default_key = ieee80211_config_default_key, |
1311 | .set_default_mgmt_key = ieee80211_config_default_mgmt_key, | ||
1152 | .add_beacon = ieee80211_add_beacon, | 1312 | .add_beacon = ieee80211_add_beacon, |
1153 | .set_beacon = ieee80211_set_beacon, | 1313 | .set_beacon = ieee80211_set_beacon, |
1154 | .del_beacon = ieee80211_del_beacon, | 1314 | .del_beacon = ieee80211_del_beacon, |
@@ -1169,4 +1329,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1169 | .change_bss = ieee80211_change_bss, | 1329 | .change_bss = ieee80211_change_bss, |
1170 | .set_txq_params = ieee80211_set_txq_params, | 1330 | .set_txq_params = ieee80211_set_txq_params, |
1171 | .set_channel = ieee80211_set_channel, | 1331 | .set_channel = ieee80211_set_channel, |
1332 | .set_mgmt_extra_ie = ieee80211_set_mgmt_extra_ie, | ||
1333 | .suspend = ieee80211_suspend, | ||
1334 | .resume = ieee80211_resume, | ||
1335 | .scan = ieee80211_scan, | ||
1172 | }; | 1336 | }; |