diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-10-17 15:05:26 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-10-17 15:05:26 -0400 |
commit | 41ebe9cde738a972d05c7282e09f5ed54cff0e8d (patch) | |
tree | 223bf0feb7305e46989b60c3f070bef87d5fcab4 /net | |
parent | fd38f734cb8200529e281338514945fcbff2364b (diff) | |
parent | 5c1381ac3f3f49ab1e0886ea8f1432c9a5def519 (diff) |
Merge branch 'master' of git://git.infradead.org/users/linville/wireless-next into for-davem
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 22 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 15 | ||||
-rw-r--r-- | net/mac80211/main.c | 6 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 9 | ||||
-rw-r--r-- | net/mac80211/scan.c | 1 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 6 | ||||
-rw-r--r-- | net/mac80211/status.c | 137 | ||||
-rw-r--r-- | net/mac80211/tx.c | 360 | ||||
-rw-r--r-- | net/mac80211/work.c | 2 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 3 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 4 |
11 files changed, 292 insertions, 273 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 55ee5a31756f..ebd7fb101fbf 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -344,7 +344,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
344 | STATION_INFO_RX_BITRATE | | 344 | STATION_INFO_RX_BITRATE | |
345 | STATION_INFO_RX_DROP_MISC | | 345 | STATION_INFO_RX_DROP_MISC | |
346 | STATION_INFO_BSS_PARAM | | 346 | STATION_INFO_BSS_PARAM | |
347 | STATION_INFO_CONNECTED_TIME; | 347 | STATION_INFO_CONNECTED_TIME | |
348 | STATION_INFO_STA_FLAGS; | ||
348 | 349 | ||
349 | do_posix_clock_monotonic_gettime(&uptime); | 350 | do_posix_clock_monotonic_gettime(&uptime); |
350 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; | 351 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; |
@@ -404,6 +405,23 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
404 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; | 405 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; |
405 | sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period; | 406 | sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period; |
406 | sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; | 407 | sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; |
408 | |||
409 | sinfo->sta_flags.set = 0; | ||
410 | sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
411 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | ||
412 | BIT(NL80211_STA_FLAG_WME) | | ||
413 | BIT(NL80211_STA_FLAG_MFP) | | ||
414 | BIT(NL80211_STA_FLAG_AUTHENTICATED); | ||
415 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
416 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED); | ||
417 | if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE)) | ||
418 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE); | ||
419 | if (test_sta_flag(sta, WLAN_STA_WME)) | ||
420 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME); | ||
421 | if (test_sta_flag(sta, WLAN_STA_MFP)) | ||
422 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP); | ||
423 | if (test_sta_flag(sta, WLAN_STA_AUTH)) | ||
424 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); | ||
407 | } | 425 | } |
408 | 426 | ||
409 | 427 | ||
@@ -1886,7 +1904,7 @@ ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) | |||
1886 | * so in that case userspace will have to deal with it. | 1904 | * so in that case userspace will have to deal with it. |
1887 | */ | 1905 | */ |
1888 | 1906 | ||
1889 | if (wk->offchan_tx.wait && wk->offchan_tx.frame) | 1907 | if (wk->offchan_tx.wait && !wk->offchan_tx.status) |
1890 | cfg80211_mgmt_tx_status(wk->sdata->dev, | 1908 | cfg80211_mgmt_tx_status(wk->sdata->dev, |
1891 | (unsigned long) wk->offchan_tx.frame, | 1909 | (unsigned long) wk->offchan_tx.frame, |
1892 | wk->ie, wk->ie_len, false, GFP_KERNEL); | 1910 | wk->ie, wk->ie_len, false, GFP_KERNEL); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9fa5f8a674bc..4c3d1f591bec 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -136,7 +136,6 @@ typedef unsigned __bitwise__ ieee80211_tx_result; | |||
136 | #define TX_DROP ((__force ieee80211_tx_result) 1u) | 136 | #define TX_DROP ((__force ieee80211_tx_result) 1u) |
137 | #define TX_QUEUED ((__force ieee80211_tx_result) 2u) | 137 | #define TX_QUEUED ((__force ieee80211_tx_result) 2u) |
138 | 138 | ||
139 | #define IEEE80211_TX_FRAGMENTED BIT(0) | ||
140 | #define IEEE80211_TX_UNICAST BIT(1) | 139 | #define IEEE80211_TX_UNICAST BIT(1) |
141 | #define IEEE80211_TX_PS_BUFFERED BIT(2) | 140 | #define IEEE80211_TX_PS_BUFFERED BIT(2) |
142 | 141 | ||
@@ -149,7 +148,6 @@ struct ieee80211_tx_data { | |||
149 | 148 | ||
150 | struct ieee80211_channel *channel; | 149 | struct ieee80211_channel *channel; |
151 | 150 | ||
152 | u16 ethertype; | ||
153 | unsigned int flags; | 151 | unsigned int flags; |
154 | }; | 152 | }; |
155 | 153 | ||
@@ -346,6 +344,7 @@ struct ieee80211_work { | |||
346 | struct { | 344 | struct { |
347 | struct sk_buff *frame; | 345 | struct sk_buff *frame; |
348 | u32 wait; | 346 | u32 wait; |
347 | bool status; | ||
349 | } offchan_tx; | 348 | } offchan_tx; |
350 | }; | 349 | }; |
351 | 350 | ||
@@ -1178,18 +1177,6 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1178 | netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | 1177 | netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, |
1179 | struct net_device *dev); | 1178 | struct net_device *dev); |
1180 | 1179 | ||
1181 | /* | ||
1182 | * radiotap header for status frames | ||
1183 | */ | ||
1184 | struct ieee80211_tx_status_rtap_hdr { | ||
1185 | struct ieee80211_radiotap_header hdr; | ||
1186 | u8 rate; | ||
1187 | u8 padding_for_rate; | ||
1188 | __le16 tx_flags; | ||
1189 | u8 data_retries; | ||
1190 | } __packed; | ||
1191 | |||
1192 | |||
1193 | /* HT */ | 1180 | /* HT */ |
1194 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | 1181 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, |
1195 | struct ieee80211_ht_cap *ht_cap_ie, | 1182 | struct ieee80211_ht_cap *ht_cap_ie, |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 17b038aeac9b..d4ee6d234a78 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -904,12 +904,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
904 | * and we need some headroom for passing the frame to monitor | 904 | * and we need some headroom for passing the frame to monitor |
905 | * interfaces, but never both at the same time. | 905 | * interfaces, but never both at the same time. |
906 | */ | 906 | */ |
907 | #ifndef __CHECKER__ | ||
908 | BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM != | ||
909 | sizeof(struct ieee80211_tx_status_rtap_hdr)); | ||
910 | #endif | ||
911 | local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, | 907 | local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, |
912 | sizeof(struct ieee80211_tx_status_rtap_hdr)); | 908 | IEEE80211_TX_STATUS_HEADROOM); |
913 | 909 | ||
914 | debugfs_hw_add(local); | 910 | debugfs_hw_add(local); |
915 | 911 | ||
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 6df7913d7ca4..174040a42887 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -789,11 +789,20 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, | |||
789 | struct ieee802_11_elems elems; | 789 | struct ieee802_11_elems elems; |
790 | size_t baselen; | 790 | size_t baselen; |
791 | u32 last_hop_metric; | 791 | u32 last_hop_metric; |
792 | struct sta_info *sta; | ||
792 | 793 | ||
793 | /* need action_code */ | 794 | /* need action_code */ |
794 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | 795 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) |
795 | return; | 796 | return; |
796 | 797 | ||
798 | rcu_read_lock(); | ||
799 | sta = sta_info_get(sdata, mgmt->sa); | ||
800 | if (!sta || sta->plink_state != NL80211_PLINK_ESTAB) { | ||
801 | rcu_read_unlock(); | ||
802 | return; | ||
803 | } | ||
804 | rcu_read_unlock(); | ||
805 | |||
797 | baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; | 806 | baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; |
798 | ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, | 807 | ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, |
799 | len - baselen, &elems); | 808 | len - baselen, &elems); |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 830e60f65779..397343a59275 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -254,6 +254,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
254 | req->ie, req->ie_len, band, | 254 | req->ie, req->ie_len, band, |
255 | req->rates[band], 0); | 255 | req->rates[band], 0); |
256 | local->hw_scan_req->ie_len = ielen; | 256 | local->hw_scan_req->ie_len = ielen; |
257 | local->hw_scan_req->no_cck = req->no_cck; | ||
257 | 258 | ||
258 | return true; | 259 | return true; |
259 | } | 260 | } |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 58b1c2bb26d2..ce962d2c8782 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -1203,11 +1203,9 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, | |||
1203 | memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); | 1203 | memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); |
1204 | memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN); | 1204 | memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN); |
1205 | 1205 | ||
1206 | skb->priority = tid; | ||
1207 | skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); | ||
1206 | if (qos) { | 1208 | if (qos) { |
1207 | skb->priority = tid; | ||
1208 | |||
1209 | skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); | ||
1210 | |||
1211 | nullfunc->qos_ctrl = cpu_to_le16(tid); | 1209 | nullfunc->qos_ctrl = cpu_to_le16(tid); |
1212 | 1210 | ||
1213 | if (reason == IEEE80211_FRAME_RELEASE_UAPSD) | 1211 | if (reason == IEEE80211_FRAME_RELEASE_UAPSD) |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 864a9c3bcf46..df643cedf9b9 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -228,6 +228,102 @@ static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn) | |||
228 | tid_tx->bar_pending = true; | 228 | tid_tx->bar_pending = true; |
229 | } | 229 | } |
230 | 230 | ||
231 | static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info) | ||
232 | { | ||
233 | int len = sizeof(struct ieee80211_radiotap_header); | ||
234 | |||
235 | /* IEEE80211_RADIOTAP_RATE rate */ | ||
236 | if (info->status.rates[0].idx >= 0 && | ||
237 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) | ||
238 | len += 2; | ||
239 | |||
240 | /* IEEE80211_RADIOTAP_TX_FLAGS */ | ||
241 | len += 2; | ||
242 | |||
243 | /* IEEE80211_RADIOTAP_DATA_RETRIES */ | ||
244 | len += 1; | ||
245 | |||
246 | /* IEEE80211_TX_RC_MCS */ | ||
247 | if (info->status.rates[0].idx >= 0 && | ||
248 | info->status.rates[0].flags & IEEE80211_TX_RC_MCS) | ||
249 | len += 3; | ||
250 | |||
251 | return len; | ||
252 | } | ||
253 | |||
254 | static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band | ||
255 | *sband, struct sk_buff *skb, | ||
256 | int retry_count, int rtap_len) | ||
257 | { | ||
258 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
259 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
260 | struct ieee80211_radiotap_header *rthdr; | ||
261 | unsigned char *pos; | ||
262 | __le16 txflags; | ||
263 | |||
264 | rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len); | ||
265 | |||
266 | memset(rthdr, 0, rtap_len); | ||
267 | rthdr->it_len = cpu_to_le16(rtap_len); | ||
268 | rthdr->it_present = | ||
269 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | | ||
270 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); | ||
271 | pos = (unsigned char *)(rthdr + 1); | ||
272 | |||
273 | /* | ||
274 | * XXX: Once radiotap gets the bitmap reset thing the vendor | ||
275 | * extensions proposal contains, we can actually report | ||
276 | * the whole set of tries we did. | ||
277 | */ | ||
278 | |||
279 | /* IEEE80211_RADIOTAP_RATE */ | ||
280 | if (info->status.rates[0].idx >= 0 && | ||
281 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) { | ||
282 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); | ||
283 | *pos = sband->bitrates[info->status.rates[0].idx].bitrate / 5; | ||
284 | /* padding for tx flags */ | ||
285 | pos += 2; | ||
286 | } | ||
287 | |||
288 | /* IEEE80211_RADIOTAP_TX_FLAGS */ | ||
289 | txflags = 0; | ||
290 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | ||
291 | !is_multicast_ether_addr(hdr->addr1)) | ||
292 | txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | ||
293 | |||
294 | if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
295 | (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
296 | txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | ||
297 | else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) | ||
298 | txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | ||
299 | |||
300 | put_unaligned_le16(txflags, pos); | ||
301 | pos += 2; | ||
302 | |||
303 | /* IEEE80211_RADIOTAP_DATA_RETRIES */ | ||
304 | /* for now report the total retry_count */ | ||
305 | *pos = retry_count; | ||
306 | pos++; | ||
307 | |||
308 | /* IEEE80211_TX_RC_MCS */ | ||
309 | if (info->status.rates[0].idx >= 0 && | ||
310 | info->status.rates[0].flags & IEEE80211_TX_RC_MCS) { | ||
311 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); | ||
312 | pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS | | ||
313 | IEEE80211_RADIOTAP_MCS_HAVE_GI | | ||
314 | IEEE80211_RADIOTAP_MCS_HAVE_BW; | ||
315 | if (info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI) | ||
316 | pos[1] |= IEEE80211_RADIOTAP_MCS_SGI; | ||
317 | if (info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
318 | pos[1] |= IEEE80211_RADIOTAP_MCS_BW_40; | ||
319 | if (info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD) | ||
320 | pos[1] |= IEEE80211_RADIOTAP_MCS_FMT_GF; | ||
321 | pos[2] = info->status.rates[0].idx; | ||
322 | pos += 3; | ||
323 | } | ||
324 | |||
325 | } | ||
326 | |||
231 | /* | 327 | /* |
232 | * Use a static threshold for now, best value to be determined | 328 | * Use a static threshold for now, best value to be determined |
233 | * by testing ... | 329 | * by testing ... |
@@ -246,7 +342,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
246 | u16 frag, type; | 342 | u16 frag, type; |
247 | __le16 fc; | 343 | __le16 fc; |
248 | struct ieee80211_supported_band *sband; | 344 | struct ieee80211_supported_band *sband; |
249 | struct ieee80211_tx_status_rtap_hdr *rthdr; | ||
250 | struct ieee80211_sub_if_data *sdata; | 345 | struct ieee80211_sub_if_data *sdata; |
251 | struct net_device *prev_dev = NULL; | 346 | struct net_device *prev_dev = NULL; |
252 | struct sta_info *sta, *tmp; | 347 | struct sta_info *sta, *tmp; |
@@ -256,6 +351,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
256 | bool acked; | 351 | bool acked; |
257 | struct ieee80211_bar *bar; | 352 | struct ieee80211_bar *bar; |
258 | u16 tid; | 353 | u16 tid; |
354 | int rtap_len; | ||
259 | 355 | ||
260 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 356 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
261 | if (info->status.rates[i].idx < 0) { | 357 | if (info->status.rates[i].idx < 0) { |
@@ -429,7 +525,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
429 | continue; | 525 | continue; |
430 | if (wk->offchan_tx.frame != skb) | 526 | if (wk->offchan_tx.frame != skb) |
431 | continue; | 527 | continue; |
432 | wk->offchan_tx.frame = NULL; | 528 | wk->offchan_tx.status = true; |
433 | break; | 529 | break; |
434 | } | 530 | } |
435 | rcu_read_unlock(); | 531 | rcu_read_unlock(); |
@@ -460,44 +556,13 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
460 | } | 556 | } |
461 | 557 | ||
462 | /* send frame to monitor interfaces now */ | 558 | /* send frame to monitor interfaces now */ |
463 | 559 | rtap_len = ieee80211_tx_radiotap_len(info); | |
464 | if (skb_headroom(skb) < sizeof(*rthdr)) { | 560 | if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { |
465 | printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); | 561 | printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); |
466 | dev_kfree_skb(skb); | 562 | dev_kfree_skb(skb); |
467 | return; | 563 | return; |
468 | } | 564 | } |
469 | 565 | ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len); | |
470 | rthdr = (struct ieee80211_tx_status_rtap_hdr *) | ||
471 | skb_push(skb, sizeof(*rthdr)); | ||
472 | |||
473 | memset(rthdr, 0, sizeof(*rthdr)); | ||
474 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); | ||
475 | rthdr->hdr.it_present = | ||
476 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | | ||
477 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES) | | ||
478 | (1 << IEEE80211_RADIOTAP_RATE)); | ||
479 | |||
480 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | ||
481 | !is_multicast_ether_addr(hdr->addr1)) | ||
482 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | ||
483 | |||
484 | /* | ||
485 | * XXX: Once radiotap gets the bitmap reset thing the vendor | ||
486 | * extensions proposal contains, we can actually report | ||
487 | * the whole set of tries we did. | ||
488 | */ | ||
489 | if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
490 | (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
491 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | ||
492 | else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) | ||
493 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | ||
494 | if (info->status.rates[0].idx >= 0 && | ||
495 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) | ||
496 | rthdr->rate = sband->bitrates[ | ||
497 | info->status.rates[0].idx].bitrate / 5; | ||
498 | |||
499 | /* for now report the total retry_count */ | ||
500 | rthdr->data_retries = retry_count; | ||
501 | 566 | ||
502 | /* XXX: is this sufficient for BPF? */ | 567 | /* XXX: is this sufficient for BPF? */ |
503 | skb_set_mac_header(skb, 0); | 568 | skb_set_mac_header(skb, 0); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ad2ee4a90ec4..48bbb96d8edb 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -898,7 +898,10 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
898 | int hdrlen; | 898 | int hdrlen; |
899 | int fragnum; | 899 | int fragnum; |
900 | 900 | ||
901 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) | 901 | if (info->flags & IEEE80211_TX_CTL_DONTFRAG) |
902 | return TX_CONTINUE; | ||
903 | |||
904 | if (tx->local->ops->set_frag_threshold) | ||
902 | return TX_CONTINUE; | 905 | return TX_CONTINUE; |
903 | 906 | ||
904 | /* | 907 | /* |
@@ -911,7 +914,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
911 | 914 | ||
912 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 915 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
913 | 916 | ||
914 | /* internal error, why is TX_FRAGMENTED set? */ | 917 | /* internal error, why isn't DONTFRAG set? */ |
915 | if (WARN_ON(skb->len + FCS_LEN <= frag_threshold)) | 918 | if (WARN_ON(skb->len + FCS_LEN <= frag_threshold)) |
916 | return TX_DROP; | 919 | return TX_DROP; |
917 | 920 | ||
@@ -1032,108 +1035,6 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) | |||
1032 | 1035 | ||
1033 | /* actual transmit path */ | 1036 | /* actual transmit path */ |
1034 | 1037 | ||
1035 | /* | ||
1036 | * deal with packet injection down monitor interface | ||
1037 | * with Radiotap Header -- only called for monitor mode interface | ||
1038 | */ | ||
1039 | static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | ||
1040 | struct sk_buff *skb) | ||
1041 | { | ||
1042 | /* | ||
1043 | * this is the moment to interpret and discard the radiotap header that | ||
1044 | * must be at the start of the packet injected in Monitor mode | ||
1045 | * | ||
1046 | * Need to take some care with endian-ness since radiotap | ||
1047 | * args are little-endian | ||
1048 | */ | ||
1049 | |||
1050 | struct ieee80211_radiotap_iterator iterator; | ||
1051 | struct ieee80211_radiotap_header *rthdr = | ||
1052 | (struct ieee80211_radiotap_header *) skb->data; | ||
1053 | bool hw_frag; | ||
1054 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1055 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, | ||
1056 | NULL); | ||
1057 | u16 txflags; | ||
1058 | |||
1059 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1060 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | ||
1061 | |||
1062 | /* packet is fragmented in HW if we have a non-NULL driver callback */ | ||
1063 | hw_frag = (tx->local->ops->set_frag_threshold != NULL); | ||
1064 | |||
1065 | /* | ||
1066 | * for every radiotap entry that is present | ||
1067 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more | ||
1068 | * entries present, or -EINVAL on error) | ||
1069 | */ | ||
1070 | |||
1071 | while (!ret) { | ||
1072 | ret = ieee80211_radiotap_iterator_next(&iterator); | ||
1073 | |||
1074 | if (ret) | ||
1075 | continue; | ||
1076 | |||
1077 | /* see if this argument is something we can use */ | ||
1078 | switch (iterator.this_arg_index) { | ||
1079 | /* | ||
1080 | * You must take care when dereferencing iterator.this_arg | ||
1081 | * for multibyte types... the pointer is not aligned. Use | ||
1082 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
1083 | * iterator.this_arg for type "type" safely on all arches. | ||
1084 | */ | ||
1085 | case IEEE80211_RADIOTAP_FLAGS: | ||
1086 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { | ||
1087 | /* | ||
1088 | * this indicates that the skb we have been | ||
1089 | * handed has the 32-bit FCS CRC at the end... | ||
1090 | * we should react to that by snipping it off | ||
1091 | * because it will be recomputed and added | ||
1092 | * on transmission | ||
1093 | */ | ||
1094 | if (skb->len < (iterator._max_length + FCS_LEN)) | ||
1095 | return false; | ||
1096 | |||
1097 | skb_trim(skb, skb->len - FCS_LEN); | ||
1098 | } | ||
1099 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) | ||
1100 | info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1101 | if ((*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) && | ||
1102 | !hw_frag) | ||
1103 | tx->flags |= IEEE80211_TX_FRAGMENTED; | ||
1104 | break; | ||
1105 | |||
1106 | case IEEE80211_RADIOTAP_TX_FLAGS: | ||
1107 | txflags = le16_to_cpu(get_unaligned((__le16*) | ||
1108 | iterator.this_arg)); | ||
1109 | if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK) | ||
1110 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1111 | break; | ||
1112 | |||
1113 | /* | ||
1114 | * Please update the file | ||
1115 | * Documentation/networking/mac80211-injection.txt | ||
1116 | * when parsing new fields here. | ||
1117 | */ | ||
1118 | |||
1119 | default: | ||
1120 | break; | ||
1121 | } | ||
1122 | } | ||
1123 | |||
1124 | if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ | ||
1125 | return false; | ||
1126 | |||
1127 | /* | ||
1128 | * remove the radiotap header | ||
1129 | * iterator->_max_length was sanity-checked against | ||
1130 | * skb->len by iterator init | ||
1131 | */ | ||
1132 | skb_pull(skb, iterator._max_length); | ||
1133 | |||
1134 | return true; | ||
1135 | } | ||
1136 | |||
1137 | static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | 1038 | static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, |
1138 | struct sk_buff *skb, | 1039 | struct sk_buff *skb, |
1139 | struct ieee80211_tx_info *info, | 1040 | struct ieee80211_tx_info *info, |
@@ -1198,7 +1099,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1198 | struct ieee80211_local *local = sdata->local; | 1099 | struct ieee80211_local *local = sdata->local; |
1199 | struct ieee80211_hdr *hdr; | 1100 | struct ieee80211_hdr *hdr; |
1200 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1101 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1201 | int hdrlen, tid; | 1102 | int tid; |
1202 | u8 *qc; | 1103 | u8 *qc; |
1203 | 1104 | ||
1204 | memset(tx, 0, sizeof(*tx)); | 1105 | memset(tx, 0, sizeof(*tx)); |
@@ -1206,26 +1107,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1206 | tx->local = local; | 1107 | tx->local = local; |
1207 | tx->sdata = sdata; | 1108 | tx->sdata = sdata; |
1208 | tx->channel = local->hw.conf.channel; | 1109 | tx->channel = local->hw.conf.channel; |
1209 | /* | ||
1210 | * Set this flag (used below to indicate "automatic fragmentation"), | ||
1211 | * it will be cleared/left by radiotap as desired. | ||
1212 | * Only valid when fragmentation is done by the stack. | ||
1213 | */ | ||
1214 | if (!local->ops->set_frag_threshold) | ||
1215 | tx->flags |= IEEE80211_TX_FRAGMENTED; | ||
1216 | |||
1217 | /* process and remove the injection radiotap header */ | ||
1218 | if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) { | ||
1219 | if (!__ieee80211_parse_tx_radiotap(tx, skb)) | ||
1220 | return TX_DROP; | ||
1221 | |||
1222 | /* | ||
1223 | * __ieee80211_parse_tx_radiotap has now removed | ||
1224 | * the radiotap header that was present and pre-filled | ||
1225 | * 'tx' with tx control information. | ||
1226 | */ | ||
1227 | info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP; | ||
1228 | } | ||
1229 | 1110 | ||
1230 | /* | 1111 | /* |
1231 | * If this flag is set to true anywhere, and we get here, | 1112 | * If this flag is set to true anywhere, and we get here, |
@@ -1281,13 +1162,11 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1281 | */ | 1162 | */ |
1282 | } | 1163 | } |
1283 | 1164 | ||
1284 | if (tx->flags & IEEE80211_TX_FRAGMENTED) { | 1165 | if (!(info->flags & IEEE80211_TX_CTL_DONTFRAG)) { |
1285 | if ((tx->flags & IEEE80211_TX_UNICAST) && | 1166 | if (!(tx->flags & IEEE80211_TX_UNICAST) || |
1286 | skb->len + FCS_LEN > local->hw.wiphy->frag_threshold && | 1167 | skb->len + FCS_LEN <= local->hw.wiphy->frag_threshold || |
1287 | !(info->flags & IEEE80211_TX_CTL_AMPDU)) | 1168 | info->flags & IEEE80211_TX_CTL_AMPDU) |
1288 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 1169 | info->flags |= IEEE80211_TX_CTL_DONTFRAG; |
1289 | else | ||
1290 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | ||
1291 | } | 1170 | } |
1292 | 1171 | ||
1293 | if (!tx->sta) | 1172 | if (!tx->sta) |
@@ -1295,11 +1174,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1295 | else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT)) | 1174 | else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT)) |
1296 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 1175 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
1297 | 1176 | ||
1298 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
1299 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { | ||
1300 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; | ||
1301 | tx->ethertype = (pos[0] << 8) | pos[1]; | ||
1302 | } | ||
1303 | info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT; | 1177 | info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT; |
1304 | 1178 | ||
1305 | return TX_CONTINUE; | 1179 | return TX_CONTINUE; |
@@ -1510,11 +1384,6 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, | |||
1510 | tail_need = max_t(int, tail_need, 0); | 1384 | tail_need = max_t(int, tail_need, 0); |
1511 | } | 1385 | } |
1512 | 1386 | ||
1513 | if (head_need || tail_need) { | ||
1514 | /* Sorry. Can't account for this any more */ | ||
1515 | skb_orphan(skb); | ||
1516 | } | ||
1517 | |||
1518 | if (skb_cloned(skb)) | 1387 | if (skb_cloned(skb)) |
1519 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); | 1388 | I802_DEBUG_INC(local->tx_expand_skb_head_cloned); |
1520 | else if (head_need || tail_need) | 1389 | else if (head_need || tail_need) |
@@ -1528,9 +1397,6 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, | |||
1528 | return -ENOMEM; | 1397 | return -ENOMEM; |
1529 | } | 1398 | } |
1530 | 1399 | ||
1531 | /* update truesize too */ | ||
1532 | skb->truesize += head_need + tail_need; | ||
1533 | |||
1534 | return 0; | 1400 | return 0; |
1535 | } | 1401 | } |
1536 | 1402 | ||
@@ -1539,55 +1405,11 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
1539 | struct ieee80211_local *local = sdata->local; | 1405 | struct ieee80211_local *local = sdata->local; |
1540 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1406 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1541 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1407 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1542 | struct ieee80211_sub_if_data *tmp_sdata; | ||
1543 | int headroom; | 1408 | int headroom; |
1544 | bool may_encrypt; | 1409 | bool may_encrypt; |
1545 | 1410 | ||
1546 | rcu_read_lock(); | 1411 | rcu_read_lock(); |
1547 | 1412 | ||
1548 | if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { | ||
1549 | int hdrlen; | ||
1550 | u16 len_rthdr; | ||
1551 | |||
1552 | info->flags |= IEEE80211_TX_CTL_INJECTED | | ||
1553 | IEEE80211_TX_INTFL_HAS_RADIOTAP; | ||
1554 | |||
1555 | len_rthdr = ieee80211_get_radiotap_len(skb->data); | ||
1556 | hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); | ||
1557 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
1558 | |||
1559 | /* check the header is complete in the frame */ | ||
1560 | if (likely(skb->len >= len_rthdr + hdrlen)) { | ||
1561 | /* | ||
1562 | * We process outgoing injected frames that have a | ||
1563 | * local address we handle as though they are our | ||
1564 | * own frames. | ||
1565 | * This code here isn't entirely correct, the local | ||
1566 | * MAC address is not necessarily enough to find | ||
1567 | * the interface to use; for that proper VLAN/WDS | ||
1568 | * support we will need a different mechanism. | ||
1569 | */ | ||
1570 | |||
1571 | list_for_each_entry_rcu(tmp_sdata, &local->interfaces, | ||
1572 | list) { | ||
1573 | if (!ieee80211_sdata_running(tmp_sdata)) | ||
1574 | continue; | ||
1575 | if (tmp_sdata->vif.type == | ||
1576 | NL80211_IFTYPE_MONITOR || | ||
1577 | tmp_sdata->vif.type == | ||
1578 | NL80211_IFTYPE_AP_VLAN || | ||
1579 | tmp_sdata->vif.type == | ||
1580 | NL80211_IFTYPE_WDS) | ||
1581 | continue; | ||
1582 | if (compare_ether_addr(tmp_sdata->vif.addr, | ||
1583 | hdr->addr2) == 0) { | ||
1584 | sdata = tmp_sdata; | ||
1585 | break; | ||
1586 | } | ||
1587 | } | ||
1588 | } | ||
1589 | } | ||
1590 | |||
1591 | may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); | 1413 | may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); |
1592 | 1414 | ||
1593 | headroom = local->tx_headroom; | 1415 | headroom = local->tx_headroom; |
@@ -1619,6 +1441,89 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
1619 | rcu_read_unlock(); | 1441 | rcu_read_unlock(); |
1620 | } | 1442 | } |
1621 | 1443 | ||
1444 | static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb) | ||
1445 | { | ||
1446 | struct ieee80211_radiotap_iterator iterator; | ||
1447 | struct ieee80211_radiotap_header *rthdr = | ||
1448 | (struct ieee80211_radiotap_header *) skb->data; | ||
1449 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1450 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, | ||
1451 | NULL); | ||
1452 | u16 txflags; | ||
1453 | |||
1454 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | | ||
1455 | IEEE80211_TX_CTL_DONTFRAG; | ||
1456 | |||
1457 | /* | ||
1458 | * for every radiotap entry that is present | ||
1459 | * (ieee80211_radiotap_iterator_next returns -ENOENT when no more | ||
1460 | * entries present, or -EINVAL on error) | ||
1461 | */ | ||
1462 | |||
1463 | while (!ret) { | ||
1464 | ret = ieee80211_radiotap_iterator_next(&iterator); | ||
1465 | |||
1466 | if (ret) | ||
1467 | continue; | ||
1468 | |||
1469 | /* see if this argument is something we can use */ | ||
1470 | switch (iterator.this_arg_index) { | ||
1471 | /* | ||
1472 | * You must take care when dereferencing iterator.this_arg | ||
1473 | * for multibyte types... the pointer is not aligned. Use | ||
1474 | * get_unaligned((type *)iterator.this_arg) to dereference | ||
1475 | * iterator.this_arg for type "type" safely on all arches. | ||
1476 | */ | ||
1477 | case IEEE80211_RADIOTAP_FLAGS: | ||
1478 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { | ||
1479 | /* | ||
1480 | * this indicates that the skb we have been | ||
1481 | * handed has the 32-bit FCS CRC at the end... | ||
1482 | * we should react to that by snipping it off | ||
1483 | * because it will be recomputed and added | ||
1484 | * on transmission | ||
1485 | */ | ||
1486 | if (skb->len < (iterator._max_length + FCS_LEN)) | ||
1487 | return false; | ||
1488 | |||
1489 | skb_trim(skb, skb->len - FCS_LEN); | ||
1490 | } | ||
1491 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) | ||
1492 | info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1493 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) | ||
1494 | info->flags &= ~IEEE80211_TX_CTL_DONTFRAG; | ||
1495 | break; | ||
1496 | |||
1497 | case IEEE80211_RADIOTAP_TX_FLAGS: | ||
1498 | txflags = get_unaligned_le16(iterator.this_arg); | ||
1499 | if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK) | ||
1500 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1501 | break; | ||
1502 | |||
1503 | /* | ||
1504 | * Please update the file | ||
1505 | * Documentation/networking/mac80211-injection.txt | ||
1506 | * when parsing new fields here. | ||
1507 | */ | ||
1508 | |||
1509 | default: | ||
1510 | break; | ||
1511 | } | ||
1512 | } | ||
1513 | |||
1514 | if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */ | ||
1515 | return false; | ||
1516 | |||
1517 | /* | ||
1518 | * remove the radiotap header | ||
1519 | * iterator->_max_length was sanity-checked against | ||
1520 | * skb->len by iterator init | ||
1521 | */ | ||
1522 | skb_pull(skb, iterator._max_length); | ||
1523 | |||
1524 | return true; | ||
1525 | } | ||
1526 | |||
1622 | netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | 1527 | netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, |
1623 | struct net_device *dev) | 1528 | struct net_device *dev) |
1624 | { | 1529 | { |
@@ -1628,8 +1533,9 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1628 | (struct ieee80211_radiotap_header *)skb->data; | 1533 | (struct ieee80211_radiotap_header *)skb->data; |
1629 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1534 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1630 | struct ieee80211_hdr *hdr; | 1535 | struct ieee80211_hdr *hdr; |
1536 | struct ieee80211_sub_if_data *tmp_sdata, *sdata; | ||
1631 | u16 len_rthdr; | 1537 | u16 len_rthdr; |
1632 | u8 *payload; | 1538 | int hdrlen; |
1633 | 1539 | ||
1634 | /* | 1540 | /* |
1635 | * Frame injection is not allowed if beaconing is not allowed | 1541 | * Frame injection is not allowed if beaconing is not allowed |
@@ -1680,30 +1586,65 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1680 | skb_set_network_header(skb, len_rthdr); | 1586 | skb_set_network_header(skb, len_rthdr); |
1681 | skb_set_transport_header(skb, len_rthdr); | 1587 | skb_set_transport_header(skb, len_rthdr); |
1682 | 1588 | ||
1589 | if (skb->len < len_rthdr + 2) | ||
1590 | goto fail; | ||
1591 | |||
1592 | hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); | ||
1593 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
1594 | |||
1595 | if (skb->len < len_rthdr + hdrlen) | ||
1596 | goto fail; | ||
1597 | |||
1683 | /* | 1598 | /* |
1684 | * Initialize skb->protocol if the injected frame is a data frame | 1599 | * Initialize skb->protocol if the injected frame is a data frame |
1685 | * carrying a rfc1042 header | 1600 | * carrying a rfc1042 header |
1686 | */ | 1601 | */ |
1687 | if (skb->len > len_rthdr + 2) { | 1602 | if (ieee80211_is_data(hdr->frame_control) && |
1688 | hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); | 1603 | skb->len >= len_rthdr + hdrlen + sizeof(rfc1042_header) + 2) { |
1689 | if (ieee80211_is_data(hdr->frame_control) && | 1604 | u8 *payload = (u8 *)hdr + hdrlen; |
1690 | skb->len >= len_rthdr + | 1605 | |
1691 | ieee80211_hdrlen(hdr->frame_control) + | 1606 | if (compare_ether_addr(payload, rfc1042_header) == 0) |
1692 | sizeof(rfc1042_header) + 2) { | 1607 | skb->protocol = cpu_to_be16((payload[6] << 8) | |
1693 | payload = (u8 *)hdr + | 1608 | payload[7]); |
1694 | ieee80211_hdrlen(hdr->frame_control); | ||
1695 | if (compare_ether_addr(payload, rfc1042_header) == 0) | ||
1696 | skb->protocol = cpu_to_be16((payload[6] << 8) | | ||
1697 | payload[7]); | ||
1698 | } | ||
1699 | } | 1609 | } |
1700 | 1610 | ||
1701 | memset(info, 0, sizeof(*info)); | 1611 | memset(info, 0, sizeof(*info)); |
1702 | 1612 | ||
1703 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | 1613 | info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS | |
1614 | IEEE80211_TX_CTL_INJECTED; | ||
1615 | |||
1616 | /* process and remove the injection radiotap header */ | ||
1617 | if (!ieee80211_parse_tx_radiotap(skb)) | ||
1618 | goto fail; | ||
1619 | |||
1620 | rcu_read_lock(); | ||
1621 | |||
1622 | /* | ||
1623 | * We process outgoing injected frames that have a local address | ||
1624 | * we handle as though they are non-injected frames. | ||
1625 | * This code here isn't entirely correct, the local MAC address | ||
1626 | * isn't always enough to find the interface to use; for proper | ||
1627 | * VLAN/WDS support we will need a different mechanism (which | ||
1628 | * likely isn't going to be monitor interfaces). | ||
1629 | */ | ||
1630 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1631 | |||
1632 | list_for_each_entry_rcu(tmp_sdata, &local->interfaces, list) { | ||
1633 | if (!ieee80211_sdata_running(tmp_sdata)) | ||
1634 | continue; | ||
1635 | if (tmp_sdata->vif.type == NL80211_IFTYPE_MONITOR || | ||
1636 | tmp_sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | ||
1637 | tmp_sdata->vif.type == NL80211_IFTYPE_WDS) | ||
1638 | continue; | ||
1639 | if (compare_ether_addr(tmp_sdata->vif.addr, hdr->addr2) == 0) { | ||
1640 | sdata = tmp_sdata; | ||
1641 | break; | ||
1642 | } | ||
1643 | } | ||
1644 | |||
1645 | ieee80211_xmit(sdata, skb); | ||
1646 | rcu_read_unlock(); | ||
1704 | 1647 | ||
1705 | /* pass the radiotap header up to xmit */ | ||
1706 | ieee80211_xmit(IEEE80211_DEV_TO_SUB_IF(dev), skb); | ||
1707 | return NETDEV_TX_OK; | 1648 | return NETDEV_TX_OK; |
1708 | 1649 | ||
1709 | fail: | 1650 | fail: |
@@ -1955,11 +1896,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1955 | * Drop unicast frames to unauthorised stations unless they are | 1896 | * Drop unicast frames to unauthorised stations unless they are |
1956 | * EAPOL frames from the local station. | 1897 | * EAPOL frames from the local station. |
1957 | */ | 1898 | */ |
1958 | if (!ieee80211_vif_is_mesh(&sdata->vif) && | 1899 | if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) && |
1959 | unlikely(!is_multicast_ether_addr(hdr.addr1) && !authorized && | 1900 | !is_multicast_ether_addr(hdr.addr1) && !authorized && |
1960 | !(cpu_to_be16(ethertype) == sdata->control_port_protocol && | 1901 | (cpu_to_be16(ethertype) != sdata->control_port_protocol || |
1961 | compare_ether_addr(sdata->vif.addr, | 1902 | compare_ether_addr(sdata->vif.addr, skb->data + ETH_ALEN)))) { |
1962 | skb->data + ETH_ALEN) == 0))) { | ||
1963 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1903 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1964 | if (net_ratelimit()) | 1904 | if (net_ratelimit()) |
1965 | printk(KERN_DEBUG "%s: dropped frame to %pM" | 1905 | printk(KERN_DEBUG "%s: dropped frame to %pM" |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index af374fab1a12..94472eb34d76 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -577,7 +577,7 @@ ieee80211_offchannel_tx(struct ieee80211_work *wk) | |||
577 | /* | 577 | /* |
578 | * After this, offchan_tx.frame remains but now is no | 578 | * After this, offchan_tx.frame remains but now is no |
579 | * longer a valid pointer -- we still need it as the | 579 | * longer a valid pointer -- we still need it as the |
580 | * cookie for canceling this work. | 580 | * cookie for canceling this work/status matching. |
581 | */ | 581 | */ |
582 | ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame); | 582 | ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame); |
583 | 583 | ||
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 7bc8702808fa..f614ce7bb6e3 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -53,7 +53,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
53 | } | 53 | } |
54 | 54 | ||
55 | if (info->control.hw_key && | 55 | if (info->control.hw_key && |
56 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && | 56 | (info->flags & IEEE80211_TX_CTL_DONTFRAG || |
57 | tx->local->ops->set_frag_threshold) && | ||
57 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { | 58 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { |
58 | /* hwaccel - with no need for SW-generated MMIC */ | 59 | /* hwaccel - with no need for SW-generated MMIC */ |
59 | return TX_CONTINUE; | 60 | return TX_CONTINUE; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index edf655aeea00..48260c2d092a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2344,6 +2344,10 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | |||
2344 | 2344 | ||
2345 | nla_nest_end(msg, bss_param); | 2345 | nla_nest_end(msg, bss_param); |
2346 | } | 2346 | } |
2347 | if (sinfo->filled & STATION_INFO_STA_FLAGS) | ||
2348 | NLA_PUT(msg, NL80211_STA_INFO_STA_FLAGS, | ||
2349 | sizeof(struct nl80211_sta_flag_update), | ||
2350 | &sinfo->sta_flags); | ||
2347 | nla_nest_end(msg, sinfoattr); | 2351 | nla_nest_end(msg, sinfoattr); |
2348 | 2352 | ||
2349 | if (sinfo->filled & STATION_INFO_ASSOC_REQ_IES) | 2353 | if (sinfo->filled & STATION_INFO_ASSOC_REQ_IES) |