Radiotap on Monitor Mode interfaces for rx and tx
cover Radiotap on Monitor Mode interfaces for rx and tx
Hi folks -
This pair of patches change the Monitor Mode wireless interfaces to use radiotap both for monitoring and for packet injection. The monitoring side is done by a patch from Michael Wu. Tcpdump knows how to handle the result.
For injecting packets, the you issue a packet using libpcap or a SOCK_PACKET socket down an interface to the wireless device that is in Monitor Mode. The packet has a normal radiotap header prepended to the IEEE80211 header. The radiotap header is variable length depending on what the user wants to specify, currently the transmit rate, power and antenna can be specified using normal radiotap semantics. Any other entries are skipped.
A usermode app packetspammer is available from here
http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammer
which allows easy injection of these packets from the commandline. At the moment it loops issuing packets at a variety of rates which can be seen from another machine's monitor mode interface on the same channel. There are instructions for build and using it on the page above.
Currently it has been tested for both rx and tx using zd1211rw-mac80211 and works except for 1Mbps TX (54Mbps - 2Mbps works) and the rx radiotap rate is not shown in tcpdump.
The patches should be based against wireless-dev.
PATCH 1/2 mac80211: Add radiotap support
From: Michael Wu <[email protected]>
---
include/net/mac80211.h | 3 ++ net/mac80211/ieee80211.c | 69 +++++++++++++++++++++++++++++++++------- net/mac80211/ieee80211_iface.c | 2 + 3 files changed, 61 insertions(+), 13 deletions(-)
include/net/mac80211.h +3 -0
@@ -529,6 +529,9 @@ struct ieee80211_hw {* per-packet RC4 key with each TX frame when doing hwcrypto */ #define IEEE80211_HW_TKIP_REQ_PHASE2_KEY (1<<14) +/* Driver supports radiotap. Temporary until all drivers support it. */ +#define IEEE80211_HW_RADIOTAP_SUPPORTED (1<<20) +u32 flags;/* hardware flags defined above */ /* Set to the size of a needed device specific skb headroom for TX skbs. */
net/mac80211/ieee80211.c +57 -12
120 lines not on this page · raw message
net/mac80211/ieee80211_iface.c +1 -1
@@ -199,7 +199,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type)break ; }case IEEE80211_IF_TYPE_MNTR : - dev->type =ARPHRD_IEEE80211_PRISM ; + dev->type =ARPHRD_IEEE80211_RADIOTAP ;break ;default : printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
PATCH 2/2 mac80211: Monitor mode radiotap-based packet injection
In reply to [email protected]From: Andy Green <[email protected]>
Try #2
- took Michael Wu's advice about better tools and basing on wireless-dev
- took Luis Rodriguez's advice about coding style makeover
- took Pavel Roskin's advice about little-endian radiotap
Index: linux-2.6.20.i386/include/net/mac80211.h
===================================================
include/net/mac80211.h +1 -0
@@ -189,6 +189,7 @@ struct ieee80211_tx_control {#define IEEE80211_TXCTL_FIRST_FRAGMENT (1<<8)/* this is a first fragment of * the frame */ #define IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY (1<<9) +#define IEEE80211_TXCTL_INJECTED_PACKET (1<<10)/* tx into monitor IF */ u32 flags;/* tx control flags defined * above */ u8 retry_limit;/* 1 = only first attempt, 2 = one retry, .. */
net/mac80211/ieee80211.c +242 -9
303 lines not on this page · raw message
net/mac80211/ieee80211_i.h +1 -0
@@ -162,6 +162,7 @@ struct ieee80211_tx_packet_data { unsigned int requeue:1; unsigned int mgmt_iface:1; unsigned int queue:4; + unsigned int is_injected_into_monitor:1; };struct ieee80211_tx_stored_packet {
Re: [PATCH 2/2] mac80211: Monitor mode radiotap-based packet injection
Quoted 15 lines · On Saturday 17 March 2007 11:58, [email protected] wrote:
From: Andy Green <[email protected]>
Try #2
- took Michael Wu's advice about better tools and basing on wireless-dev
- took Luis Rodriguez's advice about coding style makeover
- took Pavel Roskin's advice about little-endian radiotapIndex:
linux-2.6.20.i386/include/net/mac80211.h
===================================================include/net/mac80211.h +0
-0
include/net/mac80211.h struct ieee80211_tx_control { · line 192
Quoted 4 lines
include/net/mac80211.h +1
-0@@ -189,6 +189,7 @@ struct ieee80211_tx_control {#define IEEE80211_TXCTL_FIRST_FRAGMENT (1<<8)/* this is a first fragment of * the frame */ #define IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY (1<<9) +#define IEEE80211_TXCTL_INJECTED_PACKET (1<<10)/* tx into monitor IF */
What is a driver supposed to do on this flag? More documentation, please.
Signature · 1 line
Greetings Michael.
Re: [PATCH 2/2] mac80211: Monitor mode radiotap-based packet injection
Quoted 3 lines · Michael Buesch
Quoted 1 line
+#define
IEEE80211_TXCTL_INJECTED_PACKET(1<<10) /* tx into monitor IF */What is a driver supposed to do on this flag? More documentation, please.
Hi Michael -
The driver doesn't have to do anything with that flag... it's a private mac80211-internal flag to get the attribute that the packet was injected into a Monitor interface into ieee80211_tx_control where __ieee80211_tx_prepare() can access that information. By then as I understood it the information that the packet came in on the monitor interface isn't available because we redirected it to the master interface. That one bit of state, that the packet originated from a send() to a Montitor Mode interface is the meaning of the flag.
Currently the information travels like this:
- ieee80211_subif_start_xmit() sees that it is a monitor mode interface getting the packet.
- It sets ieee80211_tx_packet_data.is_injected_into_monitor, which
travels with the packet inside skb.cb.
- ieee80211_master_start_xmit() eventually gets the packet and
examines the ieee80211_tx_packet_data in the skb.cb. If is_injected_into_monitor is set, it sets control.flags |= IEEE80211_TXCTL_INJECTED_PACKET. This is done because at the start of ieee80211_master_start_xmit() there is a comment
/* * copy control out of the skb so other people can use skb->cb */
- finally the end user __ieee80211_tx_prepare() is able to find the
state information in control->flags & IEEE80211_TXCTL_INJECTED_PACKET and work out if it expects a radiotap header prepended or not from that.
If there's a simpler way I'm happy to use it.
-Andy
Re: [PATCH 2/2] mac80211: Monitor mode radiotap-based packet injection
Quoted 4 lines · Andy Green
Quoted 2 lines · Michael Buesch
Quoted 1 line
+#define
IEEE80211_TXCTL_INJECTED_PACKET(1<<10) /* tx into monitor IF */
Quoted 8 lines
Quoted 1 line
What is a driver supposed to do on this flag? More documentation, please.
Hi Michael -
The driver doesn't have to do anything with that flag... it's a private mac80211-internal flag to get the attribute that the packet was injected
If there's a simpler way I'm happy to use it.
Ok, no. I'm fine with this. But please mark it as mac80211-internal flag, so driver authors don't waste time on thinking about wtf this is. ;) Either by documenting it in a comment or by doing a special define (two underscores or something). Or both.
Signature · 1 line
Greetings Michael.
Re: [PATCH 2/2] mac80211: Monitor mode radiotap-based packet injection
Quoted 7 lines · Michael Buesch
Quoted 6 lines · Andy Green
Quoted 2 lines · Michael Buesch
Quoted 1 line
+#define
IEEE80211_TXCTL_INJECTED_PACKET(1<<10) /* tx into monitor IF */What is a driver supposed to do on this flag? More documentation, please.
Hi Michael -
Quoted 8 lines
Quoted 3 lines
The driver doesn't have to do anything with that flag... it's a private mac80211-internal flag to get the attribute that the packet was injected
If there's a simpler way I'm happy to use it.
Ok, no. I'm fine with this. But please mark it as mac80211-internal flag, so driver authors don't waste time on thinking about wtf this is. ;) Either by documenting it in a comment or by doing a special define (two underscores or something). Or both.
Both sounds like a good idea, thanks: I will wait a bit for any more comments and then add this to a try #3. I noticed Michael Wu set his flag to 1<<20 and I guess he had this in mind, so I will change mine to 1<<21 to further distance it from the other flags in bits and in meaning.
-Andy
Re: [PATCH 2/2] mac80211: Monitor mode radiotap-based packet injection
In reply to [email protected]net/mac80211/ieee80211.c line 39
Quoted 10 lines · On Saturday 17 March 2007 06:58, [email protected] wrote:
net/mac80211/ieee80211.c +1
-0@@ -35,6 +35,7 @@#include "ieee80211_led.h" #include "ieee80211_cfg.h" #include "ieee80211_sysfs.h" +#include <net/ieee80211_radiotap.h>
Already included by my patch.
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1103
Quoted 4 lines
net/mac80211/ieee80211.c +4
-0+int tap_index =0 ; +u8 *tap_arg = skb->data +sizeof (struct ieee80211_radiotap_header ); +u32 *curr_arg_bitmap = &rthdr->it_present; +u32 arg_bitmap=le32_to_cpu (*curr_arg_bitmap);
Space before and after the =.
net/mac80211/ieee80211.c
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+ +if (rthdr->it_version)return TXRX_DROP ;/* version byte used as magic */
Space after the if.
net/mac80211/ieee80211.c
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+ +/* sanity check for skb length and radiotap length field */
Keep comments indented the same as everything else.
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1109
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+if (skb->len < (le16_to_cpu (rthdr->it_len) + +sizeof (struct ieee80211_hdr )))
Using some spaces to align the start of the second line with the parenthesis often looks better.
net/mac80211/ieee80211.c __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, · line 1243
Quoted 3 lines
net/mac80211/ieee80211.c +3
-0+/* process and remove the injection radiotap header */ + +if (control->flags &IEEE80211_TXCTL_INJECTED_PACKET ) {
dev points to the virtual interface that the frame originally came in on. You can get sdata from that and figure out if the interface was a monitor interface.
Thanks,
-Michael Wu
Re: [PATCH 2/2] mac80211: Monitor mode radiotap-based packet injection
Quoted 8 lines · Michael Wu
net/mac80211/ieee80211.c __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, · line 1243
Quoted 3 lines
net/mac80211/ieee80211.c +3
-0+/* process and remove the injection radiotap header */ + +if (control->flags &IEEE80211_TXCTL_INJECTED_PACKET ) {dev points to the virtual interface that the frame originally came in on. You can get sdata from that and figure out if the interface was a monitor interface.
Of course, this depends on ifindex being set properly.
You added:
pkt_data->ifindex = local->mdev->ifindex;
but in that same function, this is used instead:
pkt_data->ifindex = sdata->dev->ifindex;
Which allows the master device to figure out which virtual interface the skb came from.
-Michael Wu
Re: [PATCH 2/2] mac80211: Monitor mode radiotap-based packet injection
Quoted 10 lines · Michael Wu
Quoted 7 lines · Michael Wu
net/mac80211/ieee80211.c __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, · line 1243
Quoted 3 lines
net/mac80211/ieee80211.c +3
-0+/* process and remove the injection radiotap header */ + +if (control->flags &IEEE80211_TXCTL_INJECTED_PACKET ) {dev points to the virtual interface that the frame originally came in on. You can get sdata from that and figure out if the interface was a monitor interface.
Of course, this depends on ifindex being set properly.
Quoted 7 lines
You added:
pkt_data->ifindex = local->mdev->ifindex;but in that same function, this is used instead:
pkt_data->ifindex = sdata->dev->ifindex;Which allows the master device to figure out which virtual interface the skb came from.
Yeah naturally it was my first move to use what was there, but the result was a panic that went away when I moved the skb to belong to the "master" interface's index and separately persistently tagged the packet as being injected.
Is it safe against race problems on interface removal to consider to look up against the interface index at actual send time?
-Andy
Re: [PATCH 2/2] mac80211: Monitor mode radiotap-based packet injection
Quoted 5 lines · Andy Green
Yeah naturally it was my first move to use what was there, but the result was a panic that went away when I moved the skb to belong to the "master" interface's index and separately persistently tagged the packet as being injected.
I don't see anything that would prevent this from working.. if you have a patch which does this and crashes, I'll take a look at it.
Quoted 3 lines
Is it safe against race problems on interface removal to consider to look up against the interface index at actual send time?
Yes. dev_get_by_index in ieee80211_master_start_xmit calls dev_hold. When it is done, dev_put is called. The headroom reservation code looks suspicious though.. it doesn't call dev_put if it fails. Fortunately, this is unlikely to happen.
Thanks,
-Michael Wu
Re: [PATCH 2/2] mac80211: Monitor mode radiotap-based packet injection
Quoted 7 lines · Michael Wu
Quoted 5 lines · Andy Green
Yeah naturally it was my first move to use what was there, but the result was a panic that went away when I moved the skb to belong to the "master" interface's index and separately persistently tagged the packet as being injected.
I don't see anything that would prevent this from working.. if you have a patch which does this and crashes, I'll take a look at it.
Okay I will try to regenerate this situation tomorrow afternoon, which will be my next chance.
-Andy
Re: [PATCH 2/2] mac80211: Monitor mode radiotap-based packet injection
Quoted 10 lines · Andy Green
Quoted 7 lines · Michael Wu
Quoted 5 lines · Andy Green
Yeah naturally it was my first move to use what was there, but the result was a panic that went away when I moved the skb to belong to the "master" interface's index and separately persistently tagged the packet as being injected.
I don't see anything that would prevent this from working.. if you have a patch which does this and crashes, I'll take a look at it.
Okay I will try to regenerate this situation tomorrow afternoon, which will be my next chance.
Well the panic did not return, I guess whatever I was doing that provoked it I am not doing any more. So I changed it back to the sdata->dev->ifindex that the normal code path uses and confirmed that continued to worked okay.
However when I went on to look at leveraging that to find out if the originating interface was in Monitor mode, it seems that it might be a little bit more expensive to do that -- and it would have to be done for every tx packet in order to find out if it was injected. By contrast with the currently proposed staged system at each level the information is always available without processing, and the overhead for the common case where the packet was not injected is just testing if the if type was monitor, and then later testing a bit in flags that are already available.
From looking around the existing code, it seems something like this is called for to use the ifindex instead:
__ieee80211_tx_prepare(...)
{
struct ieee80211_tx_packet_data *pkt_data;
/* skb->cb is still valid by this time? */
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
/* dev_get_by_index holds a read lock and iterates
* a hlist, done for every tx packet */
originating_dev = dev_get_by_index(pkt_data->ifindex);
if(!originating_dev) goto skipped;
if (unlikely(!is_ieee80211_device(originating_dev, dev))) {
goto give_up_dev;
}
originating__sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if(!originating__sdata) goto give_up_dev;
if (unlikely(originating__sdata->type==IEEE80211_IF_TYPE_MNTR)){
...
}
give_up_dev:
dev_put(originating_dev);
skipped:...
}
Given this, if it is actually the leanest implementation of using ifindex, is it still preferred?
-Andy
Re: [PATCH 2/2] mac80211: Monitor mode radiotap-based packet injection
Quoted 4 lines · Andy Green
However when I went on to look at leveraging that to find out if the originating interface was in Monitor mode, it seems that it might be a little bit more expensive to do that -- and it would have to be done for every tx packet in order to find out if it was injected. By contrast with the currently proposed staged system at each level the information is always available without processing, and the overhead for the common case where the packet was not injected is just testing if the if type was monitor, and then later testing a bit in flags that are already available.
From looking around the existing code, it seems something like this is
called for to use the ifindex instead:
Ha, ignore this, Michael's method works just with what is to hand. Try #3 coming up.
-Andy
Re: [PATCH 2/2] mac80211: Monitor mode radiotap-based packet injection
In reply to Michael WuQuoted 12 lines · Michael Wu
net/mac80211/ieee80211.c line 39
Quoted 10 lines · On Saturday 17 March 2007 06:58, [email protected] wrote:
net/mac80211/ieee80211.c +1
-0@@ -35,6 +35,7 @@#include "ieee80211_led.h" #include "ieee80211_cfg.h" #include "ieee80211_sysfs.h" +#include <net/ieee80211_radiotap.h> Already included by my patch.
OK. Not sure why that appears in my patch any longer then since I am using guilt thanks to your advice, and your patch is applied first.
Quoted 5 lines
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1103
Quoted 4 lines
net/mac80211/ieee80211.c +4
-0+int tap_index =0 ; +u8 *tap_arg = skb->data +sizeof (struct ieee80211_radiotap_header ); +u32 *curr_arg_bitmap = &rthdr->it_present; +u32 arg_bitmap=le32_to_cpu (*curr_arg_bitmap);Space before and after the =.
Fixed.
Quoted 3 lines
net/mac80211/ieee80211.c
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+ +if (rthdr->it_version)return TXRX_DROP ;/* version byte used as magic */ Space after the if.
Fixed.
Quoted 3 lines
net/mac80211/ieee80211.c
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+ +/* sanity check for skb length and radiotap length field */ Keep comments indented the same as everything else.
Fixed.
Quoted 3 lines
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1109
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+if (skb->len < (le16_to_cpu (rthdr->it_len) + +sizeof (struct ieee80211_hdr )))Using some spaces to align the start of the second line with the parenthesis often looks better.
Fixed and noted.
Quoted 4 lines
net/mac80211/ieee80211.c __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, · line 1243
Quoted 3 lines
net/mac80211/ieee80211.c +3
-0+/* process and remove the injection radiotap header */ + +if (control->flags &IEEE80211_TXCTL_INJECTED_PACKET ) {dev points to the virtual interface that the frame originally came in on. You can get sdata from that and figure out if the interface was a monitor interface.
replied in next mail...
-Andy