Skip to contentSkip to conversation

Try #5: Radiotap on Monitor Mode interfaces for rx and tx

PATCH In review [email protected] 3 participants 25 messages Mar 20, 2007 – Mar 29, 2007

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

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.

#1 lore raw

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
index 577dbe3..c598c9d 100644
@@ -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);
maintainer
#2 lore raw

Re: [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 -1
 	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)))

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 -1
 			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);

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 -2
 					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);

Same as I said for that other message.

johannes

author
#3 lore raw

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

#4 lore raw

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
index 916b21b..27cffdc 100644
@@ -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
index 3e0b4fa..51197b1 100644
@@ -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",
maintainer
#5 lore raw

Re: [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

#6 lore raw

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->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.

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

maintainer
#7 lore raw

Re: [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->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.

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

#8 lore raw

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
new file mode 100644
index 0000000..bee8931
@@ -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]>
maintainer
#9 lore raw

Re: [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

author
#10 lore raw

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.txt

This 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=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.

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

maintainer
#11 lore raw

Re: [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

#12 lore raw

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
index fb33b90..fe15612 100644
@@ -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;
 
maintainer
#13 lore raw

Re: [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

author
#14 lore raw

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 Kconfig symbol for it that drivers/stacks can 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_ACK is 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

maintainer
#15 lore raw

Re: [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 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)

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

author
#16 lore raw

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

maintainer
#17 lore raw

Re: [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

maintainer
#18 lore raw
In reply to [email protected]
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_PACKET socket 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

#19 lore raw
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_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.

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

maintainer
#20 lore raw
Quoted 3 lines · Michael Wu

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.

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_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.

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

author
#21 lore raw
In reply to Johannes Berg
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_PACKET socket 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_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.

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

maintainer
#22 lore raw
Quoted 6 lines · Andy Green
$ 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.

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

maintainer
#23 lore raw
In reply to [email protected]

Hi,

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

#24 lore raw
Quoted 7 lines · Johannes Berg

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.

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