aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-09-12 16:52:47 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-15 16:48:25 -0400
commit25d834e16294c8dfd923dae6bdb8a055391a99a5 (patch)
treeb9d756464d89949651e5acd1df97846af3028df0 /net/mac80211/tx.c
parent9c31fd635ddfae6eb61712491770befa2ce1fdde (diff)
mac80211: fix virtual interfaces vs. injection
Currently, virtual interface pointers passed to drivers might be from monitor interfaces and as such completely uninitialised because we do not tell the driver about monitor interfaces when those are created. Instead of passing them, we should therefore indicate to the driver that there is no information; do that by passing a NULL value and adjust drivers to cope with it. As a result, some mac80211 API functions also need to cope with a NULL vif pointer so drivers can still call them unconditionally. Also, when injecting frames we really don't want to pass NULL all the time, if we know we are the source address of a frame and have a local interface for that address, we can to use that interface. This also helps with processing the frame correctly for that interface which will help the 802.11w implementation. It's not entirely correct for VLANs or WDS interfaces because there the MAC address isn't unique, but it's already a lot better than what we do now. Finally, when injecting without a matching local interface, don't assign sequence numbers at all. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
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