diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/agg-tx.c | 7 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 53 | ||||
-rw-r--r-- | net/mac80211/debugfs_key.c | 37 | ||||
-rw-r--r-- | net/mac80211/debugfs_key.h | 8 | ||||
-rw-r--r-- | net/mac80211/debugfs_sta.c | 2 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 9 | ||||
-rw-r--r-- | net/mac80211/key.c | 45 | ||||
-rw-r--r-- | net/mac80211/key.h | 3 | ||||
-rw-r--r-- | net/mac80211/main.c | 15 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 52 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 22 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 3 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 2 | ||||
-rw-r--r-- | net/mac80211/rx.c | 50 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 22 |
17 files changed, 215 insertions, 119 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index d4679b265ba8..9cc472c6a6a5 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -342,10 +342,11 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
342 | /* send AddBA request */ | 342 | /* send AddBA request */ |
343 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, | 343 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, |
344 | tid_tx->dialog_token, start_seq_num, | 344 | tid_tx->dialog_token, start_seq_num, |
345 | 0x40, 5000); | 345 | 0x40, tid_tx->timeout); |
346 | } | 346 | } |
347 | 347 | ||
348 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | 348 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, |
349 | u16 timeout) | ||
349 | { | 350 | { |
350 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 351 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
351 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 352 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -420,6 +421,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
420 | skb_queue_head_init(&tid_tx->pending); | 421 | skb_queue_head_init(&tid_tx->pending); |
421 | __set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); | 422 | __set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); |
422 | 423 | ||
424 | tid_tx->timeout = timeout; | ||
425 | |||
423 | /* Tx timer */ | 426 | /* Tx timer */ |
424 | tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired; | 427 | tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired; |
425 | tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 428 | tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c30b8b72eedb..5892b0302454 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -295,11 +295,12 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
295 | 295 | ||
296 | static int ieee80211_config_default_key(struct wiphy *wiphy, | 296 | static int ieee80211_config_default_key(struct wiphy *wiphy, |
297 | struct net_device *dev, | 297 | struct net_device *dev, |
298 | u8 key_idx) | 298 | u8 key_idx, bool uni, |
299 | bool multi) | ||
299 | { | 300 | { |
300 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 301 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
301 | 302 | ||
302 | ieee80211_set_default_key(sdata, key_idx); | 303 | ieee80211_set_default_key(sdata, key_idx, uni, multi); |
303 | 304 | ||
304 | return 0; | 305 | return 0; |
305 | } | 306 | } |
@@ -983,7 +984,7 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
983 | return 0; | 984 | return 0; |
984 | } | 985 | } |
985 | 986 | ||
986 | static int ieee80211_get_mesh_params(struct wiphy *wiphy, | 987 | static int ieee80211_get_mesh_config(struct wiphy *wiphy, |
987 | struct net_device *dev, | 988 | struct net_device *dev, |
988 | struct mesh_config *conf) | 989 | struct mesh_config *conf) |
989 | { | 990 | { |
@@ -999,7 +1000,37 @@ static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask) | |||
999 | return (mask >> (parm-1)) & 0x1; | 1000 | return (mask >> (parm-1)) & 0x1; |
1000 | } | 1001 | } |
1001 | 1002 | ||
1002 | static int ieee80211_update_mesh_params(struct wiphy *wiphy, | 1003 | static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, |
1004 | const struct mesh_setup *setup) | ||
1005 | { | ||
1006 | u8 *new_ie; | ||
1007 | const u8 *old_ie; | ||
1008 | |||
1009 | /* first allocate the new vendor information element */ | ||
1010 | new_ie = NULL; | ||
1011 | old_ie = ifmsh->vendor_ie; | ||
1012 | |||
1013 | ifmsh->vendor_ie_len = setup->vendor_ie_len; | ||
1014 | if (setup->vendor_ie_len) { | ||
1015 | new_ie = kmemdup(setup->vendor_ie, setup->vendor_ie_len, | ||
1016 | GFP_KERNEL); | ||
1017 | if (!new_ie) | ||
1018 | return -ENOMEM; | ||
1019 | } | ||
1020 | |||
1021 | /* now copy the rest of the setup parameters */ | ||
1022 | ifmsh->mesh_id_len = setup->mesh_id_len; | ||
1023 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); | ||
1024 | ifmsh->mesh_pp_id = setup->path_sel_proto; | ||
1025 | ifmsh->mesh_pm_id = setup->path_metric; | ||
1026 | ifmsh->vendor_ie = new_ie; | ||
1027 | |||
1028 | kfree(old_ie); | ||
1029 | |||
1030 | return 0; | ||
1031 | } | ||
1032 | |||
1033 | static int ieee80211_update_mesh_config(struct wiphy *wiphy, | ||
1003 | struct net_device *dev, u32 mask, | 1034 | struct net_device *dev, u32 mask, |
1004 | const struct mesh_config *nconf) | 1035 | const struct mesh_config *nconf) |
1005 | { | 1036 | { |
@@ -1058,11 +1089,12 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, | |||
1058 | { | 1089 | { |
1059 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1090 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1060 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1091 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
1092 | int err; | ||
1061 | 1093 | ||
1062 | memcpy(&sdata->u.mesh.mshcfg, conf, sizeof(struct mesh_config)); | 1094 | memcpy(&ifmsh->mshcfg, conf, sizeof(struct mesh_config)); |
1063 | ifmsh->mesh_id_len = setup->mesh_id_len; | 1095 | err = copy_mesh_setup(ifmsh, setup); |
1064 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); | 1096 | if (err) |
1065 | 1097 | return err; | |
1066 | ieee80211_start_mesh(sdata); | 1098 | ieee80211_start_mesh(sdata); |
1067 | 1099 | ||
1068 | return 0; | 1100 | return 0; |
@@ -1638,6 +1670,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1638 | case NL80211_IFTYPE_AP: | 1670 | case NL80211_IFTYPE_AP: |
1639 | case NL80211_IFTYPE_AP_VLAN: | 1671 | case NL80211_IFTYPE_AP_VLAN: |
1640 | case NL80211_IFTYPE_P2P_GO: | 1672 | case NL80211_IFTYPE_P2P_GO: |
1673 | case NL80211_IFTYPE_MESH_POINT: | ||
1641 | if (!ieee80211_is_action(mgmt->frame_control) || | 1674 | if (!ieee80211_is_action(mgmt->frame_control) || |
1642 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | 1675 | mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) |
1643 | break; | 1676 | break; |
@@ -1786,8 +1819,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1786 | .change_mpath = ieee80211_change_mpath, | 1819 | .change_mpath = ieee80211_change_mpath, |
1787 | .get_mpath = ieee80211_get_mpath, | 1820 | .get_mpath = ieee80211_get_mpath, |
1788 | .dump_mpath = ieee80211_dump_mpath, | 1821 | .dump_mpath = ieee80211_dump_mpath, |
1789 | .update_mesh_params = ieee80211_update_mesh_params, | 1822 | .update_mesh_config = ieee80211_update_mesh_config, |
1790 | .get_mesh_params = ieee80211_get_mesh_params, | 1823 | .get_mesh_config = ieee80211_get_mesh_config, |
1791 | .join_mesh = ieee80211_join_mesh, | 1824 | .join_mesh = ieee80211_join_mesh, |
1792 | .leave_mesh = ieee80211_leave_mesh, | 1825 | .leave_mesh = ieee80211_leave_mesh, |
1793 | #endif | 1826 | #endif |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 5822a6ce7671..f7ef3477c24a 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -274,7 +274,8 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key) | |||
274 | debugfs_remove_recursive(key->debugfs.dir); | 274 | debugfs_remove_recursive(key->debugfs.dir); |
275 | key->debugfs.dir = NULL; | 275 | key->debugfs.dir = NULL; |
276 | } | 276 | } |
277 | void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) | 277 | |
278 | void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | ||
278 | { | 279 | { |
279 | char buf[50]; | 280 | char buf[50]; |
280 | struct ieee80211_key *key; | 281 | struct ieee80211_key *key; |
@@ -282,25 +283,29 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) | |||
282 | if (!sdata->debugfs.dir) | 283 | if (!sdata->debugfs.dir) |
283 | return; | 284 | return; |
284 | 285 | ||
285 | /* this is running under the key lock */ | 286 | lockdep_assert_held(&sdata->local->key_mtx); |
286 | 287 | ||
287 | key = sdata->default_key; | 288 | if (sdata->default_unicast_key) { |
288 | if (key) { | 289 | key = sdata->default_unicast_key; |
289 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 290 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
290 | sdata->debugfs.default_key = | 291 | sdata->debugfs.default_unicast_key = |
291 | debugfs_create_symlink("default_key", | 292 | debugfs_create_symlink("default_unicast_key", |
292 | sdata->debugfs.dir, buf); | 293 | sdata->debugfs.dir, buf); |
293 | } else | 294 | } else { |
294 | ieee80211_debugfs_key_remove_default(sdata); | 295 | debugfs_remove(sdata->debugfs.default_unicast_key); |
295 | } | 296 | sdata->debugfs.default_unicast_key = NULL; |
296 | 297 | } | |
297 | void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) | ||
298 | { | ||
299 | if (!sdata) | ||
300 | return; | ||
301 | 298 | ||
302 | debugfs_remove(sdata->debugfs.default_key); | 299 | if (sdata->default_multicast_key) { |
303 | sdata->debugfs.default_key = NULL; | 300 | key = sdata->default_multicast_key; |
301 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | ||
302 | sdata->debugfs.default_multicast_key = | ||
303 | debugfs_create_symlink("default_multicast_key", | ||
304 | sdata->debugfs.dir, buf); | ||
305 | } else { | ||
306 | debugfs_remove(sdata->debugfs.default_multicast_key); | ||
307 | sdata->debugfs.default_multicast_key = NULL; | ||
308 | } | ||
304 | } | 309 | } |
305 | 310 | ||
306 | void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) | 311 | void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h index 54717b4e1371..32adc77e9c77 100644 --- a/net/mac80211/debugfs_key.h +++ b/net/mac80211/debugfs_key.h | |||
@@ -4,8 +4,7 @@ | |||
4 | #ifdef CONFIG_MAC80211_DEBUGFS | 4 | #ifdef CONFIG_MAC80211_DEBUGFS |
5 | void ieee80211_debugfs_key_add(struct ieee80211_key *key); | 5 | void ieee80211_debugfs_key_add(struct ieee80211_key *key); |
6 | void ieee80211_debugfs_key_remove(struct ieee80211_key *key); | 6 | void ieee80211_debugfs_key_remove(struct ieee80211_key *key); |
7 | void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata); | 7 | void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata); |
8 | void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata); | ||
9 | void ieee80211_debugfs_key_add_mgmt_default( | 8 | void ieee80211_debugfs_key_add_mgmt_default( |
10 | struct ieee80211_sub_if_data *sdata); | 9 | struct ieee80211_sub_if_data *sdata); |
11 | void ieee80211_debugfs_key_remove_mgmt_default( | 10 | void ieee80211_debugfs_key_remove_mgmt_default( |
@@ -17,10 +16,7 @@ static inline void ieee80211_debugfs_key_add(struct ieee80211_key *key) | |||
17 | {} | 16 | {} |
18 | static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key) | 17 | static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key) |
19 | {} | 18 | {} |
20 | static inline void ieee80211_debugfs_key_add_default( | 19 | static inline void ieee80211_debugfs_key_update_default( |
21 | struct ieee80211_sub_if_data *sdata) | ||
22 | {} | ||
23 | static inline void ieee80211_debugfs_key_remove_default( | ||
24 | struct ieee80211_sub_if_data *sdata) | 20 | struct ieee80211_sub_if_data *sdata) |
25 | {} | 21 | {} |
26 | static inline void ieee80211_debugfs_key_add_mgmt_default( | 22 | static inline void ieee80211_debugfs_key_add_mgmt_default( |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 8bb5af85f469..c04a1396cf8d 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -189,7 +189,7 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu | |||
189 | 189 | ||
190 | if (tx) { | 190 | if (tx) { |
191 | if (start) | 191 | if (start) |
192 | ret = ieee80211_start_tx_ba_session(&sta->sta, tid); | 192 | ret = ieee80211_start_tx_ba_session(&sta->sta, tid, 5000); |
193 | else | 193 | else |
194 | ret = ieee80211_stop_tx_ba_session(&sta->sta, tid); | 194 | ret = ieee80211_stop_tx_ba_session(&sta->sta, tid); |
195 | } else { | 195 | } else { |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 4244554d218a..af0c4398cceb 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -367,7 +367,7 @@ static inline void drv_reset_tsf(struct ieee80211_local *local) | |||
367 | 367 | ||
368 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) | 368 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) |
369 | { | 369 | { |
370 | int ret = 1; | 370 | int ret = 0; /* default unsuported op for less congestion */ |
371 | 371 | ||
372 | might_sleep(); | 372 | might_sleep(); |
373 | 373 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 72499fe5fc36..eadaa243a3da 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -484,6 +484,8 @@ struct ieee80211_if_mesh { | |||
484 | struct mesh_config mshcfg; | 484 | struct mesh_config mshcfg; |
485 | u32 mesh_seqnum; | 485 | u32 mesh_seqnum; |
486 | bool accepting_plinks; | 486 | bool accepting_plinks; |
487 | const u8 *vendor_ie; | ||
488 | u8 vendor_ie_len; | ||
487 | }; | 489 | }; |
488 | 490 | ||
489 | #ifdef CONFIG_MAC80211_MESH | 491 | #ifdef CONFIG_MAC80211_MESH |
@@ -557,7 +559,7 @@ struct ieee80211_sub_if_data { | |||
557 | unsigned int fragment_next; | 559 | unsigned int fragment_next; |
558 | 560 | ||
559 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; | 561 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; |
560 | struct ieee80211_key *default_key; | 562 | struct ieee80211_key *default_unicast_key, *default_multicast_key; |
561 | struct ieee80211_key *default_mgmt_key; | 563 | struct ieee80211_key *default_mgmt_key; |
562 | 564 | ||
563 | u16 sequence_number; | 565 | u16 sequence_number; |
@@ -585,9 +587,7 @@ struct ieee80211_sub_if_data { | |||
585 | struct ieee80211_if_vlan vlan; | 587 | struct ieee80211_if_vlan vlan; |
586 | struct ieee80211_if_managed mgd; | 588 | struct ieee80211_if_managed mgd; |
587 | struct ieee80211_if_ibss ibss; | 589 | struct ieee80211_if_ibss ibss; |
588 | #ifdef CONFIG_MAC80211_MESH | ||
589 | struct ieee80211_if_mesh mesh; | 590 | struct ieee80211_if_mesh mesh; |
590 | #endif | ||
591 | u32 mntr_flags; | 591 | u32 mntr_flags; |
592 | } u; | 592 | } u; |
593 | 593 | ||
@@ -595,7 +595,8 @@ struct ieee80211_sub_if_data { | |||
595 | struct { | 595 | struct { |
596 | struct dentry *dir; | 596 | struct dentry *dir; |
597 | struct dentry *subdir_stations; | 597 | struct dentry *subdir_stations; |
598 | struct dentry *default_key; | 598 | struct dentry *default_unicast_key; |
599 | struct dentry *default_multicast_key; | ||
599 | struct dentry *default_mgmt_key; | 600 | struct dentry *default_mgmt_key; |
600 | } debugfs; | 601 | } debugfs; |
601 | #endif | 602 | #endif |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 72df1ca7299b..84cf9196820f 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -178,7 +178,7 @@ void ieee80211_key_removed(struct ieee80211_key_conf *key_conf) | |||
178 | EXPORT_SYMBOL_GPL(ieee80211_key_removed); | 178 | EXPORT_SYMBOL_GPL(ieee80211_key_removed); |
179 | 179 | ||
180 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | 180 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, |
181 | int idx) | 181 | int idx, bool uni, bool multi) |
182 | { | 182 | { |
183 | struct ieee80211_key *key = NULL; | 183 | struct ieee80211_key *key = NULL; |
184 | 184 | ||
@@ -187,18 +187,19 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | |||
187 | if (idx >= 0 && idx < NUM_DEFAULT_KEYS) | 187 | if (idx >= 0 && idx < NUM_DEFAULT_KEYS) |
188 | key = sdata->keys[idx]; | 188 | key = sdata->keys[idx]; |
189 | 189 | ||
190 | rcu_assign_pointer(sdata->default_key, key); | 190 | if (uni) |
191 | rcu_assign_pointer(sdata->default_unicast_key, key); | ||
192 | if (multi) | ||
193 | rcu_assign_pointer(sdata->default_multicast_key, key); | ||
191 | 194 | ||
192 | if (key) { | 195 | ieee80211_debugfs_key_update_default(sdata); |
193 | ieee80211_debugfs_key_remove_default(key->sdata); | ||
194 | ieee80211_debugfs_key_add_default(key->sdata); | ||
195 | } | ||
196 | } | 196 | } |
197 | 197 | ||
198 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) | 198 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, |
199 | bool uni, bool multi) | ||
199 | { | 200 | { |
200 | mutex_lock(&sdata->local->key_mtx); | 201 | mutex_lock(&sdata->local->key_mtx); |
201 | __ieee80211_set_default_key(sdata, idx); | 202 | __ieee80211_set_default_key(sdata, idx, uni, multi); |
202 | mutex_unlock(&sdata->local->key_mtx); | 203 | mutex_unlock(&sdata->local->key_mtx); |
203 | } | 204 | } |
204 | 205 | ||
@@ -215,10 +216,7 @@ __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx) | |||
215 | 216 | ||
216 | rcu_assign_pointer(sdata->default_mgmt_key, key); | 217 | rcu_assign_pointer(sdata->default_mgmt_key, key); |
217 | 218 | ||
218 | if (key) { | 219 | ieee80211_debugfs_key_update_default(sdata); |
219 | ieee80211_debugfs_key_remove_mgmt_default(key->sdata); | ||
220 | ieee80211_debugfs_key_add_mgmt_default(key->sdata); | ||
221 | } | ||
222 | } | 220 | } |
223 | 221 | ||
224 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | 222 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, |
@@ -236,7 +234,8 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
236 | struct ieee80211_key *old, | 234 | struct ieee80211_key *old, |
237 | struct ieee80211_key *new) | 235 | struct ieee80211_key *new) |
238 | { | 236 | { |
239 | int idx, defkey, defmgmtkey; | 237 | int idx; |
238 | bool defunikey, defmultikey, defmgmtkey; | ||
240 | 239 | ||
241 | if (new) | 240 | if (new) |
242 | list_add(&new->list, &sdata->key_list); | 241 | list_add(&new->list, &sdata->key_list); |
@@ -257,17 +256,24 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
257 | else | 256 | else |
258 | idx = new->conf.keyidx; | 257 | idx = new->conf.keyidx; |
259 | 258 | ||
260 | defkey = old && sdata->default_key == old; | 259 | defunikey = old && sdata->default_unicast_key == old; |
260 | defmultikey = old && sdata->default_multicast_key == old; | ||
261 | defmgmtkey = old && sdata->default_mgmt_key == old; | 261 | defmgmtkey = old && sdata->default_mgmt_key == old; |
262 | 262 | ||
263 | if (defkey && !new) | 263 | if (defunikey && !new) |
264 | __ieee80211_set_default_key(sdata, -1); | 264 | __ieee80211_set_default_key(sdata, -1, true, false); |
265 | if (defmultikey && !new) | ||
266 | __ieee80211_set_default_key(sdata, -1, false, true); | ||
265 | if (defmgmtkey && !new) | 267 | if (defmgmtkey && !new) |
266 | __ieee80211_set_default_mgmt_key(sdata, -1); | 268 | __ieee80211_set_default_mgmt_key(sdata, -1); |
267 | 269 | ||
268 | rcu_assign_pointer(sdata->keys[idx], new); | 270 | rcu_assign_pointer(sdata->keys[idx], new); |
269 | if (defkey && new) | 271 | if (defunikey && new) |
270 | __ieee80211_set_default_key(sdata, new->conf.keyidx); | 272 | __ieee80211_set_default_key(sdata, new->conf.keyidx, |
273 | true, false); | ||
274 | if (defmultikey && new) | ||
275 | __ieee80211_set_default_key(sdata, new->conf.keyidx, | ||
276 | false, true); | ||
271 | if (defmgmtkey && new) | 277 | if (defmgmtkey && new) |
272 | __ieee80211_set_default_mgmt_key(sdata, | 278 | __ieee80211_set_default_mgmt_key(sdata, |
273 | new->conf.keyidx); | 279 | new->conf.keyidx); |
@@ -509,11 +515,12 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | |||
509 | 515 | ||
510 | mutex_lock(&sdata->local->key_mtx); | 516 | mutex_lock(&sdata->local->key_mtx); |
511 | 517 | ||
512 | ieee80211_debugfs_key_remove_default(sdata); | ||
513 | ieee80211_debugfs_key_remove_mgmt_default(sdata); | 518 | ieee80211_debugfs_key_remove_mgmt_default(sdata); |
514 | 519 | ||
515 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) | 520 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) |
516 | __ieee80211_key_free(key); | 521 | __ieee80211_key_free(key); |
517 | 522 | ||
523 | ieee80211_debugfs_key_update_default(sdata); | ||
524 | |||
518 | mutex_unlock(&sdata->local->key_mtx); | 525 | mutex_unlock(&sdata->local->key_mtx); |
519 | } | 526 | } |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 0db1c0f5f697..8106aa1b7466 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -138,7 +138,8 @@ int __must_check ieee80211_key_link(struct ieee80211_key *key, | |||
138 | struct sta_info *sta); | 138 | struct sta_info *sta); |
139 | void ieee80211_key_free(struct ieee80211_local *local, | 139 | void ieee80211_key_free(struct ieee80211_local *local, |
140 | struct ieee80211_key *key); | 140 | struct ieee80211_key *key); |
141 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx); | 141 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, |
142 | bool uni, bool multi); | ||
142 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, | 143 | void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, |
143 | int idx); | 144 | int idx); |
144 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); | 145 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 973fee9f7d69..a21d049caf19 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -484,6 +484,10 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
484 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | 484 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | |
485 | BIT(IEEE80211_STYPE_ACTION >> 4), | 485 | BIT(IEEE80211_STYPE_ACTION >> 4), |
486 | }, | 486 | }, |
487 | [NL80211_IFTYPE_MESH_POINT] = { | ||
488 | .tx = 0xffff, | ||
489 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4), | ||
490 | }, | ||
487 | }; | 491 | }; |
488 | 492 | ||
489 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 493 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
@@ -517,10 +521,15 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
517 | 521 | ||
518 | wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes; | 522 | wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes; |
519 | 523 | ||
524 | wiphy->privid = mac80211_wiphy_privid; | ||
525 | |||
520 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | | 526 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | |
521 | WIPHY_FLAG_4ADDR_AP | | 527 | WIPHY_FLAG_4ADDR_AP | |
522 | WIPHY_FLAG_4ADDR_STATION; | 528 | WIPHY_FLAG_4ADDR_STATION | |
523 | wiphy->privid = mac80211_wiphy_privid; | 529 | WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS; |
530 | |||
531 | if (!ops->set_key) | ||
532 | wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | ||
524 | 533 | ||
525 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss); | 534 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss); |
526 | 535 | ||
@@ -740,6 +749,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
740 | } | 749 | } |
741 | } | 750 | } |
742 | 751 | ||
752 | local->hw.wiphy->max_remain_on_channel_duration = 5000; | ||
753 | |||
743 | result = wiphy_register(local->hw.wiphy); | 754 | result = wiphy_register(local->hw.wiphy); |
744 | if (result < 0) | 755 | if (result < 0) |
745 | goto fail_wiphy_register; | 756 | goto fail_wiphy_register; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 63e1188d5062..ca3af4685b0a 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -124,15 +124,6 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | |||
124 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); | 124 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); |
125 | } | 125 | } |
126 | 126 | ||
127 | void mesh_ids_set_default(struct ieee80211_if_mesh *sta) | ||
128 | { | ||
129 | sta->mesh_pp_id = 0; /* HWMP */ | ||
130 | sta->mesh_pm_id = 0; /* Airtime */ | ||
131 | sta->mesh_cc_id = 0; /* Disabled */ | ||
132 | sta->mesh_sp_id = 0; /* Neighbor Offset */ | ||
133 | sta->mesh_auth_id = 0; /* Disabled */ | ||
134 | } | ||
135 | |||
136 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) | 127 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) |
137 | { | 128 | { |
138 | int i; | 129 | int i; |
@@ -287,6 +278,13 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
287 | *pos++ |= sdata->u.mesh.accepting_plinks ? | 278 | *pos++ |= sdata->u.mesh.accepting_plinks ? |
288 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 279 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
289 | *pos++ = 0x00; | 280 | *pos++ = 0x00; |
281 | |||
282 | if (sdata->u.mesh.vendor_ie) { | ||
283 | int len = sdata->u.mesh.vendor_ie_len; | ||
284 | const u8 *data = sdata->u.mesh.vendor_ie; | ||
285 | if (skb_tailroom(skb) > len) | ||
286 | memcpy(skb_put(skb, len), data, len); | ||
287 | } | ||
290 | } | 288 | } |
291 | 289 | ||
292 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) | 290 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) |
@@ -412,39 +410,33 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | |||
412 | * ieee80211_new_mesh_header - create a new mesh header | 410 | * ieee80211_new_mesh_header - create a new mesh header |
413 | * @meshhdr: uninitialized mesh header | 411 | * @meshhdr: uninitialized mesh header |
414 | * @sdata: mesh interface to be used | 412 | * @sdata: mesh interface to be used |
415 | * @addr4: addr4 of the mesh frame (1st in ae header) | 413 | * @addr4or5: 1st address in the ae header, which may correspond to address 4 |
416 | * may be NULL | 414 | * (if addr6 is NULL) or address 5 (if addr6 is present). It may |
417 | * @addr5: addr5 of the mesh frame (1st or 2nd in ae header) | 415 | * be NULL. |
418 | * may be NULL unless addr6 is present | 416 | * @addr6: 2nd address in the ae header, which corresponds to addr6 of the |
419 | * @addr6: addr6 of the mesh frame (2nd or 3rd in ae header) | 417 | * mesh frame |
420 | * may be NULL unless addr5 is present | ||
421 | * | 418 | * |
422 | * Return the header length. | 419 | * Return the header length. |
423 | */ | 420 | */ |
424 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 421 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, |
425 | struct ieee80211_sub_if_data *sdata, char *addr4, | 422 | struct ieee80211_sub_if_data *sdata, char *addr4or5, |
426 | char *addr5, char *addr6) | 423 | char *addr6) |
427 | { | 424 | { |
428 | int aelen = 0; | 425 | int aelen = 0; |
426 | BUG_ON(!addr4or5 && addr6); | ||
429 | memset(meshhdr, 0, sizeof(*meshhdr)); | 427 | memset(meshhdr, 0, sizeof(*meshhdr)); |
430 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | 428 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
431 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); | 429 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); |
432 | sdata->u.mesh.mesh_seqnum++; | 430 | sdata->u.mesh.mesh_seqnum++; |
433 | if (addr4) { | 431 | if (addr4or5 && !addr6) { |
434 | meshhdr->flags |= MESH_FLAGS_AE_A4; | 432 | meshhdr->flags |= MESH_FLAGS_AE_A4; |
435 | aelen += ETH_ALEN; | 433 | aelen += ETH_ALEN; |
436 | memcpy(meshhdr->eaddr1, addr4, ETH_ALEN); | 434 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); |
437 | } | 435 | } else if (addr4or5 && addr6) { |
438 | if (addr5 && addr6) { | ||
439 | meshhdr->flags |= MESH_FLAGS_AE_A5_A6; | 436 | meshhdr->flags |= MESH_FLAGS_AE_A5_A6; |
440 | aelen += 2 * ETH_ALEN; | 437 | aelen += 2 * ETH_ALEN; |
441 | if (!addr4) { | 438 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); |
442 | memcpy(meshhdr->eaddr1, addr5, ETH_ALEN); | 439 | memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); |
443 | memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); | ||
444 | } else { | ||
445 | memcpy(meshhdr->eaddr2, addr5, ETH_ALEN); | ||
446 | memcpy(meshhdr->eaddr3, addr6, ETH_ALEN); | ||
447 | } | ||
448 | } | 440 | } |
449 | return 6 + aelen; | 441 | return 6 + aelen; |
450 | } | 442 | } |
@@ -518,6 +510,9 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
518 | atomic_inc(&local->iff_allmultis); | 510 | atomic_inc(&local->iff_allmultis); |
519 | ieee80211_configure_filter(local); | 511 | ieee80211_configure_filter(local); |
520 | 512 | ||
513 | ifmsh->mesh_cc_id = 0; /* Disabled */ | ||
514 | ifmsh->mesh_sp_id = 0; /* Neighbor Offset */ | ||
515 | ifmsh->mesh_auth_id = 0; /* Disabled */ | ||
521 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); | 516 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
522 | ieee80211_mesh_root_setup(ifmsh); | 517 | ieee80211_mesh_root_setup(ifmsh); |
523 | ieee80211_queue_work(&local->hw, &sdata->work); | 518 | ieee80211_queue_work(&local->hw, &sdata->work); |
@@ -688,7 +683,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
688 | /* Allocate all mesh structures when creating the first mesh interface. */ | 683 | /* Allocate all mesh structures when creating the first mesh interface. */ |
689 | if (!mesh_allocated) | 684 | if (!mesh_allocated) |
690 | ieee80211s_init(); | 685 | ieee80211s_init(); |
691 | mesh_ids_set_default(ifmsh); | ||
692 | setup_timer(&ifmsh->mesh_path_timer, | 686 | setup_timer(&ifmsh->mesh_path_timer, |
693 | ieee80211_mesh_path_timer, | 687 | ieee80211_mesh_path_timer, |
694 | (unsigned long) sdata); | 688 | (unsigned long) sdata); |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 039d7fa0af74..b99e230fe31c 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -164,17 +164,6 @@ struct mesh_rmc { | |||
164 | }; | 164 | }; |
165 | 165 | ||
166 | 166 | ||
167 | /* | ||
168 | * MESH_CFG_COMP_LEN Includes: | ||
169 | * - Active path selection protocol ID. | ||
170 | * - Active path selection metric ID. | ||
171 | * - Congestion control mode identifier. | ||
172 | * - Channel precedence. | ||
173 | * Does not include mesh capabilities, which may vary across nodes in the same | ||
174 | * mesh | ||
175 | */ | ||
176 | #define MESH_CFG_CMP_LEN (IEEE80211_MESH_CONFIG_LEN - 2) | ||
177 | |||
178 | #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ | 167 | #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */ |
179 | 168 | ||
180 | #define MESH_PATH_EXPIRE (600 * HZ) | 169 | #define MESH_PATH_EXPIRE (600 * HZ) |
@@ -198,8 +187,8 @@ struct mesh_rmc { | |||
198 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | 187 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
199 | const u8 *da, const u8 *sa); | 188 | const u8 *da, const u8 *sa); |
200 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 189 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, |
201 | struct ieee80211_sub_if_data *sdata, char *addr4, | 190 | struct ieee80211_sub_if_data *sdata, char *addr4or5, |
202 | char *addr5, char *addr6); | 191 | char *addr6); |
203 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, | 192 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, |
204 | struct ieee80211_sub_if_data *sdata); | 193 | struct ieee80211_sub_if_data *sdata); |
205 | bool mesh_matches_local(struct ieee802_11_elems *ie, | 194 | bool mesh_matches_local(struct ieee802_11_elems *ie, |
@@ -295,6 +284,11 @@ static inline void mesh_path_activate(struct mesh_path *mpath) | |||
295 | mpath->flags |= MESH_PATH_ACTIVE | MESH_PATH_RESOLVED; | 284 | mpath->flags |= MESH_PATH_ACTIVE | MESH_PATH_RESOLVED; |
296 | } | 285 | } |
297 | 286 | ||
287 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | ||
288 | { | ||
289 | return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP; | ||
290 | } | ||
291 | |||
298 | #define for_each_mesh_entry(x, p, node, i) \ | 292 | #define for_each_mesh_entry(x, p, node, i) \ |
299 | for (i = 0; i <= x->hash_mask; i++) \ | 293 | for (i = 0; i <= x->hash_mask; i++) \ |
300 | hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) | 294 | hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) |
@@ -315,6 +309,8 @@ static inline void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata) | |||
315 | {} | 309 | {} |
316 | static inline void mesh_plink_quiesce(struct sta_info *sta) {} | 310 | static inline void mesh_plink_quiesce(struct sta_info *sta) {} |
317 | static inline void mesh_plink_restart(struct sta_info *sta) {} | 311 | static inline void mesh_plink_restart(struct sta_info *sta) {} |
312 | static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | ||
313 | { return false; } | ||
318 | #endif | 314 | #endif |
319 | 315 | ||
320 | #endif /* IEEE80211S_H */ | 316 | #endif /* IEEE80211S_H */ |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 1c91f0f3c307..44b53931ba5e 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -160,7 +160,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
160 | enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, | 160 | enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, |
161 | __le16 reason) { | 161 | __le16 reason) { |
162 | struct ieee80211_local *local = sdata->local; | 162 | struct ieee80211_local *local = sdata->local; |
163 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 163 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + |
164 | sdata->u.mesh.vendor_ie_len); | ||
164 | struct ieee80211_mgmt *mgmt; | 165 | struct ieee80211_mgmt *mgmt; |
165 | bool include_plid = false; | 166 | bool include_plid = false; |
166 | static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; | 167 | static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 4ad7a362fcc1..165a4518bb48 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -374,7 +374,7 @@ minstrel_aggr_check(struct minstrel_priv *mp, struct ieee80211_sta *pubsta, stru | |||
374 | if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO) | 374 | if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO) |
375 | return; | 375 | return; |
376 | 376 | ||
377 | ieee80211_start_tx_ba_session(pubsta, tid); | 377 | ieee80211_start_tx_ba_session(pubsta, tid, 5000); |
378 | } | 378 | } |
379 | 379 | ||
380 | static void | 380 | static void |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 2fe8f5f86499..7c5d1b2ec453 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -955,12 +955,31 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
955 | * have been expected. | 955 | * have been expected. |
956 | */ | 956 | */ |
957 | struct ieee80211_key *key = NULL; | 957 | struct ieee80211_key *key = NULL; |
958 | struct ieee80211_sub_if_data *sdata = rx->sdata; | ||
959 | int i; | ||
960 | |||
958 | if (ieee80211_is_mgmt(fc) && | 961 | if (ieee80211_is_mgmt(fc) && |
959 | is_multicast_ether_addr(hdr->addr1) && | 962 | is_multicast_ether_addr(hdr->addr1) && |
960 | (key = rcu_dereference(rx->sdata->default_mgmt_key))) | 963 | (key = rcu_dereference(rx->sdata->default_mgmt_key))) |
961 | rx->key = key; | 964 | rx->key = key; |
962 | else if ((key = rcu_dereference(rx->sdata->default_key))) | 965 | else { |
963 | rx->key = key; | 966 | if (rx->sta) { |
967 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
968 | key = rcu_dereference(rx->sta->gtk[i]); | ||
969 | if (key) | ||
970 | break; | ||
971 | } | ||
972 | } | ||
973 | if (!key) { | ||
974 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) { | ||
975 | key = rcu_dereference(sdata->keys[i]); | ||
976 | if (key) | ||
977 | break; | ||
978 | } | ||
979 | } | ||
980 | if (key) | ||
981 | rx->key = key; | ||
982 | } | ||
964 | return RX_CONTINUE; | 983 | return RX_CONTINUE; |
965 | } else { | 984 | } else { |
966 | u8 keyid; | 985 | u8 keyid; |
@@ -1521,12 +1540,30 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | |||
1521 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | 1540 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { |
1522 | if (unlikely(!ieee80211_has_protected(fc) && | 1541 | if (unlikely(!ieee80211_has_protected(fc) && |
1523 | ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | 1542 | ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && |
1524 | rx->key)) | 1543 | rx->key)) { |
1544 | if (ieee80211_is_deauth(fc)) | ||
1545 | cfg80211_send_unprot_deauth(rx->sdata->dev, | ||
1546 | rx->skb->data, | ||
1547 | rx->skb->len); | ||
1548 | else if (ieee80211_is_disassoc(fc)) | ||
1549 | cfg80211_send_unprot_disassoc(rx->sdata->dev, | ||
1550 | rx->skb->data, | ||
1551 | rx->skb->len); | ||
1525 | return -EACCES; | 1552 | return -EACCES; |
1553 | } | ||
1526 | /* BIP does not use Protected field, so need to check MMIE */ | 1554 | /* BIP does not use Protected field, so need to check MMIE */ |
1527 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | 1555 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && |
1528 | ieee80211_get_mmie_keyidx(rx->skb) < 0)) | 1556 | ieee80211_get_mmie_keyidx(rx->skb) < 0)) { |
1557 | if (ieee80211_is_deauth(fc)) | ||
1558 | cfg80211_send_unprot_deauth(rx->sdata->dev, | ||
1559 | rx->skb->data, | ||
1560 | rx->skb->len); | ||
1561 | else if (ieee80211_is_disassoc(fc)) | ||
1562 | cfg80211_send_unprot_disassoc(rx->sdata->dev, | ||
1563 | rx->skb->data, | ||
1564 | rx->skb->len); | ||
1529 | return -EACCES; | 1565 | return -EACCES; |
1566 | } | ||
1530 | /* | 1567 | /* |
1531 | * When using MFP, Action frames are not allowed prior to | 1568 | * When using MFP, Action frames are not allowed prior to |
1532 | * having configured keys. | 1569 | * having configured keys. |
@@ -2124,10 +2161,13 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2124 | } | 2161 | } |
2125 | break; | 2162 | break; |
2126 | case WLAN_CATEGORY_MESH_PLINK: | 2163 | case WLAN_CATEGORY_MESH_PLINK: |
2127 | case WLAN_CATEGORY_MESH_PATH_SEL: | ||
2128 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | 2164 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
2129 | break; | 2165 | break; |
2130 | goto queue; | 2166 | goto queue; |
2167 | case WLAN_CATEGORY_MESH_PATH_SEL: | ||
2168 | if (!mesh_path_sel_is_hwmp(sdata)) | ||
2169 | break; | ||
2170 | goto queue; | ||
2131 | } | 2171 | } |
2132 | 2172 | ||
2133 | return RX_CONTINUE; | 2173 | return RX_CONTINUE; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index fdca52cf88de..bbdd2a86a94b 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -78,6 +78,7 @@ enum ieee80211_sta_info_flags { | |||
78 | * @addba_resp_timer: timer for peer's response to addba request | 78 | * @addba_resp_timer: timer for peer's response to addba request |
79 | * @pending: pending frames queue -- use sta's spinlock to protect | 79 | * @pending: pending frames queue -- use sta's spinlock to protect |
80 | * @dialog_token: dialog token for aggregation session | 80 | * @dialog_token: dialog token for aggregation session |
81 | * @timeout: session timeout value to be filled in ADDBA requests | ||
81 | * @state: session state (see above) | 82 | * @state: session state (see above) |
82 | * @stop_initiator: initiator of a session stop | 83 | * @stop_initiator: initiator of a session stop |
83 | * @tx_stop: TX DelBA frame when stopping | 84 | * @tx_stop: TX DelBA frame when stopping |
@@ -96,6 +97,7 @@ struct tid_ampdu_tx { | |||
96 | struct timer_list addba_resp_timer; | 97 | struct timer_list addba_resp_timer; |
97 | struct sk_buff_head pending; | 98 | struct sk_buff_head pending; |
98 | unsigned long state; | 99 | unsigned long state; |
100 | u16 timeout; | ||
99 | u8 dialog_token; | 101 | u8 dialog_token; |
100 | u8 stop_initiator; | 102 | u8 stop_initiator; |
101 | bool tx_stop; | 103 | bool tx_stop; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0ee56bb0ea7e..d2b4b67a7b53 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -539,7 +539,11 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
539 | ieee80211_is_robust_mgmt_frame(hdr) && | 539 | ieee80211_is_robust_mgmt_frame(hdr) && |
540 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) | 540 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) |
541 | tx->key = key; | 541 | tx->key = key; |
542 | else if ((key = rcu_dereference(tx->sdata->default_key))) | 542 | else if (is_multicast_ether_addr(hdr->addr1) && |
543 | (key = rcu_dereference(tx->sdata->default_multicast_key))) | ||
544 | tx->key = key; | ||
545 | else if (!is_multicast_ether_addr(hdr->addr1) && | ||
546 | (key = rcu_dereference(tx->sdata->default_unicast_key))) | ||
543 | tx->key = key; | 547 | tx->key = key; |
544 | else if (tx->sdata->drop_unencrypted && | 548 | else if (tx->sdata->drop_unencrypted && |
545 | (tx->skb->protocol != tx->sdata->control_port_protocol) && | 549 | (tx->skb->protocol != tx->sdata->control_port_protocol) && |
@@ -1542,8 +1546,10 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1542 | 1546 | ||
1543 | if (skb_header_cloned(skb)) | 1547 | if (skb_header_cloned(skb)) |
1544 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); | 1548 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); |
1545 | else | 1549 | else if (head_need || tail_need) |
1546 | I802_DEBUG_INC(local->tx_expand_skb_head); | 1550 | I802_DEBUG_INC(local->tx_expand_skb_head); |
1551 | else | ||
1552 | return 0; | ||
1547 | 1553 | ||
1548 | if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { | 1554 | if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) { |
1549 | wiphy_debug(local->hw.wiphy, | 1555 | wiphy_debug(local->hw.wiphy, |
@@ -1735,7 +1741,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1735 | { | 1741 | { |
1736 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1742 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1737 | struct ieee80211_local *local = sdata->local; | 1743 | struct ieee80211_local *local = sdata->local; |
1738 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1744 | struct ieee80211_tx_info *info; |
1739 | int ret = NETDEV_TX_BUSY, head_need; | 1745 | int ret = NETDEV_TX_BUSY, head_need; |
1740 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1746 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1741 | __le16 fc; | 1747 | __le16 fc; |
@@ -1807,7 +1813,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1807 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1813 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1808 | skb->data, skb->data + ETH_ALEN); | 1814 | skb->data, skb->data + ETH_ALEN); |
1809 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1815 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, |
1810 | sdata, NULL, NULL, NULL); | 1816 | sdata, NULL, NULL); |
1811 | } else { | 1817 | } else { |
1812 | /* packet from other interface */ | 1818 | /* packet from other interface */ |
1813 | struct mesh_path *mppath; | 1819 | struct mesh_path *mppath; |
@@ -1840,13 +1846,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1840 | ieee80211_new_mesh_header(&mesh_hdr, | 1846 | ieee80211_new_mesh_header(&mesh_hdr, |
1841 | sdata, | 1847 | sdata, |
1842 | skb->data + ETH_ALEN, | 1848 | skb->data + ETH_ALEN, |
1843 | NULL, | ||
1844 | NULL); | 1849 | NULL); |
1845 | else | 1850 | else |
1846 | meshhdrlen = | 1851 | meshhdrlen = |
1847 | ieee80211_new_mesh_header(&mesh_hdr, | 1852 | ieee80211_new_mesh_header(&mesh_hdr, |
1848 | sdata, | 1853 | sdata, |
1849 | NULL, | ||
1850 | skb->data, | 1854 | skb->data, |
1851 | skb->data + ETH_ALEN); | 1855 | skb->data + ETH_ALEN); |
1852 | 1856 | ||
@@ -1930,7 +1934,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1930 | */ | 1934 | */ |
1931 | if (skb_shared(skb)) { | 1935 | if (skb_shared(skb)) { |
1932 | tmp_skb = skb; | 1936 | tmp_skb = skb; |
1933 | skb = skb_copy(skb, GFP_ATOMIC); | 1937 | skb = skb_clone(skb, GFP_ATOMIC); |
1934 | kfree_skb(tmp_skb); | 1938 | kfree_skb(tmp_skb); |
1935 | 1939 | ||
1936 | if (!skb) { | 1940 | if (!skb) { |
@@ -2026,6 +2030,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2026 | skb_set_network_header(skb, nh_pos); | 2030 | skb_set_network_header(skb, nh_pos); |
2027 | skb_set_transport_header(skb, h_pos); | 2031 | skb_set_transport_header(skb, h_pos); |
2028 | 2032 | ||
2033 | info = IEEE80211_SKB_CB(skb); | ||
2029 | memset(info, 0, sizeof(*info)); | 2034 | memset(info, 0, sizeof(*info)); |
2030 | 2035 | ||
2031 | dev->trans_start = jiffies; | 2036 | dev->trans_start = jiffies; |
@@ -2286,7 +2291,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2286 | u8 *pos; | 2291 | u8 *pos; |
2287 | 2292 | ||
2288 | /* headroom, head length, tail length and maximum TIM length */ | 2293 | /* headroom, head length, tail length and maximum TIM length */ |
2289 | skb = dev_alloc_skb(local->tx_headroom + 400); | 2294 | skb = dev_alloc_skb(local->tx_headroom + 400 + |
2295 | sdata->u.mesh.vendor_ie_len); | ||
2290 | if (!skb) | 2296 | if (!skb) |
2291 | goto out; | 2297 | goto out; |
2292 | 2298 | ||