diff options
Diffstat (limited to 'net')
33 files changed, 943 insertions, 513 deletions
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index af4dfbadf2a0..7d748542d97e 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -789,12 +789,13 @@ static const void *net_netlink_ns(struct sock *sk) | |||
789 | return sock_net(sk); | 789 | return sock_net(sk); |
790 | } | 790 | } |
791 | 791 | ||
792 | static struct kobj_ns_type_operations net_ns_type_operations = { | 792 | struct kobj_ns_type_operations net_ns_type_operations = { |
793 | .type = KOBJ_NS_TYPE_NET, | 793 | .type = KOBJ_NS_TYPE_NET, |
794 | .current_ns = net_current_ns, | 794 | .current_ns = net_current_ns, |
795 | .netlink_ns = net_netlink_ns, | 795 | .netlink_ns = net_netlink_ns, |
796 | .initial_ns = net_initial_ns, | 796 | .initial_ns = net_initial_ns, |
797 | }; | 797 | }; |
798 | EXPORT_SYMBOL_GPL(net_ns_type_operations); | ||
798 | 799 | ||
799 | static void net_kobj_ns_exit(struct net *net) | 800 | static void net_kobj_ns_exit(struct net *net) |
800 | { | 801 | { |
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index a87cb3ba2df6..d2b03e0851ef 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c | |||
@@ -138,10 +138,8 @@ struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]) | |||
138 | struct crypto_cipher *tfm; | 138 | struct crypto_cipher *tfm; |
139 | 139 | ||
140 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); | 140 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); |
141 | if (IS_ERR(tfm)) | 141 | if (!IS_ERR(tfm)) |
142 | return NULL; | 142 | crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN); |
143 | |||
144 | crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN); | ||
145 | 143 | ||
146 | return tfm; | 144 | return tfm; |
147 | } | 145 | } |
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index 3d097b3d7b62..b4d66cca76d6 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c | |||
@@ -119,10 +119,8 @@ struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]) | |||
119 | struct crypto_cipher *tfm; | 119 | struct crypto_cipher *tfm; |
120 | 120 | ||
121 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); | 121 | tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); |
122 | if (IS_ERR(tfm)) | 122 | if (!IS_ERR(tfm)) |
123 | return NULL; | 123 | crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN); |
124 | |||
125 | crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN); | ||
126 | 124 | ||
127 | return tfm; | 125 | return tfm; |
128 | } | 126 | } |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 965b272499fd..58eab9e8e4ee 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -86,6 +86,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
86 | tid, 0, reason); | 86 | tid, 0, reason); |
87 | 87 | ||
88 | del_timer_sync(&tid_rx->session_timer); | 88 | del_timer_sync(&tid_rx->session_timer); |
89 | del_timer_sync(&tid_rx->reorder_timer); | ||
89 | 90 | ||
90 | call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); | 91 | call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); |
91 | } | 92 | } |
@@ -120,6 +121,20 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
120 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); | 121 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); |
121 | } | 122 | } |
122 | 123 | ||
124 | static void sta_rx_agg_reorder_timer_expired(unsigned long data) | ||
125 | { | ||
126 | u8 *ptid = (u8 *)data; | ||
127 | u8 *timer_to_id = ptid - *ptid; | ||
128 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | ||
129 | timer_to_tid[0]); | ||
130 | |||
131 | rcu_read_lock(); | ||
132 | spin_lock(&sta->lock); | ||
133 | ieee80211_release_reorder_timeout(sta, *ptid); | ||
134 | spin_unlock(&sta->lock); | ||
135 | rcu_read_unlock(); | ||
136 | } | ||
137 | |||
123 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | 138 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, |
124 | u8 dialog_token, u16 status, u16 policy, | 139 | u8 dialog_token, u16 status, u16 policy, |
125 | u16 buf_size, u16 timeout) | 140 | u16 buf_size, u16 timeout) |
@@ -251,11 +266,18 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
251 | goto end; | 266 | goto end; |
252 | } | 267 | } |
253 | 268 | ||
269 | spin_lock_init(&tid_agg_rx->reorder_lock); | ||
270 | |||
254 | /* rx timer */ | 271 | /* rx timer */ |
255 | tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; | 272 | tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; |
256 | tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 273 | tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
257 | init_timer(&tid_agg_rx->session_timer); | 274 | init_timer(&tid_agg_rx->session_timer); |
258 | 275 | ||
276 | /* rx reorder timer */ | ||
277 | tid_agg_rx->reorder_timer.function = sta_rx_agg_reorder_timer_expired; | ||
278 | tid_agg_rx->reorder_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | ||
279 | init_timer(&tid_agg_rx->reorder_timer); | ||
280 | |||
259 | /* prepare reordering buffer */ | 281 | /* prepare reordering buffer */ |
260 | tid_agg_rx->reorder_buf = | 282 | tid_agg_rx->reorder_buf = |
261 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); | 283 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 29ac8e1a509e..94787d21282c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -116,7 +116,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
116 | { | 116 | { |
117 | struct ieee80211_sub_if_data *sdata; | 117 | struct ieee80211_sub_if_data *sdata; |
118 | struct sta_info *sta = NULL; | 118 | struct sta_info *sta = NULL; |
119 | enum ieee80211_key_alg alg; | ||
120 | struct ieee80211_key *key; | 119 | struct ieee80211_key *key; |
121 | int err; | 120 | int err; |
122 | 121 | ||
@@ -125,33 +124,22 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
125 | 124 | ||
126 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 125 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
127 | 126 | ||
127 | /* reject WEP and TKIP keys if WEP failed to initialize */ | ||
128 | switch (params->cipher) { | 128 | switch (params->cipher) { |
129 | case WLAN_CIPHER_SUITE_WEP40: | 129 | case WLAN_CIPHER_SUITE_WEP40: |
130 | case WLAN_CIPHER_SUITE_WEP104: | ||
131 | alg = ALG_WEP; | ||
132 | break; | ||
133 | case WLAN_CIPHER_SUITE_TKIP: | 130 | case WLAN_CIPHER_SUITE_TKIP: |
134 | alg = ALG_TKIP; | 131 | case WLAN_CIPHER_SUITE_WEP104: |
135 | break; | 132 | if (IS_ERR(sdata->local->wep_tx_tfm)) |
136 | case WLAN_CIPHER_SUITE_CCMP: | 133 | return -EINVAL; |
137 | alg = ALG_CCMP; | ||
138 | break; | ||
139 | case WLAN_CIPHER_SUITE_AES_CMAC: | ||
140 | alg = ALG_AES_CMAC; | ||
141 | break; | 134 | break; |
142 | default: | 135 | default: |
143 | return -EINVAL; | 136 | break; |
144 | } | 137 | } |
145 | 138 | ||
146 | /* reject WEP and TKIP keys if WEP failed to initialize */ | 139 | key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len, |
147 | if ((alg == ALG_WEP || alg == ALG_TKIP) && | 140 | params->key, params->seq_len, params->seq); |
148 | IS_ERR(sdata->local->wep_tx_tfm)) | 141 | if (IS_ERR(key)) |
149 | return -EINVAL; | 142 | 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 | 143 | ||
156 | mutex_lock(&sdata->local->sta_mtx); | 144 | mutex_lock(&sdata->local->sta_mtx); |
157 | 145 | ||
@@ -247,10 +235,10 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
247 | 235 | ||
248 | memset(¶ms, 0, sizeof(params)); | 236 | memset(¶ms, 0, sizeof(params)); |
249 | 237 | ||
250 | switch (key->conf.alg) { | 238 | params.cipher = key->conf.cipher; |
251 | case ALG_TKIP: | ||
252 | params.cipher = WLAN_CIPHER_SUITE_TKIP; | ||
253 | 239 | ||
240 | switch (key->conf.cipher) { | ||
241 | case WLAN_CIPHER_SUITE_TKIP: | ||
254 | iv32 = key->u.tkip.tx.iv32; | 242 | iv32 = key->u.tkip.tx.iv32; |
255 | iv16 = key->u.tkip.tx.iv16; | 243 | iv16 = key->u.tkip.tx.iv16; |
256 | 244 | ||
@@ -268,8 +256,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
268 | params.seq = seq; | 256 | params.seq = seq; |
269 | params.seq_len = 6; | 257 | params.seq_len = 6; |
270 | break; | 258 | break; |
271 | case ALG_CCMP: | 259 | case WLAN_CIPHER_SUITE_CCMP: |
272 | params.cipher = WLAN_CIPHER_SUITE_CCMP; | ||
273 | seq[0] = key->u.ccmp.tx_pn[5]; | 260 | seq[0] = key->u.ccmp.tx_pn[5]; |
274 | seq[1] = key->u.ccmp.tx_pn[4]; | 261 | seq[1] = key->u.ccmp.tx_pn[4]; |
275 | seq[2] = key->u.ccmp.tx_pn[3]; | 262 | seq[2] = key->u.ccmp.tx_pn[3]; |
@@ -279,14 +266,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
279 | params.seq = seq; | 266 | params.seq = seq; |
280 | params.seq_len = 6; | 267 | params.seq_len = 6; |
281 | break; | 268 | break; |
282 | case ALG_WEP: | 269 | 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]; | 270 | seq[0] = key->u.aes_cmac.tx_pn[5]; |
291 | seq[1] = key->u.aes_cmac.tx_pn[4]; | 271 | seq[1] = key->u.aes_cmac.tx_pn[4]; |
292 | seq[2] = key->u.aes_cmac.tx_pn[3]; | 272 | seq[2] = key->u.aes_cmac.tx_pn[3]; |
@@ -1541,11 +1521,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
1541 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | 1521 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); |
1542 | } | 1522 | } |
1543 | 1523 | ||
1544 | static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | 1524 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, |
1545 | struct ieee80211_channel *chan, | 1525 | struct ieee80211_channel *chan, |
1546 | enum nl80211_channel_type channel_type, | 1526 | enum nl80211_channel_type channel_type, |
1547 | bool channel_type_valid, | 1527 | bool channel_type_valid, |
1548 | const u8 *buf, size_t len, u64 *cookie) | 1528 | const u8 *buf, size_t len, u64 *cookie) |
1549 | { | 1529 | { |
1550 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1530 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1551 | struct ieee80211_local *local = sdata->local; | 1531 | struct ieee80211_local *local = sdata->local; |
@@ -1575,8 +1555,6 @@ static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | |||
1575 | return -ENOLINK; | 1555 | return -ENOLINK; |
1576 | break; | 1556 | break; |
1577 | case NL80211_IFTYPE_STATION: | 1557 | case NL80211_IFTYPE_STATION: |
1578 | if (!(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED)) | ||
1579 | flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1580 | break; | 1558 | break; |
1581 | default: | 1559 | default: |
1582 | return -EOPNOTSUPP; | 1560 | return -EOPNOTSUPP; |
@@ -1647,6 +1625,6 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1647 | .set_bitrate_mask = ieee80211_set_bitrate_mask, | 1625 | .set_bitrate_mask = ieee80211_set_bitrate_mask, |
1648 | .remain_on_channel = ieee80211_remain_on_channel, | 1626 | .remain_on_channel = ieee80211_remain_on_channel, |
1649 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | 1627 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, |
1650 | .action = ieee80211_action, | 1628 | .mgmt_tx = ieee80211_mgmt_tx, |
1651 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, | 1629 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, |
1652 | }; | 1630 | }; |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index fa5e76e658ef..1647f8dc5cda 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -64,26 +64,13 @@ static ssize_t key_algorithm_read(struct file *file, | |||
64 | char __user *userbuf, | 64 | char __user *userbuf, |
65 | size_t count, loff_t *ppos) | 65 | size_t count, loff_t *ppos) |
66 | { | 66 | { |
67 | char *alg; | 67 | char buf[15]; |
68 | struct ieee80211_key *key = file->private_data; | 68 | struct ieee80211_key *key = file->private_data; |
69 | u32 c = key->conf.cipher; | ||
69 | 70 | ||
70 | switch (key->conf.alg) { | 71 | sprintf(buf, "%.2x-%.2x-%.2x:%d\n", |
71 | case ALG_WEP: | 72 | c >> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff); |
72 | alg = "WEP\n"; | 73 | return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); |
73 | break; | ||
74 | case ALG_TKIP: | ||
75 | alg = "TKIP\n"; | ||
76 | break; | ||
77 | case ALG_CCMP: | ||
78 | alg = "CCMP\n"; | ||
79 | break; | ||
80 | case ALG_AES_CMAC: | ||
81 | alg = "AES-128-CMAC\n"; | ||
82 | break; | ||
83 | default: | ||
84 | return 0; | ||
85 | } | ||
86 | return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg)); | ||
87 | } | 74 | } |
88 | KEY_OPS(algorithm); | 75 | KEY_OPS(algorithm); |
89 | 76 | ||
@@ -95,21 +82,22 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, | |||
95 | int len; | 82 | int len; |
96 | struct ieee80211_key *key = file->private_data; | 83 | struct ieee80211_key *key = file->private_data; |
97 | 84 | ||
98 | switch (key->conf.alg) { | 85 | switch (key->conf.cipher) { |
99 | case ALG_WEP: | 86 | case WLAN_CIPHER_SUITE_WEP40: |
87 | case WLAN_CIPHER_SUITE_WEP104: | ||
100 | len = scnprintf(buf, sizeof(buf), "\n"); | 88 | len = scnprintf(buf, sizeof(buf), "\n"); |
101 | break; | 89 | break; |
102 | case ALG_TKIP: | 90 | case WLAN_CIPHER_SUITE_TKIP: |
103 | len = scnprintf(buf, sizeof(buf), "%08x %04x\n", | 91 | len = scnprintf(buf, sizeof(buf), "%08x %04x\n", |
104 | key->u.tkip.tx.iv32, | 92 | key->u.tkip.tx.iv32, |
105 | key->u.tkip.tx.iv16); | 93 | key->u.tkip.tx.iv16); |
106 | break; | 94 | break; |
107 | case ALG_CCMP: | 95 | case WLAN_CIPHER_SUITE_CCMP: |
108 | tpn = key->u.ccmp.tx_pn; | 96 | tpn = key->u.ccmp.tx_pn; |
109 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | 97 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", |
110 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); | 98 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); |
111 | break; | 99 | break; |
112 | case ALG_AES_CMAC: | 100 | case WLAN_CIPHER_SUITE_AES_CMAC: |
113 | tpn = key->u.aes_cmac.tx_pn; | 101 | tpn = key->u.aes_cmac.tx_pn; |
114 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", | 102 | len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", |
115 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], | 103 | tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], |
@@ -130,11 +118,12 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
130 | int i, len; | 118 | int i, len; |
131 | const u8 *rpn; | 119 | const u8 *rpn; |
132 | 120 | ||
133 | switch (key->conf.alg) { | 121 | switch (key->conf.cipher) { |
134 | case ALG_WEP: | 122 | case WLAN_CIPHER_SUITE_WEP40: |
123 | case WLAN_CIPHER_SUITE_WEP104: | ||
135 | len = scnprintf(buf, sizeof(buf), "\n"); | 124 | len = scnprintf(buf, sizeof(buf), "\n"); |
136 | break; | 125 | break; |
137 | case ALG_TKIP: | 126 | case WLAN_CIPHER_SUITE_TKIP: |
138 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | 127 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) |
139 | p += scnprintf(p, sizeof(buf)+buf-p, | 128 | p += scnprintf(p, sizeof(buf)+buf-p, |
140 | "%08x %04x\n", | 129 | "%08x %04x\n", |
@@ -142,7 +131,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
142 | key->u.tkip.rx[i].iv16); | 131 | key->u.tkip.rx[i].iv16); |
143 | len = p - buf; | 132 | len = p - buf; |
144 | break; | 133 | break; |
145 | case ALG_CCMP: | 134 | case WLAN_CIPHER_SUITE_CCMP: |
146 | for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) { | 135 | for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) { |
147 | rpn = key->u.ccmp.rx_pn[i]; | 136 | rpn = key->u.ccmp.rx_pn[i]; |
148 | p += scnprintf(p, sizeof(buf)+buf-p, | 137 | p += scnprintf(p, sizeof(buf)+buf-p, |
@@ -152,7 +141,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
152 | } | 141 | } |
153 | len = p - buf; | 142 | len = p - buf; |
154 | break; | 143 | break; |
155 | case ALG_AES_CMAC: | 144 | case WLAN_CIPHER_SUITE_AES_CMAC: |
156 | rpn = key->u.aes_cmac.rx_pn; | 145 | rpn = key->u.aes_cmac.rx_pn; |
157 | p += scnprintf(p, sizeof(buf)+buf-p, | 146 | p += scnprintf(p, sizeof(buf)+buf-p, |
158 | "%02x%02x%02x%02x%02x%02x\n", | 147 | "%02x%02x%02x%02x%02x%02x\n", |
@@ -174,11 +163,11 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf, | |||
174 | char buf[20]; | 163 | char buf[20]; |
175 | int len; | 164 | int len; |
176 | 165 | ||
177 | switch (key->conf.alg) { | 166 | switch (key->conf.cipher) { |
178 | case ALG_CCMP: | 167 | case WLAN_CIPHER_SUITE_CCMP: |
179 | len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); | 168 | len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); |
180 | break; | 169 | break; |
181 | case ALG_AES_CMAC: | 170 | case WLAN_CIPHER_SUITE_AES_CMAC: |
182 | len = scnprintf(buf, sizeof(buf), "%u\n", | 171 | len = scnprintf(buf, sizeof(buf), "%u\n", |
183 | key->u.aes_cmac.replays); | 172 | key->u.aes_cmac.replays); |
184 | break; | 173 | break; |
@@ -196,8 +185,8 @@ static ssize_t key_icverrors_read(struct file *file, char __user *userbuf, | |||
196 | char buf[20]; | 185 | char buf[20]; |
197 | int len; | 186 | int len; |
198 | 187 | ||
199 | switch (key->conf.alg) { | 188 | switch (key->conf.cipher) { |
200 | case ALG_AES_CMAC: | 189 | case WLAN_CIPHER_SUITE_AES_CMAC: |
201 | len = scnprintf(buf, sizeof(buf), "%u\n", | 190 | len = scnprintf(buf, sizeof(buf), "%u\n", |
202 | key->u.aes_cmac.icverrors); | 191 | key->u.aes_cmac.icverrors); |
203 | break; | 192 | break; |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 5d5d2a974668..b5a95582d816 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -336,7 +336,7 @@ TRACE_EVENT(drv_set_key, | |||
336 | LOCAL_ENTRY | 336 | LOCAL_ENTRY |
337 | VIF_ENTRY | 337 | VIF_ENTRY |
338 | STA_ENTRY | 338 | STA_ENTRY |
339 | __field(enum ieee80211_key_alg, alg) | 339 | __field(u32, cipher) |
340 | __field(u8, hw_key_idx) | 340 | __field(u8, hw_key_idx) |
341 | __field(u8, flags) | 341 | __field(u8, flags) |
342 | __field(s8, keyidx) | 342 | __field(s8, keyidx) |
@@ -346,7 +346,7 @@ TRACE_EVENT(drv_set_key, | |||
346 | LOCAL_ASSIGN; | 346 | LOCAL_ASSIGN; |
347 | VIF_ASSIGN; | 347 | VIF_ASSIGN; |
348 | STA_ASSIGN; | 348 | STA_ASSIGN; |
349 | __entry->alg = key->alg; | 349 | __entry->cipher = key->cipher; |
350 | __entry->flags = key->flags; | 350 | __entry->flags = key->flags; |
351 | __entry->keyidx = key->keyidx; | 351 | __entry->keyidx = key->keyidx; |
352 | __entry->hw_key_idx = key->hw_key_idx; | 352 | __entry->hw_key_idx = key->hw_key_idx; |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 9d101fb33861..11f74f5f7b2f 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -265,3 +265,31 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | |||
265 | 265 | ||
266 | return 0; | 266 | return 0; |
267 | } | 267 | } |
268 | |||
269 | void ieee80211_request_smps_work(struct work_struct *work) | ||
270 | { | ||
271 | struct ieee80211_sub_if_data *sdata = | ||
272 | container_of(work, struct ieee80211_sub_if_data, | ||
273 | u.mgd.request_smps_work); | ||
274 | |||
275 | mutex_lock(&sdata->u.mgd.mtx); | ||
276 | __ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode); | ||
277 | mutex_unlock(&sdata->u.mgd.mtx); | ||
278 | } | ||
279 | |||
280 | void ieee80211_request_smps(struct ieee80211_vif *vif, | ||
281 | enum ieee80211_smps_mode smps_mode) | ||
282 | { | ||
283 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
284 | |||
285 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) | ||
286 | return; | ||
287 | |||
288 | if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF)) | ||
289 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | ||
290 | |||
291 | ieee80211_queue_work(&sdata->local->hw, | ||
292 | &sdata->u.mgd.request_smps_work); | ||
293 | } | ||
294 | /* this might change ... don't want non-open drivers using it */ | ||
295 | EXPORT_SYMBOL_GPL(ieee80211_request_smps); | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index c691780725a7..32af97108425 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -920,12 +920,14 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
920 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); | 920 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); |
921 | sdata->u.ibss.ssid_len = params->ssid_len; | 921 | sdata->u.ibss.ssid_len = params->ssid_len; |
922 | 922 | ||
923 | mutex_unlock(&sdata->u.ibss.mtx); | ||
924 | |||
925 | mutex_lock(&sdata->local->mtx); | ||
923 | ieee80211_recalc_idle(sdata->local); | 926 | ieee80211_recalc_idle(sdata->local); |
927 | mutex_unlock(&sdata->local->mtx); | ||
924 | 928 | ||
925 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); | 929 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
926 | 930 | ||
927 | mutex_unlock(&sdata->u.ibss.mtx); | ||
928 | |||
929 | return 0; | 931 | return 0; |
930 | } | 932 | } |
931 | 933 | ||
@@ -980,7 +982,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
980 | 982 | ||
981 | mutex_unlock(&sdata->u.ibss.mtx); | 983 | mutex_unlock(&sdata->u.ibss.mtx); |
982 | 984 | ||
985 | mutex_lock(&local->mtx); | ||
983 | ieee80211_recalc_idle(sdata->local); | 986 | ieee80211_recalc_idle(sdata->local); |
987 | mutex_unlock(&local->mtx); | ||
984 | 988 | ||
985 | return 0; | 989 | return 0; |
986 | } | 990 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 65e0ed6c2975..e73ae51dc036 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -170,6 +170,7 @@ typedef unsigned __bitwise__ ieee80211_rx_result; | |||
170 | #define IEEE80211_RX_RA_MATCH BIT(1) | 170 | #define IEEE80211_RX_RA_MATCH BIT(1) |
171 | #define IEEE80211_RX_AMSDU BIT(2) | 171 | #define IEEE80211_RX_AMSDU BIT(2) |
172 | #define IEEE80211_RX_FRAGMENTED BIT(3) | 172 | #define IEEE80211_RX_FRAGMENTED BIT(3) |
173 | #define IEEE80211_MALFORMED_ACTION_FRM BIT(4) | ||
173 | /* only add flags here that do not change with subframes of an aMPDU */ | 174 | /* only add flags here that do not change with subframes of an aMPDU */ |
174 | 175 | ||
175 | struct ieee80211_rx_data { | 176 | struct ieee80211_rx_data { |
@@ -343,7 +344,10 @@ struct ieee80211_if_managed { | |||
343 | unsigned long timers_running; /* used for quiesce/restart */ | 344 | unsigned long timers_running; /* used for quiesce/restart */ |
344 | bool powersave; /* powersave requested for this iface */ | 345 | bool powersave; /* powersave requested for this iface */ |
345 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ | 346 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ |
346 | ap_smps; /* smps mode AP thinks we're in */ | 347 | ap_smps, /* smps mode AP thinks we're in */ |
348 | driver_smps_mode; /* smps mode request */ | ||
349 | |||
350 | struct work_struct request_smps_work; | ||
347 | 351 | ||
348 | unsigned int flags; | 352 | unsigned int flags; |
349 | 353 | ||
@@ -497,6 +501,9 @@ struct ieee80211_sub_if_data { | |||
497 | */ | 501 | */ |
498 | bool ht_opmode_valid; | 502 | bool ht_opmode_valid; |
499 | 503 | ||
504 | /* to detect idle changes */ | ||
505 | bool old_idle; | ||
506 | |||
500 | /* Fragment table for host-based reassembly */ | 507 | /* Fragment table for host-based reassembly */ |
501 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 508 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
502 | unsigned int fragment_next; | 509 | unsigned int fragment_next; |
@@ -634,7 +641,6 @@ struct ieee80211_local { | |||
634 | /* | 641 | /* |
635 | * work stuff, potentially off-channel (in the future) | 642 | * work stuff, potentially off-channel (in the future) |
636 | */ | 643 | */ |
637 | struct mutex work_mtx; | ||
638 | struct list_head work_list; | 644 | struct list_head work_list; |
639 | struct timer_list work_timer; | 645 | struct timer_list work_timer; |
640 | struct work_struct work_work; | 646 | struct work_struct work_work; |
@@ -746,9 +752,10 @@ struct ieee80211_local { | |||
746 | */ | 752 | */ |
747 | struct mutex key_mtx; | 753 | struct mutex key_mtx; |
748 | 754 | ||
755 | /* mutex for scan and work locking */ | ||
756 | struct mutex mtx; | ||
749 | 757 | ||
750 | /* Scanning and BSS list */ | 758 | /* Scanning and BSS list */ |
751 | struct mutex scan_mtx; | ||
752 | unsigned long scanning; | 759 | unsigned long scanning; |
753 | struct cfg80211_ssid scan_ssid; | 760 | struct cfg80211_ssid scan_ssid; |
754 | struct cfg80211_scan_request *int_scan_req; | 761 | struct cfg80211_scan_request *int_scan_req; |
@@ -870,6 +877,11 @@ struct ieee80211_local { | |||
870 | struct dentry *keys; | 877 | struct dentry *keys; |
871 | } debugfs; | 878 | } debugfs; |
872 | #endif | 879 | #endif |
880 | |||
881 | /* dummy netdev for use w/ NAPI */ | ||
882 | struct net_device napi_dev; | ||
883 | |||
884 | struct napi_struct napi; | ||
873 | }; | 885 | }; |
874 | 886 | ||
875 | static inline struct ieee80211_sub_if_data * | 887 | static inline struct ieee80211_sub_if_data * |
@@ -1105,6 +1117,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
1105 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | 1117 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, |
1106 | enum ieee80211_smps_mode smps, const u8 *da, | 1118 | enum ieee80211_smps_mode smps, const u8 *da, |
1107 | const u8 *bssid); | 1119 | const u8 *bssid); |
1120 | void ieee80211_request_smps_work(struct work_struct *work); | ||
1108 | 1121 | ||
1109 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1122 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1110 | u16 initiator, u16 reason); | 1123 | u16 initiator, u16 reason); |
@@ -1131,6 +1144,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); | |||
1131 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); | 1144 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); |
1132 | void ieee80211_ba_session_work(struct work_struct *work); | 1145 | void ieee80211_ba_session_work(struct work_struct *work); |
1133 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid); | 1146 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid); |
1147 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid); | ||
1134 | 1148 | ||
1135 | /* Spectrum management */ | 1149 | /* Spectrum management */ |
1136 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 1150 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ebbe264e2b0b..86f434f234ae 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -177,7 +177,7 @@ static int ieee80211_open(struct net_device *dev) | |||
177 | /* no special treatment */ | 177 | /* no special treatment */ |
178 | break; | 178 | break; |
179 | case NL80211_IFTYPE_UNSPECIFIED: | 179 | case NL80211_IFTYPE_UNSPECIFIED: |
180 | case __NL80211_IFTYPE_AFTER_LAST: | 180 | case NUM_NL80211_IFTYPES: |
181 | /* cannot happen */ | 181 | /* cannot happen */ |
182 | WARN_ON(1); | 182 | WARN_ON(1); |
183 | break; | 183 | break; |
@@ -187,6 +187,8 @@ static int ieee80211_open(struct net_device *dev) | |||
187 | res = drv_start(local); | 187 | res = drv_start(local); |
188 | if (res) | 188 | if (res) |
189 | goto err_del_bss; | 189 | goto err_del_bss; |
190 | if (local->ops->napi_poll) | ||
191 | napi_enable(&local->napi); | ||
190 | /* we're brought up, everything changes */ | 192 | /* we're brought up, everything changes */ |
191 | hw_reconf_flags = ~0; | 193 | hw_reconf_flags = ~0; |
192 | ieee80211_led_radio(local, true); | 194 | ieee80211_led_radio(local, true); |
@@ -307,7 +309,9 @@ static int ieee80211_open(struct net_device *dev) | |||
307 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 309 | if (sdata->flags & IEEE80211_SDATA_PROMISC) |
308 | atomic_inc(&local->iff_promiscs); | 310 | atomic_inc(&local->iff_promiscs); |
309 | 311 | ||
312 | mutex_lock(&local->mtx); | ||
310 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | 313 | hw_reconf_flags |= __ieee80211_recalc_idle(local); |
314 | mutex_unlock(&local->mtx); | ||
311 | 315 | ||
312 | local->open_count++; | 316 | local->open_count++; |
313 | if (hw_reconf_flags) { | 317 | if (hw_reconf_flags) { |
@@ -514,11 +518,15 @@ static int ieee80211_stop(struct net_device *dev) | |||
514 | 518 | ||
515 | sdata->bss = NULL; | 519 | sdata->bss = NULL; |
516 | 520 | ||
521 | mutex_lock(&local->mtx); | ||
517 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | 522 | hw_reconf_flags |= __ieee80211_recalc_idle(local); |
523 | mutex_unlock(&local->mtx); | ||
518 | 524 | ||
519 | ieee80211_recalc_ps(local, -1); | 525 | ieee80211_recalc_ps(local, -1); |
520 | 526 | ||
521 | if (local->open_count == 0) { | 527 | if (local->open_count == 0) { |
528 | if (local->ops->napi_poll) | ||
529 | napi_disable(&local->napi); | ||
522 | ieee80211_clear_tx_pending(local); | 530 | ieee80211_clear_tx_pending(local); |
523 | ieee80211_stop_device(local); | 531 | ieee80211_stop_device(local); |
524 | 532 | ||
@@ -626,7 +634,7 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
626 | case NL80211_IFTYPE_MONITOR: | 634 | case NL80211_IFTYPE_MONITOR: |
627 | break; | 635 | break; |
628 | case NL80211_IFTYPE_UNSPECIFIED: | 636 | case NL80211_IFTYPE_UNSPECIFIED: |
629 | case __NL80211_IFTYPE_AFTER_LAST: | 637 | case NUM_NL80211_IFTYPES: |
630 | BUG(); | 638 | BUG(); |
631 | break; | 639 | break; |
632 | } | 640 | } |
@@ -878,7 +886,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
878 | case NL80211_IFTYPE_AP_VLAN: | 886 | case NL80211_IFTYPE_AP_VLAN: |
879 | break; | 887 | break; |
880 | case NL80211_IFTYPE_UNSPECIFIED: | 888 | case NL80211_IFTYPE_UNSPECIFIED: |
881 | case __NL80211_IFTYPE_AFTER_LAST: | 889 | case NUM_NL80211_IFTYPES: |
882 | BUG(); | 890 | BUG(); |
883 | break; | 891 | break; |
884 | } | 892 | } |
@@ -1195,28 +1203,61 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
1195 | { | 1203 | { |
1196 | struct ieee80211_sub_if_data *sdata; | 1204 | struct ieee80211_sub_if_data *sdata; |
1197 | int count = 0; | 1205 | int count = 0; |
1206 | bool working = false, scanning = false; | ||
1207 | struct ieee80211_work *wk; | ||
1198 | 1208 | ||
1199 | if (!list_empty(&local->work_list)) | 1209 | #ifdef CONFIG_PROVE_LOCKING |
1200 | return ieee80211_idle_off(local, "working"); | 1210 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && |
1201 | 1211 | !lockdep_is_held(&local->iflist_mtx)); | |
1202 | if (local->scanning) | 1212 | #endif |
1203 | return ieee80211_idle_off(local, "scanning"); | 1213 | lockdep_assert_held(&local->mtx); |
1204 | 1214 | ||
1205 | list_for_each_entry(sdata, &local->interfaces, list) { | 1215 | list_for_each_entry(sdata, &local->interfaces, list) { |
1206 | if (!ieee80211_sdata_running(sdata)) | 1216 | if (!ieee80211_sdata_running(sdata)) { |
1217 | sdata->vif.bss_conf.idle = true; | ||
1207 | continue; | 1218 | continue; |
1219 | } | ||
1220 | |||
1221 | sdata->old_idle = sdata->vif.bss_conf.idle; | ||
1222 | |||
1208 | /* do not count disabled managed interfaces */ | 1223 | /* do not count disabled managed interfaces */ |
1209 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1224 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
1210 | !sdata->u.mgd.associated) | 1225 | !sdata->u.mgd.associated) { |
1226 | sdata->vif.bss_conf.idle = true; | ||
1211 | continue; | 1227 | continue; |
1228 | } | ||
1212 | /* do not count unused IBSS interfaces */ | 1229 | /* do not count unused IBSS interfaces */ |
1213 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 1230 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
1214 | !sdata->u.ibss.ssid_len) | 1231 | !sdata->u.ibss.ssid_len) { |
1232 | sdata->vif.bss_conf.idle = true; | ||
1215 | continue; | 1233 | continue; |
1234 | } | ||
1216 | /* count everything else */ | 1235 | /* count everything else */ |
1217 | count++; | 1236 | count++; |
1218 | } | 1237 | } |
1219 | 1238 | ||
1239 | list_for_each_entry(wk, &local->work_list, list) { | ||
1240 | working = true; | ||
1241 | wk->sdata->vif.bss_conf.idle = false; | ||
1242 | } | ||
1243 | |||
1244 | if (local->scan_sdata) { | ||
1245 | scanning = true; | ||
1246 | local->scan_sdata->vif.bss_conf.idle = false; | ||
1247 | } | ||
1248 | |||
1249 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1250 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | ||
1251 | continue; | ||
1252 | if (!ieee80211_sdata_running(sdata)) | ||
1253 | continue; | ||
1254 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | ||
1255 | } | ||
1256 | |||
1257 | if (working) | ||
1258 | return ieee80211_idle_off(local, "working"); | ||
1259 | if (scanning) | ||
1260 | return ieee80211_idle_off(local, "scanning"); | ||
1220 | if (!count) | 1261 | if (!count) |
1221 | return ieee80211_idle_on(local); | 1262 | return ieee80211_idle_on(local); |
1222 | else | 1263 | else |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 1b9d87ed143a..9c27c53cfae5 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -227,20 +227,18 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
227 | } | 227 | } |
228 | } | 228 | } |
229 | 229 | ||
230 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | 230 | struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, |
231 | int idx, | ||
232 | size_t key_len, | ||
233 | const u8 *key_data, | 231 | const u8 *key_data, |
234 | size_t seq_len, const u8 *seq) | 232 | size_t seq_len, const u8 *seq) |
235 | { | 233 | { |
236 | struct ieee80211_key *key; | 234 | struct ieee80211_key *key; |
237 | int i, j; | 235 | int i, j, err; |
238 | 236 | ||
239 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); | 237 | BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS); |
240 | 238 | ||
241 | key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); | 239 | key = kzalloc(sizeof(struct ieee80211_key) + key_len, GFP_KERNEL); |
242 | if (!key) | 240 | if (!key) |
243 | return NULL; | 241 | return ERR_PTR(-ENOMEM); |
244 | 242 | ||
245 | /* | 243 | /* |
246 | * Default to software encryption; we'll later upload the | 244 | * Default to software encryption; we'll later upload the |
@@ -249,15 +247,16 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
249 | key->conf.flags = 0; | 247 | key->conf.flags = 0; |
250 | key->flags = 0; | 248 | key->flags = 0; |
251 | 249 | ||
252 | key->conf.alg = alg; | 250 | key->conf.cipher = cipher; |
253 | key->conf.keyidx = idx; | 251 | key->conf.keyidx = idx; |
254 | key->conf.keylen = key_len; | 252 | key->conf.keylen = key_len; |
255 | switch (alg) { | 253 | switch (cipher) { |
256 | case ALG_WEP: | 254 | case WLAN_CIPHER_SUITE_WEP40: |
255 | case WLAN_CIPHER_SUITE_WEP104: | ||
257 | key->conf.iv_len = WEP_IV_LEN; | 256 | key->conf.iv_len = WEP_IV_LEN; |
258 | key->conf.icv_len = WEP_ICV_LEN; | 257 | key->conf.icv_len = WEP_ICV_LEN; |
259 | break; | 258 | break; |
260 | case ALG_TKIP: | 259 | case WLAN_CIPHER_SUITE_TKIP: |
261 | key->conf.iv_len = TKIP_IV_LEN; | 260 | key->conf.iv_len = TKIP_IV_LEN; |
262 | key->conf.icv_len = TKIP_ICV_LEN; | 261 | key->conf.icv_len = TKIP_ICV_LEN; |
263 | if (seq) { | 262 | if (seq) { |
@@ -269,7 +268,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
269 | } | 268 | } |
270 | } | 269 | } |
271 | break; | 270 | break; |
272 | case ALG_CCMP: | 271 | case WLAN_CIPHER_SUITE_CCMP: |
273 | key->conf.iv_len = CCMP_HDR_LEN; | 272 | key->conf.iv_len = CCMP_HDR_LEN; |
274 | key->conf.icv_len = CCMP_MIC_LEN; | 273 | key->conf.icv_len = CCMP_MIC_LEN; |
275 | if (seq) { | 274 | if (seq) { |
@@ -278,42 +277,38 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
278 | key->u.ccmp.rx_pn[i][j] = | 277 | key->u.ccmp.rx_pn[i][j] = |
279 | seq[CCMP_PN_LEN - j - 1]; | 278 | seq[CCMP_PN_LEN - j - 1]; |
280 | } | 279 | } |
281 | break; | ||
282 | case ALG_AES_CMAC: | ||
283 | key->conf.iv_len = 0; | ||
284 | key->conf.icv_len = sizeof(struct ieee80211_mmie); | ||
285 | if (seq) | ||
286 | for (j = 0; j < 6; j++) | ||
287 | key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; | ||
288 | break; | ||
289 | } | ||
290 | memcpy(key->conf.key, key_data, key_len); | ||
291 | INIT_LIST_HEAD(&key->list); | ||
292 | |||
293 | if (alg == ALG_CCMP) { | ||
294 | /* | 280 | /* |
295 | * Initialize AES key state here as an optimization so that | 281 | * Initialize AES key state here as an optimization so that |
296 | * it does not need to be initialized for every packet. | 282 | * it does not need to be initialized for every packet. |
297 | */ | 283 | */ |
298 | key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); | 284 | key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); |
299 | if (!key->u.ccmp.tfm) { | 285 | if (IS_ERR(key->u.ccmp.tfm)) { |
286 | err = PTR_ERR(key->u.ccmp.tfm); | ||
300 | kfree(key); | 287 | kfree(key); |
301 | return NULL; | 288 | key = ERR_PTR(err); |
302 | } | 289 | } |
303 | } | 290 | break; |
304 | 291 | case WLAN_CIPHER_SUITE_AES_CMAC: | |
305 | if (alg == ALG_AES_CMAC) { | 292 | key->conf.iv_len = 0; |
293 | key->conf.icv_len = sizeof(struct ieee80211_mmie); | ||
294 | if (seq) | ||
295 | for (j = 0; j < 6; j++) | ||
296 | key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; | ||
306 | /* | 297 | /* |
307 | * Initialize AES key state here as an optimization so that | 298 | * Initialize AES key state here as an optimization so that |
308 | * it does not need to be initialized for every packet. | 299 | * it does not need to be initialized for every packet. |
309 | */ | 300 | */ |
310 | key->u.aes_cmac.tfm = | 301 | key->u.aes_cmac.tfm = |
311 | ieee80211_aes_cmac_key_setup(key_data); | 302 | ieee80211_aes_cmac_key_setup(key_data); |
312 | if (!key->u.aes_cmac.tfm) { | 303 | if (IS_ERR(key->u.aes_cmac.tfm)) { |
304 | err = PTR_ERR(key->u.aes_cmac.tfm); | ||
313 | kfree(key); | 305 | kfree(key); |
314 | return NULL; | 306 | key = ERR_PTR(err); |
315 | } | 307 | } |
308 | break; | ||
316 | } | 309 | } |
310 | memcpy(key->conf.key, key_data, key_len); | ||
311 | INIT_LIST_HEAD(&key->list); | ||
317 | 312 | ||
318 | return key; | 313 | return key; |
319 | } | 314 | } |
@@ -326,9 +321,9 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) | |||
326 | if (key->local) | 321 | if (key->local) |
327 | ieee80211_key_disable_hw_accel(key); | 322 | ieee80211_key_disable_hw_accel(key); |
328 | 323 | ||
329 | if (key->conf.alg == ALG_CCMP) | 324 | if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP) |
330 | ieee80211_aes_key_free(key->u.ccmp.tfm); | 325 | ieee80211_aes_key_free(key->u.ccmp.tfm); |
331 | if (key->conf.alg == ALG_AES_CMAC) | 326 | if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) |
332 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); | 327 | ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); |
333 | if (key->local) | 328 | if (key->local) |
334 | ieee80211_debugfs_key_remove(key); | 329 | ieee80211_debugfs_key_remove(key); |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index b665bbb7a471..53b5ce12536f 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -123,9 +123,7 @@ struct ieee80211_key { | |||
123 | struct ieee80211_key_conf conf; | 123 | struct ieee80211_key_conf conf; |
124 | }; | 124 | }; |
125 | 125 | ||
126 | struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | 126 | struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, |
127 | int idx, | ||
128 | size_t key_len, | ||
129 | const u8 *key_data, | 127 | const u8 *key_data, |
130 | size_t seq_len, const u8 *seq); | 128 | size_t seq_len, const u8 *seq); |
131 | /* | 129 | /* |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 798a91b100cc..a53feac4618c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -99,11 +99,13 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
99 | int ret = 0; | 99 | int ret = 0; |
100 | int power; | 100 | int power; |
101 | enum nl80211_channel_type channel_type; | 101 | enum nl80211_channel_type channel_type; |
102 | u32 offchannel_flag; | ||
102 | 103 | ||
103 | might_sleep(); | 104 | might_sleep(); |
104 | 105 | ||
105 | scan_chan = local->scan_channel; | 106 | scan_chan = local->scan_channel; |
106 | 107 | ||
108 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | ||
107 | if (scan_chan) { | 109 | if (scan_chan) { |
108 | chan = scan_chan; | 110 | chan = scan_chan; |
109 | channel_type = NL80211_CHAN_NO_HT; | 111 | channel_type = NL80211_CHAN_NO_HT; |
@@ -117,8 +119,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
117 | channel_type = local->_oper_channel_type; | 119 | channel_type = local->_oper_channel_type; |
118 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; | 120 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; |
119 | } | 121 | } |
122 | offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | ||
120 | 123 | ||
121 | if (chan != local->hw.conf.channel || | 124 | if (offchannel_flag || chan != local->hw.conf.channel || |
122 | channel_type != local->hw.conf.channel_type) { | 125 | channel_type != local->hw.conf.channel_type) { |
123 | local->hw.conf.channel = chan; | 126 | local->hw.conf.channel = chan; |
124 | local->hw.conf.channel_type = channel_type; | 127 | local->hw.conf.channel_type = channel_type; |
@@ -390,6 +393,65 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
390 | } | 393 | } |
391 | #endif | 394 | #endif |
392 | 395 | ||
396 | static int ieee80211_napi_poll(struct napi_struct *napi, int budget) | ||
397 | { | ||
398 | struct ieee80211_local *local = | ||
399 | container_of(napi, struct ieee80211_local, napi); | ||
400 | |||
401 | return local->ops->napi_poll(&local->hw, budget); | ||
402 | } | ||
403 | |||
404 | void ieee80211_napi_schedule(struct ieee80211_hw *hw) | ||
405 | { | ||
406 | struct ieee80211_local *local = hw_to_local(hw); | ||
407 | |||
408 | napi_schedule(&local->napi); | ||
409 | } | ||
410 | EXPORT_SYMBOL(ieee80211_napi_schedule); | ||
411 | |||
412 | void ieee80211_napi_complete(struct ieee80211_hw *hw) | ||
413 | { | ||
414 | struct ieee80211_local *local = hw_to_local(hw); | ||
415 | |||
416 | napi_complete(&local->napi); | ||
417 | } | ||
418 | EXPORT_SYMBOL(ieee80211_napi_complete); | ||
419 | |||
420 | /* There isn't a lot of sense in it, but you can transmit anything you like */ | ||
421 | static const struct ieee80211_txrx_stypes | ||
422 | ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | ||
423 | [NL80211_IFTYPE_ADHOC] = { | ||
424 | .tx = 0xffff, | ||
425 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4), | ||
426 | }, | ||
427 | [NL80211_IFTYPE_STATION] = { | ||
428 | .tx = 0xffff, | ||
429 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
430 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4), | ||
431 | }, | ||
432 | [NL80211_IFTYPE_AP] = { | ||
433 | .tx = 0xffff, | ||
434 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
435 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
436 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
437 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
438 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
439 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
440 | BIT(IEEE80211_STYPE_ACTION >> 4), | ||
441 | }, | ||
442 | [NL80211_IFTYPE_AP_VLAN] = { | ||
443 | /* copy AP */ | ||
444 | .tx = 0xffff, | ||
445 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
446 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
447 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
448 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
449 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
450 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
451 | BIT(IEEE80211_STYPE_ACTION >> 4), | ||
452 | }, | ||
453 | }; | ||
454 | |||
393 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 455 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
394 | const struct ieee80211_ops *ops) | 456 | const struct ieee80211_ops *ops) |
395 | { | 457 | { |
@@ -419,6 +481,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
419 | if (!wiphy) | 481 | if (!wiphy) |
420 | return NULL; | 482 | return NULL; |
421 | 483 | ||
484 | wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes; | ||
485 | |||
422 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | | 486 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | |
423 | WIPHY_FLAG_4ADDR_AP | | 487 | WIPHY_FLAG_4ADDR_AP | |
424 | WIPHY_FLAG_4ADDR_STATION; | 488 | WIPHY_FLAG_4ADDR_STATION; |
@@ -455,7 +519,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
455 | __hw_addr_init(&local->mc_list); | 519 | __hw_addr_init(&local->mc_list); |
456 | 520 | ||
457 | mutex_init(&local->iflist_mtx); | 521 | mutex_init(&local->iflist_mtx); |
458 | mutex_init(&local->scan_mtx); | 522 | mutex_init(&local->mtx); |
459 | 523 | ||
460 | mutex_init(&local->key_mtx); | 524 | mutex_init(&local->key_mtx); |
461 | spin_lock_init(&local->filter_lock); | 525 | spin_lock_init(&local->filter_lock); |
@@ -494,6 +558,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
494 | skb_queue_head_init(&local->skb_queue); | 558 | skb_queue_head_init(&local->skb_queue); |
495 | skb_queue_head_init(&local->skb_queue_unreliable); | 559 | skb_queue_head_init(&local->skb_queue_unreliable); |
496 | 560 | ||
561 | /* init dummy netdev for use w/ NAPI */ | ||
562 | init_dummy_netdev(&local->napi_dev); | ||
563 | |||
497 | return local_to_hw(local); | 564 | return local_to_hw(local); |
498 | } | 565 | } |
499 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 566 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
@@ -506,6 +573,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
506 | int channels, max_bitrates; | 573 | int channels, max_bitrates; |
507 | bool supp_ht; | 574 | bool supp_ht; |
508 | static const u32 cipher_suites[] = { | 575 | static const u32 cipher_suites[] = { |
576 | /* keep WEP first, it may be removed below */ | ||
509 | WLAN_CIPHER_SUITE_WEP40, | 577 | WLAN_CIPHER_SUITE_WEP40, |
510 | WLAN_CIPHER_SUITE_WEP104, | 578 | WLAN_CIPHER_SUITE_WEP104, |
511 | WLAN_CIPHER_SUITE_TKIP, | 579 | WLAN_CIPHER_SUITE_TKIP, |
@@ -593,6 +661,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
593 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 661 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
594 | if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) | 662 | if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) |
595 | local->hw.wiphy->n_cipher_suites--; | 663 | local->hw.wiphy->n_cipher_suites--; |
664 | if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) { | ||
665 | local->hw.wiphy->cipher_suites += 2; | ||
666 | local->hw.wiphy->n_cipher_suites -= 2; | ||
667 | } | ||
596 | 668 | ||
597 | result = wiphy_register(local->hw.wiphy); | 669 | result = wiphy_register(local->hw.wiphy); |
598 | if (result < 0) | 670 | if (result < 0) |
@@ -683,6 +755,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
683 | goto fail_ifa; | 755 | goto fail_ifa; |
684 | #endif | 756 | #endif |
685 | 757 | ||
758 | netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, | ||
759 | local->hw.napi_weight); | ||
760 | |||
686 | return 0; | 761 | return 0; |
687 | 762 | ||
688 | #ifdef CONFIG_INET | 763 | #ifdef CONFIG_INET |
@@ -758,7 +833,7 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) | |||
758 | struct ieee80211_local *local = hw_to_local(hw); | 833 | struct ieee80211_local *local = hw_to_local(hw); |
759 | 834 | ||
760 | mutex_destroy(&local->iflist_mtx); | 835 | mutex_destroy(&local->iflist_mtx); |
761 | mutex_destroy(&local->scan_mtx); | 836 | mutex_destroy(&local->mtx); |
762 | 837 | ||
763 | wiphy_free(local->hw.wiphy); | 838 | wiphy_free(local->hw.wiphy); |
764 | } | 839 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b6c163ac22da..38996a44aa8e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1103,8 +1103,11 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1103 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); | 1103 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); |
1104 | 1104 | ||
1105 | ieee80211_set_disassoc(sdata, true); | 1105 | ieee80211_set_disassoc(sdata, true); |
1106 | ieee80211_recalc_idle(local); | ||
1107 | mutex_unlock(&ifmgd->mtx); | 1106 | mutex_unlock(&ifmgd->mtx); |
1107 | |||
1108 | mutex_lock(&local->mtx); | ||
1109 | ieee80211_recalc_idle(local); | ||
1110 | mutex_unlock(&local->mtx); | ||
1108 | /* | 1111 | /* |
1109 | * must be outside lock due to cfg80211, | 1112 | * must be outside lock due to cfg80211, |
1110 | * but that's not a problem. | 1113 | * but that's not a problem. |
@@ -1173,7 +1176,9 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1173 | sdata->name, bssid, reason_code); | 1176 | sdata->name, bssid, reason_code); |
1174 | 1177 | ||
1175 | ieee80211_set_disassoc(sdata, true); | 1178 | ieee80211_set_disassoc(sdata, true); |
1179 | mutex_lock(&sdata->local->mtx); | ||
1176 | ieee80211_recalc_idle(sdata->local); | 1180 | ieee80211_recalc_idle(sdata->local); |
1181 | mutex_unlock(&sdata->local->mtx); | ||
1177 | 1182 | ||
1178 | return RX_MGMT_CFG80211_DEAUTH; | 1183 | return RX_MGMT_CFG80211_DEAUTH; |
1179 | } | 1184 | } |
@@ -1203,7 +1208,9 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1203 | sdata->name, mgmt->sa, reason_code); | 1208 | sdata->name, mgmt->sa, reason_code); |
1204 | 1209 | ||
1205 | ieee80211_set_disassoc(sdata, true); | 1210 | ieee80211_set_disassoc(sdata, true); |
1211 | mutex_lock(&sdata->local->mtx); | ||
1206 | ieee80211_recalc_idle(sdata->local); | 1212 | ieee80211_recalc_idle(sdata->local); |
1213 | mutex_unlock(&sdata->local->mtx); | ||
1207 | return RX_MGMT_CFG80211_DISASSOC; | 1214 | return RX_MGMT_CFG80211_DISASSOC; |
1208 | } | 1215 | } |
1209 | 1216 | ||
@@ -1751,7 +1758,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1751 | struct ieee80211_local *local = sdata->local; | 1758 | struct ieee80211_local *local = sdata->local; |
1752 | struct ieee80211_work *wk; | 1759 | struct ieee80211_work *wk; |
1753 | 1760 | ||
1754 | mutex_lock(&local->work_mtx); | 1761 | mutex_lock(&local->mtx); |
1755 | list_for_each_entry(wk, &local->work_list, list) { | 1762 | list_for_each_entry(wk, &local->work_list, list) { |
1756 | if (wk->sdata != sdata) | 1763 | if (wk->sdata != sdata) |
1757 | continue; | 1764 | continue; |
@@ -1783,7 +1790,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1783 | free_work(wk); | 1790 | free_work(wk); |
1784 | break; | 1791 | break; |
1785 | } | 1792 | } |
1786 | mutex_unlock(&local->work_mtx); | 1793 | mutex_unlock(&local->mtx); |
1787 | 1794 | ||
1788 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); | 1795 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); |
1789 | } | 1796 | } |
@@ -1840,8 +1847,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1840 | " after %dms, disconnecting.\n", | 1847 | " after %dms, disconnecting.\n", |
1841 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 1848 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
1842 | ieee80211_set_disassoc(sdata, true); | 1849 | ieee80211_set_disassoc(sdata, true); |
1843 | ieee80211_recalc_idle(local); | ||
1844 | mutex_unlock(&ifmgd->mtx); | 1850 | mutex_unlock(&ifmgd->mtx); |
1851 | mutex_lock(&local->mtx); | ||
1852 | ieee80211_recalc_idle(local); | ||
1853 | mutex_unlock(&local->mtx); | ||
1845 | /* | 1854 | /* |
1846 | * must be outside lock due to cfg80211, | 1855 | * must be outside lock due to cfg80211, |
1847 | * but that's not a problem. | 1856 | * but that's not a problem. |
@@ -1917,6 +1926,8 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
1917 | * time -- the code here is properly synchronised. | 1926 | * time -- the code here is properly synchronised. |
1918 | */ | 1927 | */ |
1919 | 1928 | ||
1929 | cancel_work_sync(&ifmgd->request_smps_work); | ||
1930 | |||
1920 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); | 1931 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); |
1921 | if (del_timer_sync(&ifmgd->timer)) | 1932 | if (del_timer_sync(&ifmgd->timer)) |
1922 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | 1933 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); |
@@ -1952,6 +1963,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
1952 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); | 1963 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); |
1953 | INIT_WORK(&ifmgd->beacon_connection_loss_work, | 1964 | INIT_WORK(&ifmgd->beacon_connection_loss_work, |
1954 | ieee80211_beacon_connection_loss_work); | 1965 | ieee80211_beacon_connection_loss_work); |
1966 | INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work); | ||
1955 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 1967 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
1956 | (unsigned long) sdata); | 1968 | (unsigned long) sdata); |
1957 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, | 1969 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, |
@@ -2275,7 +2287,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2275 | 2287 | ||
2276 | mutex_unlock(&ifmgd->mtx); | 2288 | mutex_unlock(&ifmgd->mtx); |
2277 | 2289 | ||
2278 | mutex_lock(&local->work_mtx); | 2290 | mutex_lock(&local->mtx); |
2279 | list_for_each_entry(wk, &local->work_list, list) { | 2291 | list_for_each_entry(wk, &local->work_list, list) { |
2280 | if (wk->sdata != sdata) | 2292 | if (wk->sdata != sdata) |
2281 | continue; | 2293 | continue; |
@@ -2294,7 +2306,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2294 | free_work(wk); | 2306 | free_work(wk); |
2295 | break; | 2307 | break; |
2296 | } | 2308 | } |
2297 | mutex_unlock(&local->work_mtx); | 2309 | mutex_unlock(&local->mtx); |
2298 | 2310 | ||
2299 | /* | 2311 | /* |
2300 | * If somebody requests authentication and we haven't | 2312 | * If somebody requests authentication and we haven't |
@@ -2319,7 +2331,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2319 | if (assoc_bss) | 2331 | if (assoc_bss) |
2320 | sta_info_destroy_addr(sdata, bssid); | 2332 | sta_info_destroy_addr(sdata, bssid); |
2321 | 2333 | ||
2334 | mutex_lock(&sdata->local->mtx); | ||
2322 | ieee80211_recalc_idle(sdata->local); | 2335 | ieee80211_recalc_idle(sdata->local); |
2336 | mutex_unlock(&sdata->local->mtx); | ||
2323 | 2337 | ||
2324 | return 0; | 2338 | return 0; |
2325 | } | 2339 | } |
@@ -2357,7 +2371,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2357 | cookie, !req->local_state_change); | 2371 | cookie, !req->local_state_change); |
2358 | sta_info_destroy_addr(sdata, bssid); | 2372 | sta_info_destroy_addr(sdata, bssid); |
2359 | 2373 | ||
2374 | mutex_lock(&sdata->local->mtx); | ||
2360 | ieee80211_recalc_idle(sdata->local); | 2375 | ieee80211_recalc_idle(sdata->local); |
2376 | mutex_unlock(&sdata->local->mtx); | ||
2361 | 2377 | ||
2362 | return 0; | 2378 | return 0; |
2363 | } | 2379 | } |
diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c index 47438b4a9af5..135f36fd4d5d 100644 --- a/net/mac80211/rc80211_pid_debugfs.c +++ b/net/mac80211/rc80211_pid_debugfs.c | |||
@@ -162,7 +162,7 @@ static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf, | |||
162 | file_info->next_entry = (file_info->next_entry + 1) % | 162 | file_info->next_entry = (file_info->next_entry + 1) % |
163 | RC_PID_EVENT_RING_SIZE; | 163 | RC_PID_EVENT_RING_SIZE; |
164 | 164 | ||
165 | /* Print information about the event. Note that userpace needs to | 165 | /* Print information about the event. Note that userspace needs to |
166 | * provide large enough buffers. */ | 166 | * provide large enough buffers. */ |
167 | length = length < RC_PID_PRINT_BUF_SIZE ? | 167 | length = length < RC_PID_PRINT_BUF_SIZE ? |
168 | length : RC_PID_PRINT_BUF_SIZE; | 168 | length : RC_PID_PRINT_BUF_SIZE; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fa0f37e4afe4..aa41e382bbb3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -538,20 +538,12 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | |||
538 | int index, | 538 | int index, |
539 | struct sk_buff_head *frames) | 539 | struct sk_buff_head *frames) |
540 | { | 540 | { |
541 | struct ieee80211_supported_band *sband; | ||
542 | struct ieee80211_rate *rate = NULL; | ||
543 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; | 541 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; |
544 | struct ieee80211_rx_status *status; | ||
545 | 542 | ||
546 | if (!skb) | 543 | if (!skb) |
547 | goto no_frame; | 544 | goto no_frame; |
548 | 545 | ||
549 | status = IEEE80211_SKB_RXCB(skb); | 546 | /* release the frame from the reorder ring buffer */ |
550 | |||
551 | /* release the reordered frames to stack */ | ||
552 | sband = hw->wiphy->bands[status->band]; | ||
553 | if (!(status->flag & RX_FLAG_HT)) | ||
554 | rate = &sband->bitrates[status->rate_idx]; | ||
555 | tid_agg_rx->stored_mpdu_num--; | 547 | tid_agg_rx->stored_mpdu_num--; |
556 | tid_agg_rx->reorder_buf[index] = NULL; | 548 | tid_agg_rx->reorder_buf[index] = NULL; |
557 | __skb_queue_tail(frames, skb); | 549 | __skb_queue_tail(frames, skb); |
@@ -580,9 +572,80 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, | |||
580 | * frames that have not yet been received are assumed to be lost and the skb | 572 | * frames that have not yet been received are assumed to be lost and the skb |
581 | * can be released for processing. This may also release other skb's from the | 573 | * can be released for processing. This may also release other skb's from the |
582 | * reorder buffer if there are no additional gaps between the frames. | 574 | * reorder buffer if there are no additional gaps between the frames. |
575 | * | ||
576 | * Callers must hold tid_agg_rx->reorder_lock. | ||
583 | */ | 577 | */ |
584 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) | 578 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) |
585 | 579 | ||
580 | static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | ||
581 | struct tid_ampdu_rx *tid_agg_rx, | ||
582 | struct sk_buff_head *frames) | ||
583 | { | ||
584 | int index, j; | ||
585 | |||
586 | /* release the buffer until next missing frame */ | ||
587 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
588 | tid_agg_rx->buf_size; | ||
589 | if (!tid_agg_rx->reorder_buf[index] && | ||
590 | tid_agg_rx->stored_mpdu_num > 1) { | ||
591 | /* | ||
592 | * No buffers ready to be released, but check whether any | ||
593 | * frames in the reorder buffer have timed out. | ||
594 | */ | ||
595 | int skipped = 1; | ||
596 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; | ||
597 | j = (j + 1) % tid_agg_rx->buf_size) { | ||
598 | if (!tid_agg_rx->reorder_buf[j]) { | ||
599 | skipped++; | ||
600 | continue; | ||
601 | } | ||
602 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + | ||
603 | HT_RX_REORDER_BUF_TIMEOUT)) | ||
604 | goto set_release_timer; | ||
605 | |||
606 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
607 | if (net_ratelimit()) | ||
608 | printk(KERN_DEBUG "%s: release an RX reorder " | ||
609 | "frame due to timeout on earlier " | ||
610 | "frames\n", | ||
611 | wiphy_name(hw->wiphy)); | ||
612 | #endif | ||
613 | ieee80211_release_reorder_frame(hw, tid_agg_rx, | ||
614 | j, frames); | ||
615 | |||
616 | /* | ||
617 | * Increment the head seq# also for the skipped slots. | ||
618 | */ | ||
619 | tid_agg_rx->head_seq_num = | ||
620 | (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; | ||
621 | skipped = 0; | ||
622 | } | ||
623 | } else while (tid_agg_rx->reorder_buf[index]) { | ||
624 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames); | ||
625 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
626 | tid_agg_rx->buf_size; | ||
627 | } | ||
628 | |||
629 | if (tid_agg_rx->stored_mpdu_num) { | ||
630 | j = index = seq_sub(tid_agg_rx->head_seq_num, | ||
631 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | ||
632 | |||
633 | for (; j != (index - 1) % tid_agg_rx->buf_size; | ||
634 | j = (j + 1) % tid_agg_rx->buf_size) { | ||
635 | if (tid_agg_rx->reorder_buf[j]) | ||
636 | break; | ||
637 | } | ||
638 | |||
639 | set_release_timer: | ||
640 | |||
641 | mod_timer(&tid_agg_rx->reorder_timer, | ||
642 | tid_agg_rx->reorder_time[j] + | ||
643 | HT_RX_REORDER_BUF_TIMEOUT); | ||
644 | } else { | ||
645 | del_timer(&tid_agg_rx->reorder_timer); | ||
646 | } | ||
647 | } | ||
648 | |||
586 | /* | 649 | /* |
587 | * As this function belongs to the RX path it must be under | 650 | * As this function belongs to the RX path it must be under |
588 | * rcu_read_lock protection. It returns false if the frame | 651 | * rcu_read_lock protection. It returns false if the frame |
@@ -598,14 +661,16 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
598 | u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; | 661 | u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; |
599 | u16 head_seq_num, buf_size; | 662 | u16 head_seq_num, buf_size; |
600 | int index; | 663 | int index; |
664 | bool ret = true; | ||
601 | 665 | ||
602 | buf_size = tid_agg_rx->buf_size; | 666 | buf_size = tid_agg_rx->buf_size; |
603 | head_seq_num = tid_agg_rx->head_seq_num; | 667 | head_seq_num = tid_agg_rx->head_seq_num; |
604 | 668 | ||
669 | spin_lock(&tid_agg_rx->reorder_lock); | ||
605 | /* frame with out of date sequence number */ | 670 | /* frame with out of date sequence number */ |
606 | if (seq_less(mpdu_seq_num, head_seq_num)) { | 671 | if (seq_less(mpdu_seq_num, head_seq_num)) { |
607 | dev_kfree_skb(skb); | 672 | dev_kfree_skb(skb); |
608 | return true; | 673 | goto out; |
609 | } | 674 | } |
610 | 675 | ||
611 | /* | 676 | /* |
@@ -626,7 +691,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
626 | /* check if we already stored this frame */ | 691 | /* check if we already stored this frame */ |
627 | if (tid_agg_rx->reorder_buf[index]) { | 692 | if (tid_agg_rx->reorder_buf[index]) { |
628 | dev_kfree_skb(skb); | 693 | dev_kfree_skb(skb); |
629 | return true; | 694 | goto out; |
630 | } | 695 | } |
631 | 696 | ||
632 | /* | 697 | /* |
@@ -636,58 +701,19 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
636 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && | 701 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && |
637 | tid_agg_rx->stored_mpdu_num == 0) { | 702 | tid_agg_rx->stored_mpdu_num == 0) { |
638 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 703 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); |
639 | return false; | 704 | ret = false; |
705 | goto out; | ||
640 | } | 706 | } |
641 | 707 | ||
642 | /* put the frame in the reordering buffer */ | 708 | /* put the frame in the reordering buffer */ |
643 | tid_agg_rx->reorder_buf[index] = skb; | 709 | tid_agg_rx->reorder_buf[index] = skb; |
644 | tid_agg_rx->reorder_time[index] = jiffies; | 710 | tid_agg_rx->reorder_time[index] = jiffies; |
645 | tid_agg_rx->stored_mpdu_num++; | 711 | tid_agg_rx->stored_mpdu_num++; |
646 | /* release the buffer until next missing frame */ | 712 | ieee80211_sta_reorder_release(hw, tid_agg_rx, frames); |
647 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
648 | tid_agg_rx->buf_size; | ||
649 | if (!tid_agg_rx->reorder_buf[index] && | ||
650 | tid_agg_rx->stored_mpdu_num > 1) { | ||
651 | /* | ||
652 | * No buffers ready to be released, but check whether any | ||
653 | * frames in the reorder buffer have timed out. | ||
654 | */ | ||
655 | int j; | ||
656 | int skipped = 1; | ||
657 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; | ||
658 | j = (j + 1) % tid_agg_rx->buf_size) { | ||
659 | if (!tid_agg_rx->reorder_buf[j]) { | ||
660 | skipped++; | ||
661 | continue; | ||
662 | } | ||
663 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + | ||
664 | HT_RX_REORDER_BUF_TIMEOUT)) | ||
665 | break; | ||
666 | |||
667 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
668 | if (net_ratelimit()) | ||
669 | printk(KERN_DEBUG "%s: release an RX reorder " | ||
670 | "frame due to timeout on earlier " | ||
671 | "frames\n", | ||
672 | wiphy_name(hw->wiphy)); | ||
673 | #endif | ||
674 | ieee80211_release_reorder_frame(hw, tid_agg_rx, | ||
675 | j, frames); | ||
676 | 713 | ||
677 | /* | 714 | out: |
678 | * Increment the head seq# also for the skipped slots. | 715 | spin_unlock(&tid_agg_rx->reorder_lock); |
679 | */ | 716 | return ret; |
680 | tid_agg_rx->head_seq_num = | ||
681 | (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; | ||
682 | skipped = 0; | ||
683 | } | ||
684 | } else while (tid_agg_rx->reorder_buf[index]) { | ||
685 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames); | ||
686 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
687 | tid_agg_rx->buf_size; | ||
688 | } | ||
689 | |||
690 | return true; | ||
691 | } | 717 | } |
692 | 718 | ||
693 | /* | 719 | /* |
@@ -873,6 +899,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
873 | 899 | ||
874 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { | 900 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { |
875 | rx->key = stakey; | 901 | rx->key = stakey; |
902 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
903 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
904 | return RX_CONTINUE; | ||
876 | /* Skip decryption if the frame is not protected. */ | 905 | /* Skip decryption if the frame is not protected. */ |
877 | if (!ieee80211_has_protected(fc)) | 906 | if (!ieee80211_has_protected(fc)) |
878 | return RX_CONTINUE; | 907 | return RX_CONTINUE; |
@@ -935,7 +964,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
935 | * pairwise or station-to-station keys, but for WEP we allow | 964 | * pairwise or station-to-station keys, but for WEP we allow |
936 | * using a key index as well. | 965 | * using a key index as well. |
937 | */ | 966 | */ |
938 | if (rx->key && rx->key->conf.alg != ALG_WEP && | 967 | if (rx->key && rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 && |
968 | rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 && | ||
939 | !is_multicast_ether_addr(hdr->addr1)) | 969 | !is_multicast_ether_addr(hdr->addr1)) |
940 | rx->key = NULL; | 970 | rx->key = NULL; |
941 | } | 971 | } |
@@ -951,8 +981,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
951 | return RX_DROP_UNUSABLE; | 981 | return RX_DROP_UNUSABLE; |
952 | /* the hdr variable is invalid now! */ | 982 | /* the hdr variable is invalid now! */ |
953 | 983 | ||
954 | switch (rx->key->conf.alg) { | 984 | switch (rx->key->conf.cipher) { |
955 | case ALG_WEP: | 985 | case WLAN_CIPHER_SUITE_WEP40: |
986 | case WLAN_CIPHER_SUITE_WEP104: | ||
956 | /* Check for weak IVs if possible */ | 987 | /* Check for weak IVs if possible */ |
957 | if (rx->sta && ieee80211_is_data(fc) && | 988 | if (rx->sta && ieee80211_is_data(fc) && |
958 | (!(status->flag & RX_FLAG_IV_STRIPPED) || | 989 | (!(status->flag & RX_FLAG_IV_STRIPPED) || |
@@ -962,13 +993,13 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
962 | 993 | ||
963 | result = ieee80211_crypto_wep_decrypt(rx); | 994 | result = ieee80211_crypto_wep_decrypt(rx); |
964 | break; | 995 | break; |
965 | case ALG_TKIP: | 996 | case WLAN_CIPHER_SUITE_TKIP: |
966 | result = ieee80211_crypto_tkip_decrypt(rx); | 997 | result = ieee80211_crypto_tkip_decrypt(rx); |
967 | break; | 998 | break; |
968 | case ALG_CCMP: | 999 | case WLAN_CIPHER_SUITE_CCMP: |
969 | result = ieee80211_crypto_ccmp_decrypt(rx); | 1000 | result = ieee80211_crypto_ccmp_decrypt(rx); |
970 | break; | 1001 | break; |
971 | case ALG_AES_CMAC: | 1002 | case WLAN_CIPHER_SUITE_AES_CMAC: |
972 | result = ieee80211_crypto_aes_cmac_decrypt(rx); | 1003 | result = ieee80211_crypto_aes_cmac_decrypt(rx); |
973 | break; | 1004 | break; |
974 | } | 1005 | } |
@@ -1265,7 +1296,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1265 | /* This is the first fragment of a new frame. */ | 1296 | /* This is the first fragment of a new frame. */ |
1266 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, | 1297 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, |
1267 | rx->queue, &(rx->skb)); | 1298 | rx->queue, &(rx->skb)); |
1268 | if (rx->key && rx->key->conf.alg == ALG_CCMP && | 1299 | if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && |
1269 | ieee80211_has_protected(fc)) { | 1300 | ieee80211_has_protected(fc)) { |
1270 | int queue = ieee80211_is_mgmt(fc) ? | 1301 | int queue = ieee80211_is_mgmt(fc) ? |
1271 | NUM_RX_DATA_QUEUES : rx->queue; | 1302 | NUM_RX_DATA_QUEUES : rx->queue; |
@@ -1294,7 +1325,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1294 | int i; | 1325 | int i; |
1295 | u8 pn[CCMP_PN_LEN], *rpn; | 1326 | u8 pn[CCMP_PN_LEN], *rpn; |
1296 | int queue; | 1327 | int queue; |
1297 | if (!rx->key || rx->key->conf.alg != ALG_CCMP) | 1328 | if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP) |
1298 | return RX_DROP_UNUSABLE; | 1329 | return RX_DROP_UNUSABLE; |
1299 | memcpy(pn, entry->last_pn, CCMP_PN_LEN); | 1330 | memcpy(pn, entry->last_pn, CCMP_PN_LEN); |
1300 | for (i = CCMP_PN_LEN - 1; i >= 0; i--) { | 1331 | for (i = CCMP_PN_LEN - 1; i >= 0; i--) { |
@@ -1909,13 +1940,36 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, | |||
1909 | } | 1940 | } |
1910 | 1941 | ||
1911 | static ieee80211_rx_result debug_noinline | 1942 | static ieee80211_rx_result debug_noinline |
1943 | ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) | ||
1944 | { | ||
1945 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
1946 | |||
1947 | /* | ||
1948 | * From here on, look only at management frames. | ||
1949 | * Data and control frames are already handled, | ||
1950 | * and unknown (reserved) frames are useless. | ||
1951 | */ | ||
1952 | if (rx->skb->len < 24) | ||
1953 | return RX_DROP_MONITOR; | ||
1954 | |||
1955 | if (!ieee80211_is_mgmt(mgmt->frame_control)) | ||
1956 | return RX_DROP_MONITOR; | ||
1957 | |||
1958 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | ||
1959 | return RX_DROP_MONITOR; | ||
1960 | |||
1961 | if (ieee80211_drop_unencrypted_mgmt(rx)) | ||
1962 | return RX_DROP_UNUSABLE; | ||
1963 | |||
1964 | return RX_CONTINUE; | ||
1965 | } | ||
1966 | |||
1967 | static ieee80211_rx_result debug_noinline | ||
1912 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | 1968 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) |
1913 | { | 1969 | { |
1914 | struct ieee80211_local *local = rx->local; | 1970 | struct ieee80211_local *local = rx->local; |
1915 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1971 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1916 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 1972 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; |
1917 | struct sk_buff *nskb; | ||
1918 | struct ieee80211_rx_status *status; | ||
1919 | int len = rx->skb->len; | 1973 | int len = rx->skb->len; |
1920 | 1974 | ||
1921 | if (!ieee80211_is_action(mgmt->frame_control)) | 1975 | if (!ieee80211_is_action(mgmt->frame_control)) |
@@ -1931,9 +1985,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1931 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1985 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1932 | return RX_DROP_UNUSABLE; | 1986 | return RX_DROP_UNUSABLE; |
1933 | 1987 | ||
1934 | if (ieee80211_drop_unencrypted_mgmt(rx)) | ||
1935 | return RX_DROP_UNUSABLE; | ||
1936 | |||
1937 | switch (mgmt->u.action.category) { | 1988 | switch (mgmt->u.action.category) { |
1938 | case WLAN_CATEGORY_BACK: | 1989 | case WLAN_CATEGORY_BACK: |
1939 | /* | 1990 | /* |
@@ -2024,17 +2075,36 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2024 | goto queue; | 2075 | goto queue; |
2025 | } | 2076 | } |
2026 | 2077 | ||
2078 | return RX_CONTINUE; | ||
2079 | |||
2027 | invalid: | 2080 | invalid: |
2028 | /* | 2081 | rx->flags |= IEEE80211_MALFORMED_ACTION_FRM; |
2029 | * For AP mode, hostapd is responsible for handling any action | 2082 | /* will return in the next handlers */ |
2030 | * frames that we didn't handle, including returning unknown | 2083 | return RX_CONTINUE; |
2031 | * ones. For all other modes we will return them to the sender, | 2084 | |
2032 | * setting the 0x80 bit in the action category, as required by | 2085 | handled: |
2033 | * 802.11-2007 7.3.1.11. | 2086 | if (rx->sta) |
2034 | */ | 2087 | rx->sta->rx_packets++; |
2035 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 2088 | dev_kfree_skb(rx->skb); |
2036 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 2089 | return RX_QUEUED; |
2037 | return RX_DROP_MONITOR; | 2090 | |
2091 | queue: | ||
2092 | rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; | ||
2093 | skb_queue_tail(&sdata->skb_queue, rx->skb); | ||
2094 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
2095 | if (rx->sta) | ||
2096 | rx->sta->rx_packets++; | ||
2097 | return RX_QUEUED; | ||
2098 | } | ||
2099 | |||
2100 | static ieee80211_rx_result debug_noinline | ||
2101 | ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) | ||
2102 | { | ||
2103 | struct ieee80211_rx_status *status; | ||
2104 | |||
2105 | /* skip known-bad action frames and return them in the next handler */ | ||
2106 | if (rx->flags & IEEE80211_MALFORMED_ACTION_FRM) | ||
2107 | return RX_CONTINUE; | ||
2038 | 2108 | ||
2039 | /* | 2109 | /* |
2040 | * Getting here means the kernel doesn't know how to handle | 2110 | * Getting here means the kernel doesn't know how to handle |
@@ -2044,10 +2114,44 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2044 | */ | 2114 | */ |
2045 | status = IEEE80211_SKB_RXCB(rx->skb); | 2115 | status = IEEE80211_SKB_RXCB(rx->skb); |
2046 | 2116 | ||
2047 | if (cfg80211_rx_action(rx->sdata->dev, status->freq, | 2117 | if (cfg80211_rx_mgmt(rx->sdata->dev, status->freq, |
2048 | rx->skb->data, rx->skb->len, | 2118 | rx->skb->data, rx->skb->len, |
2049 | GFP_ATOMIC)) | 2119 | GFP_ATOMIC)) { |
2050 | goto handled; | 2120 | if (rx->sta) |
2121 | rx->sta->rx_packets++; | ||
2122 | dev_kfree_skb(rx->skb); | ||
2123 | return RX_QUEUED; | ||
2124 | } | ||
2125 | |||
2126 | |||
2127 | return RX_CONTINUE; | ||
2128 | } | ||
2129 | |||
2130 | static ieee80211_rx_result debug_noinline | ||
2131 | ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) | ||
2132 | { | ||
2133 | struct ieee80211_local *local = rx->local; | ||
2134 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
2135 | struct sk_buff *nskb; | ||
2136 | struct ieee80211_sub_if_data *sdata = rx->sdata; | ||
2137 | |||
2138 | if (!ieee80211_is_action(mgmt->frame_control)) | ||
2139 | return RX_CONTINUE; | ||
2140 | |||
2141 | /* | ||
2142 | * For AP mode, hostapd is responsible for handling any action | ||
2143 | * frames that we didn't handle, including returning unknown | ||
2144 | * ones. For all other modes we will return them to the sender, | ||
2145 | * setting the 0x80 bit in the action category, as required by | ||
2146 | * 802.11-2007 7.3.1.11. | ||
2147 | * Newer versions of hostapd shall also use the management frame | ||
2148 | * registration mechanisms, but older ones still use cooked | ||
2149 | * monitor interfaces so push all frames there. | ||
2150 | */ | ||
2151 | if (!(rx->flags & IEEE80211_MALFORMED_ACTION_FRM) && | ||
2152 | (sdata->vif.type == NL80211_IFTYPE_AP || | ||
2153 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) | ||
2154 | return RX_DROP_MONITOR; | ||
2051 | 2155 | ||
2052 | /* do not return rejected action frames */ | 2156 | /* do not return rejected action frames */ |
2053 | if (mgmt->u.action.category & 0x80) | 2157 | if (mgmt->u.action.category & 0x80) |
@@ -2066,20 +2170,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2066 | 2170 | ||
2067 | ieee80211_tx_skb(rx->sdata, nskb); | 2171 | ieee80211_tx_skb(rx->sdata, nskb); |
2068 | } | 2172 | } |
2069 | |||
2070 | handled: | ||
2071 | if (rx->sta) | ||
2072 | rx->sta->rx_packets++; | ||
2073 | dev_kfree_skb(rx->skb); | 2173 | dev_kfree_skb(rx->skb); |
2074 | return RX_QUEUED; | 2174 | return RX_QUEUED; |
2075 | |||
2076 | queue: | ||
2077 | rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; | ||
2078 | skb_queue_tail(&sdata->skb_queue, rx->skb); | ||
2079 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
2080 | if (rx->sta) | ||
2081 | rx->sta->rx_packets++; | ||
2082 | return RX_QUEUED; | ||
2083 | } | 2175 | } |
2084 | 2176 | ||
2085 | static ieee80211_rx_result debug_noinline | 2177 | static ieee80211_rx_result debug_noinline |
@@ -2090,15 +2182,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
2090 | struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; | 2182 | struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; |
2091 | __le16 stype; | 2183 | __le16 stype; |
2092 | 2184 | ||
2093 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | ||
2094 | return RX_DROP_MONITOR; | ||
2095 | |||
2096 | if (rx->skb->len < 24) | ||
2097 | return RX_DROP_MONITOR; | ||
2098 | |||
2099 | if (ieee80211_drop_unencrypted_mgmt(rx)) | ||
2100 | return RX_DROP_UNUSABLE; | ||
2101 | |||
2102 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); | 2185 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); |
2103 | if (rxs != RX_CONTINUE) | 2186 | if (rxs != RX_CONTINUE) |
2104 | return rxs; | 2187 | return rxs; |
@@ -2267,19 +2350,46 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, | |||
2267 | dev_kfree_skb(skb); | 2350 | dev_kfree_skb(skb); |
2268 | } | 2351 | } |
2269 | 2352 | ||
2353 | static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, | ||
2354 | ieee80211_rx_result res) | ||
2355 | { | ||
2356 | switch (res) { | ||
2357 | case RX_DROP_MONITOR: | ||
2358 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); | ||
2359 | if (rx->sta) | ||
2360 | rx->sta->rx_dropped++; | ||
2361 | /* fall through */ | ||
2362 | case RX_CONTINUE: { | ||
2363 | struct ieee80211_rate *rate = NULL; | ||
2364 | struct ieee80211_supported_band *sband; | ||
2365 | struct ieee80211_rx_status *status; | ||
2366 | |||
2367 | status = IEEE80211_SKB_RXCB((rx->skb)); | ||
2368 | |||
2369 | sband = rx->local->hw.wiphy->bands[status->band]; | ||
2370 | if (!(status->flag & RX_FLAG_HT)) | ||
2371 | rate = &sband->bitrates[status->rate_idx]; | ||
2372 | |||
2373 | ieee80211_rx_cooked_monitor(rx, rate); | ||
2374 | break; | ||
2375 | } | ||
2376 | case RX_DROP_UNUSABLE: | ||
2377 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); | ||
2378 | if (rx->sta) | ||
2379 | rx->sta->rx_dropped++; | ||
2380 | dev_kfree_skb(rx->skb); | ||
2381 | break; | ||
2382 | case RX_QUEUED: | ||
2383 | I802_DEBUG_INC(rx->sdata->local->rx_handlers_queued); | ||
2384 | break; | ||
2385 | } | ||
2386 | } | ||
2270 | 2387 | ||
2271 | static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | 2388 | static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, |
2272 | struct ieee80211_rx_data *rx, | 2389 | struct sk_buff_head *frames) |
2273 | struct sk_buff *skb, | ||
2274 | struct ieee80211_rate *rate) | ||
2275 | { | 2390 | { |
2276 | struct sk_buff_head reorder_release; | ||
2277 | ieee80211_rx_result res = RX_DROP_MONITOR; | 2391 | ieee80211_rx_result res = RX_DROP_MONITOR; |
2278 | 2392 | struct sk_buff *skb; | |
2279 | __skb_queue_head_init(&reorder_release); | ||
2280 | |||
2281 | rx->skb = skb; | ||
2282 | rx->sdata = sdata; | ||
2283 | 2393 | ||
2284 | #define CALL_RXH(rxh) \ | 2394 | #define CALL_RXH(rxh) \ |
2285 | do { \ | 2395 | do { \ |
@@ -2288,17 +2398,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
2288 | goto rxh_next; \ | 2398 | goto rxh_next; \ |
2289 | } while (0); | 2399 | } while (0); |
2290 | 2400 | ||
2291 | /* | 2401 | while ((skb = __skb_dequeue(frames))) { |
2292 | * NB: the rxh_next label works even if we jump | ||
2293 | * to it from here because then the list will | ||
2294 | * be empty, which is a trivial check | ||
2295 | */ | ||
2296 | CALL_RXH(ieee80211_rx_h_passive_scan) | ||
2297 | CALL_RXH(ieee80211_rx_h_check) | ||
2298 | |||
2299 | ieee80211_rx_reorder_ampdu(rx, &reorder_release); | ||
2300 | |||
2301 | while ((skb = __skb_dequeue(&reorder_release))) { | ||
2302 | /* | 2402 | /* |
2303 | * all the other fields are valid across frames | 2403 | * all the other fields are valid across frames |
2304 | * that belong to an aMPDU since they are on the | 2404 | * that belong to an aMPDU since they are on the |
@@ -2316,42 +2416,91 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
2316 | CALL_RXH(ieee80211_rx_h_remove_qos_control) | 2416 | CALL_RXH(ieee80211_rx_h_remove_qos_control) |
2317 | CALL_RXH(ieee80211_rx_h_amsdu) | 2417 | CALL_RXH(ieee80211_rx_h_amsdu) |
2318 | #ifdef CONFIG_MAC80211_MESH | 2418 | #ifdef CONFIG_MAC80211_MESH |
2319 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 2419 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) |
2320 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | 2420 | CALL_RXH(ieee80211_rx_h_mesh_fwding); |
2321 | #endif | 2421 | #endif |
2322 | CALL_RXH(ieee80211_rx_h_data) | 2422 | CALL_RXH(ieee80211_rx_h_data) |
2323 | 2423 | ||
2324 | /* special treatment -- needs the queue */ | 2424 | /* special treatment -- needs the queue */ |
2325 | res = ieee80211_rx_h_ctrl(rx, &reorder_release); | 2425 | res = ieee80211_rx_h_ctrl(rx, frames); |
2326 | if (res != RX_CONTINUE) | 2426 | if (res != RX_CONTINUE) |
2327 | goto rxh_next; | 2427 | goto rxh_next; |
2328 | 2428 | ||
2429 | CALL_RXH(ieee80211_rx_h_mgmt_check) | ||
2329 | CALL_RXH(ieee80211_rx_h_action) | 2430 | CALL_RXH(ieee80211_rx_h_action) |
2431 | CALL_RXH(ieee80211_rx_h_userspace_mgmt) | ||
2432 | CALL_RXH(ieee80211_rx_h_action_return) | ||
2330 | CALL_RXH(ieee80211_rx_h_mgmt) | 2433 | CALL_RXH(ieee80211_rx_h_mgmt) |
2331 | 2434 | ||
2435 | rxh_next: | ||
2436 | ieee80211_rx_handlers_result(rx, res); | ||
2437 | |||
2332 | #undef CALL_RXH | 2438 | #undef CALL_RXH |
2439 | } | ||
2440 | } | ||
2441 | |||
2442 | static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | ||
2443 | struct ieee80211_rx_data *rx, | ||
2444 | struct sk_buff *skb) | ||
2445 | { | ||
2446 | struct sk_buff_head reorder_release; | ||
2447 | ieee80211_rx_result res = RX_DROP_MONITOR; | ||
2448 | |||
2449 | __skb_queue_head_init(&reorder_release); | ||
2450 | |||
2451 | rx->skb = skb; | ||
2452 | rx->sdata = sdata; | ||
2453 | |||
2454 | #define CALL_RXH(rxh) \ | ||
2455 | do { \ | ||
2456 | res = rxh(rx); \ | ||
2457 | if (res != RX_CONTINUE) \ | ||
2458 | goto rxh_next; \ | ||
2459 | } while (0); | ||
2460 | |||
2461 | CALL_RXH(ieee80211_rx_h_passive_scan) | ||
2462 | CALL_RXH(ieee80211_rx_h_check) | ||
2463 | |||
2464 | ieee80211_rx_reorder_ampdu(rx, &reorder_release); | ||
2465 | |||
2466 | ieee80211_rx_handlers(rx, &reorder_release); | ||
2467 | return; | ||
2333 | 2468 | ||
2334 | rxh_next: | 2469 | rxh_next: |
2335 | switch (res) { | 2470 | ieee80211_rx_handlers_result(rx, res); |
2336 | case RX_DROP_MONITOR: | 2471 | |
2337 | I802_DEBUG_INC(sdata->local->rx_handlers_drop); | 2472 | #undef CALL_RXH |
2338 | if (rx->sta) | 2473 | } |
2339 | rx->sta->rx_dropped++; | 2474 | |
2340 | /* fall through */ | 2475 | /* |
2341 | case RX_CONTINUE: | 2476 | * This function makes calls into the RX path. Therefore the |
2342 | ieee80211_rx_cooked_monitor(rx, rate); | 2477 | * caller must hold the sta_info->lock and everything has to |
2343 | break; | 2478 | * be under rcu_read_lock protection as well. |
2344 | case RX_DROP_UNUSABLE: | 2479 | */ |
2345 | I802_DEBUG_INC(sdata->local->rx_handlers_drop); | 2480 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) |
2346 | if (rx->sta) | 2481 | { |
2347 | rx->sta->rx_dropped++; | 2482 | struct sk_buff_head frames; |
2348 | dev_kfree_skb(rx->skb); | 2483 | struct ieee80211_rx_data rx = { }; |
2349 | break; | 2484 | |
2350 | case RX_QUEUED: | 2485 | __skb_queue_head_init(&frames); |
2351 | I802_DEBUG_INC(sdata->local->rx_handlers_queued); | 2486 | |
2352 | break; | 2487 | /* construct rx struct */ |
2353 | } | 2488 | rx.sta = sta; |
2354 | } | 2489 | rx.sdata = sta->sdata; |
2490 | rx.local = sta->local; | ||
2491 | rx.queue = tid; | ||
2492 | rx.flags |= IEEE80211_RX_RA_MATCH; | ||
2493 | |||
2494 | if (unlikely(test_bit(SCAN_HW_SCANNING, &sta->local->scanning) || | ||
2495 | test_bit(SCAN_OFF_CHANNEL, &sta->local->scanning))) | ||
2496 | rx.flags |= IEEE80211_RX_IN_SCAN; | ||
2497 | |||
2498 | spin_lock(&sta->ampdu_mlme.tid_rx[tid]->reorder_lock); | ||
2499 | ieee80211_sta_reorder_release(&sta->local->hw, | ||
2500 | sta->ampdu_mlme.tid_rx[tid], &frames); | ||
2501 | spin_unlock(&sta->ampdu_mlme.tid_rx[tid]->reorder_lock); | ||
2502 | |||
2503 | ieee80211_rx_handlers(&rx, &frames); | ||
2355 | } | 2504 | } |
2356 | 2505 | ||
2357 | /* main receive path */ | 2506 | /* main receive path */ |
@@ -2433,7 +2582,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2433 | break; | 2582 | break; |
2434 | case NL80211_IFTYPE_MONITOR: | 2583 | case NL80211_IFTYPE_MONITOR: |
2435 | case NL80211_IFTYPE_UNSPECIFIED: | 2584 | case NL80211_IFTYPE_UNSPECIFIED: |
2436 | case __NL80211_IFTYPE_AFTER_LAST: | 2585 | case NUM_NL80211_IFTYPES: |
2437 | /* should never get here */ | 2586 | /* should never get here */ |
2438 | WARN_ON(1); | 2587 | WARN_ON(1); |
2439 | break; | 2588 | break; |
@@ -2447,8 +2596,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2447 | * be called with rcu_read_lock protection. | 2596 | * be called with rcu_read_lock protection. |
2448 | */ | 2597 | */ |
2449 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | 2598 | static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, |
2450 | struct sk_buff *skb, | 2599 | struct sk_buff *skb) |
2451 | struct ieee80211_rate *rate) | ||
2452 | { | 2600 | { |
2453 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 2601 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
2454 | struct ieee80211_local *local = hw_to_local(hw); | 2602 | struct ieee80211_local *local = hw_to_local(hw); |
@@ -2556,7 +2704,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2556 | prev->name); | 2704 | prev->name); |
2557 | goto next; | 2705 | goto next; |
2558 | } | 2706 | } |
2559 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); | 2707 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new); |
2560 | next: | 2708 | next: |
2561 | prev = sdata; | 2709 | prev = sdata; |
2562 | } | 2710 | } |
@@ -2572,7 +2720,7 @@ next: | |||
2572 | } | 2720 | } |
2573 | } | 2721 | } |
2574 | if (prev) | 2722 | if (prev) |
2575 | ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); | 2723 | ieee80211_invoke_rx_handlers(prev, &rx, skb); |
2576 | else | 2724 | else |
2577 | dev_kfree_skb(skb); | 2725 | dev_kfree_skb(skb); |
2578 | } | 2726 | } |
@@ -2615,28 +2763,37 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2615 | if (WARN_ON(!local->started)) | 2763 | if (WARN_ON(!local->started)) |
2616 | goto drop; | 2764 | goto drop; |
2617 | 2765 | ||
2618 | if (status->flag & RX_FLAG_HT) { | 2766 | if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) { |
2619 | /* | 2767 | /* |
2620 | * rate_idx is MCS index, which can be [0-76] as documented on: | 2768 | * Validate the rate, unless a PLCP error means that |
2621 | * | 2769 | * we probably can't have a valid rate here anyway. |
2622 | * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n | ||
2623 | * | ||
2624 | * Anything else would be some sort of driver or hardware error. | ||
2625 | * The driver should catch hardware errors. | ||
2626 | */ | 2770 | */ |
2627 | if (WARN((status->rate_idx < 0 || | 2771 | |
2628 | status->rate_idx > 76), | 2772 | if (status->flag & RX_FLAG_HT) { |
2629 | "Rate marked as an HT rate but passed " | 2773 | /* |
2630 | "status->rate_idx is not " | 2774 | * rate_idx is MCS index, which can be [0-76] |
2631 | "an MCS index [0-76]: %d (0x%02x)\n", | 2775 | * as documented on: |
2632 | status->rate_idx, | 2776 | * |
2633 | status->rate_idx)) | 2777 | * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n |
2634 | goto drop; | 2778 | * |
2635 | } else { | 2779 | * Anything else would be some sort of driver or |
2636 | if (WARN_ON(status->rate_idx < 0 || | 2780 | * hardware error. The driver should catch hardware |
2637 | status->rate_idx >= sband->n_bitrates)) | 2781 | * errors. |
2638 | goto drop; | 2782 | */ |
2639 | rate = &sband->bitrates[status->rate_idx]; | 2783 | if (WARN((status->rate_idx < 0 || |
2784 | status->rate_idx > 76), | ||
2785 | "Rate marked as an HT rate but passed " | ||
2786 | "status->rate_idx is not " | ||
2787 | "an MCS index [0-76]: %d (0x%02x)\n", | ||
2788 | status->rate_idx, | ||
2789 | status->rate_idx)) | ||
2790 | goto drop; | ||
2791 | } else { | ||
2792 | if (WARN_ON(status->rate_idx < 0 || | ||
2793 | status->rate_idx >= sband->n_bitrates)) | ||
2794 | goto drop; | ||
2795 | rate = &sband->bitrates[status->rate_idx]; | ||
2796 | } | ||
2640 | } | 2797 | } |
2641 | 2798 | ||
2642 | /* | 2799 | /* |
@@ -2658,7 +2815,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2658 | return; | 2815 | return; |
2659 | } | 2816 | } |
2660 | 2817 | ||
2661 | __ieee80211_rx_handle_packet(hw, skb, rate); | 2818 | __ieee80211_rx_handle_packet(hw, skb); |
2662 | 2819 | ||
2663 | rcu_read_unlock(); | 2820 | rcu_read_unlock(); |
2664 | 2821 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 872d7b6ef6b3..31f233f7f51a 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -255,7 +255,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
255 | 255 | ||
256 | trace_api_scan_completed(local, aborted); | 256 | trace_api_scan_completed(local, aborted); |
257 | 257 | ||
258 | mutex_lock(&local->scan_mtx); | 258 | mutex_lock(&local->mtx); |
259 | 259 | ||
260 | /* | 260 | /* |
261 | * It's ok to abort a not-yet-running scan (that | 261 | * It's ok to abort a not-yet-running scan (that |
@@ -267,7 +267,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
267 | aborted = true; | 267 | aborted = true; |
268 | 268 | ||
269 | if (WARN_ON(!local->scan_req)) { | 269 | if (WARN_ON(!local->scan_req)) { |
270 | mutex_unlock(&local->scan_mtx); | 270 | mutex_unlock(&local->mtx); |
271 | return; | 271 | return; |
272 | } | 272 | } |
273 | 273 | ||
@@ -275,7 +275,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
275 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { | 275 | if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { |
276 | ieee80211_queue_delayed_work(&local->hw, | 276 | ieee80211_queue_delayed_work(&local->hw, |
277 | &local->scan_work, 0); | 277 | &local->scan_work, 0); |
278 | mutex_unlock(&local->scan_mtx); | 278 | mutex_unlock(&local->mtx); |
279 | return; | 279 | return; |
280 | } | 280 | } |
281 | 281 | ||
@@ -291,7 +291,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
291 | local->scan_channel = NULL; | 291 | local->scan_channel = NULL; |
292 | 292 | ||
293 | /* we only have to protect scan_req and hw/sw scan */ | 293 | /* we only have to protect scan_req and hw/sw scan */ |
294 | mutex_unlock(&local->scan_mtx); | 294 | mutex_unlock(&local->mtx); |
295 | 295 | ||
296 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 296 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
297 | if (was_hw_scan) | 297 | if (was_hw_scan) |
@@ -304,7 +304,9 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
304 | ieee80211_offchannel_return(local, true); | 304 | ieee80211_offchannel_return(local, true); |
305 | 305 | ||
306 | done: | 306 | done: |
307 | mutex_lock(&local->mtx); | ||
307 | ieee80211_recalc_idle(local); | 308 | ieee80211_recalc_idle(local); |
309 | mutex_unlock(&local->mtx); | ||
308 | ieee80211_mlme_notify_scan_completed(local); | 310 | ieee80211_mlme_notify_scan_completed(local); |
309 | ieee80211_ibss_notify_scan_completed(local); | 311 | ieee80211_ibss_notify_scan_completed(local); |
310 | ieee80211_mesh_notify_scan_completed(local); | 312 | ieee80211_mesh_notify_scan_completed(local); |
@@ -639,15 +641,15 @@ void ieee80211_scan_work(struct work_struct *work) | |||
639 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 641 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; |
640 | unsigned long next_delay = 0; | 642 | unsigned long next_delay = 0; |
641 | 643 | ||
642 | mutex_lock(&local->scan_mtx); | 644 | mutex_lock(&local->mtx); |
643 | if (!sdata || !local->scan_req) { | 645 | if (!sdata || !local->scan_req) { |
644 | mutex_unlock(&local->scan_mtx); | 646 | mutex_unlock(&local->mtx); |
645 | return; | 647 | return; |
646 | } | 648 | } |
647 | 649 | ||
648 | if (local->hw_scan_req) { | 650 | if (local->hw_scan_req) { |
649 | int rc = drv_hw_scan(local, sdata, local->hw_scan_req); | 651 | int rc = drv_hw_scan(local, sdata, local->hw_scan_req); |
650 | mutex_unlock(&local->scan_mtx); | 652 | mutex_unlock(&local->mtx); |
651 | if (rc) | 653 | if (rc) |
652 | ieee80211_scan_completed(&local->hw, true); | 654 | ieee80211_scan_completed(&local->hw, true); |
653 | return; | 655 | return; |
@@ -661,14 +663,14 @@ void ieee80211_scan_work(struct work_struct *work) | |||
661 | local->scan_sdata = NULL; | 663 | local->scan_sdata = NULL; |
662 | 664 | ||
663 | rc = __ieee80211_start_scan(sdata, req); | 665 | rc = __ieee80211_start_scan(sdata, req); |
664 | mutex_unlock(&local->scan_mtx); | 666 | mutex_unlock(&local->mtx); |
665 | 667 | ||
666 | if (rc) | 668 | if (rc) |
667 | ieee80211_scan_completed(&local->hw, true); | 669 | ieee80211_scan_completed(&local->hw, true); |
668 | return; | 670 | return; |
669 | } | 671 | } |
670 | 672 | ||
671 | mutex_unlock(&local->scan_mtx); | 673 | mutex_unlock(&local->mtx); |
672 | 674 | ||
673 | /* | 675 | /* |
674 | * Avoid re-scheduling when the sdata is going away. | 676 | * Avoid re-scheduling when the sdata is going away. |
@@ -711,9 +713,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |||
711 | { | 713 | { |
712 | int res; | 714 | int res; |
713 | 715 | ||
714 | mutex_lock(&sdata->local->scan_mtx); | 716 | mutex_lock(&sdata->local->mtx); |
715 | res = __ieee80211_start_scan(sdata, req); | 717 | res = __ieee80211_start_scan(sdata, req); |
716 | mutex_unlock(&sdata->local->scan_mtx); | 718 | mutex_unlock(&sdata->local->mtx); |
717 | 719 | ||
718 | return res; | 720 | return res; |
719 | } | 721 | } |
@@ -726,7 +728,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
726 | int ret = -EBUSY; | 728 | int ret = -EBUSY; |
727 | enum ieee80211_band band; | 729 | enum ieee80211_band band; |
728 | 730 | ||
729 | mutex_lock(&local->scan_mtx); | 731 | mutex_lock(&local->mtx); |
730 | 732 | ||
731 | /* busy scanning */ | 733 | /* busy scanning */ |
732 | if (local->scan_req) | 734 | if (local->scan_req) |
@@ -761,7 +763,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
761 | 763 | ||
762 | ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req); | 764 | ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req); |
763 | unlock: | 765 | unlock: |
764 | mutex_unlock(&local->scan_mtx); | 766 | mutex_unlock(&local->mtx); |
765 | return ret; | 767 | return ret; |
766 | } | 768 | } |
767 | 769 | ||
@@ -775,10 +777,10 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
775 | * Only call this function when a scan can't be | 777 | * Only call this function when a scan can't be |
776 | * queued -- mostly at suspend under RTNL. | 778 | * queued -- mostly at suspend under RTNL. |
777 | */ | 779 | */ |
778 | mutex_lock(&local->scan_mtx); | 780 | mutex_lock(&local->mtx); |
779 | abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || | 781 | abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || |
780 | (!local->scanning && local->scan_req); | 782 | (!local->scanning && local->scan_req); |
781 | mutex_unlock(&local->scan_mtx); | 783 | mutex_unlock(&local->mtx); |
782 | 784 | ||
783 | if (abortscan) | 785 | if (abortscan) |
784 | ieee80211_scan_completed(&local->hw, true); | 786 | ieee80211_scan_completed(&local->hw, true); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 54262e72376d..810c5ce98316 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -103,6 +103,7 @@ struct tid_ampdu_tx { | |||
103 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs | 103 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs |
104 | * @reorder_time: jiffies when skb was added | 104 | * @reorder_time: jiffies when skb was added |
105 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) | 105 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) |
106 | * @reorder_timer: releases expired frames from the reorder buffer. | ||
106 | * @head_seq_num: head sequence number in reordering buffer. | 107 | * @head_seq_num: head sequence number in reordering buffer. |
107 | * @stored_mpdu_num: number of MPDUs in reordering buffer | 108 | * @stored_mpdu_num: number of MPDUs in reordering buffer |
108 | * @ssn: Starting Sequence Number expected to be aggregated. | 109 | * @ssn: Starting Sequence Number expected to be aggregated. |
@@ -110,20 +111,25 @@ struct tid_ampdu_tx { | |||
110 | * @timeout: reset timer value (in TUs). | 111 | * @timeout: reset timer value (in TUs). |
111 | * @dialog_token: dialog token for aggregation session | 112 | * @dialog_token: dialog token for aggregation session |
112 | * @rcu_head: RCU head used for freeing this struct | 113 | * @rcu_head: RCU head used for freeing this struct |
114 | * @reorder_lock: serializes access to reorder buffer, see below. | ||
113 | * | 115 | * |
114 | * This structure is protected by RCU and the per-station | 116 | * This structure is protected by RCU and the per-station |
115 | * spinlock. Assignments to the array holding it must hold | 117 | * spinlock. Assignments to the array holding it must hold |
116 | * the spinlock, only the RX path can access it under RCU | 118 | * the spinlock. |
117 | * lock-free. The RX path, since it is single-threaded, | 119 | * |
118 | * can even modify the structure without locking since the | 120 | * The @reorder_lock is used to protect the variables and |
119 | * only other modifications to it are done when the struct | 121 | * arrays such as @reorder_buf, @reorder_time, @head_seq_num, |
120 | * can not yet or no longer be found by the RX path. | 122 | * @stored_mpdu_num and @reorder_time from being corrupted by |
123 | * concurrent access of the RX path and the expired frame | ||
124 | * release timer. | ||
121 | */ | 125 | */ |
122 | struct tid_ampdu_rx { | 126 | struct tid_ampdu_rx { |
123 | struct rcu_head rcu_head; | 127 | struct rcu_head rcu_head; |
128 | spinlock_t reorder_lock; | ||
124 | struct sk_buff **reorder_buf; | 129 | struct sk_buff **reorder_buf; |
125 | unsigned long *reorder_time; | 130 | unsigned long *reorder_time; |
126 | struct timer_list session_timer; | 131 | struct timer_list session_timer; |
132 | struct timer_list reorder_timer; | ||
127 | u16 head_seq_num; | 133 | u16 head_seq_num; |
128 | u16 stored_mpdu_num; | 134 | u16 stored_mpdu_num; |
129 | u16 ssn; | 135 | u16 ssn; |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 10caec5ea8fa..67a35841bef0 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -296,7 +296,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
296 | } | 296 | } |
297 | 297 | ||
298 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) | 298 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) |
299 | cfg80211_action_tx_status( | 299 | cfg80211_mgmt_tx_status( |
300 | skb->dev, (unsigned long) skb, skb->data, skb->len, | 300 | skb->dev, (unsigned long) skb, skb->data, skb->len, |
301 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); | 301 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); |
302 | 302 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c54db966926b..bc4fefc91663 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -543,15 +543,16 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
543 | tx->key->tx_rx_count++; | 543 | tx->key->tx_rx_count++; |
544 | /* TODO: add threshold stuff again */ | 544 | /* TODO: add threshold stuff again */ |
545 | 545 | ||
546 | switch (tx->key->conf.alg) { | 546 | switch (tx->key->conf.cipher) { |
547 | case ALG_WEP: | 547 | case WLAN_CIPHER_SUITE_WEP40: |
548 | case WLAN_CIPHER_SUITE_WEP104: | ||
548 | if (ieee80211_is_auth(hdr->frame_control)) | 549 | if (ieee80211_is_auth(hdr->frame_control)) |
549 | break; | 550 | break; |
550 | case ALG_TKIP: | 551 | case WLAN_CIPHER_SUITE_TKIP: |
551 | if (!ieee80211_is_data_present(hdr->frame_control)) | 552 | if (!ieee80211_is_data_present(hdr->frame_control)) |
552 | tx->key = NULL; | 553 | tx->key = NULL; |
553 | break; | 554 | break; |
554 | case ALG_CCMP: | 555 | case WLAN_CIPHER_SUITE_CCMP: |
555 | if (!ieee80211_is_data_present(hdr->frame_control) && | 556 | if (!ieee80211_is_data_present(hdr->frame_control) && |
556 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, | 557 | !ieee80211_use_mfp(hdr->frame_control, tx->sta, |
557 | tx->skb)) | 558 | tx->skb)) |
@@ -561,7 +562,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
561 | IEEE80211_KEY_FLAG_SW_MGMT) && | 562 | IEEE80211_KEY_FLAG_SW_MGMT) && |
562 | ieee80211_is_mgmt(hdr->frame_control); | 563 | ieee80211_is_mgmt(hdr->frame_control); |
563 | break; | 564 | break; |
564 | case ALG_AES_CMAC: | 565 | case WLAN_CIPHER_SUITE_AES_CMAC: |
565 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 566 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
566 | tx->key = NULL; | 567 | tx->key = NULL; |
567 | break; | 568 | break; |
@@ -949,14 +950,15 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) | |||
949 | if (!tx->key) | 950 | if (!tx->key) |
950 | return TX_CONTINUE; | 951 | return TX_CONTINUE; |
951 | 952 | ||
952 | switch (tx->key->conf.alg) { | 953 | switch (tx->key->conf.cipher) { |
953 | case ALG_WEP: | 954 | case WLAN_CIPHER_SUITE_WEP40: |
955 | case WLAN_CIPHER_SUITE_WEP104: | ||
954 | return ieee80211_crypto_wep_encrypt(tx); | 956 | return ieee80211_crypto_wep_encrypt(tx); |
955 | case ALG_TKIP: | 957 | case WLAN_CIPHER_SUITE_TKIP: |
956 | return ieee80211_crypto_tkip_encrypt(tx); | 958 | return ieee80211_crypto_tkip_encrypt(tx); |
957 | case ALG_CCMP: | 959 | case WLAN_CIPHER_SUITE_CCMP: |
958 | return ieee80211_crypto_ccmp_encrypt(tx); | 960 | return ieee80211_crypto_ccmp_encrypt(tx); |
959 | case ALG_AES_CMAC: | 961 | case WLAN_CIPHER_SUITE_AES_CMAC: |
960 | return ieee80211_crypto_aes_cmac_encrypt(tx); | 962 | return ieee80211_crypto_aes_cmac_encrypt(tx); |
961 | } | 963 | } |
962 | 964 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 748387d45bc0..cd2b485fed4f 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -471,7 +471,7 @@ void ieee80211_iterate_active_interfaces( | |||
471 | 471 | ||
472 | list_for_each_entry(sdata, &local->interfaces, list) { | 472 | list_for_each_entry(sdata, &local->interfaces, list) { |
473 | switch (sdata->vif.type) { | 473 | switch (sdata->vif.type) { |
474 | case __NL80211_IFTYPE_AFTER_LAST: | 474 | case NUM_NL80211_IFTYPES: |
475 | case NL80211_IFTYPE_UNSPECIFIED: | 475 | case NL80211_IFTYPE_UNSPECIFIED: |
476 | case NL80211_IFTYPE_MONITOR: | 476 | case NL80211_IFTYPE_MONITOR: |
477 | case NL80211_IFTYPE_AP_VLAN: | 477 | case NL80211_IFTYPE_AP_VLAN: |
@@ -505,7 +505,7 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
505 | 505 | ||
506 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 506 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
507 | switch (sdata->vif.type) { | 507 | switch (sdata->vif.type) { |
508 | case __NL80211_IFTYPE_AFTER_LAST: | 508 | case NUM_NL80211_IFTYPES: |
509 | case NL80211_IFTYPE_UNSPECIFIED: | 509 | case NL80211_IFTYPE_UNSPECIFIED: |
510 | case NL80211_IFTYPE_MONITOR: | 510 | case NL80211_IFTYPE_MONITOR: |
511 | case NL80211_IFTYPE_AP_VLAN: | 511 | case NL80211_IFTYPE_AP_VLAN: |
@@ -1189,7 +1189,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1189 | /* ignore virtual */ | 1189 | /* ignore virtual */ |
1190 | break; | 1190 | break; |
1191 | case NL80211_IFTYPE_UNSPECIFIED: | 1191 | case NL80211_IFTYPE_UNSPECIFIED: |
1192 | case __NL80211_IFTYPE_AFTER_LAST: | 1192 | case NUM_NL80211_IFTYPES: |
1193 | WARN_ON(1); | 1193 | WARN_ON(1); |
1194 | break; | 1194 | break; |
1195 | } | 1195 | } |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 9ebc8d8a1f5b..f27484c22b9f 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -240,7 +240,7 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, | |||
240 | 240 | ||
241 | keyidx = skb->data[hdrlen + 3] >> 6; | 241 | keyidx = skb->data[hdrlen + 3] >> 6; |
242 | 242 | ||
243 | if (!key || keyidx != key->conf.keyidx || key->conf.alg != ALG_WEP) | 243 | if (!key || keyidx != key->conf.keyidx) |
244 | return -1; | 244 | return -1; |
245 | 245 | ||
246 | klen = 3 + key->conf.keylen; | 246 | klen = 3 + key->conf.keylen; |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 81d4ad64184a..ae344d1ba056 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -43,7 +43,7 @@ enum work_action { | |||
43 | /* utils */ | 43 | /* utils */ |
44 | static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) | 44 | static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) |
45 | { | 45 | { |
46 | WARN_ON(!mutex_is_locked(&local->work_mtx)); | 46 | lockdep_assert_held(&local->mtx); |
47 | } | 47 | } |
48 | 48 | ||
49 | /* | 49 | /* |
@@ -757,7 +757,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
757 | mgmt = (struct ieee80211_mgmt *) skb->data; | 757 | mgmt = (struct ieee80211_mgmt *) skb->data; |
758 | fc = le16_to_cpu(mgmt->frame_control); | 758 | fc = le16_to_cpu(mgmt->frame_control); |
759 | 759 | ||
760 | mutex_lock(&local->work_mtx); | 760 | mutex_lock(&local->mtx); |
761 | 761 | ||
762 | list_for_each_entry(wk, &local->work_list, list) { | 762 | list_for_each_entry(wk, &local->work_list, list) { |
763 | const u8 *bssid = NULL; | 763 | const u8 *bssid = NULL; |
@@ -833,7 +833,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
833 | WARN(1, "unexpected: %d", rma); | 833 | WARN(1, "unexpected: %d", rma); |
834 | } | 834 | } |
835 | 835 | ||
836 | mutex_unlock(&local->work_mtx); | 836 | mutex_unlock(&local->mtx); |
837 | 837 | ||
838 | if (rma != WORK_ACT_DONE) | 838 | if (rma != WORK_ACT_DONE) |
839 | goto out; | 839 | goto out; |
@@ -845,9 +845,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
845 | case WORK_DONE_REQUEUE: | 845 | case WORK_DONE_REQUEUE: |
846 | synchronize_rcu(); | 846 | synchronize_rcu(); |
847 | wk->started = false; /* restart */ | 847 | wk->started = false; /* restart */ |
848 | mutex_lock(&local->work_mtx); | 848 | mutex_lock(&local->mtx); |
849 | list_add_tail(&wk->list, &local->work_list); | 849 | list_add_tail(&wk->list, &local->work_list); |
850 | mutex_unlock(&local->work_mtx); | 850 | mutex_unlock(&local->mtx); |
851 | } | 851 | } |
852 | 852 | ||
853 | out: | 853 | out: |
@@ -888,9 +888,9 @@ static void ieee80211_work_work(struct work_struct *work) | |||
888 | while ((skb = skb_dequeue(&local->work_skb_queue))) | 888 | while ((skb = skb_dequeue(&local->work_skb_queue))) |
889 | ieee80211_work_rx_queued_mgmt(local, skb); | 889 | ieee80211_work_rx_queued_mgmt(local, skb); |
890 | 890 | ||
891 | ieee80211_recalc_idle(local); | 891 | mutex_lock(&local->mtx); |
892 | 892 | ||
893 | mutex_lock(&local->work_mtx); | 893 | ieee80211_recalc_idle(local); |
894 | 894 | ||
895 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | 895 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { |
896 | bool started = wk->started; | 896 | bool started = wk->started; |
@@ -995,20 +995,16 @@ static void ieee80211_work_work(struct work_struct *work) | |||
995 | run_again(local, jiffies + HZ/2); | 995 | run_again(local, jiffies + HZ/2); |
996 | } | 996 | } |
997 | 997 | ||
998 | mutex_lock(&local->scan_mtx); | ||
999 | |||
1000 | if (list_empty(&local->work_list) && local->scan_req && | 998 | if (list_empty(&local->work_list) && local->scan_req && |
1001 | !local->scanning) | 999 | !local->scanning) |
1002 | ieee80211_queue_delayed_work(&local->hw, | 1000 | ieee80211_queue_delayed_work(&local->hw, |
1003 | &local->scan_work, | 1001 | &local->scan_work, |
1004 | round_jiffies_relative(0)); | 1002 | round_jiffies_relative(0)); |
1005 | 1003 | ||
1006 | mutex_unlock(&local->scan_mtx); | ||
1007 | |||
1008 | mutex_unlock(&local->work_mtx); | ||
1009 | |||
1010 | ieee80211_recalc_idle(local); | 1004 | ieee80211_recalc_idle(local); |
1011 | 1005 | ||
1006 | mutex_unlock(&local->mtx); | ||
1007 | |||
1012 | list_for_each_entry_safe(wk, tmp, &free_work, list) { | 1008 | list_for_each_entry_safe(wk, tmp, &free_work, list) { |
1013 | wk->done(wk, NULL); | 1009 | wk->done(wk, NULL); |
1014 | list_del(&wk->list); | 1010 | list_del(&wk->list); |
@@ -1035,16 +1031,15 @@ void ieee80211_add_work(struct ieee80211_work *wk) | |||
1035 | wk->started = false; | 1031 | wk->started = false; |
1036 | 1032 | ||
1037 | local = wk->sdata->local; | 1033 | local = wk->sdata->local; |
1038 | mutex_lock(&local->work_mtx); | 1034 | mutex_lock(&local->mtx); |
1039 | list_add_tail(&wk->list, &local->work_list); | 1035 | list_add_tail(&wk->list, &local->work_list); |
1040 | mutex_unlock(&local->work_mtx); | 1036 | mutex_unlock(&local->mtx); |
1041 | 1037 | ||
1042 | ieee80211_queue_work(&local->hw, &local->work_work); | 1038 | ieee80211_queue_work(&local->hw, &local->work_work); |
1043 | } | 1039 | } |
1044 | 1040 | ||
1045 | void ieee80211_work_init(struct ieee80211_local *local) | 1041 | void ieee80211_work_init(struct ieee80211_local *local) |
1046 | { | 1042 | { |
1047 | mutex_init(&local->work_mtx); | ||
1048 | INIT_LIST_HEAD(&local->work_list); | 1043 | INIT_LIST_HEAD(&local->work_list); |
1049 | setup_timer(&local->work_timer, ieee80211_work_timer, | 1044 | setup_timer(&local->work_timer, ieee80211_work_timer, |
1050 | (unsigned long)local); | 1045 | (unsigned long)local); |
@@ -1057,7 +1052,7 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | |||
1057 | struct ieee80211_local *local = sdata->local; | 1052 | struct ieee80211_local *local = sdata->local; |
1058 | struct ieee80211_work *wk; | 1053 | struct ieee80211_work *wk; |
1059 | 1054 | ||
1060 | mutex_lock(&local->work_mtx); | 1055 | mutex_lock(&local->mtx); |
1061 | list_for_each_entry(wk, &local->work_list, list) { | 1056 | list_for_each_entry(wk, &local->work_list, list) { |
1062 | if (wk->sdata != sdata) | 1057 | if (wk->sdata != sdata) |
1063 | continue; | 1058 | continue; |
@@ -1065,19 +1060,19 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | |||
1065 | wk->started = true; | 1060 | wk->started = true; |
1066 | wk->timeout = jiffies; | 1061 | wk->timeout = jiffies; |
1067 | } | 1062 | } |
1068 | mutex_unlock(&local->work_mtx); | 1063 | mutex_unlock(&local->mtx); |
1069 | 1064 | ||
1070 | /* run cleanups etc. */ | 1065 | /* run cleanups etc. */ |
1071 | ieee80211_work_work(&local->work_work); | 1066 | ieee80211_work_work(&local->work_work); |
1072 | 1067 | ||
1073 | mutex_lock(&local->work_mtx); | 1068 | mutex_lock(&local->mtx); |
1074 | list_for_each_entry(wk, &local->work_list, list) { | 1069 | list_for_each_entry(wk, &local->work_list, list) { |
1075 | if (wk->sdata != sdata) | 1070 | if (wk->sdata != sdata) |
1076 | continue; | 1071 | continue; |
1077 | WARN_ON(1); | 1072 | WARN_ON(1); |
1078 | break; | 1073 | break; |
1079 | } | 1074 | } |
1080 | mutex_unlock(&local->work_mtx); | 1075 | mutex_unlock(&local->mtx); |
1081 | } | 1076 | } |
1082 | 1077 | ||
1083 | ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, | 1078 | ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, |
@@ -1163,7 +1158,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, | |||
1163 | struct ieee80211_work *wk, *tmp; | 1158 | struct ieee80211_work *wk, *tmp; |
1164 | bool found = false; | 1159 | bool found = false; |
1165 | 1160 | ||
1166 | mutex_lock(&local->work_mtx); | 1161 | mutex_lock(&local->mtx); |
1167 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | 1162 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { |
1168 | if ((unsigned long) wk == cookie) { | 1163 | if ((unsigned long) wk == cookie) { |
1169 | wk->timeout = jiffies; | 1164 | wk->timeout = jiffies; |
@@ -1171,7 +1166,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, | |||
1171 | break; | 1166 | break; |
1172 | } | 1167 | } |
1173 | } | 1168 | } |
1174 | mutex_unlock(&local->work_mtx); | 1169 | mutex_unlock(&local->mtx); |
1175 | 1170 | ||
1176 | if (!found) | 1171 | if (!found) |
1177 | return -ENOENT; | 1172 | return -ENOENT; |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 8d59d27d887e..43882b36da55 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -36,8 +36,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
36 | int tail; | 36 | int tail; |
37 | 37 | ||
38 | hdr = (struct ieee80211_hdr *)skb->data; | 38 | hdr = (struct ieee80211_hdr *)skb->data; |
39 | if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 || | 39 | if (!tx->key || tx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || |
40 | !ieee80211_is_data_present(hdr->frame_control)) | 40 | skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control)) |
41 | return TX_CONTINUE; | 41 | return TX_CONTINUE; |
42 | 42 | ||
43 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 43 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
@@ -94,7 +94,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
94 | if (status->flag & RX_FLAG_MMIC_STRIPPED) | 94 | if (status->flag & RX_FLAG_MMIC_STRIPPED) |
95 | return RX_CONTINUE; | 95 | return RX_CONTINUE; |
96 | 96 | ||
97 | if (!rx->key || rx->key->conf.alg != ALG_TKIP || | 97 | if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP || |
98 | !ieee80211_has_protected(hdr->frame_control) || | 98 | !ieee80211_has_protected(hdr->frame_control) || |
99 | !ieee80211_is_data_present(hdr->frame_control)) | 99 | !ieee80211_is_data_present(hdr->frame_control)) |
100 | return RX_CONTINUE; | 100 | return RX_CONTINUE; |
@@ -221,19 +221,13 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
221 | if (!rx->sta || skb->len - hdrlen < 12) | 221 | if (!rx->sta || skb->len - hdrlen < 12) |
222 | return RX_DROP_UNUSABLE; | 222 | return RX_DROP_UNUSABLE; |
223 | 223 | ||
224 | if (status->flag & RX_FLAG_DECRYPTED) { | 224 | /* |
225 | if (status->flag & RX_FLAG_IV_STRIPPED) { | 225 | * Let TKIP code verify IV, but skip decryption. |
226 | /* | 226 | * In the case where hardware checks the IV as well, |
227 | * Hardware took care of all processing, including | 227 | * we don't even get here, see ieee80211_rx_h_decrypt() |
228 | * replay protection, and stripped the ICV/IV so | 228 | */ |
229 | * we cannot do any checks here. | 229 | if (status->flag & RX_FLAG_DECRYPTED) |
230 | */ | ||
231 | return RX_CONTINUE; | ||
232 | } | ||
233 | |||
234 | /* let TKIP code verify IV, but skip decryption */ | ||
235 | hwaccel = 1; | 230 | hwaccel = 1; |
236 | } | ||
237 | 231 | ||
238 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, | 232 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, |
239 | key, skb->data + hdrlen, | 233 | key, skb->data + hdrlen, |
@@ -447,10 +441,6 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
447 | if (!rx->sta || data_len < 0) | 441 | if (!rx->sta || data_len < 0) |
448 | return RX_DROP_UNUSABLE; | 442 | return RX_DROP_UNUSABLE; |
449 | 443 | ||
450 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
451 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
452 | return RX_CONTINUE; | ||
453 | |||
454 | ccmp_hdr2pn(pn, skb->data + hdrlen); | 444 | ccmp_hdr2pn(pn, skb->data + hdrlen); |
455 | 445 | ||
456 | queue = ieee80211_is_mgmt(hdr->frame_control) ? | 446 | queue = ieee80211_is_mgmt(hdr->frame_control) ? |
@@ -564,10 +554,6 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) | |||
564 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 554 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
565 | return RX_CONTINUE; | 555 | return RX_CONTINUE; |
566 | 556 | ||
567 | if ((status->flag & RX_FLAG_DECRYPTED) && | ||
568 | (status->flag & RX_FLAG_IV_STRIPPED)) | ||
569 | return RX_CONTINUE; | ||
570 | |||
571 | if (skb->len < 24 + sizeof(*mmie)) | 557 | if (skb->len < 24 + sizeof(*mmie)) |
572 | return RX_DROP_UNUSABLE; | 558 | return RX_DROP_UNUSABLE; |
573 | 559 | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index 541e2fff5e9c..d52630bbab04 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -253,11 +253,16 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, | |||
253 | WARN_ON(err); | 253 | WARN_ON(err); |
254 | wdev->netdev->features |= NETIF_F_NETNS_LOCAL; | 254 | wdev->netdev->features |= NETIF_F_NETNS_LOCAL; |
255 | } | 255 | } |
256 | |||
257 | return err; | ||
256 | } | 258 | } |
257 | 259 | ||
258 | wiphy_net_set(&rdev->wiphy, net); | 260 | wiphy_net_set(&rdev->wiphy, net); |
259 | 261 | ||
260 | return err; | 262 | err = device_rename(&rdev->wiphy.dev, dev_name(&rdev->wiphy.dev)); |
263 | WARN_ON(err); | ||
264 | |||
265 | return 0; | ||
261 | } | 266 | } |
262 | 267 | ||
263 | static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) | 268 | static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) |
@@ -428,7 +433,7 @@ int wiphy_register(struct wiphy *wiphy) | |||
428 | 433 | ||
429 | /* sanity check ifmodes */ | 434 | /* sanity check ifmodes */ |
430 | WARN_ON(!ifmodes); | 435 | WARN_ON(!ifmodes); |
431 | ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; | 436 | ifmodes &= ((1 << NUM_NL80211_IFTYPES) - 1) & ~1; |
432 | if (WARN_ON(ifmodes != wiphy->interface_modes)) | 437 | if (WARN_ON(ifmodes != wiphy->interface_modes)) |
433 | wiphy->interface_modes = ifmodes; | 438 | wiphy->interface_modes = ifmodes; |
434 | 439 | ||
@@ -680,8 +685,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
680 | INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); | 685 | INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); |
681 | INIT_LIST_HEAD(&wdev->event_list); | 686 | INIT_LIST_HEAD(&wdev->event_list); |
682 | spin_lock_init(&wdev->event_lock); | 687 | spin_lock_init(&wdev->event_lock); |
683 | INIT_LIST_HEAD(&wdev->action_registrations); | 688 | INIT_LIST_HEAD(&wdev->mgmt_registrations); |
684 | spin_lock_init(&wdev->action_registrations_lock); | 689 | spin_lock_init(&wdev->mgmt_registrations_lock); |
685 | 690 | ||
686 | mutex_lock(&rdev->devlist_mtx); | 691 | mutex_lock(&rdev->devlist_mtx); |
687 | list_add_rcu(&wdev->list, &rdev->netdev_list); | 692 | list_add_rcu(&wdev->list, &rdev->netdev_list); |
@@ -801,7 +806,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
801 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); | 806 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); |
802 | list_del_rcu(&wdev->list); | 807 | list_del_rcu(&wdev->list); |
803 | rdev->devlist_generation++; | 808 | rdev->devlist_generation++; |
804 | cfg80211_mlme_purge_actions(wdev); | 809 | cfg80211_mlme_purge_registrations(wdev); |
805 | #ifdef CONFIG_CFG80211_WEXT | 810 | #ifdef CONFIG_CFG80211_WEXT |
806 | kfree(wdev->wext.keys); | 811 | kfree(wdev->wext.keys); |
807 | #endif | 812 | #endif |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 63d57ae399c3..58ab2c791d28 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -331,16 +331,17 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
331 | const u8 *resp_ie, size_t resp_ie_len, | 331 | const u8 *resp_ie, size_t resp_ie_len, |
332 | u16 status, bool wextev, | 332 | u16 status, bool wextev, |
333 | struct cfg80211_bss *bss); | 333 | struct cfg80211_bss *bss); |
334 | int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, | 334 | int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, |
335 | const u8 *match_data, int match_len); | 335 | u16 frame_type, const u8 *match_data, |
336 | void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid); | 336 | int match_len); |
337 | void cfg80211_mlme_purge_actions(struct wireless_dev *wdev); | 337 | void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid); |
338 | int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, | 338 | void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); |
339 | struct net_device *dev, | 339 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, |
340 | struct ieee80211_channel *chan, | 340 | struct net_device *dev, |
341 | enum nl80211_channel_type channel_type, | 341 | struct ieee80211_channel *chan, |
342 | bool channel_type_valid, | 342 | enum nl80211_channel_type channel_type, |
343 | const u8 *buf, size_t len, u64 *cookie); | 343 | bool channel_type_valid, |
344 | const u8 *buf, size_t len, u64 *cookie); | ||
344 | 345 | ||
345 | /* SME */ | 346 | /* SME */ |
346 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | 347 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index d1a3fb99fdf2..8515b1e5c578 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -149,7 +149,7 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
149 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | 149 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; |
150 | const u8 *bssid = mgmt->bssid; | 150 | const u8 *bssid = mgmt->bssid; |
151 | int i; | 151 | int i; |
152 | bool found = false; | 152 | bool found = false, was_current = false; |
153 | 153 | ||
154 | ASSERT_WDEV_LOCK(wdev); | 154 | ASSERT_WDEV_LOCK(wdev); |
155 | 155 | ||
@@ -159,6 +159,7 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
159 | cfg80211_put_bss(&wdev->current_bss->pub); | 159 | cfg80211_put_bss(&wdev->current_bss->pub); |
160 | wdev->current_bss = NULL; | 160 | wdev->current_bss = NULL; |
161 | found = true; | 161 | found = true; |
162 | was_current = true; | ||
162 | } else for (i = 0; i < MAX_AUTH_BSSES; i++) { | 163 | } else for (i = 0; i < MAX_AUTH_BSSES; i++) { |
163 | if (wdev->auth_bsses[i] && | 164 | if (wdev->auth_bsses[i] && |
164 | memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { | 165 | memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { |
@@ -183,7 +184,7 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
183 | 184 | ||
184 | nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); | 185 | nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); |
185 | 186 | ||
186 | if (wdev->sme_state == CFG80211_SME_CONNECTED) { | 187 | if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) { |
187 | u16 reason_code; | 188 | u16 reason_code; |
188 | bool from_ap; | 189 | bool from_ap; |
189 | 190 | ||
@@ -747,31 +748,51 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | |||
747 | } | 748 | } |
748 | EXPORT_SYMBOL(cfg80211_new_sta); | 749 | EXPORT_SYMBOL(cfg80211_new_sta); |
749 | 750 | ||
750 | struct cfg80211_action_registration { | 751 | struct cfg80211_mgmt_registration { |
751 | struct list_head list; | 752 | struct list_head list; |
752 | 753 | ||
753 | u32 nlpid; | 754 | u32 nlpid; |
754 | 755 | ||
755 | int match_len; | 756 | int match_len; |
756 | 757 | ||
758 | __le16 frame_type; | ||
759 | |||
757 | u8 match[]; | 760 | u8 match[]; |
758 | }; | 761 | }; |
759 | 762 | ||
760 | int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, | 763 | int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, |
761 | const u8 *match_data, int match_len) | 764 | u16 frame_type, const u8 *match_data, |
765 | int match_len) | ||
762 | { | 766 | { |
763 | struct cfg80211_action_registration *reg, *nreg; | 767 | struct cfg80211_mgmt_registration *reg, *nreg; |
764 | int err = 0; | 768 | int err = 0; |
769 | u16 mgmt_type; | ||
770 | |||
771 | if (!wdev->wiphy->mgmt_stypes) | ||
772 | return -EOPNOTSUPP; | ||
773 | |||
774 | if ((frame_type & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) | ||
775 | return -EINVAL; | ||
776 | |||
777 | if (frame_type & ~(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) | ||
778 | return -EINVAL; | ||
779 | |||
780 | mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4; | ||
781 | if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].rx & BIT(mgmt_type))) | ||
782 | return -EINVAL; | ||
765 | 783 | ||
766 | nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL); | 784 | nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL); |
767 | if (!nreg) | 785 | if (!nreg) |
768 | return -ENOMEM; | 786 | return -ENOMEM; |
769 | 787 | ||
770 | spin_lock_bh(&wdev->action_registrations_lock); | 788 | spin_lock_bh(&wdev->mgmt_registrations_lock); |
771 | 789 | ||
772 | list_for_each_entry(reg, &wdev->action_registrations, list) { | 790 | list_for_each_entry(reg, &wdev->mgmt_registrations, list) { |
773 | int mlen = min(match_len, reg->match_len); | 791 | int mlen = min(match_len, reg->match_len); |
774 | 792 | ||
793 | if (frame_type != le16_to_cpu(reg->frame_type)) | ||
794 | continue; | ||
795 | |||
775 | if (memcmp(reg->match, match_data, mlen) == 0) { | 796 | if (memcmp(reg->match, match_data, mlen) == 0) { |
776 | err = -EALREADY; | 797 | err = -EALREADY; |
777 | break; | 798 | break; |
@@ -786,62 +807,75 @@ int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, | |||
786 | memcpy(nreg->match, match_data, match_len); | 807 | memcpy(nreg->match, match_data, match_len); |
787 | nreg->match_len = match_len; | 808 | nreg->match_len = match_len; |
788 | nreg->nlpid = snd_pid; | 809 | nreg->nlpid = snd_pid; |
789 | list_add(&nreg->list, &wdev->action_registrations); | 810 | nreg->frame_type = cpu_to_le16(frame_type); |
811 | list_add(&nreg->list, &wdev->mgmt_registrations); | ||
790 | 812 | ||
791 | out: | 813 | out: |
792 | spin_unlock_bh(&wdev->action_registrations_lock); | 814 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
793 | return err; | 815 | return err; |
794 | } | 816 | } |
795 | 817 | ||
796 | void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid) | 818 | void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid) |
797 | { | 819 | { |
798 | struct cfg80211_action_registration *reg, *tmp; | 820 | struct cfg80211_mgmt_registration *reg, *tmp; |
799 | 821 | ||
800 | spin_lock_bh(&wdev->action_registrations_lock); | 822 | spin_lock_bh(&wdev->mgmt_registrations_lock); |
801 | 823 | ||
802 | list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { | 824 | list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) { |
803 | if (reg->nlpid == nlpid) { | 825 | if (reg->nlpid == nlpid) { |
804 | list_del(®->list); | 826 | list_del(®->list); |
805 | kfree(reg); | 827 | kfree(reg); |
806 | } | 828 | } |
807 | } | 829 | } |
808 | 830 | ||
809 | spin_unlock_bh(&wdev->action_registrations_lock); | 831 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
810 | } | 832 | } |
811 | 833 | ||
812 | void cfg80211_mlme_purge_actions(struct wireless_dev *wdev) | 834 | void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev) |
813 | { | 835 | { |
814 | struct cfg80211_action_registration *reg, *tmp; | 836 | struct cfg80211_mgmt_registration *reg, *tmp; |
815 | 837 | ||
816 | spin_lock_bh(&wdev->action_registrations_lock); | 838 | spin_lock_bh(&wdev->mgmt_registrations_lock); |
817 | 839 | ||
818 | list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { | 840 | list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) { |
819 | list_del(®->list); | 841 | list_del(®->list); |
820 | kfree(reg); | 842 | kfree(reg); |
821 | } | 843 | } |
822 | 844 | ||
823 | spin_unlock_bh(&wdev->action_registrations_lock); | 845 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
824 | } | 846 | } |
825 | 847 | ||
826 | int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, | 848 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, |
827 | struct net_device *dev, | 849 | struct net_device *dev, |
828 | struct ieee80211_channel *chan, | 850 | struct ieee80211_channel *chan, |
829 | enum nl80211_channel_type channel_type, | 851 | enum nl80211_channel_type channel_type, |
830 | bool channel_type_valid, | 852 | bool channel_type_valid, |
831 | const u8 *buf, size_t len, u64 *cookie) | 853 | const u8 *buf, size_t len, u64 *cookie) |
832 | { | 854 | { |
833 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 855 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
834 | const struct ieee80211_mgmt *mgmt; | 856 | const struct ieee80211_mgmt *mgmt; |
857 | u16 stype; | ||
858 | |||
859 | if (!wdev->wiphy->mgmt_stypes) | ||
860 | return -EOPNOTSUPP; | ||
835 | 861 | ||
836 | if (rdev->ops->action == NULL) | 862 | if (!rdev->ops->mgmt_tx) |
837 | return -EOPNOTSUPP; | 863 | return -EOPNOTSUPP; |
864 | |||
838 | if (len < 24 + 1) | 865 | if (len < 24 + 1) |
839 | return -EINVAL; | 866 | return -EINVAL; |
840 | 867 | ||
841 | mgmt = (const struct ieee80211_mgmt *) buf; | 868 | mgmt = (const struct ieee80211_mgmt *) buf; |
842 | if (!ieee80211_is_action(mgmt->frame_control)) | 869 | |
870 | if (!ieee80211_is_mgmt(mgmt->frame_control)) | ||
843 | return -EINVAL; | 871 | return -EINVAL; |
844 | if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { | 872 | |
873 | stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; | ||
874 | if (!(wdev->wiphy->mgmt_stypes[wdev->iftype].tx & BIT(stype >> 4))) | ||
875 | return -EINVAL; | ||
876 | |||
877 | if (ieee80211_is_action(mgmt->frame_control) && | ||
878 | mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { | ||
845 | /* Verify that we are associated with the destination AP */ | 879 | /* Verify that we are associated with the destination AP */ |
846 | wdev_lock(wdev); | 880 | wdev_lock(wdev); |
847 | 881 | ||
@@ -862,64 +896,75 @@ int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, | |||
862 | return -EINVAL; | 896 | return -EINVAL; |
863 | 897 | ||
864 | /* Transmit the Action frame as requested by user space */ | 898 | /* Transmit the Action frame as requested by user space */ |
865 | return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type, | 899 | return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, channel_type, |
866 | channel_type_valid, buf, len, cookie); | 900 | channel_type_valid, buf, len, cookie); |
867 | } | 901 | } |
868 | 902 | ||
869 | bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, | 903 | bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, |
870 | size_t len, gfp_t gfp) | 904 | size_t len, gfp_t gfp) |
871 | { | 905 | { |
872 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 906 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
873 | struct wiphy *wiphy = wdev->wiphy; | 907 | struct wiphy *wiphy = wdev->wiphy; |
874 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 908 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
875 | struct cfg80211_action_registration *reg; | 909 | struct cfg80211_mgmt_registration *reg; |
876 | const u8 *action_data; | 910 | const struct ieee80211_txrx_stypes *stypes = |
877 | int action_data_len; | 911 | &wiphy->mgmt_stypes[wdev->iftype]; |
912 | struct ieee80211_mgmt *mgmt = (void *)buf; | ||
913 | const u8 *data; | ||
914 | int data_len; | ||
878 | bool result = false; | 915 | bool result = false; |
916 | __le16 ftype = mgmt->frame_control & | ||
917 | cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE); | ||
918 | u16 stype; | ||
879 | 919 | ||
880 | /* frame length - min size excluding category */ | 920 | stype = (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) >> 4; |
881 | action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1); | ||
882 | 921 | ||
883 | /* action data starts with category */ | 922 | if (!(stypes->rx & BIT(stype))) |
884 | action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1; | 923 | return false; |
885 | 924 | ||
886 | spin_lock_bh(&wdev->action_registrations_lock); | 925 | data = buf + ieee80211_hdrlen(mgmt->frame_control); |
926 | data_len = len - ieee80211_hdrlen(mgmt->frame_control); | ||
927 | |||
928 | spin_lock_bh(&wdev->mgmt_registrations_lock); | ||
929 | |||
930 | list_for_each_entry(reg, &wdev->mgmt_registrations, list) { | ||
931 | if (reg->frame_type != ftype) | ||
932 | continue; | ||
887 | 933 | ||
888 | list_for_each_entry(reg, &wdev->action_registrations, list) { | 934 | if (reg->match_len > data_len) |
889 | if (reg->match_len > action_data_len) | ||
890 | continue; | 935 | continue; |
891 | 936 | ||
892 | if (memcmp(reg->match, action_data, reg->match_len)) | 937 | if (memcmp(reg->match, data, reg->match_len)) |
893 | continue; | 938 | continue; |
894 | 939 | ||
895 | /* found match! */ | 940 | /* found match! */ |
896 | 941 | ||
897 | /* Indicate the received Action frame to user space */ | 942 | /* Indicate the received Action frame to user space */ |
898 | if (nl80211_send_action(rdev, dev, reg->nlpid, freq, | 943 | if (nl80211_send_mgmt(rdev, dev, reg->nlpid, freq, |
899 | buf, len, gfp)) | 944 | buf, len, gfp)) |
900 | continue; | 945 | continue; |
901 | 946 | ||
902 | result = true; | 947 | result = true; |
903 | break; | 948 | break; |
904 | } | 949 | } |
905 | 950 | ||
906 | spin_unlock_bh(&wdev->action_registrations_lock); | 951 | spin_unlock_bh(&wdev->mgmt_registrations_lock); |
907 | 952 | ||
908 | return result; | 953 | return result; |
909 | } | 954 | } |
910 | EXPORT_SYMBOL(cfg80211_rx_action); | 955 | EXPORT_SYMBOL(cfg80211_rx_mgmt); |
911 | 956 | ||
912 | void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, | 957 | void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie, |
913 | const u8 *buf, size_t len, bool ack, gfp_t gfp) | 958 | const u8 *buf, size_t len, bool ack, gfp_t gfp) |
914 | { | 959 | { |
915 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 960 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
916 | struct wiphy *wiphy = wdev->wiphy; | 961 | struct wiphy *wiphy = wdev->wiphy; |
917 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 962 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
918 | 963 | ||
919 | /* Indicate TX status of the Action frame to user space */ | 964 | /* Indicate TX status of the Action frame to user space */ |
920 | nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp); | 965 | nl80211_send_mgmt_tx_status(rdev, dev, cookie, buf, len, ack, gfp); |
921 | } | 966 | } |
922 | EXPORT_SYMBOL(cfg80211_action_tx_status); | 967 | EXPORT_SYMBOL(cfg80211_mgmt_tx_status); |
923 | 968 | ||
924 | void cfg80211_cqm_rssi_notify(struct net_device *dev, | 969 | void cfg80211_cqm_rssi_notify(struct net_device *dev, |
925 | enum nl80211_cqm_rssi_threshold_event rssi_event, | 970 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 37902a54e9c1..927ffbd2aebc 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -156,6 +156,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
156 | 156 | ||
157 | [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, | 157 | [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, |
158 | [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, | 158 | [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, |
159 | [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, | ||
159 | }; | 160 | }; |
160 | 161 | ||
161 | /* policy for the attributes */ | 162 | /* policy for the attributes */ |
@@ -437,6 +438,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
437 | struct ieee80211_rate *rate; | 438 | struct ieee80211_rate *rate; |
438 | int i; | 439 | int i; |
439 | u16 ifmodes = dev->wiphy.interface_modes; | 440 | u16 ifmodes = dev->wiphy.interface_modes; |
441 | const struct ieee80211_txrx_stypes *mgmt_stypes = | ||
442 | dev->wiphy.mgmt_stypes; | ||
440 | 443 | ||
441 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); | 444 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); |
442 | if (!hdr) | 445 | if (!hdr) |
@@ -587,7 +590,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
587 | CMD(flush_pmksa, FLUSH_PMKSA); | 590 | CMD(flush_pmksa, FLUSH_PMKSA); |
588 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); | 591 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); |
589 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); | 592 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); |
590 | CMD(action, ACTION); | 593 | CMD(mgmt_tx, FRAME); |
591 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { | 594 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { |
592 | i++; | 595 | i++; |
593 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); | 596 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); |
@@ -608,6 +611,53 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
608 | 611 | ||
609 | nla_nest_end(msg, nl_cmds); | 612 | nla_nest_end(msg, nl_cmds); |
610 | 613 | ||
614 | if (mgmt_stypes) { | ||
615 | u16 stypes; | ||
616 | struct nlattr *nl_ftypes, *nl_ifs; | ||
617 | enum nl80211_iftype ift; | ||
618 | |||
619 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_TX_FRAME_TYPES); | ||
620 | if (!nl_ifs) | ||
621 | goto nla_put_failure; | ||
622 | |||
623 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | ||
624 | nl_ftypes = nla_nest_start(msg, ift); | ||
625 | if (!nl_ftypes) | ||
626 | goto nla_put_failure; | ||
627 | i = 0; | ||
628 | stypes = mgmt_stypes[ift].tx; | ||
629 | while (stypes) { | ||
630 | if (stypes & 1) | ||
631 | NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, | ||
632 | (i << 4) | IEEE80211_FTYPE_MGMT); | ||
633 | stypes >>= 1; | ||
634 | i++; | ||
635 | } | ||
636 | nla_nest_end(msg, nl_ftypes); | ||
637 | } | ||
638 | |||
639 | nl_ifs = nla_nest_start(msg, NL80211_ATTR_RX_FRAME_TYPES); | ||
640 | if (!nl_ifs) | ||
641 | goto nla_put_failure; | ||
642 | |||
643 | for (ift = 0; ift < NUM_NL80211_IFTYPES; ift++) { | ||
644 | nl_ftypes = nla_nest_start(msg, ift); | ||
645 | if (!nl_ftypes) | ||
646 | goto nla_put_failure; | ||
647 | i = 0; | ||
648 | stypes = mgmt_stypes[ift].rx; | ||
649 | while (stypes) { | ||
650 | if (stypes & 1) | ||
651 | NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, | ||
652 | (i << 4) | IEEE80211_FTYPE_MGMT); | ||
653 | stypes >>= 1; | ||
654 | i++; | ||
655 | } | ||
656 | nla_nest_end(msg, nl_ftypes); | ||
657 | } | ||
658 | nla_nest_end(msg, nl_ifs); | ||
659 | } | ||
660 | |||
611 | return genlmsg_end(msg, hdr); | 661 | return genlmsg_end(msg, hdr); |
612 | 662 | ||
613 | nla_put_failure: | 663 | nla_put_failure: |
@@ -3572,6 +3622,21 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3572 | if (err) | 3622 | if (err) |
3573 | goto unlock_rtnl; | 3623 | goto unlock_rtnl; |
3574 | 3624 | ||
3625 | if (key.idx >= 0) { | ||
3626 | int i; | ||
3627 | bool ok = false; | ||
3628 | for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) { | ||
3629 | if (key.p.cipher == rdev->wiphy.cipher_suites[i]) { | ||
3630 | ok = true; | ||
3631 | break; | ||
3632 | } | ||
3633 | } | ||
3634 | if (!ok) { | ||
3635 | err = -EINVAL; | ||
3636 | goto out; | ||
3637 | } | ||
3638 | } | ||
3639 | |||
3575 | if (!rdev->ops->auth) { | 3640 | if (!rdev->ops->auth) { |
3576 | err = -EOPNOTSUPP; | 3641 | err = -EOPNOTSUPP; |
3577 | goto out; | 3642 | goto out; |
@@ -4717,17 +4782,18 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
4717 | return err; | 4782 | return err; |
4718 | } | 4783 | } |
4719 | 4784 | ||
4720 | static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | 4785 | static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) |
4721 | { | 4786 | { |
4722 | struct cfg80211_registered_device *rdev; | 4787 | struct cfg80211_registered_device *rdev; |
4723 | struct net_device *dev; | 4788 | struct net_device *dev; |
4789 | u16 frame_type = IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION; | ||
4724 | int err; | 4790 | int err; |
4725 | 4791 | ||
4726 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) | 4792 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) |
4727 | return -EINVAL; | 4793 | return -EINVAL; |
4728 | 4794 | ||
4729 | if (nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]) < 1) | 4795 | if (info->attrs[NL80211_ATTR_FRAME_TYPE]) |
4730 | return -EINVAL; | 4796 | frame_type = nla_get_u16(info->attrs[NL80211_ATTR_FRAME_TYPE]); |
4731 | 4797 | ||
4732 | rtnl_lock(); | 4798 | rtnl_lock(); |
4733 | 4799 | ||
@@ -4742,12 +4808,13 @@ static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | |||
4742 | } | 4808 | } |
4743 | 4809 | ||
4744 | /* not much point in registering if we can't reply */ | 4810 | /* not much point in registering if we can't reply */ |
4745 | if (!rdev->ops->action) { | 4811 | if (!rdev->ops->mgmt_tx) { |
4746 | err = -EOPNOTSUPP; | 4812 | err = -EOPNOTSUPP; |
4747 | goto out; | 4813 | goto out; |
4748 | } | 4814 | } |
4749 | 4815 | ||
4750 | err = cfg80211_mlme_register_action(dev->ieee80211_ptr, info->snd_pid, | 4816 | err = cfg80211_mlme_register_mgmt(dev->ieee80211_ptr, info->snd_pid, |
4817 | frame_type, | ||
4751 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), | 4818 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), |
4752 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); | 4819 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); |
4753 | out: | 4820 | out: |
@@ -4758,7 +4825,7 @@ static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | |||
4758 | return err; | 4825 | return err; |
4759 | } | 4826 | } |
4760 | 4827 | ||
4761 | static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | 4828 | static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) |
4762 | { | 4829 | { |
4763 | struct cfg80211_registered_device *rdev; | 4830 | struct cfg80211_registered_device *rdev; |
4764 | struct net_device *dev; | 4831 | struct net_device *dev; |
@@ -4781,7 +4848,7 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | |||
4781 | if (err) | 4848 | if (err) |
4782 | goto unlock_rtnl; | 4849 | goto unlock_rtnl; |
4783 | 4850 | ||
4784 | if (!rdev->ops->action) { | 4851 | if (!rdev->ops->mgmt_tx) { |
4785 | err = -EOPNOTSUPP; | 4852 | err = -EOPNOTSUPP; |
4786 | goto out; | 4853 | goto out; |
4787 | } | 4854 | } |
@@ -4824,17 +4891,17 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | |||
4824 | } | 4891 | } |
4825 | 4892 | ||
4826 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 4893 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
4827 | NL80211_CMD_ACTION); | 4894 | NL80211_CMD_FRAME); |
4828 | 4895 | ||
4829 | if (IS_ERR(hdr)) { | 4896 | if (IS_ERR(hdr)) { |
4830 | err = PTR_ERR(hdr); | 4897 | err = PTR_ERR(hdr); |
4831 | goto free_msg; | 4898 | goto free_msg; |
4832 | } | 4899 | } |
4833 | err = cfg80211_mlme_action(rdev, dev, chan, channel_type, | 4900 | err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, channel_type, |
4834 | channel_type_valid, | 4901 | channel_type_valid, |
4835 | nla_data(info->attrs[NL80211_ATTR_FRAME]), | 4902 | nla_data(info->attrs[NL80211_ATTR_FRAME]), |
4836 | nla_len(info->attrs[NL80211_ATTR_FRAME]), | 4903 | nla_len(info->attrs[NL80211_ATTR_FRAME]), |
4837 | &cookie); | 4904 | &cookie); |
4838 | if (err) | 4905 | if (err) |
4839 | goto free_msg; | 4906 | goto free_msg; |
4840 | 4907 | ||
@@ -5333,14 +5400,14 @@ static struct genl_ops nl80211_ops[] = { | |||
5333 | .flags = GENL_ADMIN_PERM, | 5400 | .flags = GENL_ADMIN_PERM, |
5334 | }, | 5401 | }, |
5335 | { | 5402 | { |
5336 | .cmd = NL80211_CMD_REGISTER_ACTION, | 5403 | .cmd = NL80211_CMD_REGISTER_FRAME, |
5337 | .doit = nl80211_register_action, | 5404 | .doit = nl80211_register_mgmt, |
5338 | .policy = nl80211_policy, | 5405 | .policy = nl80211_policy, |
5339 | .flags = GENL_ADMIN_PERM, | 5406 | .flags = GENL_ADMIN_PERM, |
5340 | }, | 5407 | }, |
5341 | { | 5408 | { |
5342 | .cmd = NL80211_CMD_ACTION, | 5409 | .cmd = NL80211_CMD_FRAME, |
5343 | .doit = nl80211_action, | 5410 | .doit = nl80211_tx_mgmt, |
5344 | .policy = nl80211_policy, | 5411 | .policy = nl80211_policy, |
5345 | .flags = GENL_ADMIN_PERM, | 5412 | .flags = GENL_ADMIN_PERM, |
5346 | }, | 5413 | }, |
@@ -6040,9 +6107,9 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
6040 | nl80211_mlme_mcgrp.id, gfp); | 6107 | nl80211_mlme_mcgrp.id, gfp); |
6041 | } | 6108 | } |
6042 | 6109 | ||
6043 | int nl80211_send_action(struct cfg80211_registered_device *rdev, | 6110 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
6044 | struct net_device *netdev, u32 nlpid, | 6111 | struct net_device *netdev, u32 nlpid, |
6045 | int freq, const u8 *buf, size_t len, gfp_t gfp) | 6112 | int freq, const u8 *buf, size_t len, gfp_t gfp) |
6046 | { | 6113 | { |
6047 | struct sk_buff *msg; | 6114 | struct sk_buff *msg; |
6048 | void *hdr; | 6115 | void *hdr; |
@@ -6052,7 +6119,7 @@ int nl80211_send_action(struct cfg80211_registered_device *rdev, | |||
6052 | if (!msg) | 6119 | if (!msg) |
6053 | return -ENOMEM; | 6120 | return -ENOMEM; |
6054 | 6121 | ||
6055 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION); | 6122 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME); |
6056 | if (!hdr) { | 6123 | if (!hdr) { |
6057 | nlmsg_free(msg); | 6124 | nlmsg_free(msg); |
6058 | return -ENOMEM; | 6125 | return -ENOMEM; |
@@ -6080,10 +6147,10 @@ int nl80211_send_action(struct cfg80211_registered_device *rdev, | |||
6080 | return -ENOBUFS; | 6147 | return -ENOBUFS; |
6081 | } | 6148 | } |
6082 | 6149 | ||
6083 | void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | 6150 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, |
6084 | struct net_device *netdev, u64 cookie, | 6151 | struct net_device *netdev, u64 cookie, |
6085 | const u8 *buf, size_t len, bool ack, | 6152 | const u8 *buf, size_t len, bool ack, |
6086 | gfp_t gfp) | 6153 | gfp_t gfp) |
6087 | { | 6154 | { |
6088 | struct sk_buff *msg; | 6155 | struct sk_buff *msg; |
6089 | void *hdr; | 6156 | void *hdr; |
@@ -6092,7 +6159,7 @@ void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | |||
6092 | if (!msg) | 6159 | if (!msg) |
6093 | return; | 6160 | return; |
6094 | 6161 | ||
6095 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION_TX_STATUS); | 6162 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME_TX_STATUS); |
6096 | if (!hdr) { | 6163 | if (!hdr) { |
6097 | nlmsg_free(msg); | 6164 | nlmsg_free(msg); |
6098 | return; | 6165 | return; |
@@ -6179,7 +6246,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb, | |||
6179 | 6246 | ||
6180 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) | 6247 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) |
6181 | list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) | 6248 | list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) |
6182 | cfg80211_mlme_unregister_actions(wdev, notify->pid); | 6249 | cfg80211_mlme_unregister_socket(wdev, notify->pid); |
6183 | 6250 | ||
6184 | rcu_read_unlock(); | 6251 | rcu_read_unlock(); |
6185 | 6252 | ||
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 2ad7fbc7d9f1..30d2f939150d 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -74,13 +74,13 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
74 | struct net_device *dev, const u8 *mac_addr, | 74 | struct net_device *dev, const u8 *mac_addr, |
75 | struct station_info *sinfo, gfp_t gfp); | 75 | struct station_info *sinfo, gfp_t gfp); |
76 | 76 | ||
77 | int nl80211_send_action(struct cfg80211_registered_device *rdev, | 77 | int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, |
78 | struct net_device *netdev, u32 nlpid, int freq, | 78 | struct net_device *netdev, u32 nlpid, int freq, |
79 | const u8 *buf, size_t len, gfp_t gfp); | 79 | const u8 *buf, size_t len, gfp_t gfp); |
80 | void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | 80 | void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, |
81 | struct net_device *netdev, u64 cookie, | 81 | struct net_device *netdev, u64 cookie, |
82 | const u8 *buf, size_t len, bool ack, | 82 | const u8 *buf, size_t len, bool ack, |
83 | gfp_t gfp); | 83 | gfp_t gfp); |
84 | 84 | ||
85 | void | 85 | void |
86 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, | 86 | nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f180db0de66c..b0d9a08447c9 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/list.h> | 37 | #include <linux/list.h> |
38 | #include <linux/random.h> | 38 | #include <linux/random.h> |
39 | #include <linux/ctype.h> | ||
39 | #include <linux/nl80211.h> | 40 | #include <linux/nl80211.h> |
40 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
41 | #include <net/cfg80211.h> | 42 | #include <net/cfg80211.h> |
@@ -181,14 +182,6 @@ static bool is_alpha2_set(const char *alpha2) | |||
181 | return false; | 182 | return false; |
182 | } | 183 | } |
183 | 184 | ||
184 | static bool is_alpha_upper(char letter) | ||
185 | { | ||
186 | /* ASCII A - Z */ | ||
187 | if (letter >= 65 && letter <= 90) | ||
188 | return true; | ||
189 | return false; | ||
190 | } | ||
191 | |||
192 | static bool is_unknown_alpha2(const char *alpha2) | 185 | static bool is_unknown_alpha2(const char *alpha2) |
193 | { | 186 | { |
194 | if (!alpha2) | 187 | if (!alpha2) |
@@ -220,7 +213,7 @@ static bool is_an_alpha2(const char *alpha2) | |||
220 | { | 213 | { |
221 | if (!alpha2) | 214 | if (!alpha2) |
222 | return false; | 215 | return false; |
223 | if (is_alpha_upper(alpha2[0]) && is_alpha_upper(alpha2[1])) | 216 | if (isalpha(alpha2[0]) && isalpha(alpha2[1])) |
224 | return true; | 217 | return true; |
225 | return false; | 218 | return false; |
226 | } | 219 | } |
@@ -1399,6 +1392,11 @@ static DECLARE_WORK(reg_work, reg_todo); | |||
1399 | 1392 | ||
1400 | static void queue_regulatory_request(struct regulatory_request *request) | 1393 | static void queue_regulatory_request(struct regulatory_request *request) |
1401 | { | 1394 | { |
1395 | if (isalpha(request->alpha2[0])) | ||
1396 | request->alpha2[0] = toupper(request->alpha2[0]); | ||
1397 | if (isalpha(request->alpha2[1])) | ||
1398 | request->alpha2[1] = toupper(request->alpha2[1]); | ||
1399 | |||
1402 | spin_lock(®_requests_lock); | 1400 | spin_lock(®_requests_lock); |
1403 | list_add_tail(&request->list, ®_requests_list); | 1401 | list_add_tail(&request->list, ®_requests_list); |
1404 | spin_unlock(®_requests_lock); | 1402 | spin_unlock(®_requests_lock); |
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 9f2cef3e0ca0..74a9e3cce452 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c | |||
@@ -110,6 +110,13 @@ static int wiphy_resume(struct device *dev) | |||
110 | return ret; | 110 | return ret; |
111 | } | 111 | } |
112 | 112 | ||
113 | static const void *wiphy_namespace(struct device *d) | ||
114 | { | ||
115 | struct wiphy *wiphy = container_of(d, struct wiphy, dev); | ||
116 | |||
117 | return wiphy_net(wiphy); | ||
118 | } | ||
119 | |||
113 | struct class ieee80211_class = { | 120 | struct class ieee80211_class = { |
114 | .name = "ieee80211", | 121 | .name = "ieee80211", |
115 | .owner = THIS_MODULE, | 122 | .owner = THIS_MODULE, |
@@ -120,6 +127,8 @@ struct class ieee80211_class = { | |||
120 | #endif | 127 | #endif |
121 | .suspend = wiphy_suspend, | 128 | .suspend = wiphy_suspend, |
122 | .resume = wiphy_resume, | 129 | .resume = wiphy_resume, |
130 | .ns_type = &net_ns_type_operations, | ||
131 | .namespace = wiphy_namespace, | ||
123 | }; | 132 | }; |
124 | 133 | ||
125 | int wiphy_sysfs_init(void) | 134 | int wiphy_sysfs_init(void) |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 0c8a1e8b7690..8d961cc4ae98 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -221,7 +221,7 @@ const unsigned char bridge_tunnel_header[] __aligned(2) = | |||
221 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; | 221 | { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; |
222 | EXPORT_SYMBOL(bridge_tunnel_header); | 222 | EXPORT_SYMBOL(bridge_tunnel_header); |
223 | 223 | ||
224 | unsigned int ieee80211_hdrlen(__le16 fc) | 224 | unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc) |
225 | { | 225 | { |
226 | unsigned int hdrlen = 24; | 226 | unsigned int hdrlen = 24; |
227 | 227 | ||
@@ -823,7 +823,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
823 | /* monitor can't bridge anyway */ | 823 | /* monitor can't bridge anyway */ |
824 | break; | 824 | break; |
825 | case NL80211_IFTYPE_UNSPECIFIED: | 825 | case NL80211_IFTYPE_UNSPECIFIED: |
826 | case __NL80211_IFTYPE_AFTER_LAST: | 826 | case NUM_NL80211_IFTYPES: |
827 | /* not happening */ | 827 | /* not happening */ |
828 | break; | 828 | break; |
829 | } | 829 | } |