aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c64
1 files changed, 60 insertions, 4 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 698c8233e6b3..c12f361d7185 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -624,7 +624,14 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
624 u8 *qc; 624 u8 *qc;
625 int tid; 625 int tid;
626 626
627 /* only for injected frames */ 627 /*
628 * Packet injection may want to control the sequence
629 * number, if we have no matching interface then we
630 * neither assign one ourselves nor ask the driver to.
631 */
632 if (unlikely(!info->control.vif))
633 return TX_CONTINUE;
634
628 if (unlikely(ieee80211_is_ctl(hdr->frame_control))) 635 if (unlikely(ieee80211_is_ctl(hdr->frame_control)))
629 return TX_CONTINUE; 636 return TX_CONTINUE;
630 637
@@ -849,7 +856,6 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
849 sband = tx->local->hw.wiphy->bands[tx->channel->band]; 856 sband = tx->local->hw.wiphy->bands[tx->channel->band];
850 857
851 skb->do_not_encrypt = 1; 858 skb->do_not_encrypt = 1;
852 info->flags |= IEEE80211_TX_CTL_INJECTED;
853 tx->flags &= ~IEEE80211_TX_FRAGMENTED; 859 tx->flags &= ~IEEE80211_TX_FRAGMENTED;
854 860
855 /* 861 /*
@@ -981,7 +987,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
981 987
982 /* process and remove the injection radiotap header */ 988 /* process and remove the injection radiotap header */
983 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 989 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
984 if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { 990 if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) {
985 if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP) 991 if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP)
986 return TX_DROP; 992 return TX_DROP;
987 993
@@ -1300,6 +1306,11 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
1300 struct ieee80211_sub_if_data *osdata; 1306 struct ieee80211_sub_if_data *osdata;
1301 int headroom; 1307 int headroom;
1302 bool may_encrypt; 1308 bool may_encrypt;
1309 enum {
1310 NOT_MONITOR,
1311 FOUND_SDATA,
1312 UNKNOWN_ADDRESS,
1313 } monitor_iface = NOT_MONITOR;
1303 int ret; 1314 int ret;
1304 1315
1305 if (skb->iif) 1316 if (skb->iif)
@@ -1335,6 +1346,50 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
1335 IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, 1346 IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh,
1336 fwded_frames); 1347 fwded_frames);
1337 } 1348 }
1349 } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) {
1350 struct ieee80211_sub_if_data *sdata;
1351 struct ieee80211_local *local = osdata->local;
1352 struct ieee80211_hdr *hdr;
1353 int hdrlen;
1354 u16 len_rthdr;
1355
1356 info->flags |= IEEE80211_TX_CTL_INJECTED;
1357 monitor_iface = UNKNOWN_ADDRESS;
1358
1359 len_rthdr = ieee80211_get_radiotap_len(skb->data);
1360 hdr = (struct ieee80211_hdr *)skb->data + len_rthdr;
1361 hdrlen = ieee80211_hdrlen(hdr->frame_control);
1362
1363 /* check the header is complete in the frame */
1364 if (likely(skb->len >= len_rthdr + hdrlen)) {
1365 /*
1366 * We process outgoing injected frames that have a
1367 * local address we handle as though they are our
1368 * own frames.
1369 * This code here isn't entirely correct, the local
1370 * MAC address is not necessarily enough to find
1371 * the interface to use; for that proper VLAN/WDS
1372 * support we will need a different mechanism.
1373 */
1374
1375 rcu_read_lock();
1376 list_for_each_entry_rcu(sdata, &local->interfaces,
1377 list) {
1378 if (!netif_running(sdata->dev))
1379 continue;
1380 if (compare_ether_addr(sdata->dev->dev_addr,
1381 hdr->addr2)) {
1382 dev_hold(sdata->dev);
1383 dev_put(odev);
1384 osdata = sdata;
1385 odev = osdata->dev;
1386 skb->iif = sdata->dev->ifindex;
1387 monitor_iface = FOUND_SDATA;
1388 break;
1389 }
1390 }
1391 rcu_read_unlock();
1392 }
1338 } 1393 }
1339 1394
1340 may_encrypt = !skb->do_not_encrypt; 1395 may_encrypt = !skb->do_not_encrypt;
@@ -1355,7 +1410,8 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
1355 osdata = container_of(osdata->bss, 1410 osdata = container_of(osdata->bss,
1356 struct ieee80211_sub_if_data, 1411 struct ieee80211_sub_if_data,
1357 u.ap); 1412 u.ap);
1358 info->control.vif = &osdata->vif; 1413 if (likely(monitor_iface != UNKNOWN_ADDRESS))
1414 info->control.vif = &osdata->vif;
1359 ret = ieee80211_tx(odev, skb); 1415 ret = ieee80211_tx(odev, skb);
1360 dev_put(odev); 1416 dev_put(odev);
1361 1417