Hi folks -

I have written a patch (attached) which tries to provide a new usage mode for the zd1211rw. It works for me, but only in Monitor mode: the intention is that it should work in Managed mode too, associated or unassociated, and I welcome any pointers getting that going.

What the patch does is provide a second network interface object, penumbra0. If you fire packets down this new network interface, they are sent on the zd1211rw as unencrypted packets outside of the 80211 stack. Likewise, any unencrypted packets to a specific MAC address are very early routed down the new network interface instead of the 80211 stack and on to zd1211rw's eth one. All other packets go on as normal through the 80211 stack.

The intended effect is that you can simultaneously run your encrypted network connection, keeping your normal traffic and internet connectivity private as usual, and yet also participate in a general, unencrypted (on the transport layer, anyway) broadcast-based network with anyone in range. I have evolved a protocol system for such a network and am in the process of implementing it using this patch.

I have done this on zd1211 because I have 3 Belkin sticks and the driver was FOSS, however the end goal is to try to allow this kind of mode to everyone on any adapter and Windows.

DSD on IRC proposed that this functionality should go in the 80211 stack, if people have comments about that or anything else please do give your opinion and advice.

-Andy
--- original-patched-zd1211rw-2007.01.09-arm/./Kbuild	2007-01-04 03:32:47.000000000 +0000
+++ /projects/octotux/packages/zd1211rw-2007.01.09/./Kbuild	2007-01-09 22:55:54.000000000 +0000
@@ -9,7 +9,8 @@
 	zd_rf_rf2959.o \
 	zd_rf_al2230.o \
 	zd_rf_al7230b.o \
-	zd_util.o
+	zd_util.o \
+	penumbra-netdev.o
 
 ifeq ($(ZD1211_DEBUG),y)
 	EXTRA_CFLAGS := -DDEBUG -Werror
--- original-patched-zd1211rw-2007.01.09-arm/./Makefile	2007-01-04 03:32:47.000000000 +0000
+++ /projects/octotux/packages/zd1211rw-2007.01.09/./Makefile	2007-01-09 22:55:54.000000000 +0000
@@ -1,5 +1,4 @@
-KERNELDIR := /lib/modules/`uname -r`/build
-
+#KERNELDIR ?=/usr/src/kernels/`uname -r`-i686
 module := zd1211rw
 
 ifneq ($(USER),root)
--- original-patched-zd1211rw-2007.01.09-arm/./penumbra-netdev.c	1970-01-01 01:00:00.000000000 +0100
+++ /projects/octotux/packages/zd1211rw-2007.01.09/./penumbra-netdev.c	2007-01-10 14:17:12.000000000 +0000
@@ -0,0 +1,243 @@
+/* penumbra-netdev.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <net/ieee80211.h>
+#include <net/ieee80211softmac.h>
+#include <net/ieee80211softmac_wx.h>
+#include <net/iw_handler.h>
+
+#include "zd_def.h"
+#include "zd_netdev.h"
+#include "zd_mac.h"
+#include "zd_ieee80211.h"
+
+#include "penumbra-netdev.h"
+
+// driver-specific tx action
+int zd_usb_tx_penumbra(struct net_device *netdevWifi, u8 *pu8aFrame, int len);
+
+
+		// struct zd_ctrlset (11 bytes)
+		// IEEE802.11 header (24 bytes)
+		// payload
+		// IEEE80211_FCS_LEN checksum (4 bytes)
+
+u8 u8aHeaderPenumbra[] = { // all Penumbra TX packets used this fixed IEEE80211 header
+
+	0x48, 0x00, 0x00, 0x00, 
+	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, // RECIPIENT ADS: our Penumbra MAC used by ALL stations for penumbra packet tx
+	0x00, 0x11, 0x22, 0x33, 0x44, 0xaa, // SOURCE ADS: every station transmits using this MAC
+	0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+	0x00, 0x60,
+};
+
+
+int penumbra_open(struct net_device *dev)
+{
+
+	struct penumbra_priv * priv=(struct penumbra_priv *)netdev_priv(dev);
+//	int n=dev_mc_add(priv->netdevice_wifi, &u8aHeaderPenumbra[4], ETH_ALEN, 1);
+//	if(n) {
+//		printk("dev_mc_add returned %d\n", n);
+//	}
+
+	printk("penumbra_open\n");
+	netif_start_queue(dev);
+	return 0;
+}
+
+int penumbra_release(struct net_device *dev)
+{
+//	struct penumbra_priv * priv=(struct penumbra_priv *)netdev_priv(dev);
+	netif_stop_queue(dev);
+//	dev_mc_delete(priv->netdevice_wifi, &u8aHeaderPenumbra[4], ETH_ALEN, 1);
+	return 0;
+}
+
+struct net_device_stats * penumbra_get_stats(struct net_device *dev)
+{
+	struct penumbra_priv * priv=(struct penumbra_priv *)netdev_priv(dev);
+	return &priv->stats;
+}
+
+
+int penumbra_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	extern void tx_urb_complete(struct urb *urb);
+	struct penumbra_priv * priv=(struct penumbra_priv *)netdev_priv(dev);
+	struct net_device *netdevWifi=priv->netdevice_wifi;
+	int nPayload=skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+	struct zd_mac *mac=zd_netdev_mac(netdevWifi);
+	unsigned int length_buffer=sizeof(struct zd_ctrlset)+IEEE80211_3ADDR_LEN+nPayload;
+	struct usb_device *udev = zd_usb_to_usbdev(&mac->chip.usb);
+	struct urb *urb=usb_alloc_urb(0, GFP_ATOMIC);
+	void *buffer_urb;
+	int r;
+
+	if (!urb) {
+		r = -ENOMEM;
+		goto out;
+	}
+
+	buffer_urb = usb_buffer_alloc(udev, length_buffer, GFP_ATOMIC, &urb->transfer_dma);
+
+	if (!buffer_urb) {
+		r = -ENOMEM;
+		goto error_free_urb;
+	}
+
+	{
+		struct zd_ctrlset *pzdc=(struct zd_ctrlset *)buffer_urb;
+		unsigned int frag_len = IEEE80211_3ADDR_LEN + nPayload + IEEE80211_FCS_LEN;
+		int packet_length= length_buffer + IEEE80211_FCS_LEN + ZD_MAGIC_LENGTH_ADJUST;
+
+		memcpy(
+			buffer_urb+sizeof(struct zd_ctrlset),
+			u8aHeaderPenumbra,
+			IEEE80211_3ADDR_LEN
+		);
+
+		pzdc->next_frame_length = 0;
+		pzdc->modulation=ZD_CS_OFDM|ZD_OFDM_RATE_54M;
+		pzdc->tx_length = cpu_to_le16(frag_len);
+		pzdc->control =ZD_CS_MULTICAST;
+		pzdc->packet_length = cpu_to_le16(
+			mac->chip.is_zd1211b ?
+				packet_length - frag_len : 
+				packet_length
+		);
+	
+		pzdc->service = 0;
+		r = zd_calc_tx_length_us(
+			&pzdc->service, 
+			ZD_CS_RATE(pzdc->modulation),
+			le16_to_cpu(pzdc->tx_length)
+		);
+		if (r < 0) {
+			return r;
+		}
+		pzdc->current_length = cpu_to_le16(r);
+
+		memcpy(buffer_urb+sizeof(struct zd_ctrlset)+IEEE80211_3ADDR_LEN,
+			skb->data, skb->len); // copy the payload into the URB
+	}
+
+	usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT),
+		          buffer_urb, length_buffer, tx_urb_complete, NULL);
+	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	r = usb_submit_urb(urb, GFP_ATOMIC);
+	if (r)
+		goto error;
+
+	dev->trans_start = jiffies;
+	priv->stats.tx_packets++;
+	priv->stats.tx_bytes+=skb->len;
+	
+	dev_kfree_skb(skb);  // retire the skb right away, it is copied into the urb
+	return 0;
+
+error:
+	dev_kfree_skb(skb);  // retire the skb right away, it is copied into the urb
+	usb_buffer_free(udev, length_buffer, buffer_urb,
+		        urb->transfer_dma);
+error_free_urb:
+	usb_free_urb(urb);
+out:
+	return r;
+
+}
+
+
+void penumbra_init(struct net_device *dev)
+{
+
+	ether_setup(dev);
+	dev->open            = penumbra_open;
+	dev->stop            = penumbra_release;
+	dev->hard_start_xmit = penumbra_tx;
+	dev->get_stats = penumbra_get_stats;
+}
+
+
+
+// returns the allocated net_device for the penumbra interface
+// call this from the wlan device interface init code
+
+struct net_device * penumbra_alloc_netdev(struct net_device *devWifi)
+{
+	struct net_device * pnetdevicePenumbra = 
+		alloc_netdev(sizeof(struct penumbra_priv), "penumbra%d", penumbra_init);
+
+	if (pnetdevicePenumbra==NULL) {
+			printk("Allocating penumbra interface netdev failed\n");
+	} else {
+		int err;
+		struct penumbra_priv * priv=(struct penumbra_priv *)netdev_priv(pnetdevicePenumbra);
+
+		priv->netdevice_wifi=devWifi; // point to main network device as our private penumbra network interface pointer	
+
+		memcpy(pnetdevicePenumbra->dev_addr, &u8aHeaderPenumbra[10], ETH_ALEN); // our standard SOURCE MAC
+
+		if ((err = register_netdev(pnetdevicePenumbra))) {
+			printk("Registering penumbra net device failed\n");
+		} else {
+			printk("penumbra device registered\n");
+		}
+
+
+	}
+	return pnetdevicePenumbra;
+}
+
+	// decides if it is a Penumbra packet, eats it if it likes it and returns 1, else 0
+	// if we return 1, caller should leave skb alone, ie, not free it, and return
+
+int penumbra_handle_rx_packet(struct net_device * pnetdevicePenumbra, struct sk_buff *skb)
+{
+	u8 * pu8=((u8*)skb->data)+ZD_PLCP_HEADER_SIZE+4; // examine dest address
+
+	if (memcmp(pu8, &u8aHeaderPenumbra[4], ETH_ALEN) == 0 ) { // is it sent to the magic Penumbra MAC address?
+		struct penumbra_priv * priv_penumbra=
+			(struct penumbra_priv *)netdev_priv(pnetdevicePenumbra);
+
+		__skb_pull(skb, ZD_PLCP_HEADER_SIZE+ETH_HLEN); // lose the ethernet header
+		__skb_trim(skb, skb->len -	(IEEE80211_FCS_LEN + sizeof(struct rx_status))); // lose the crap at the end
+
+		skb->dev=pnetdevicePenumbra; // assign the SKB to the penumbra device instead
+		skb->protocol=ETH_P_LOOP; // has to be something
+		skb->ip_summed = CHECKSUM_UNNECESSARY; // we will take care of it
+		skb->pkt_type = PACKET_HOST;
+		skb->mac.raw = ((u8*)skb->data)+10; // to the magic MAC address
+		skb->h.raw = ((u8*)skb->data)+IEEE80211_3ADDR_LEN; // to the magic MAC address
+		skb->nh.raw = ((u8*)skb->data)+IEEE80211_3ADDR_LEN; // to the magic MAC address
+
+		netif_rx(skb); // Penumbra packets are not handled by the 80211 stack
+
+		priv_penumbra->stats.rx_packets++;
+		priv_penumbra->stats.rx_bytes+=skb->len;
+
+		return 1; // we dealt with packet, caller must ignore it
+	}
+
+	return 0; // caller should deal with packet
+}
+
+
--- original-patched-zd1211rw-2007.01.09-arm/./penumbra-netdev.h	1970-01-01 01:00:00.000000000 +0100
+++ /projects/octotux/packages/zd1211rw-2007.01.09/./penumbra-netdev.h	2007-01-09 22:55:54.000000000 +0000
@@ -0,0 +1,14 @@
+#ifndef __PENUMBRA_H__
+#define __PENUMBRA_H__
+
+
+
+struct penumbra_priv {
+	struct net_device * netdevice_wifi;
+	struct net_device_stats stats;
+};
+
+extern struct net_device * penumbra_alloc_netdev(struct net_device *devWifi);
+extern int penumbra_handle_rx_packet(struct net_device * pnetdevicePenumbra, struct sk_buff *skb);
+
+#endif
--- original-patched-zd1211rw-2007.01.09-arm/./RECOOK	1970-01-01 01:00:00.000000000 +0100
+++ /projects/octotux/packages/zd1211rw-2007.01.09/./RECOOK	2007-01-09 22:55:54.000000000 +0000
@@ -0,0 +1,13 @@
+#!/bin/sh
+modprobe -r zd1211rw && \
+make KERNELDIR=/usr/src/kernels/`uname -r`-i686 clean && \
+make KERNELDIR=/usr/src/kernels/`uname -r`-i686 && \
+rm -f /lib/modules/2.6.19-1.2888.fc6/kernel/drivers/net/wireless/zd1211rw/zd1211rw.ko && \
+cp zd1211rw.ko /lib/modules/2.6.19-1.2888.fc6/kernel/drivers/net/wireless/zd1211rw && \
+make KERNELDIR=/usr/src/kernels/`uname -r`-i686 clean && \
+depmod -a && \
+modprobe zd1211rw && \
+ifconfig eth1 up && \
+ifconfig penumbra0 up && \
+iwconfig eth1 mode monitor && \
+iwconfig eth1 channel 2
--- original-patched-zd1211rw-2007.01.09-arm/./zd_mac.c	2007-01-10 14:17:18.000000000 +0000
+++ /projects/octotux/packages/zd1211rw-2007.01.09/./zd_mac.c	2007-01-10 08:40:41.000000000 +0000
@@ -30,6 +30,9 @@
 #include "zd_rf.h"
 #include "zd_util.h"
 
+#include "penumbra-netdev.h"
+
+
 static void ieee_init(struct ieee80211_device *ieee);
 static void softmac_init(struct ieee80211softmac_device *sm);
 static void set_rts_cts_work(WORK_FUNCTION_ARGS);
@@ -577,10 +580,10 @@
 int zd_mac_request_channel(struct zd_mac *mac, u8 channel)
 {
 	unsigned long lock_flags;
-	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+//	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
 
-	if (ieee->iw_mode == IW_MODE_INFRA)
-		return -EPERM;
+//	if (ieee->iw_mode == IW_MODE_INFRA)
+//		return -EPERM;
 
 	spin_lock_irqsave(&mac->lock, lock_flags);
 	if (!zd_regdomain_supports_channel(mac->regdomain, channel)) {
@@ -726,7 +729,7 @@
 	return 0;
 }
 
-static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
+int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
 {
 	static const u8 rate_divisor[] = {
 		[ZD_CCK_RATE_1M]	=  1,
@@ -1131,6 +1134,12 @@
 		goto free_skb;
 	}
 
+		// penumbra: look for packets with our magic MAC
+		// and divert them to the penumbra interface
+		// otherwise we continue to process it normally
+
+	if(penumbra_handle_rx_packet(mac->pnetdevicePenumbra, skb)) return;
+
 	r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
 	if (r) {
 		/* Only packets with rx errors are included here. */
--- original-patched-zd1211rw-2007.01.09-arm/./zd_mac.h	2007-01-10 14:17:18.000000000 +0000
+++ /projects/octotux/packages/zd1211rw-2007.01.09/./zd_mac.h	2007-01-10 08:52:39.000000000 +0000
@@ -157,6 +157,7 @@
 	struct zd_chip chip;
 	spinlock_t lock;
 	struct net_device *netdev;
+	struct net_device *pnetdevicePenumbra;  // one penumbra device per wifi stick
 
 	/* Unlocked reading possible */
 	struct iw_statistics iw_stats;
--- original-patched-zd1211rw-2007.01.09-arm/./zd_netdev.c	2007-01-04 03:32:47.000000000 +0000
+++ /projects/octotux/packages/zd1211rw-2007.01.09/./zd_netdev.c	2007-01-09 22:55:54.000000000 +0000
@@ -28,6 +28,8 @@
 #include "zd_mac.h"
 #include "zd_ieee80211.h"
 
+#include "penumbra-netdev.h"
+
 /* Region 0 means reset regdomain to default. */
 static int zd_set_regdomain(struct net_device *netdev,
 	                    struct iw_request_info *info,
@@ -246,6 +248,11 @@
 	netdev->wireless_handlers = &iw_handler_def;
 	/* netdev->ethtool_ops = */
 
+		// allocate a network interface for penumbra
+
+	printk("zd_netdev_alloc\n");
+	mac->pnetdevicePenumbra = penumbra_alloc_netdev(netdev);
+
 	return netdev;
 }
 
@@ -254,6 +261,14 @@
 	if (!netdev)
 		return;
 
+		// free up the penumbra network interface
+
+	if(zd_netdev_mac(netdev)->pnetdevicePenumbra!=NULL) {
+		unregister_netdev(zd_netdev_mac(netdev)->pnetdevicePenumbra);
+		free_netdev(zd_netdev_mac(netdev)->pnetdevicePenumbra);
+		zd_netdev_mac(netdev)->pnetdevicePenumbra=NULL;
+	}
+
 	zd_mac_clear(zd_netdev_mac(netdev));
 	free_ieee80211(netdev);
 }
--- original-patched-zd1211rw-2007.01.09-arm/./zd_netdev.h	2007-01-04 03:32:47.000000000 +0000
+++ /projects/octotux/packages/zd1211rw-2007.01.09/./zd_netdev.h	2007-01-09 23:44:00.000000000 +0000
@@ -22,6 +22,9 @@
 #include <linux/netdevice.h>
 #include <net/ieee80211.h>
 
+#define ZD_MAGIC_LENGTH_ADJUST 10
+
+
 #define ZD_PRIV_SET_REGDOMAIN (SIOCIWFIRSTPRIV)
 #define ZD_PRIV_GET_REGDOMAIN (SIOCIWFIRSTPRIV+1)
 
@@ -42,4 +45,7 @@
 
 void zd_netdev_disconnect(struct net_device *netdev);
 
+extern int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length);
+
+
 #endif /* _ZD_NETDEV_H */
--- original-patched-zd1211rw-2007.01.09-arm/./zd_usb.c	2007-01-04 03:32:47.000000000 +0000
+++ /projects/octotux/packages/zd1211rw-2007.01.09/./zd_usb.c	2007-01-10 09:45:25.000000000 +0000
@@ -32,6 +32,7 @@
 #include "zd_mac.h"
 #include "zd_usb.h"
 #include "zd_util.h"
+#include "zd_ieee80211.h"
 
 static struct usb_device_id usb_ids[] = {
 	/* ZD1211 */
@@ -690,7 +691,7 @@
 	spin_unlock_irqrestore(&rx->lock, flags);
 }
 
-static void tx_urb_complete(struct urb *urb)
+void tx_urb_complete(struct urb *urb)
 {
 	int r;
 
@@ -738,8 +739,8 @@
 		goto out;
 	}
 
-	buffer = usb_buffer_alloc(zd_usb_to_usbdev(usb), length, GFP_ATOMIC,
-		                  &urb->transfer_dma);
+	buffer = usb_buffer_alloc(udev, length, GFP_ATOMIC, &urb->transfer_dma);
+
 	if (!buffer) {
 		r = -ENOMEM;
 		goto error_free_urb;
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Zd1211-devs mailing list - http://zd1211.ath.cx/
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/zd1211-devs

Reply via email to