lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Sat, 16 Dec 2006 18:01:03 -0500
From:	Michael Wu <flamingice@...rmilk.net>
To:	Jiri Benc <jbenc@...e.cz>
Cc:	netdev@...r.kernel.org, John Linville <linville@...driver.com>
Subject: [PATCH] d80211: add radiotap support

d80211: add radiotap support

This patch adds support for radiotap to d80211. The driver must set
IEEE80211_HW_MONITOR_DURING_OPER as well as
IEEE80211_HW_RADIOTAP_SUPPORTED, and it must send radiotap frames when
there is at least one monitor interface up. Tested with zd1211rw-d80211.

Signed-off-by: Michael Wu <flamingice@...rmilk.net>
---

 include/net/d80211.h         |    3 +++
 net/d80211/ieee80211.c       |   43 ++++++++++++++++++++++++++++++++----------
 net/d80211/ieee80211_iface.c |    5 ++++-
 3 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/include/net/d80211.h b/include/net/d80211.h
index 30980e1..27b2487 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -501,6 +501,9 @@ struct ieee80211_hw {
 	 * per-packet RC4 key with each TX frame when doing hwcrypto */
 #define IEEE80211_HW_TKIP_REQ_PHASE2_KEY (1<<14)
 
+	/* Driver supports radiotap. Temporary until all drivers support it. */
+#define IEEE80211_HW_RADIOTAP_SUPPORTED (1<<20)
+
 	u32 flags;			/* hardware flags defined above */
 
 	/* Set to the size of a needed device specific skb headroom for TX skbs. */
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 6e10db5..c686f02 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -8,6 +8,7 @@
  */
 
 #include <net/d80211.h>
+#include <net/ieee80211_radiotap.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
@@ -284,6 +285,14 @@ int ieee80211_get_hdrlen_from_skb(struct
 }
 EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
 
+static int ieee80211_get_radiotap_len(struct sk_buff *skb)
+{
+	struct ieee80211_radiotap_header *hdr =
+		(struct ieee80211_radiotap_header *) skb->data;
+
+	return le16_to_cpu(hdr->it_len);
+}
+
 #ifdef CONFIG_D80211_LOWTX_FRAME_DUMP
 static void ieee80211_dump_frame(const char *ifname, const char *title,
 				 struct sk_buff *skb)
@@ -2650,24 +2659,26 @@ ieee80211_rx_monitor(struct net_device *
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-	if (skb_headroom(skb) < hlen) {
-		I802_DEBUG_INC(local->rx_expand_skb_head);
-		if (pskb_expand_head(skb, hlen, 0, GFP_ATOMIC)) {
-			dev_kfree_skb(skb);
-                        return;
+	if (!(local->hw.flags & IEEE80211_HW_RADIOTAP_SUPPORTED)) {
+		if (skb_headroom(skb) < hlen) {
+			I802_DEBUG_INC(local->rx_expand_skb_head);
+			if (pskb_expand_head(skb, hlen, 0, GFP_ATOMIC)) {
+				dev_kfree_skb(skb);
+				return;
+			}
 		}
-	}
 
-	fi = (struct ieee80211_frame_info *) skb_push(skb, hlen);
+		fi = (struct ieee80211_frame_info *) skb_push(skb, hlen);
+		ieee80211_fill_frame_info(local, fi, status);
+	}
 
-	ieee80211_fill_frame_info(local, fi, status);
 	sdata->stats.rx_packets++;
 	sdata->stats.rx_bytes += skb->len;
 
 	skb->mac.raw = skb->data;
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 	skb->pkt_type = PACKET_OTHERHOST;
-	skb->protocol = htons(ETH_P_802_2);
+	skb->protocol = __constant_htons(ETH_P_802_2);
 	memset(skb->cb, 0, sizeof(skb->cb));
 	netif_rx(skb);
 }
@@ -3064,6 +3075,10 @@ ieee80211_rx_h_monitor(struct ieee80211_
 		return TXRX_QUEUED;
 	}
 
+	if (rx->local->monitors &&
+	    rx->local->hw.flags & IEEE80211_HW_RADIOTAP_SUPPORTED)
+		skb_pull(rx->skb, ieee80211_get_radiotap_len(rx->skb));
+
 	return TXRX_CONTINUE;
 }
 
@@ -3628,6 +3643,13 @@ void __ieee80211_rx(struct ieee80211_hw
 	struct ieee80211_txrx_data rx;
 	u16 type;
 	int multicast;
+	int radiotap_len = 0;
+
+	if (local->monitors &&
+	    local->hw.flags & IEEE80211_HW_RADIOTAP_SUPPORTED) {
+		radiotap_len = ieee80211_get_radiotap_len(skb);
+		skb_pull(skb, radiotap_len);
+	}
 
 	hdr = (struct ieee80211_hdr *) skb->data;
 	memset(&rx, 0, sizeof(rx));
@@ -3664,6 +3686,7 @@ void __ieee80211_rx(struct ieee80211_hw
 		goto end;
 	skb = rx.skb;
 
+	skb_push(skb, radiotap_len);
 	if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) &&
 	    !local->iff_promiscs && !multicast) {
 		rx.u.rx.ra_match = 1;
@@ -3672,7 +3695,7 @@ void __ieee80211_rx(struct ieee80211_hw
 	} else {
 		struct ieee80211_sub_if_data *prev = NULL;
 		struct sk_buff *skb_new;
-		u8 *bssid = ieee80211_get_bssid(hdr, skb->len);
+		u8 *bssid = ieee80211_get_bssid(hdr, skb->len - radiotap_len);
 
 		list_for_each_entry(sdata, &local->sub_if_list, list) {
 			rx.u.rx.ra_match = 1;
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 3e9d531..c1bb6d0 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -198,7 +198,10 @@ void ieee80211_if_set_type(struct net_de
 		break;
 	}
 	case IEEE80211_IF_TYPE_MNTR:
-		dev->type = ARPHRD_IEEE80211_PRISM;
+		if (sdata->local->hw.flags & IEEE80211_HW_RADIOTAP_SUPPORTED)
+			dev->type = ARPHRD_IEEE80211_RADIOTAP;
+		else
+			dev->type = ARPHRD_IEEE80211_PRISM;
 		break;
 	default:
 		printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",

Content of type "application/pgp-signature" skipped

Powered by blists - more mailing lists