Try #5: Radiotap on Monitor Mode interfaces for rx and tx
Subsystems (3)
cover Try #5: Radiotap on Monitor Mode interfaces for rx and tx
Hi folks -
This set 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.
The patches should be based against wireless-dev.
I also added a documentation file patch which explains how to use the injection functionality.
PATCH 1/4 mac80211: Coding style cleanups
Stop existing code in ieee80211.c giving me panic attacks that I let my edits go over 80 cols
From: Andy Green <[email protected]>
net/mac80211/ieee80211.c +74 -39
@@ -275,7 +275,8 @@ EXPORT_SYMBOL(ieee80211_get_hdrlen);int ieee80211_get_hdrlen_from_skb (const struct sk_buff *skb) { -const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) skb->data; +const struct ieee80211_hdr *hdr = + (const struct ieee80211_hdr *) skb->data;int hdrlen;if (unlikely (skb->len <10 ))
@@ -489,7 +490,8 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx) fhdr = (struct ieee80211_hdr *)skb_put (frag, hdrlen);memcpy (fhdr, first->data, hdrlen);if (i == num_fragm -2 ) - fhdr->frame_control &=cpu_to_le16 (~IEEE80211_FCTL_MOREFRAGS ); + fhdr->frame_control &= +cpu_to_le16 (~IEEE80211_FCTL_MOREFRAGS ); fhdr->seq_ctrl =cpu_to_le16 (i +1 ); copylen = left > per_fragm ? per_fragm : left;memcpy (skb_put (frag, copylen), pos, copylen);
@@ -545,7 +547,8 @@ void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx)for (i =0 ; i < tx->u.tx.num_extra_frag; i++) { fhdr = (struct ieee80211_hdr *) tx->u.tx.extra_frag[i]->data; - fhdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_PROTECTED ); + fhdr->frame_control |= +cpu_to_le16 (IEEE80211_FCTL_PROTECTED ); } } }
@@ -861,7 +864,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)if (likely (tx->u.tx.unicast)) {if (unlikely (!(sta_flags &WLAN_STA_ASSOC ) && tx->sdata->type !=IEEE80211_IF_TYPE_IBSS && - (tx->fc &IEEE80211_FCTL_FTYPE ) ==IEEE80211_FTYPE_DATA )) { + (tx->fc &IEEE80211_FCTL_FTYPE ) +==IEEE80211_FTYPE_DATA )) {#ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: dropped data frame to not " "associated station " MAC_FMT "\n",
@@ -871,7 +875,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)return TXRX_DROP ; } }else { -if (unlikely ((tx->fc &IEEE80211_FCTL_FTYPE ) ==IEEE80211_FTYPE_DATA && +if (unlikely ((tx->fc &IEEE80211_FCTL_FTYPE ) == +IEEE80211_FTYPE_DATA && tx->local->num_sta ==0 && !tx->local->allow_broadcast_always && tx->sdata->type !=IEEE80211_IF_TYPE_IBSS )) {
@@ -982,7 +987,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)if (unlikely (!sta || ((tx->fc &IEEE80211_FCTL_FTYPE ) ==IEEE80211_FTYPE_MGMT && - (tx->fc &IEEE80211_FCTL_STYPE ) ==IEEE80211_STYPE_PROBE_RESP ))) + (tx->fc &IEEE80211_FCTL_STYPE ) == +IEEE80211_STYPE_PROBE_RESP )))return TXRX_CONTINUE ;if (unlikely ((sta->flags &WLAN_STA_PS ) && !sta->pspoll)) {
@@ -1012,7 +1018,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx) tx->local->ops->set_tim (local_to_hw (tx->local), sta->aid,1 );if (tx->sdata->bss) -bss_tim_set (tx->local, tx->sdata->bss, sta->aid); +bss_tim_set (tx->local, tx->sdata->bss, + sta->aid); } pkt_data = (struct ieee80211_tx_packet_data *)tx->skb->cb; pkt_data->jiffies = jiffies;
@@ -1146,7 +1153,8 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,int ret, i;if (skb) { -ieee80211_dump_frame (local->mdev->name,"TX to low-level driver" , skb); +ieee80211_dump_frame (local->mdev->name, +"TX to low-level driver" , skb); ret = local->ops->tx (local_to_hw (local), skb, control);if (ret)return IEEE80211_TX_AGAIN ;
@@ -1170,7 +1178,8 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,IEEE80211_TXCTL_RATE_CTRL_PROBE ; else control->flags &= - ~IEEE80211_TXCTL_RATE_CTRL_PROBE; + ~IEEE80211_TXCTL_RATE_CTRL_PROBE + ; } ieee80211_dump_frame(local->mdev->name,
@@ -1783,7 +1792,8 @@ struct sk_buff * ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id, rate =rate_control_get_rate (local, local->mdev, skb, &extra);if (!rate) {if (net_ratelimit ()) { -printk (KERN_DEBUG "%s: ieee80211_beacon_get: no rate " +printk (KERN_DEBUG +"%s: ieee80211_beacon_get: no rate " "found\n" , local->mdev->name); }dev_kfree_skb (skb);
@@ -1835,7 +1845,8 @@ EXPORT_SYMBOL(ieee80211_rts_duration);__le16 ieee80211_ctstoself_duration (struct ieee80211_hw *hw,size_t frame_len, -const struct ieee80211_tx_control *frame_txctl) +const struct ieee80211_tx_control + *frame_txctl) {struct ieee80211_local *local =hw_to_local (hw);struct ieee80211_rate *rate;
@@ -1885,7 +1896,8 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw, fctl =IEEE80211_FTYPE_CTL |IEEE80211_STYPE_CTS ; cts->frame_control =cpu_to_le16 (fctl); - cts->duration =ieee80211_ctstoself_duration (hw, frame_len, frame_txctl); + cts->duration =ieee80211_ctstoself_duration (hw, frame_len, + frame_txctl);memcpy (cts->ra, hdr->addr1,sizeof (cts->ra)); }EXPORT_SYMBOL (ieee80211_ctstoself_get);
@@ -2942,10 +2954,12 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)/* Use MoreData flag to indicate whether there are more * buffered frames for this STA */ if (no_pending_pkts) { - hdr->frame_control &=cpu_to_le16 (~IEEE80211_FCTL_MOREDATA ); + hdr->frame_control &= +cpu_to_le16 (~IEEE80211_FCTL_MOREDATA ); rx->sta->flags &= ~WLAN_STA_TIM ; }else - hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_MOREDATA ); + hdr->frame_control |= +cpu_to_le16 (IEEE80211_FCTL_MOREDATA );dev_queue_xmit (skb);
@@ -2954,7 +2968,8 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx) rx->local->ops->set_tim (local_to_hw (rx->local), rx->sta->aid,0 );if (rx->sdata->bss) -bss_tim_clear (rx->local, rx->sdata->bss, rx->sta->aid); +bss_tim_clear (rx->local, rx->sdata->bss, + rx->sta->aid); } #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG }else if (!rx->u.rx.sent_ps_buffered) {
@@ -3040,7 +3055,8 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, f_hdr = (struct ieee80211_hdr *) entry->skb_list.next->data; f_fc =le16_to_cpu (f_hdr->frame_control); -if ((fc &IEEE80211_FCTL_FTYPE ) != (f_fc &IEEE80211_FCTL_FTYPE ) || +if ((fc &IEEE80211_FCTL_FTYPE ) != + (f_fc &IEEE80211_FCTL_FTYPE ) ||compare_ether_addr (hdr->addr1, f_hdr->addr1) !=0 ||compare_ether_addr (hdr->addr2, f_hdr->addr2) !=0 )continue ;
@@ -3231,7 +3247,8 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)*/ if (unlikely (((rx->fc &IEEE80211_FCTL_FTYPE ) ==IEEE80211_FTYPE_DATA || ((rx->fc &IEEE80211_FCTL_FTYPE ) ==IEEE80211_FTYPE_CTL && - (rx->fc &IEEE80211_FCTL_STYPE ) ==IEEE80211_STYPE_PSPOLL )) && + (rx->fc &IEEE80211_FCTL_STYPE ) == +IEEE80211_STYPE_PSPOLL )) && rx->sdata->type !=IEEE80211_IF_TYPE_IBSS && (!rx->sta || !(rx->sta->flags &WLAN_STA_ASSOC )))) { if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
@@ -3445,7 +3462,8 @@ ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx)if (unlikely (rx->sdata->ieee802_1x && (rx->fc &IEEE80211_FCTL_FTYPE ) ==IEEE80211_FTYPE_DATA && - (rx->fc &IEEE80211_FCTL_STYPE ) !=IEEE80211_STYPE_NULLFUNC && + (rx->fc &IEEE80211_FCTL_STYPE ) != +IEEE80211_STYPE_NULLFUNC && (!rx->sta || !(rx->sta->flags &WLAN_STA_AUTHORIZED )) && !ieee80211_is_eapol (rx->skb))) {#ifdef CONFIG_MAC80211_DEBUG
@@ -3472,7 +3490,8 @@ ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx)/* Drop unencrypted frames if key is set. */ if (unlikely (!(rx->fc &IEEE80211_FCTL_PROTECTED ) && (rx->fc &IEEE80211_FCTL_FTYPE ) ==IEEE80211_FTYPE_DATA && - (rx->fc &IEEE80211_FCTL_STYPE ) !=IEEE80211_STYPE_NULLFUNC && + (rx->fc &IEEE80211_FCTL_STYPE ) != +IEEE80211_STYPE_NULLFUNC && (rx->key || rx->sdata->drop_unencrypted) && (rx->sdata->eapol ==0 || !ieee80211_is_eapol (rx->skb)))) {
@@ -3537,7 +3556,8 @@ ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx) local->scan.rx_beacon++;/* Need to trim FCS here because it is normally * removed only after this passive scan handler. */ -if ((rx->local->hw.flags &IEEE80211_HW_RX_INCLUDES_FCS ) && +if ((rx->local->hw.flags & +IEEE80211_HW_RX_INCLUDES_FCS ) && rx->skb->len >FCS_LEN )skb_trim (rx->skb, rx->skb->len -FCS_LEN );
@@ -3800,8 +3820,9 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,continue ; rx.u.rx.ra_match =0 ; }else if (!multicast && -compare_ether_addr (sdata->dev->dev_addr, - hdr->addr1) !=0 ) { +compare_ether_addr ( + sdata->dev->dev_addr, + hdr->addr1) !=0 ) {if (!sdata->promisc)continue ; rx.u.rx.ra_match =0 ;
@@ -3816,22 +3837,27 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,continue ; rx.u.rx.ra_match =0 ; }else if (!multicast && -compare_ether_addr (sdata->dev->dev_addr, - hdr->addr1) !=0 ) { +compare_ether_addr ( + sdata->dev->dev_addr, + hdr->addr1) !=0 ) {if (!sdata->promisc)continue ; rx.u.rx.ra_match =0 ; }else if (!sta) sta = rx.sta = -ieee80211_ibss_add_sta (local->mdev, - skb, bssid, - hdr->addr2); -/* FIXME: call with sdata->dev */ +ieee80211_ibss_add_sta ( + local->mdev, + skb, bssid, + hdr->addr2); +/* FIXME: call with +* sdata->dev +*/ break ;case IEEE80211_IF_TYPE_AP :if (!bssid) { -if (compare_ether_addr (sdata->dev->dev_addr, - hdr->addr1) !=0 ) +if (compare_ether_addr ( + sdata->dev->dev_addr, + hdr->addr1) !=0 )continue ; }else if (!ieee80211_bssid_match (bssid, sdata->dev->dev_addr)) {
@@ -3847,7 +3873,8 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,break ;case IEEE80211_IF_TYPE_WDS :if (bssid || - (rx.fc &IEEE80211_FCTL_FTYPE ) !=IEEE80211_FTYPE_DATA ) + (rx.fc &IEEE80211_FCTL_FTYPE ) != +IEEE80211_FTYPE_DATA )continue ;if (compare_ether_addr (sdata->u.wds.remote_addr, hdr->addr2) !=0 )
@@ -3859,9 +3886,11 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, skb_new =skb_copy (skb,GFP_ATOMIC );if (!skb_new) {if (net_ratelimit ()) -printk (KERN_DEBUG "%s: failed to copy " +printk (KERN_DEBUG +"%s: failed to copy " "multicast frame for %s" , - local->mdev->name, prev->dev->name); + local->mdev->name, + prev->dev->name);continue ; } rx.skb = skb_new;
@@ -4149,9 +4178,12 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; pkt_data->ifindex = control->ifindex; pkt_data->mgmt_iface = (control->type ==IEEE80211_IF_TYPE_MGMT ); - pkt_data->req_tx_status = !!(control->flags &IEEE80211_TXCTL_REQ_TX_STATUS ); - pkt_data->do_not_encrypt = !!(control->flags &IEEE80211_TXCTL_DO_NOT_ENCRYPT ); - pkt_data->requeue = !!(control->flags &IEEE80211_TXCTL_REQUEUE ); + pkt_data->req_tx_status = !!(control->flags & +IEEE80211_TXCTL_REQ_TX_STATUS ); + pkt_data->do_not_encrypt = !!(control->flags & +IEEE80211_TXCTL_DO_NOT_ENCRYPT ); + pkt_data->requeue = !!(control->flags & +IEEE80211_TXCTL_REQUEUE ); pkt_data->queue = control->queue; hdrlen =ieee80211_get_hdrlen_from_skb (skb);
@@ -4223,7 +4255,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,* that this TX packet failed because of that. */ status->excessive_retries =0 ; - status->flags |=IEEE80211_TX_STATUS_TX_FILTERED ; + status->flags |= +IEEE80211_TX_STATUS_TX_FILTERED ; }sta_info_put (sta); }
@@ -4254,9 +4287,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, &status->control);skb_queue_tail (&sta->tx_filtered, skb); }else if (!(sta->flags &WLAN_STA_PS ) && - !(status->control.flags &IEEE80211_TXCTL_REQUEUE )) { + !(status->control.flags & +IEEE80211_TXCTL_REQUEUE )) {/* Software retry the packet once */ - status->control.flags |=IEEE80211_TXCTL_REQUEUE ; + status->control.flags |= +IEEE80211_TXCTL_REQUEUE ;ieee80211_remove_tx_extra (local, sta->key, skb, &status->control);
Johannes Berg
maintainerRe: [PATCH 1/4] mac80211: Coding style cleanups
On Tue, 2007-03-20 at 10:39 +0000, [email protected] wrote:
I don't really see why this is necessary at all, but anyway.
net/mac80211/ieee80211.c ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx) · line 868
Quoted 3 lines
net/mac80211/ieee80211.c +2
-1- (tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { + (tx->fc & IEEE80211_FCTL_FTYPE) +== IEEE80211_FTYPE_DATA)) {
That's totally borked.
net/mac80211/ieee80211.c ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx) · line 879
Quoted 3 lines
net/mac80211/ieee80211.c +2
-1- if (unlikely((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && + if (unlikely((tx->fc & IEEE80211_FCTL_FTYPE) == + IEEE80211_FTYPE_DATA &&
Indent that a bit more so it's clear it belongs to the line above and isn't a condition itself.
net/mac80211/ieee80211.c ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx) · line 991
Quoted 5 lines
net/mac80211/ieee80211.c +2
-1if (unlikely (!sta || ((tx->fc &IEEE80211_FCTL_FTYPE ) ==IEEE80211_FTYPE_MGMT && - (tx->fc &IEEE80211_FCTL_STYPE ) ==IEEE80211_STYPE_PROBE_RESP ))) + (tx->fc &IEEE80211_FCTL_STYPE ) == +IEEE80211_STYPE_PROBE_RESP )))
ditto.
net/mac80211/ieee80211.c static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, · line 1182
Quoted 7 lines
net/mac80211/ieee80211.c +2
-1@@ -1170,7 +1178,8 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,IEEE80211_TXCTL_RATE_CTRL_PROBE ; else control->flags &= - ~IEEE80211_TXCTL_RATE_CTRL_PROBE; + ~IEEE80211_TXCTL_RATE_CTRL_PROBE + ;
ahem.
net/mac80211/ieee80211.c struct sk_buff * ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id, · line 1797
Quoted 4 lines
net/mac80211/ieee80211.c +2
-1-printk (KERN_DEBUG "%s: ieee80211_beacon_get: no rate " +printk (KERN_DEBUG +"%s: ieee80211_beacon_get: no rate " "found\n" , local->mdev->name);
Please change that to
... no " "rate found\n", ...
instead.
net/mac80211/ieee80211.c EXPORT_SYMBOL(ieee80211_rts_duration); · line 1849
Quoted 5 lines
net/mac80211/ieee80211.c +2
-1__le16 ieee80211_ctstoself_duration (struct ieee80211_hw *hw,size_t frame_len, -const struct ieee80211_tx_control *frame_txctl) +const struct ieee80211_tx_control + *frame_txctl)
That's not how the kernel looks like in that case. I'd prefer this as
__le16 ieee80211_ctstoself_duration(
struct ieee80211_hw *hw, size_t frame_len, const struct ieee80211_tx_control *frame_txctl)
net/mac80211/ieee80211.c ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx) · line 2972
Quoted 4 lines
net/mac80211/ieee80211.c +2
-1if (rx->sdata->bss) -bss_tim_clear (rx->local, rx->sdata->bss, rx->sta->aid); +bss_tim_clear (rx->local, rx->sdata->bss, + rx->sta->aid);
You have lots of space to indent it to the parenthesis.
net/mac80211/ieee80211.c ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, · line 3059
Quoted 3 lines
net/mac80211/ieee80211.c +2
-1- if ((fc & IEEE80211_FCTL_FTYPE) != (f_fc & IEEE80211_FCTL_FTYPE) || + if ((fc & IEEE80211_FCTL_FTYPE) != + (f_fc & IEEE80211_FCTL_FTYPE) ||
same as above.
net/mac80211/ieee80211.c ieee80211_rx_h_check(struct ieee80211_txrx_data *rx) · line 3251
Quoted 3 lines
net/mac80211/ieee80211.c +2
-1- (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) && + (rx->fc &IEEE80211_FCTL_STYPE ) == + IEEE80211_STYPE_PSPOLL)) &&
ditto.
net/mac80211/ieee80211.c ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx) · line 3466
Quoted 4 lines
net/mac80211/ieee80211.c +2
-1(rx->fc &IEEE80211_FCTL_FTYPE ) ==IEEE80211_FTYPE_DATA && - (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && + (rx->fc &IEEE80211_FCTL_STYPE ) != + IEEE80211_STYPE_NULLFUNC &&
ditto.
net/mac80211/ieee80211.c ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx) · line 3466
Quoted 3 lines
net/mac80211/ieee80211.c +2
-1- (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && + (rx->fc &IEEE80211_FCTL_STYPE ) != + IEEE80211_STYPE_NULLFUNC &&
ditto.
net/mac80211/ieee80211.c void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, · line 3827
Quoted 11 lines
net/mac80211/ieee80211.c +3
-2@@ -3800,8 +3820,9 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,continue ; rx.u.rx.ra_match =0 ; }else if (!multicast && -compare_ether_addr (sdata->dev->dev_addr, - hdr->addr1) !=0 ) { +compare_ether_addr ( + sdata->dev->dev_addr, + hdr->addr1) !=0 ) {if (!sdata->promisc)continue ;
Ugh. Somebody really needs to take this code and delete some indent by moving stuff into new functions.
net/mac80211/ieee80211.c void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, · line 3893
Quoted 8 lines
net/mac80211/ieee80211.c +4
-2if (net_ratelimit ()) -printk (KERN_DEBUG "%s: failed to copy " +printk (KERN_DEBUG +"%s: failed to copy " "multicast frame for %s" , - local->mdev->name, prev->dev->name); + local->mdev->name, + prev->dev->name);
Same as I said for that other message.
johannes
Re: [PATCH 1/4] mac80211: Coding style cleanups
Quoted 3 lines · Johannes Berg
On Tue, 2007-03-20 at 10:39 +0000, [email protected] wrote:
I don't really see why this is necessary at all, but anyway.
Yeah I cam to the same view -- I changed the file to match your suggestions here and realized that the (many) existing function defs do not follow your style recommendation. So I mass-changed them and it came to me I will only annoy the original author by this attempt at consistency. I started breaking out code into other functions and I realized I wasn't taking enough care, because it wasn't what I was trying to achieve, and would have to test it, might introduce bugs and would be run out of town by a mob with pitchforks.
I deleted the patch and learned to stop getting a tic in my eye every time a line > 80 cols flys by.
-Andy
PATCH 2/4 mac80211: Add radiotap support for Monitor mode RX
In reply to [email protected]Try #2
- Fix radiotap bitmap generation (Andy Green)
- Fix radiotap padding (Michael Wu)
From: Michael Wu <[email protected]>
---
include/net/mac80211.h | 3 ++ net/mac80211/ieee80211.c | 67 +++++++++++++++++++++++++++++++++------- net/mac80211/ieee80211_iface.c | 2 + 3 files changed, 59 insertions(+), 13 deletions(-)
include/net/mac80211.h +3 -0
@@ -518,6 +518,9 @@ struct ieee80211_hw {* normal operation. */ #define IEEE80211_HW_MONITOR_DURING_OPER (1<<9) +/* Driver supports radiotap. */ +#define IEEE80211_HW_RADIOTAP_SUPPORTED (1<<10) +/* please fill this gap when adding new flags */ /* calculate Michael MIC for an MSDU when doing hwcrypto */
net/mac80211/ieee80211.c +55 -12
118 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",
Johannes Berg
maintainerRe: [PATCH 2/4] mac80211: Add radiotap support for Monitor mode RX
net/mac80211/ieee80211.c void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, · line 3775
Quoted 9 lines
net/mac80211/ieee80211.c +7
-0+/* Driver supports radiotap. */ +#define IEEE80211_HW_RADIOTAP_SUPPORTED (1<<10) +if (local->monitors && + local->hw.flags &IEEE80211_HW_RADIOTAP_SUPPORTED ) { + radiotap_len =ieee80211_get_radiotap_len (skb); +skb_pull (skb, radiotap_len); + }
I don't think that can work.
1) it needs a lot more documentation on what a driver needs to do for this (for example that it should only add radiotap headers if a monitor interface was added)
2) afaik local->monitors is increased even for soft monitor interfaces, thus this will really fall on its nose when the driver supports radiotap but not monitor during operation.
johannes
Re: [PATCH 2/4] mac80211: Add radiotap support for Monitor mode RX
Quoted 11 lines · Johannes Berg
net/mac80211/ieee80211.c void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, · line 3775
Quoted 8 lines
net/mac80211/ieee80211.c +7
-0+/* Driver supports radiotap. */ +#define IEEE80211_HW_RADIOTAP_SUPPORTED (1<<10) +if (local->monitors && + local->hw.flags &IEEE80211_HW_RADIOTAP_SUPPORTED ) { + radiotap_len =ieee80211_get_radiotap_len (skb); +skb_pull (skb, radiotap_len); + }I don't think that can work.
Quoted 4 lines
1) it needs a lot more documentation on what a driver needs to do for this (for example that it should only add radiotap headers if a monitor interface was added)
Lack of documentation makes code not work?
Quoted 4 lines
2) afaik
local->monitorsis increased even for soft monitor interfaces, thus this will really fall on its nose when the driver supports radiotap but not monitor during operation.
Yes. I noted that in December when the patch was first posted. This will be fixed when I post a radiotap RX patch that's actually signed off. No sign off from me means it's not done and probably not tested enough if at all.
-Michael Wu
Johannes Berg
maintainerRe: [PATCH 2/4] mac80211: Add radiotap support for Monitor mode RX
Quoted 5 lines · Michael Wu
Quoted 4 lines
1) it needs a lot more documentation on what a driver needs to do for this (for example that it should only add radiotap headers if a monitor interface was added)
Lack of documentation makes code not work?
Heh, no, but it adds new driver API.
Quoted 7 lines
Quoted 4 lines
2) afaik
local->monitorsis increased even for soft monitor interfaces, thus this will really fall on its nose when the driver supports radiotap but not monitor during operation.Yes. I noted that in December when the patch was first posted. This will be fixed when I post a radiotap RX patch that's actually signed off. No sign off from me means it's not done and probably not tested enough if at all.
Ok, good.
johannes
PATCH 3/4 mac80211: Monitor mode radiotap injection docs
In reply to [email protected]From: Andy Green <[email protected]>
Documentation/networking/mac80211-injection.txt new file +77 -0
@@ -0,0 +1,77 @@ +How to use packet injection with mac80211 +========================================= + +mac80211 now allows arbitrary packets to be injected down any Monitor Mode +interface from userland. The packet you inject needs to be composed in the +following format: + + [ radiotap header ] + [ ieee80211 header ] + [ payload ] + +Radiotap headers are variable-length and extensible, you can get most of the +information you need to know on them from: + +./include/net/ieee80211_radiotap.h + +But note: all fields in the radiotap header are *little endian*. + +There is a fixed portion at the start which contains a u32 bitmap that defines +if the possible argument is present or not. At the moment there are only 13 +possible arguments defined, but in case we run out of space in the u32 it is +defined that b31 set indicates that there is another u32 bitmap following, and +the start of the arguments is moved forward 4 bytes each time. + +After the fixed part of the header, the arguments follow. + + - the arguments are all little-endian! + + - the arguments must be aligned to a boundary of the argument size using + padding. So a u16 argument must start on the next u16 boundary if it isn't + already on one, a u32 must start on the next u32 boundary and so on. + +Despite 13 radiotap argument types are currently defined, most only make sense +to appear on received packets. Currently three kinds of argument are used by +the injection code, although it knows to skip any other arguments that are +present (facilitating replay of captured radiotap headers directly): + + - IEEE80211_RADIOTAP_RATE - u8 arg in 500kbps units (0x02 --> 1Mbps) + + - IEEE80211_RADIOTAP_ANTENNA - u8 arg, 0x00 = ant1, 0x01 = ant2 + + - IEEE80211_RADIOTAP_DBM_TX_POWER - u8 arg, dBm + +Here is an example valid radiotap header defining these three parameters + + 0x00, 0x00, // <-- radiotap version + 0x0b, 0x00, // <- radiotap header length + 0x04, 0x0c, 0x00, 0x00, // <-- bitmap + 0x6c, // <-- rate + 0x0c, //<-- tx power + 0x01 //<-- antenna + +The ieee80211 header follows immediately afterwards, looking for example like +this: + + 0x08, 0x01, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x10, 0x86 + +Then lastly there is the payload. + +After composing the packet contents, it is sent by send()-ing it to a logical +mac80211 interface that is in Monitor mode. Libpcap can also be used, +(which is easier than doing the work to bind the socket to the right +interface), along the following lines: + + ppcap = pcap_open_live(szInterfaceName, 800, 1, 20, szErrbuf); +... + r = pcap_inject(ppcap, u8aSendBuffer, nLength); + +You can also find sources for a complete inject test applet here: + +http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammer + +Andy Green <[email protected]>
Johannes Berg
maintainerRe: [PATCH 3/4] mac80211: Monitor mode radiotap injection docs
Quoted 1 line · On Tue, 2007-03-20 at 10:39 +0000, [email protected] wrote:
+++
b/Documentation/networking/mac80211-injection.txt
This needs to be for cfg80211.
Documentation/networking/mac80211-injection.txt line 23
Quoted 12 lines
Documentation/networking/mac80211-injection.txt new file +12
-0+Radiotap headers are variable-length and extensible, you can get most of the +information you need to know on them from: + +./include/net/ieee80211_radiotap.h + +But note: all fields in the radiotap header are *little endian*. + +There is a fixed portion at the start which contains a u32 bitmap that defines +if the possible argument is present or not. At the moment there are only 13 +possible arguments defined, but in case we run out of space in the u32 it is +defined that b31 set indicates that there is another u32 bitmap following, and +the start of the arguments is moved forward 4 bytes each time.
Drop all that, it's generic radiotap description. Put it into another file if you want.
Documentation/networking/mac80211-injection.txt line 27
Quoted 3 lines
Documentation/networking/mac80211-injection.txt new file +3
-0+After the fixed part of the header, the arguments follow. + + - the arguments are all little-endian!
duplicated information.
Documentation/networking/mac80211-injection.txt line 62
Quoted 10 lines
Documentation/networking/mac80211-injection.txt new file +10
-0+The ieee80211 header follows immediately afterwards, looking for example like +this: + + 0x08, 0x01, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x10, 0x86 + +Then lastly there is the payload.
Scratch that, somebody who doesn't know how a IEEE 802.11 header looks like has no business reading that file anyway ;)
Documentation/networking/mac80211-injection.txt line 75
Quoted 11 lines
Libpcap can also be used,
Documentation/networking/mac80211-injection.txt new file +10
-0+(which is easier than doing the work to bind the socket to the right +interface), along the following lines: + + ppcap = pcap_open_live(szInterfaceName, 800, 1, 20, szErrbuf); +... + r = pcap_inject(ppcap, u8aSendBuffer, nLength); + +You can also find sources for a complete inject test applet here: + +http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammer
Is it big enough to warrant being elsewhere? I don't see how an example program can be more than a few lines of code and then it could be included here as a C file.
johannes
Re: [PATCH 3/4] mac80211: Monitor mode radiotap injection docs
Quoted 5 lines · Johannes Berg
Quoted 1 line · On Tue, 2007-03-20 at 10:39 +0000, [email protected] wrote:
+++
b/Documentation/networking/mac80211-injection.txtThis needs to be for cfg80211.
Well, the actual injection action is happening in mac80211. I think you're looking at it as a cfg80211 wext-replacing type thing and I am looking at it as completely generic mac80211 packet injection from userspace.
Quoted 7 lines
Quoted 7 lines
Documentation/networking/mac80211-injection.txt new file +7
-0+Radiotap headers are variable-length and extensible, you can get most of the +information you need to know on them from: + +./include/net/ieee80211_radiotap.h + +But note: all fields in the radiotap header are *little endian*. +
Quoted 8 lines
Documentation/networking/mac80211-injection.txt line 23
Quoted 5 lines
Documentation/networking/mac80211-injection.txt new file +5
-0+There is a fixed portion at the start which contains a u32 bitmap that defines +if the possible argument is present or not. At the moment there are only 13 +possible arguments defined, but in case we run out of space in the u32 it is +defined that b31 set indicates that there is another u32 bitmap following, and +the start of the arguments is moved forward 4 bytes each time.Drop all that, it's generic radiotap description. Put it into another file if you want.
This kind of description makes documentation useful to the reader, who may never have heard of radiotap (it is not very visible in Google right now in a useful way).
Quoted 5 lines
Documentation/networking/mac80211-injection.txt line 27
Quoted 3 lines
Documentation/networking/mac80211-injection.txt new file +3
-0+After the fixed part of the header, the arguments follow. + + - the arguments are all little-endian!duplicated information.
Yes when documenting something, you duplicate critical information, it is not an error but a static Forward Error Correction technology for lossy readers.
Quoted 5 lines
Quoted 5 lines
Documentation/networking/mac80211-injection.txt new file +5
-0+The ieee80211 header follows immediately afterwards, looking for example like +this: + + 0x08, 0x01, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
Quoted 8 lines
Documentation/networking/mac80211-injection.txt line 62
Quoted 5 lines
Documentation/networking/mac80211-injection.txt new file +5
-0+ 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, + 0x10, 0x86 + +Then lastly there is the payload.Scratch that, somebody who doesn't know how a IEEE 802.11 header looks like has no business reading that file anyway ;)
Everybody has to learn from nothing!
Quoted 7 lines
Quoted 7 lines
Libpcap can also be used,
Documentation/networking/mac80211-injection.txt new file +6
-0+(which is easier than doing the work to bind the socket to the right +interface), along the following lines: + + ppcap = pcap_open_live(szInterfaceName, 800, 1, 20, szErrbuf); +... + r = pcap_inject(ppcap, u8aSendBuffer, nLength);
Quoted 8 lines
Documentation/networking/mac80211-injection.txt line 75
Quoted 4 lines
Documentation/networking/mac80211-injection.txt new file +4
-0+ +You can also find sources for a complete inject test applet here: + +http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammerIs it big enough to warrant being elsewhere? I don't see how an example program can be more than a few lines of code and then it could be included here as a C file.
It's ~380 lines. It also knows how to conjure up management interfaces.
I can chop it down and put it in here if you feel it is important.
I appreciate the comments, but I am 100% sure that some correct documentation that may be over-chatty is better than no documentation at all. After hesitating and starting to change it I left it as it is, if you still feel these things are important comment in that direction again on the new patch and I will grit my teeth and change it.
-Andy
Johannes Berg
maintainerRe: [PATCH 3/4] mac80211: Monitor mode radiotap injection docs
Quoted 4 lines · Andy Green
Well, the actual injection action is happening in mac80211. I think you're looking at it as a cfg80211 wext-replacing type thing and I am looking at it as completely generic mac80211 packet injection from userspace.
Yeah. Don't worry about it. We can move it later and define it for cfg80211 when we introduce the userspace mlme stuff.
Quoted 6 lines
Quoted 2 lines
Drop all that, it's generic radiotap description. Put it into another file if you want.
This kind of description makes documentation useful to the reader, who may never have heard of radiotap (it is not very visible in Google right now in a useful way).
Maybe just stick it into a radiotap file and refer to that? I'm just a bit worried that it'll get outdated because somebody looking for radiotap stuff won't find it here when updating. Not sure it can even get outdated though.
Quoted 2 lines
It's ~380 lines. It also knows how to conjure up management interfaces.
I can chop it down and put it in here if you feel it is important.
It's probably easy enough to write from the docs so probably not really necessary. I think when I wrote this I was offline so couldn't actually check out the demo program ;)
Quoted 5 lines
I appreciate the comments, but I am 100% sure that some correct documentation that may be over-chatty is better than no documentation at all. After hesitating and starting to change it I left it as it is, if you still feel these things are important comment in that direction again on the new patch and I will grit my teeth and change it.
No, don't take me too seriously. I appreciate documentation I may not agree with in all points much more than the lack thereof :)
johannes
PATCH 4/4 mac80211: Monitor mode radiotap-based packet injection
In reply to [email protected]From: Andy Green <[email protected]>
Try #5
- De-indent last few indented comments
Try #4
- All from Michael Wu's feedback: further style heresies removed
- took account of radiotap arg alignment requirement. n-byte arg must be placed on n-byte boundary using padding where necessary
Try #3
- moved to Michael Wu's method of tracking if we came in on a monitor interface by using ifindex
- removed older proposed monitor interface tracking method and flags
- style fixes
- removed duped #include that is present in Michael Wu's patch already
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
===================================================
net/mac80211/ieee80211.c +264 -10
@@ -1054,7 +1054,180 @@ ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) } -static void inline +/* deal with packet injection down monitor interface +* with Radiotap Header -- only called for monitor mode interface +*/ + +static ieee80211_txrx_result +__ieee80211_convert_radiotap_to_control_and_remove ( +struct ieee80211_txrx_data *tx, +struct sk_buff *skb,struct ieee80211_tx_control *control) +{ +/* this is the moment to interpret the radiotap header that +* must be at the start of the packet injected in Monitor +* mode into control and then discard the radiotap header +* +* Need to take some care with endian-ness since radiotap +* is apparently a little-endian struct, including the args +* +* There is also some pervacious arg padding, so that args +* of a given length must begin at a boundary of that length +*/ + +struct ieee80211_radiotap_header *rthdr = + (struct ieee80211_radiotap_header *) skb->data; + +/* small length lookup table for all radiotap types we heard of +* starting from b0 in the bitmap, so we can walk the payload +* area of the radiotap header +*/ + +static const u8 radiotap_entry_sizes[] = { +8 ,/* IEEE80211_RADIOTAP_TSFT */ +1 ,/* IEEE80211_RADIOTAP_FLAGS */ +1 ,/* IEEE80211_RADIOTAP_RATE */ +4 ,/* IEEE80211_RADIOTAP_CHANNEL */ +2 ,/* IEEE80211_RADIOTAP_FHSS */ +1 ,/* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ +1 ,/* IEEE80211_RADIOTAP_DBM_ANTNOISE */ +2 ,/* IEEE80211_RADIOTAP_LOCK_QUALITY */ +2 ,/* IEEE80211_RADIOTAP_TX_ATTENUATION */ +2 ,/* IEEE80211_RADIOTAP_DB_TX_ATTENUATION */ +1 ,/* IEEE80211_RADIOTAP_DBM_TX_POWER */ +1 ,/* IEEE80211_RADIOTAP_ANTENNA */ +1 ,/* IEEE80211_RADIOTAP_DB_ANTSIGNAL */ +1 /* IEEE80211_RADIOTAP_DB_ANTNOISE */ +/* add more here as they are defined */ + }; +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); + +if (rthdr->it_version) +return TXRX_DROP ;/* version byte as magic */ + +/* sanity check for skb length and radiotap length field */ +if (skb->len < (le16_to_cpu (rthdr->it_len) + +sizeof (struct ieee80211_hdr ))) +return TXRX_DROP ; + +/* find payload start allowing for extended bitmap(s) */ + +if (le32_to_cpu (rthdr->it_present) &0x80000000 ) { +while (le32_to_cpu (*((u32 *)tap_arg)) &0x80000000 ) + tap_arg +=sizeof (u32); + tap_arg +=sizeof (u32); + } + +/* default control situation for all injected packets */ + + control->retry_limit =1 ;/* no retry */ + control->key_idx =-1 ;/* no encryption key */ + control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS | +IEEE80211_TXCTL_USE_CTS_PROTECT ); + control->flags |= (IEEE80211_TXCTL_DO_NOT_ENCRYPT | +IEEE80211_TXCTL_NO_ACK ); + control->antenna_sel_tx =0 ;/* default to default antenna */ + +/* for every radiotap entry we can at +* least skip (by knowing the length)... +*/ + +while (tap_index <sizeof (radiotap_entry_sizes)) { +int i, target_rate; + +if (!(arg_bitmap &1 )) + goto next_entry; + +/* arg is present, account for alignment padding +* 8-bit args can be at any alignment +* 16-bit args must start on 16-bit boundary +* 32-bit args must start on 32-bit boundary +* 64-bit args must start on 64-bit boundary +*/ + +if (((int )tap_arg) & (radiotap_entry_sizes[tap_index]-1 )) + tap_arg += radiotap_entry_sizes[tap_index]- + (((int )tap_arg) & + (radiotap_entry_sizes[tap_index]-1 )); + +/* see if this argument is something that interests us */ + +switch (tap_index) { + +case IEEE80211_RADIOTAP_RATE : +/* radiotap "rate" u8 is in +* 500kbps units, eg, 0x02=1Mbps +* ieee80211 "rate" int is +* in 100kbps units, eg, 0x0a=1Mbps +*/ + target_rate = (*tap_arg) *5 ; +for (i =0 ; i < tx->local->num_curr_rates; i++) { +struct ieee80211_rate *r = + &tx->local->curr_rates[i]; + +if (r->rate <= target_rate) { +if (r->flags & +IEEE80211_RATE_PREAMBLE2 ) { + control->tx_rate = r->val2; + }else { + control->tx_rate = r->val; + } + + +/* end on exact match */ +if (r->rate == target_rate) + i = tx->local->num_curr_rates; + } + } +break ; + +case IEEE80211_RADIOTAP_ANTENNA : +/* radiotap uses 0 for 1st ant, +* mac80211 is 1 for 1st ant +* absence of IEEE80211_RADIOTAP_ANTENNA +* gives default/diversity +*/ + control->antenna_sel_tx = (*tap_arg) +1 ; +break ; + +case IEEE80211_RADIOTAP_DBM_TX_POWER : + control->power_level = *tap_arg; +break ; + +default : +break ; + } + + tap_arg += radiotap_entry_sizes[tap_index]; + + next_entry: + + tap_index++; +if (unlikely ((tap_index &31 ) ==0 )) { +/* completed current u32 bitmap */ +if (arg_bitmap &1 ) {/* b31 was set, there is more */ +/* move to next u32 bitmap */ + curr_arg_bitmap++; + arg_bitmap =le32_to_cpu (*curr_arg_bitmap); + }else { +/* no more bitmaps: end */ + tap_index =sizeof (radiotap_entry_sizes); + } + }else {/* just try the next bit */ + arg_bitmap >>=1 ; + } + } + +/* remove the radiotap header */ +skb_pull (skb,le16_to_cpu (rthdr->it_len)); + +return TXRX_CONTINUE ; +} + + +static ieee80211_txrx_result inline __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, struct sk_buff *skb, struct net_device *dev,
@@ -1062,6 +1235,9 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, {struct ieee80211_local *local =wdev_priv (dev->ieee80211_ptr);struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; +struct ieee80211_sub_if_data *sdata; +ieee80211_txrx_result res =TXRX_CONTINUE ; +int hdrlen;memset (tx,0 ,sizeof (*tx));
@@ -1071,7 +1247,32 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, tx->sdata =IEEE80211_DEV_TO_SUB_IF (dev); tx->sta =sta_info_get (local, hdr->addr1); tx->fc =le16_to_cpu (hdr->frame_control); + +/* set defaults for things that can be set by +* injected radiotap headers +*/ + control->power_level = local->hw.conf.power_level; + control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; +if (local->sta_antenna_sel !=STA_ANTENNA_SEL_AUTO && tx->sta) + control->antenna_sel_tx = tx->sta->antenna_sel_tx; + +/* process and remove the injection radiotap header */ + + sdata =IEEE80211_DEV_TO_SUB_IF (dev); +if (unlikely (sdata->type ==IEEE80211_IF_TYPE_MNTR )) { +if (__ieee80211_convert_radiotap_to_control_and_remove ( + tx, skb, control) ==TXRX_DROP ) { +return TXRX_DROP ; + } +/* we removed the radiotap header after this point, +* we filled control with what we could use +* set to the actual ieee header now +*/ + hdr = (struct ieee80211_hdr *) skb->data; + res =TXRX_QUEUED ;/* indication it was monitor packet */ + } + tx->u.tx.control = control; tx->u.tx.unicast = !is_multicast_ether_addr (hdr->addr1);if (is_multicast_ether_addr (hdr->addr1))
@@ -1088,9 +1289,6 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, control->flags |=IEEE80211_TXCTL_CLEAR_DST_MASK ; tx->sta->clear_dst_mask =0 ; } - control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; -if (local->sta_antenna_sel !=STA_ANTENNA_SEL_AUTO && tx->sta) - control->antenna_sel_tx = tx->sta->antenna_sel_tx; hdrlen =ieee80211_get_hdrlen (tx->fc);if (skb->len > hdrlen +sizeof (rfc1042_header) +2 ) {u8 *pos = &skb->data[hdrlen +sizeof (rfc1042_header)];
@@ -1098,6 +1296,7 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, } control->flags |=IEEE80211_TXCTL_FIRST_FRAGMENT ; +return res; } static int inline is_ieee80211_device(struct net_device *dev,
@@ -1205,7 +1404,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,struct sta_info *sta;ieee80211_tx_handler *handler;struct ieee80211_txrx_data tx; -ieee80211_txrx_result res =TXRX_DROP ; +ieee80211_txrx_result res =TXRX_DROP , res_prepare;int ret, i;WARN_ON (__ieee80211_queue_pending (local, control->queue));
@@ -1215,14 +1414,24 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,return 0 ; } -__ieee80211_tx_prepare (&tx, skb, dev, control); + res_prepare =__ieee80211_tx_prepare (&tx, skb, dev, control); + +if (res_prepare ==TXRX_DROP ) { +dev_kfree_skb (skb); +return 0 ; + } + sta = tx.sta; tx.u.tx.mgmt_interface = mgmt; -for (handler = local->tx_handlers; *handler !=NULL ; handler++) { - res = (*handler)(&tx); -if (res !=TXRX_CONTINUE ) -break ; +if (res_prepare ==TXRX_QUEUED ) {/* if it was an injected packet */ + res =TXRX_CONTINUE ; + }else { +for (handler = local->tx_handlers; *handler !=NULL ; handler++) { + res = (*handler)(&tx); +if (res !=TXRX_CONTINUE ) +break ; + } } skb = tx.skb;/* handlers are allowed to change skb */
@@ -1456,6 +1665,51 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb, goto fail; } +if (unlikely (sdata->type ==IEEE80211_IF_TYPE_MNTR )) { +struct ieee80211_radiotap_header * prthdr = + (struct ieee80211_radiotap_header *)skb->data; + +/* there must be a radiotap header at the +* start in this case +*/ + +if (unlikely (prthdr->it_version)) { +/* radiotap version used as magic */ + ret =0 ; + goto fail; + } + + skb->dev = local->mdev; + + pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; +memset (pkt_data,0 ,sizeof (struct ieee80211_tx_packet_data )); + pkt_data->ifindex = sdata->dev->ifindex; + pkt_data->mgmt_iface =0 ; + pkt_data->do_not_encrypt =1 ; + +/* above needed because we set skb device to master */ + +/* fix up the pointers accounting for the radiotap +* header still being in there. We are being given +* a precooked IEEE80211 header so no need for +* normal processing +*/ + + skb->mac.raw = skb->data+prthdr->it_len; + skb->nh.raw = skb->data+prthdr->it_len+ +sizeof (struct ieee80211_hdr ); + skb->h.raw = skb->data+prthdr->it_len+ +sizeof (struct ieee80211_hdr ); + +/* pass the radiotap header up to +* the next stage intact +*/ + +dev_queue_xmit (skb); + +return 0 ; + } + nh_pos = skb->nh.raw - skb->data; h_pos = skb->h.raw - skb->data;
Johannes Berg
maintainerRe: [PATCH 4/4] mac80211: Monitor mode radiotap-based packet injection
Quoted 6 lines · On Tue, 2007-03-20 at 10:39 +0000, [email protected] wrote:
net/mac80211/ieee80211.c +0
-0@@ -1054,7 +1054,180 @@ ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) }
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1065
Quoted 10 lines
net/mac80211/ieee80211.c +9
-1-static void inline +/* deal with packet injection down monitor interface +* with Radiotap Header -- only called for monitor mode interface +*/ + +static ieee80211_txrx_result +__ieee80211_convert_radiotap_to_control_and_remove ( +struct ieee80211_txrx_data *tx, +struct sk_buff *skb,struct ieee80211_tx_control *control) +{
The actual parsing should live in cfg80211 (preferably in a new file) so that others can use it. If it's a lot of code then add a new invisible Kconfig symbol for it that drivers/stacks can select.
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1073
Quoted 1 line
net/mac80211/ieee80211.c +1
-0+* There is also some pervacious arg padding, so that args
perwhat?
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1087
Quoted 3 lines
net/mac80211/ieee80211.c +3
-0+static const u8 radiotap_entry_sizes[] = { +8 ,/* IEEE80211_RADIOTAP_TSFT */ +1 ,/* IEEE80211_RADIOTAP_FLAGS */
[...]
I'd prefer C99 style for this.
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1108
Quoted 1 line
net/mac80211/ieee80211.c +1
-0+return TXRX_DROP ;/* version byte as magic */
Bad idea. At least the comment. If you mean "drop the packet if it has a radiotap version we don't parse" then say so.
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1118
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+if (le32_to_cpu (rthdr->it_present) &0x80000000 ) { +while (le32_to_cpu (*((u32 *)tap_arg)) &0x80000000 )
Use a constant for that, introduce one if necessary.
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1126
Quoted 1 line
net/mac80211/ieee80211.c +1
-0+ control->key_idx =-1 ;/* no encryption key */
Is there any way to indicate encryption? I think there might need to be for 802.11w.
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1128
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+ control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS | +IEEE80211_TXCTL_USE_CTS_PROTECT );
These really should be selectable as well.
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1130
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+ control->flags |= (IEEE80211_TXCTL_DO_NOT_ENCRYPT | +IEEE80211_TXCTL_NO_ACK );
And NO_ACK is a really really totally bad idea for a userspace MLME. Needs to be selectable for sure.
We also need to be able to assign some magic cookie to a packet that we get back along with the packet so that we know when the injected packet has been acked by the peer.
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1224
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+/* remove the radiotap header */ +skb_pull (skb,le16_to_cpu (rthdr->it_len));
Shouldn't there be some sort of sanity check here so we don't pull too much if userspace asks us to?
net/mac80211/ieee80211.c static int ieee80211_subif_start_xmit(struct sk_buff *skb, · line 1677
Quoted 1 line
net/mac80211/ieee80211.c +1
-0+/* radiotap version used as magic */
Same comment as above, there's nothing magic about the radiotap version.
johannes
Re: [PATCH 4/4] mac80211: Monitor mode radiotap-based packet injection
Johannes Berg wrote:
Hi Johannes -
I am going to issue a new patch set for the injection stuff shortly, so I can reply to your comments with what has happened about them.
Quoted 3 lines
The actual parsing should live in cfg80211 (preferably in a new file) so that others can use it. If it's a lot of code then add a new invisible
Kconfigsymbol for it thatdrivers/stackscan select.
I did this -- it's pretty small so I just added it to the Makefile.
Quoted 3 lines
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1073
Quoted 1 line
net/mac80211/ieee80211.c +1
-0+* There is also some pervacious arg padding, so that args perwhat?
http://www.urbandictionary.com/define.php?term=pervacious
Rephrased to something less exciting.
Quoted 6 lines
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1087
Quoted 3 lines
net/mac80211/ieee80211.c +3
-0+static const u8 radiotap_entry_sizes[] = { +8 ,/* IEEE80211_RADIOTAP_TSFT */ +1 ,/* IEEE80211_RADIOTAP_FLAGS */ [...]
I'd prefer C99 style for this.
Shocked that stuff from as late as 1999 is allowed. I normally use // myself, I was making a special effort.
Quoted 4 lines
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1108
Quoted 1 line
net/mac80211/ieee80211.c +1
-0+return TXRX_DROP ;/* version byte as magic */ Bad idea. At least the comment. If you mean "drop the packet if it has a radiotap version we don't parse" then say so.
the PRISM format stuff that this replaces (on rx anyway) has an explicit magic at the start. Hence the thought to treat the version byte as a "magic". But changed.
Quoted 4 lines
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1118
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+if (le32_to_cpu (rthdr->it_present) &0x80000000 ) { +while (le32_to_cpu (*((u32 *)tap_arg)) &0x80000000 )Use a constant for that, introduce one if necessary.
Done.
Quoted 10 lines
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1126
Quoted 1 line
net/mac80211/ieee80211.c +1
-0+ control->key_idx =-1 ;/* no encryption key */ Is there any way to indicate encryption? I think there might need to be for 802.11w.
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1128
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+ control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS | +IEEE80211_TXCTL_USE_CTS_PROTECT );These really should be selectable as well.
Quoted 5 lines
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1130
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+ control->flags |= (IEEE80211_TXCTL_DO_NOT_ENCRYPT | +IEEE80211_TXCTL_NO_ACK );And
NO_ACKis a really really totally bad idea for a userspace MLME. Needs to be selectable for sure.
Yes to cover more usage cases setting more things is needed. The game seems to be to set the elements of the control struct from the radiotap header. For clear discussion here is the list of things that can be set in control, first the ones we allow control of with this patch
int tx_rate; /* Transmit rate, given as the hw specific value for the
* rate (from struct ieee80211_rate) */
u8 power_level; /* per-packet transmit power level, in dBm */
u8 antenna_sel_tx; /* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
and the ones we might possibly want to fiddle with
int rts_cts_rate; /* Transmit rate for RTS/CTS frame, given as the hw
* specific value for the rate (from
* struct ieee80211_rate) */
u32 flags; /* tx control flags defined
* above */
u8 retry_limit; /* 1 = only first attempt, 2 = one retry, .. */
s8 key_idx; /* -1 = do not encrypt, >= 0 keyidx from
* hw->set_key() */
u8 icv_len; /* length of the ICV/MIC field in octets */
u8 iv_len; /* length of the IV field in octets */
u8 tkip_key[16]; /* generated phase2/phase1 key for hw TKIP */
u8 queue; /* hardware queue to use for this frame;
* 0 = highest, hw->queues-1 = lowest */
u8 sw_retry_attempt; /* number of times hw has tried to
* transmit frame (not incl. hw retries) */
int alt_retry_rate; /* retry rate for the last retries, given as the
* hw specific value for the rate (from
* struct ieee80211_rate). To be used to limit
* packet dropping when probing higher rates, if hw
* supports multiple retry rates. -1 = not used */
the flags are these
#define IEEE80211_TXCTL_REQ_TX_STATUS (1<<0)/* request TX status callback for
* this frame */
#define IEEE80211_TXCTL_DO_NOT_ENCRYPT (1<<1) /* send this frame without
* encryption; e.g., for EAPOL
* frames */
#define IEEE80211_TXCTL_USE_RTS_CTS (1<<2) /* use RTS-CTS before sending
* frame */
#define IEEE80211_TXCTL_USE_CTS_PROTECT (1<<3) /* use CTS protection for the
* frame (e.g., for combined
* 802.11g / 802.11b networks) */
#define IEEE80211_TXCTL_NO_ACK (1<<4) /* tell the low level not to
* wait for an ack */
#define IEEE80211_TXCTL_RATE_CTRL_PROBE (1<<5)
#define IEEE80211_TXCTL_CLEAR_DST_MASK (1<<6)
#define IEEE80211_TXCTL_REQUEUE (1<<7)
#define IEEE80211_TXCTL_FIRST_FRAGMENT (1<<8) /* this is a first fragment of
* the frame */
#define IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY (1<<9)
I guess the method is to work out what is useful to control and to define a minimal set of new radiotap arg indexes to cover them, and propose it to the radiotap folks.
Quoted 3 lines
We also need to be able to assign some magic cookie to a packet that we get back along with the packet so that we know when the injected packet has been acked by the peer.
The idea here is to synthesize an rx packet later after the tx has happened, reflecting the tx status back to userspace that way (if he elects to listen out for them)?
Quoted 5 lines
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1224
Quoted 2 lines
net/mac80211/ieee80211.c +2
-0+/* remove the radiotap header */ +skb_pull (skb,le16_to_cpu (rthdr->it_len));Shouldn't there be some sort of sanity check here so we don't pull too much if userspace asks us to?
The sanity check for length of the radiotap header vs length of the packet is done right after the mag-^H^H^H version test. It is moved into the radiotap iteration init function in cfg80211 in the new patches.
-Andy
Johannes Berg
maintainerRe: [PATCH 4/4] mac80211: Monitor mode radiotap-based packet injection
Quoted 9 lines · Andy Green
Quoted 6 lines
net/mac80211/ieee80211.c ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) · line 1087
Quoted 3 lines
net/mac80211/ieee80211.c +3
-0+static const u8 radiotap_entry_sizes[] = { +8 ,/* IEEE80211_RADIOTAP_TSFT */ +1 ,/* IEEE80211_RADIOTAP_FLAGS */ [...]
I'd prefer C99 style for this.
Shocked that stuff from as late as 1999 is allowed. I normally use // myself, I was making a special effort.
Oh, dang, that was ambiguous. I was thinking
static const u8 radiotap_entry_sizes[] = {
[IEEE80211_RADIOTAP_TSFT] = 8,
...Quoted 56 lines
Yes to cover more usage cases setting more things is needed. The game seems to be to set the elements of the control struct from the radiotap header. For clear discussion here is the list of things that can be set in control, first the ones we allow control of with this patch
int
tx_rate; /* Transmit rate, given as the hw specific value for the
* rate (from structieee80211_rate) */
u8power_level; /* per-packet transmit power level, in dBm */
u8antenna_sel_tx; /* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */and the ones we might possibly want to fiddle with
int
rts_cts_rate; /* Transmit rate for RTS/CTS frame, given as the hw
* specific value for the rate (from
* structieee80211_rate) */
u32 flags; /* tx control flags defined
* above */
u8retry_limit; /* 1 = only first attempt, 2 = one retry, .. */
s8key_idx; /* -1 = do not encrypt, >= 0 keyidx from
*hw->set_key()*/
u8icv_len; /* length of the ICV/MIC field in octets */
u8iv_len; /* length of the IV field in octets */
u8 tkip_key[16]; /* generated phase2/phase1 key for hw TKIP */
u8 queue; /* hardware queue to use for this frame;
* 0 = highest, hw->queues-1 = lowest */
u8sw_retry_attempt; /* number of times hw has tried to
* transmit frame (not incl. hw retries) */
intalt_retry_rate; /* retry rate for the last retries, given as the
* hw specific value for the rate (from
* structieee80211_rate). To be used to limit
* packet dropping when probing higher rates, if hw
* supports multiple retry rates. -1 = not used */the flags are these
#define
IEEE80211_TXCTL_REQ_TX_STATUS(1<<0)/* request TX status
callback for
* this frame */
#defineIEEE80211_TXCTL_DO_NOT_ENCRYPT(1<<1) /* send this frame without
* encryption; e.g., for EAPOL
* frames */
#defineIEEE80211_TXCTL_USE_RTS_CTS(1<<2) /* use RTS-CTS before sending
* frame */
#defineIEEE80211_TXCTL_USE_CTS_PROTECT(1<<3) /* use CTS protection for the
* frame (e.g., for combined
* 802.11g / 802.11b networks) */
#defineIEEE80211_TXCTL_NO_ACK(1<<4) /* tell the low level not to
* wait for an ack */
#defineIEEE80211_TXCTL_RATE_CTRL_PROBE(1<<5)
#defineIEEE80211_TXCTL_CLEAR_DST_MASK(1<<6)
#defineIEEE80211_TXCTL_REQUEUE(1<<7)
#defineIEEE80211_TXCTL_FIRST_FRAGMENT(1<<8) /* this is a first fragment of
* the frame */
#defineIEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY(1<<9)
Quoted 3 lines
I guess the method is to work out what is useful to control and to define a minimal set of new radiotap arg indexes to cover them, and propose it to the radiotap folks.
Yeah, not really necessary right from the start anyway. It's doable which is/was my biggest concern.
Quoted 3 lines
The idea here is to synthesize an rx packet later after the tx has happened, reflecting the tx status back to userspace that way (if he elects to listen out for them)?
Yeah. Michael Wu says we don't need the magic cookie though.
johannes
Re: [PATCH 4/4] mac80211: Monitor mode radiotap-based packet injection
Quoted 7 lines · Johannes Berg
Quoted 5 lines · Andy Green
Quoted 5 lines
Quoted 3 lines
net/mac80211/ieee80211.c +3
-0+static const u8 radiotap_entry_sizes[] = { +8 ,/* IEEE80211_RADIOTAP_TSFT */ +1 ,/* IEEE80211_RADIOTAP_FLAGS */ [...]
Quoted 7 lines
Quoted 2 lines
Quoted 1 line
I'd prefer C99 style for this.
Shocked that stuff from as late as 1999 is allowed. I normally use // myself, I was making a special effort.
Oh, dang, that was ambiguous. I was thinking
static const u8 radiotap_entry_sizes[] = { [IEEE80211_RADIOTAP_TSFT] = 8, ...
Ha, well I will fix that up then. I couldn't really understand how the coding style that insists to turn code into 80-col Bonsai Kittens can also allow //.
Quoted 3 lines
Quoted 1 line
The idea here is to synthesize an rx packet later after the tx has happened, reflecting the tx status back to userspace that way (if he elects to listen out for them)?
Yeah. Michael Wu says we don't need the magic cookie though.
I missed this conversation evidently, didn't find it just now either. In case the plan is to block the thread doing the injection until the packet has gone out and is retired and can return an "acknowledged" status direct to the send()er, throughput is an issue.
-Andy
Johannes Berg
maintainerRe: [PATCH 4/4] mac80211: Monitor mode radiotap-based packet injection
Quoted 1 line · Andy Green
I missed this conversation evidently, didn't find it just now either.
Sorry. It was on IRC.
Quoted 3 lines
In case the plan is to block the thread doing the injection until the packet has gone out and is retired and can return an "acknowledged" status direct to the send()er, throughput is an issue.
I don't think that's the plan. But apparently the current interface doesn't allow userspace to exactly map the sent packet to the tx status it gets in the monitor interface (when the sent packet shows up there). I'm a bit worried that it would need such an exact mapping especially when others may be injecting frames at the same time, but I suppose that can be solved when we get to it.
johannes
Johannes Berg
maintainerQuoted 2 lines · On Tue, 2007-03-20 at 10:39 +0000, [email protected] wrote:
For injecting packets, the you issue a packet using libpcap or a
SOCK_PACKETsocket down an interface to the wireless device that is in Monitor Mode.
Ok so people don't want to have this in cfg80211, all the better for me since it's less work.
I urge you to solve the issues with this injection interface, we've established that you can use packet filters to grab only management frames but monitor interfaces definitely still interact very badly with power management, and when the hardware has a BSS filter then this will also be disabled with a monitor interface (if monitor during operation is supported) which again puts more load on the host.
I have previously suggested to use the IFF_PROMISC bit for this, but this will also need good driver/stack API since currently drivers that support monitor during operation will just turn off BSS filters and such when a monitor interface is added. That will have to be changed in drivers as well.
Also, and I'm going to reply to your patches as well, this is not something that should be restricted to mac80211 since cfg80211 generically supports virtual interfaces and anybody could in theory use a userspace MLME even with a full-mac card given a special no-management firmware mode. Hence, this should be documented for cfg80211 users.
Please work out these issues before adding this interface to the kernel.
johannes
Quoted 10 lines · Johannes Berg
Ok so people don't want to have this in cfg80211, all the better for me since it's less work.
I urge you to solve the issues with this injection interface, we've established that you can use packet filters to grab only management frames but monitor interfaces definitely still interact very badly with power management, and when the hardware has a BSS filter then this will also be disabled with a monitor interface (if monitor during operation is supported) which again puts more load on the host.
Quoted 6 lines
I have previously suggested to use the
IFF_PROMISCbit for this, but this will also need good driver/stack API since currently drivers that support monitor during operation will just turn off BSS filters and such when a monitor interface is added. That will have to be changed in drivers as well.
Note that my patch predates the suggestion that IFF_PROMISC be used to turn on monitor mode on the hardware. (2006-12-18) I merely updated it so that monitor interfaces output radiotap whether or not the driver supports.
This patch series is not meant to replace the management interface. I just gave Andy Green the radiotap RX patch so he could do some work in the right direction, but that patch isn't complete by itself. (That's why I didn't sign off on it) In particular, patches doing these things in addition to what this current patch series does will be needed to finally remove the management interface:
1. Make it easy to flip monitor mode on and off in drivers and support your IFF_PROMISC suggestion.
2. Make the use of radiotap by drivers configurable independently of monitor mode.
3. Report the result of a TX through monitor interfaces after ieee80211_tx_status is called. This requires new radiotap definitions.
4. Move things like radar detection and the rest of ieee80211_msg_* to cfg/nl80211 if they are necessary.
5. Port hostap and wpa_supplicant to the new interface. Will require some fun with packet filtering..
6. Kill the mgmt interface once and for all.
We don't need to replace the mgmt interface at once however. Addressing the first two issues should be sufficient to merge the radiotap RX/TX patches. After that, 3-6 can be done one by one.
-Michael Wu
Johannes Berg
maintainerQuoted 3 lines · Michael Wu
Note that my patch predates the suggestion that
IFF_PROMISCbe used to turn on monitor mode on the hardware. (2006-12-18) I merely updated it so that monitor interfaces output radiotap whether or not the driver supports.
Right.
Quoted 1 line
This patch series is not meant to replace the management interface.
I know. However, ultimately something that will grow out of this patch series will replace the management interface, otherwise this just adds redundant API.
Quoted 12 lines
1. Make it easy to flip monitor mode on and off in drivers and support your
IFF_PROMISCsuggestion.
2. Make the use of radiotap by drivers configurable independently of monitor mode.
3. Report the result of a TX through monitor interfaces afterieee80211_tx_statusis called. This requires new radiotap definitions.
4. Move things like radar detection and the rest of ieee80211_msg_* to cfg/nl80211 if they are necessary.
5. Port hostap andwpa_supplicantto the new interface. Will require some fun with packet filtering..
6. Kill the mgmt interface once and for all.
Quoted 3 lines
We don't need to replace the mgmt interface at once however. Addressing the first two issues should be sufficient to merge the radiotap RX/TX patches. After that, 3-6 can be done one by one.
Those are all good points, and 1 isn't even required for just this injection stuff that Andy is after, but I don't like adding this API without having a clear plan of how it can replace the management interface. One of the things you haven't convinced me of is that you will be able to convince the BSD people to add new radiotap definitions that we need. Also, if we can't have a good way to know exactly and easily which frame we have when we see one on ACK (the cookie thing about mapping injected frames to status updates) then I don't see how this can possibly replace the management interface.
johannes
Quoted 7 lines · Johannes Berg
Quoted 2 lines · On Tue, 2007-03-20 at 10:39 +0000, [email protected] wrote:
For injecting packets, the you issue a packet using libpcap or a
SOCK_PACKETsocket down an interface to the wireless device that is in Monitor Mode.Ok so people don't want to have this in cfg80211, all the better for me since it's less work.
$ cd wireless-dev $ grep cfg80211 Documentation/* -R
As a Johnny-come-lately noob, how should I find out that cfg80211 either exists or how it works? Far from some kind of turf war initiating gauntlet throwing, I was unaware cfg80211 was an option.
My interest is being able to inject broadcast packets from userspace with fine control over how it goes out. I have now tried several ways to get that to happen with varying success, patching drivers in the old stack (worked but impractical for wide uptake), using the management interface in the new stack (works but it is heading towards deprecation and did not allow rate control) and finally the Monitor mode injection (works perfectly but requires to convince you guys to include it).
send()ing packets back up a Monitor Mode interface with the same radiotap semantics as the came out of it with is the most natural and portable (libpcap pcap_inject() just works with it on the same network interface as it can capture on) way to do injection from a usermode and architectural standpoint.
I wouldn't say it is the "best" way to push the weirdo wext/prism Ioctls out of the stack, I don't know enough about the details of it, but I don't think this and the cfg80211 methods need to be in conflict. In a real sense you can look at this patchset as intending to max out the promise of libpcap to usermode. Sine they then have enough tools, if someone wants to implement a userspace MLME or other unthinkable hacks in userspace their way is open without any more kernelside cooperation needed.
Quoted 6 lines
I urge you to solve the issues with this injection interface, we've established that you can use packet filters to grab only management frames but monitor interfaces definitely still interact very badly with power management, and when the hardware has a BSS filter then this will also be disabled with a monitor interface (if monitor during operation is supported) which again puts more load on the host.
Those aren't issues with "this injection interface" but in optimizing the receive action for the existing Monitor mode.
Quoted 5 lines
I have previously suggested to use the
IFF_PROMISCbit for this, but this will also need good driver/stack API since currently drivers that support monitor during operation will just turn off BSS filters and such when a monitor interface is added. That will have to be changed in drivers as well.
Sure. Monitor mode can deliver sensible default results with IFF_PROMISC off: it will just show traffic that was flying about inside the associated connection with the client anyway. Just making the only way to enable hardware promisc being via IFF_PROMISC ioctl handler will allow control over whether you want to see everything with the power hit (the power hit doesn't matter for a box wired to the mains) or you just want to see things aimed at you. So it sounds like a good enhancement exploiting an existing traditional attribute whatever way you look at it.
Quoted 5 lines
Also, and I'm going to reply to your patches as well, this is not something that should be restricted to mac80211 since cfg80211 generically supports virtual interfaces and anybody could in theory use a userspace MLME even with a full-mac card given a special no-management firmware mode. Hence, this should be documented for cfg80211 users.
I don't understand why Monitor Mode injection needs to fly under the cfg80211 flag. It seems to belong to mac80211 code and would continue to work if cfg80211 was disabled. Can you explain a bit more why it logically belongs in that category?
-Andy
Johannes Berg
maintainerQuoted 6 lines · Andy Green
$ cd wireless-dev $ grep cfg80211 Documentation/* -RAs a Johnny-come-lately noob, how should I find out that cfg80211 either exists or how it works? Far from some kind of turf war initiating gauntlet throwing, I was unaware cfg80211 was an option.
Yep, my mistake. I blame lack of time and cooperation, nobody but me seems to be actually interested in working on cfg80211.
Quoted 7 lines
My interest is being able to inject broadcast packets from userspace with fine control over how it goes out. I have now tried several ways to get that to happen with varying success, patching drivers in the old stack (worked but impractical for wide uptake), using the management interface in the new stack (works but it is heading towards deprecation and did not allow rate control) and finally the Monitor mode injection (works perfectly but requires to convince you guys to include it).
Yep, I know.
Quoted 5 lines
send()ing packets back up a Monitor Mode interface with the same radiotap semantics as the came out of it with is the most natural and portable (libpcap
pcap_inject()just works with it on the same network interface as it can capture on) way to do injection from a usermode and architectural standpoint.
Right, and I'm not saying it doesn't make sense. I'm just trying to say that before we add this interface we really need to figure out whether it's feasible that this interface replaces all the wext/prism ioctl foo.
Quoted 4 lines
I don't understand why Monitor Mode injection needs to fly under the cfg80211 flag. It seems to belong to mac80211 code and would continue to work if cfg80211 was disabled. Can you explain a bit more why it logically belongs in that category?
Because of the userspace MLME that cfg80211 needs to support. At the second wireless summit in London we have decided that the userspace MLME should be transparent to users in that they still simply use nl80211 and the kernel forwards the requests to the userspace MLME and also forwards the responses. Therefore, most of the userspace MLME handling needs to live in cfg80211, which makes cfg80211 also the logical point to define injection at since the userspace MLME requires it.
johannes
Johannes Berg
maintainerHi,
Here are some more issues using monitor interfaces for management that will need to be addressed before I'm convinced that doing injection on monitor interfaces is viable.
If the driver does not support radiotap, ieee80211_rx_monitor needs to expand the head for each packet. Currently, this is also true, but since currently no non-management frames are sent down the management interface, this is not an issue. If each data packet needs to be first reallocated though, it quickly becomes a problem for low-power embedded access points running hostapd.
Additionally, the overhead of tacking on radiotap headers to each received frame is also rather high if you're only interested in receiving the information for management frames.
johannes
Quoted 7 lines · Johannes Berg
If the driver does not support radiotap,
ieee80211_rx_monitorneeds to expand the head for each packet. Currently, this is also true, but since currently no non-management frames are sent down the management interface, this is not an issue. If each data packet needs to be first reallocated though, it quickly becomes a problem for low-power embedded access points running hostapd.
That's why drivers should be modified to support radiotap.
Quoted 4 lines
Additionally, the overhead of tacking on radiotap headers to each received frame is also rather high if you're only interested in receiving the information for management frames.
It's really not that much overhead.
-Michael Wu