[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Approaches to enabling scanning for AirPort (not Extreme)



Barry Hawkins wrote:
Eric Gaumer wrote:
[...]
| Yes I have patches that enable scanning. I wouldn't be able to function
| without kismet ;-)
| I have a Titanium PB with an airport card.
|
| deb ftp://corp.primenetwork.net/debian/ prime contrib
| deb-src ftp://corp.primenetwork.net/debian prime contrib
|
| ]$ apt-get update
| ]$ apt-get install kernel-image-2.6.10-powerpc_1.1_powerpc.deb
|
| Or I can send you the patch if you'd like to build your own kernel.
[...]
Eric, you are my hero.  Please send the patch; I will build that
tonight.  Has there been any talk of having that be standard with the
Debian kernels for ppc?  I can't think of a case where someone wouldn't
want scanning enabled.

There must be obvious reasons why this isn't the case though I'm not sure of them myself.
Perhaps someone can shed some light.

I've used this patch pretty heavily and it's never shown any instability for me.

The patch is from 2.6.9 but applies cleanly to 2.6.10 as well.

--
"Education is what remains after one has forgotten everything he learned in school."
	- Albert Einstein
diff -ur linux-2.6.9/drivers/net/wireless/hermes.c linux-2.6.9-orinoco/drivers/net/wireless/hermes.c
--- linux-2.6.9/drivers/net/wireless/hermes.c	2004-10-20 15:26:41.000000000 -0400
+++ linux-2.6.9-orinoco/drivers/net/wireless/hermes.c	2004-10-20 14:55:01.000000000 -0400
@@ -182,6 +182,10 @@
 	if (err)
 		return err;

+        for ( k = 0; k < HERMES_NUMPORTS_MAX; k++) {
+		hw->port_enabled[k] = 0;
+	}
+
 	reg = hermes_read_regn(hw, EVSTAT);
 	k = CMD_INIT_TIMEOUT;
 	while ( (! (reg & HERMES_EV_CMD)) && k) {
diff -ur linux-2.6.9/drivers/net/wireless/hermes.h linux-2.6.9-orinoco/drivers/net/wireless/hermes.h
--- linux-2.6.9/drivers/net/wireless/hermes.h	2004-10-20 15:26:41.000000000 -0400
+++ linux-2.6.9-orinoco/drivers/net/wireless/hermes.h	2004-10-20 15:24:55.000000000 -0400
@@ -34,6 +34,10 @@
 #include <linux/if_ether.h>
 #include <asm/byteorder.h>

+#define		HFA384x_PORTTYPE_IBSS			((uint16_t)3)
+#define		HFA384x_WEPFLAGS_DISABLE_TXCRYPT	(0x10)
+#define		HFA384x_WEPFLAGS_DISABLE_RXCRYPT	(0x80)
+
 /*
  * Limits and constants
  */
@@ -150,6 +154,11 @@
 /*--- Debugging Commands -----------------------------*/
 #define 	HERMES_CMD_TEST			(0x0038)

+/*--- Debugging Commands -----------------------------*/
+/* We want these in this byte arrangement.  Why is it even being changed? */
+#define 	HERMES_CMD_MONITOR		(0x0038)
+#define		HERMES_MONITOR_ENABLE		(0x000b)
+#define		HERMES_MONITOR_DISABLE		(0x000f)

 /* Test command arguments */
 #define		HERMES_TEST_SET_CHANNEL		0x0800
@@ -173,6 +182,38 @@
 #define		HERMES_HOSTSCAN_SYMBOL_BCAST	0x0080

 /*
+ * Configuration RIDs
+ */
+
+#define		HERMES_RID_CNF_PORTTYPE		(0xfc00)
+#define		HERMES_RID_CNF_CHANNEL		(0xfc03)
+#define		HERMES_RID_CNF_PRISM2_WEP_ON	(0xfc28)
+
+/*-- Status Fields --*/
+#define		HERMES_RXSTATUS_MSGTYPE		(0xE000)
+#define		HERMES_RXSTATUS_MACPORT		(0x0700)
+#define		HERMES_RXSTATUS_UNDECR		(0x0002)
+#define		HERMES_RXSTATUS_FCSERR		(0x0001)
+
+/*--------------------------------------------------------------------
+Communication Frames: Test/Get/Set Field Values for Receive Frames
+--------------------------------------------------------------------*/
+#define		HERMES_RXSTATUS_MSGTYPE_GET(value)	(((value) & HERMES_RXSTATUS_MSGTYPE) >> 13)
+#define		HERMES_RXSTATUS_MSGTYPE_SET(value)	((value) << 13)
+#define		HERMES_RXSTATUS_MACPORT_GET(value)	(((value) & HERMES_RXSTATUS_MACPORT) >> 8)
+#define		HERMES_RXSTATUS_MACPORT_SET(value)	((value) << 8)
+#define		HERMES_RXSTATUS_ISUNDECR(value)	((value) & HERMES_RXSTATUS_UNDECR)
+#define		HERMES_RXSTATUS_ISFCSERR(value)	((value) & HERMES_RXSTATUS_FCSERR)
+
+/*--------------------------------------------------------------------
+Communication Frames: Field Masks for Receive Frames
+--------------------------------------------------------------------*/
+/*-- Offsets --------*/
+#define		HERMES_RX_DATA_LEN_OFF		(44)
+#define		HERMES_RX_80211HDR_OFF		(14)
+#define		HERMES_RX_DATA_OFF			(60)
+
+/*
  * Frame structures and constants
  */

@@ -181,6 +222,16 @@
 #define HERMES_802_3_OFFSET		(14+32)
 #define HERMES_802_2_OFFSET		(14+32+14)

+struct hermes_rx_descriptor {
+	u16 status;
+	u32 time;
+	u8 silence;
+	u8 signal;
+	u8 rate;
+	u8 rxflow;
+	u32 reserved;
+} __attribute__ ((packed));
+
 #define HERMES_RXSTAT_ERR		(0x0003)
 #define	HERMES_RXSTAT_BADCRC		(0x0001)
 #define	HERMES_RXSTAT_UNDECRYPTABLE	(0x0002)
@@ -353,6 +404,7 @@
 #define HERMES_32BIT_REGSPACING	1

 	u16 inten; /* Which interrupts should be enabled? */
+ 	uint8_t		port_enabled[HERMES_NUMPORTS_MAX];

 #ifdef HERMES_DEBUG_BUFFER
 	struct hermes_debug_entry dbuf[HERMES_DEBUG_BUFSIZE];
@@ -406,12 +458,14 @@

 static inline int hermes_enable_port(hermes_t *hw, int port)
 {
+        hw->port_enabled[port] = 1;
 	return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
 				 0, NULL);
 }

 static inline int hermes_disable_port(hermes_t *hw, int port)
 {
+        hw->port_enabled[port] = 0;
 	return hermes_docmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
 				 0, NULL);
 }
diff -ur linux-2.6.9/drivers/net/wireless/orinoco.c linux-2.6.9-orinoco/drivers/net/wireless/orinoco.c
--- linux-2.6.9/drivers/net/wireless/orinoco.c	2004-10-20 15:26:41.000000000 -0400
+++ linux-2.6.9-orinoco/drivers/net/wireless/orinoco.c	2004-10-20 15:23:04.000000000 -0400
@@ -466,6 +466,7 @@
 #endif

 static int suppress_linkstatus; /* = 0 */
+static int suppress_linkstatus_copy; /* = 0 */
 MODULE_PARM(suppress_linkstatus, "i");

 /********************************************************************/
@@ -562,16 +563,6 @@

 #define ENCAPS_OVERHEAD		(sizeof(encaps_hdr) + 2)

-struct hermes_rx_descriptor {
-	u16 status;
-	u32 time;
-	u8 silence;
-	u8 signal;
-	u8 rate;
-	u8 rxflow;
-	u32 reserved;
-} __attribute__ ((packed));
-
 /********************************************************************/
 /* Function prototypes                                              */
 /********************************************************************/
@@ -786,10 +777,13 @@
 		return 1;
 	}

-	if (! priv->connected) {
+    if (! priv->connected || dev->type == ARPHRD_IEEE80211_PRISM ||
+        dev->type == ARPHRD_IEEE80211) {
 		/* Oops, the firmware hasn't established a connection,
                    silently drop the packet (this seems to be the
                    safest approach). */
+        /* Also silently drop the packet if we're in rfmon, because it won't do
+         * very good things to try to write to the BAP. - Dragorn */
 		stats->tx_errors++;
 		orinoco_unlock(priv, &flags);
 		dev_kfree_skb(skb);
@@ -942,6 +936,24 @@
 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
 }

+//#define SET_MAC_ADDRESS
+#ifdef SET_MAC_ADDRESS
+static int
+orinoco_set_mac_address(struct net_device *dev, void *addr)
+{
+  struct orinoco_private *priv = dev->priv;
+  struct sockaddr *mac = addr;
+
+  /* Copy the address */
+  memcpy(dev->dev_addr, mac->sa_data, WLAN_ADDR_LEN);
+
+  /* Reconfig the beast */
+  orinoco_reset(priv);
+
+  return 0;
+}
+#endif	/* SET_MAC_ADDRESS */
+
 static void orinoco_tx_timeout(struct net_device *dev)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
@@ -1027,6 +1039,7 @@
 	struct header_struct hdr;
 	struct ethhdr *eh;
 	int err;
+	struct ieee802_11_hdr hdr80211;

 	rxfid = hermes_read_regn(hw, RXFID);

@@ -1043,6 +1056,7 @@

 	if (status & HERMES_RXSTAT_ERR) {
 		if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
+			if (dev->type != ARPHRD_ETHER) goto sniffing;
 			wstats->discard.code++;
 			DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
 			       dev->name);
@@ -1054,6 +1068,7 @@
 		goto drop;
 	}

+sniffing:
 	/* For now we ignore the 802.11 header completely, assuming
            that the card's firmware has handled anything vital */

@@ -1084,6 +1099,11 @@
 		goto drop;
 	}

+	/* Now handle frame based on port# */
+	switch( HERMES_RXSTATUS_MACPORT_GET(status) )
+	{
+		case 0:
+
 	/* We need space for the packet data itself, plus an ethernet
 	   header, plus 2 bytes so we can align the IP header on a
 	   32bit boundary, plus 1 byte so we can read in odd length
@@ -1158,6 +1178,26 @@

 	return;

+ 	case 7:
+         	if ( ! HERMES_RXSTATUS_ISFCSERR(status) ) {
+                    if (hermes_bap_pread(hw, IRQ_BAP, &hdr80211, sizeof(hdr80211),
+                                        rxfid, HERMES_RX_80211HDR_OFF)) {
+                       stats->rx_errors++;
+                    }
+                    else {
+                         /* Copy to wlansnif skb */
+                         orinoco_int_rxmonitor( priv, rxfid, length, &desc, &hdr80211);
+                    }
+                 } else {
+                         printk("Received monitor frame: FCSerr set\n");
+                 }
+                 break;
+ 	default:
+ 		printk("Received frame on unsupported port=%d\n",
+ 			HERMES_RXSTATUS_MACPORT_GET(status) );
+ 		break;
+ 	}
+
  drop:
 	stats->rx_dropped++;

@@ -1543,6 +1583,8 @@
 	hermes_t *hw = &priv->hw;
 	int err;
 	struct hermes_idstring idbuf;
+    int word;
+    struct hermes_response resp;

 	/* Set the MAC address */
 	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
@@ -1737,6 +1779,27 @@
 	priv->mc_count = 0;
 	__orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */

+    /*
+     * Set the rfmon mode of the card, if we're in rfmon.  Otherwise, the firmware
+     * starts sending out a flood of probe requests.  We already reinited the firmware
+     * before.
+     *    - Dragorn
+     */
+    if (dev->type == ARPHRD_IEEE80211_PRISM || dev->type == ARPHRD_IEEE80211) {
+        word = HFA384x_PORTTYPE_IBSS;
+        err = hermes_write_wordrec(hw, USER_BAP,
+                                      HERMES_RID_CNF_PORTTYPE, word);
+        if (err)
+            return err;
+
+        /* Enable monitor mode */
+        word = HERMES_CMD_MONITOR | (HERMES_MONITOR_ENABLE << 8);
+        err = hermes_docmd_wait(hw, word, 0, &resp);
+        if (err)
+            return err;
+    }
+
+
 	return 0;
 }

@@ -1823,6 +1886,17 @@
 	if (err)
 		return err;

+    /*
+     * If we are in rmfmon mode we need to treat this like going into rfmon again,
+     * so re-init the firmware like the rfmon function does.
+     * We'll also need to do some other rfmonish behavior in config_rids
+     *     - Dragorn
+     */
+    if (dev->type == ARPHRD_IEEE80211_PRISM || dev->type == ARPHRD_IEEE80211) {
+        hermes_set_irqmask(hw, 0);
+        hermes_init(hw);
+        hermes_set_irqmask(hw, ORINOCO_INTEN);
+    }

 	err = hermes_disable_port(hw, 0);
 	if (err) {
@@ -2375,6 +2449,9 @@
 	dev->tx_timeout = orinoco_tx_timeout;
 	dev->watchdog_timeo = HZ; /* 1 second timeout */
 	dev->get_stats = orinoco_get_stats;
+#ifdef SET_MAC_ADDRESS
+	dev->set_mac_address = orinoco_set_mac_address;
+#endif	/* SET_MAC_ADDRESS */
 	dev->get_wireless_stats = orinoco_get_wireless_stats;
 	dev->do_ioctl = orinoco_ioctl;
 	dev->change_mtu = orinoco_change_mtu;
@@ -3585,6 +3662,170 @@
 	return 0;
 }

+/*----------------------------------------------------------------
+* orinoco_wlansniff
+*
+* Start or stop sniffing.
+*
+* Arguments:
+*	wlandev		wlan device structure
+*	msgp		ptr to msg buffer
+*
+* Returns:
+*	0	success and done
+*	<0	success, but we're waiting for something to finish.
+*	>0	an error occurred while handling the message.
+* Side effects:
+*
+* Call context:
+*	process thread  (usually)
+*	interrupt
+----------------------------------------------------------------*/
+static int orinoco_wlansniff(struct net_device *dev, struct iwreq *wrq)
+{
+	struct orinoco_private *priv = dev->priv;
+	hermes_t *hw = &(priv->hw);
+	struct hermes_response  resp;
+	int result = 0;
+	uint16_t word;
+
+	int *parms = (int *) wrq->u.name;
+	int enable = parms[0] > 0;
+	unsigned long flags;
+	int noMonitor = dev->type != ARPHRD_IEEE80211_PRISM &&
+	                dev->type != ARPHRD_IEEE80211;
+
+	orinoco_lock(priv, &flags);
+
+	switch (enable)
+	{
+	case P80211ENUM_truth_false:
+		/* Confirm that we're in monitor mode */
+		if ( noMonitor ) {
+			result = -EFAULT;
+		}
+		/* Disable monitor mode */
+		suppress_linkstatus = suppress_linkstatus_copy;
+	        word =	HERMES_CMD_MONITOR | (HERMES_MONITOR_DISABLE << 8);
+	        result = hermes_docmd_wait(hw, word, 0, &resp);
+
+		if ( result ) break;
+
+		/* Disable port 0 */
+		result = hermes_disable_port(hw, 0);
+		if ( result ) break;
+
+		/* Clear the driver state */
+		dev->type = ARPHRD_ETHER;
+
+		/* Restore the wepflags */   //Orinoco doesn't like this
+/*
+		result = hermes_write_wordrec(hw, USER_BAP,
+				HERMES_RID_CNF_PRISM2_WEP_ON,
+				priv->presniff_wepflags);
+		if ( result ) break;
+
+*/
+		/* Set the port to its prior type and enable (if necessary) */
+		if (priv->presniff_port_type != 0 ) {
+			word = priv->presniff_port_type;
+			result = hermes_write_wordrec(hw, USER_BAP,
+				HERMES_RID_CNF_PORTTYPE, word);
+		    if ( result ) break;
+
+			/* Enable the port */
+			result = hermes_enable_port(hw, 0);
+		    if ( result ) break;
+
+		}
+
+		break;
+	case P80211ENUM_truth_true:
+        	// Only do this if we're not in monitor mode already
+	        if (noMonitor) {
+	            /* Re-initialize the card before changing channel as advised at
+        	     * http://lists.samba.org/pipermail/wireless/2002-June/004491.html
+        	     * by Ian Goldberg.  Implementation by Pat Swieskowski.
+        	     */
+        	    //		__orinoco_down(dev);
+        	    hermes_set_irqmask(hw, 0);
+        	    hermes_init(hw);
+        	    //		_orinoco_up(dev);
+        	    hermes_set_irqmask(hw, ORINOCO_INTEN);
+		    suppress_linkstatus = 1;
+        	    /*
+        	       __orinoco_stop_irqs(priv);
+        	       hermes_reset(hw);
+        	       __orinoco_start_irqs(priv, HERMES_EV_RX | HERMES_EV_ALLOC |
+        	       HERMES_EV_TX | HERMES_EV_TXEXC |
+        	       HERMES_EV_WTERR | HERMES_EV_INFO |
+        	       HERMES_EV_INFDROP);
+        	       */
+        	    /* Disable the port (if enabled), only check Port 0 */
+        	    if ( hw->port_enabled[0] ) {
+        	        /* Save macport 0 state */
+        	        result = hermes_read_wordrec(hw, USER_BAP,
+        	                                     HERMES_RID_CNF_PORTTYPE,
+        	                                     &(priv->presniff_port_type));
+        	        if ( result ) break;
+
+        	        /* Save the wepflags state */
+        	        result = hermes_read_wordrec(hw, USER_BAP,
+        	                                     HERMES_RID_CNF_PRISM2_WEP_ON,
+	                                             &(priv->presniff_wepflags));
+        	        if ( result ) break;
+        	    }
+        	    else {
+        	        priv->presniff_port_type = 0;
+        	    }
+        	}
+
+        	// Disable the port
+        	result = hermes_disable_port(hw, 0);
+        	if ( result ) break;
+
+        	/* Set the channel we wish to sniff  */
+        	if (parms[1] > 0 && parms[1] < 15) {
+        	    word = parms[1];
+        	    result = hermes_write_wordrec(hw, USER_BAP,
+        	                                  HERMES_RID_CNF_CHANNEL, word);
+        	} else {
+        	    result = -EFAULT;
+        	}
+
+        	if ( result ) break;
+
+        	if (noMonitor) {
+        	    /* Set the port type to pIbss */
+        	    word = HFA384x_PORTTYPE_IBSS;
+        	    result = hermes_write_wordrec(hw, USER_BAP,
+        	                                  HERMES_RID_CNF_PORTTYPE, word);
+        	    if ( result ) break;
+
+        	    /* Enable monitor mode */
+        	    word = HERMES_CMD_MONITOR | (HERMES_MONITOR_ENABLE << 8);
+        	    result = hermes_docmd_wait(hw, word, 0, &resp);
+        	    if ( result ) break;
+        	}
+
+        	/* Enable the port */
+        	result = hermes_enable_port(hw, 0);
+        	if ( result ) break;
+		/* Set the driver state */
+		/* Do we want the prism2 header? */
+		if (parms[0] == 1)
+		  dev->type = ARPHRD_IEEE80211_PRISM;
+		else
+		  dev->type = ARPHRD_IEEE80211;
+		break;
+	default:
+		result = -EFAULT;
+		break;
+	}
+	orinoco_unlock(priv, &flags);
+	return result;
+}
+
 static int
 orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
@@ -3815,6 +4056,9 @@
 				{ SIOCIWFIRSTPRIV + 0x7, 0,
 				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
 				  "get_ibssport" },
+				{ SIOCIWFIRSTPRIV + 0x8,
+				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2,
+				  0, "monitor" },
 				{ SIOCIWLASTPRIV, 0, 0, "dump_recs" },
 			};

@@ -3905,6 +4149,16 @@
 		err = orinoco_ioctl_getibssport(dev, wrq);
 		break;

+	case SIOCIWFIRSTPRIV + 0x8: /* set sniff (monitor) mode */
+		DEBUG(1, "%s: SIOCIWFIRSTPRIV + 0x8 (monitor)\n",
+			  dev->name);
+		if (! capable(CAP_NET_ADMIN)) {
+			err = -EPERM;
+			break;
+		}
+		err = orinoco_wlansniff(dev, wrq);
+		break;
+
 	case SIOCIWLASTPRIV:
 		err = orinoco_debug_dump_recs(dev);
 		if (err)
@@ -4049,6 +4303,7 @@
 	int i,j;
 	u16 length;
 	int err;
+        struct ieee802_11_hdr hdr80211;

 	/* I'm not sure: we might have a lock here, so we'd better go
            atomic, just in case. */
@@ -4171,6 +4426,197 @@
 }
 #endif /* 0 */

+/*----------------------------------------------------------------
+* orinoco_int_rxmonitor
+*
+* Helper function for int_rx.  Handles monitor frames.
+* Note that this function allocates space for the FCS and sets it
+* to 0xffffffff.  The hfa384x doesn't give us the FCS value but the
+* higher layers expect it.  0xffffffff is used as a flag to indicate
+* the FCS is bogus.
+*
+* Arguments:
+*	dev		wlan device structure
+*	rxfid		received FID
+*	rxdesc		rx descriptor read from card in int_rx
+*
+* Returns:
+*	nothing
+*
+* Side effects:
+*	Allocates an skb and passes it up via the PF_PACKET interface.
+* Call context:
+*	interrupt
+----------------------------------------------------------------*/
+void orinoco_int_rxmonitor( struct orinoco_private *dev, uint16_t rxfid, int len,
+                            struct hermes_rx_descriptor *rxdesc, struct ieee802_11_hdr *hdr)
+{
+	hermes_t			*hw = &(dev->hw);
+	uint32_t				hdrlen = 0;
+	uint32_t				datalen = 0;
+	uint32_t				skblen = 0;
+	p80211msg_lnxind_wlansniffrm_t	*msg;
+	struct net_device_stats *stats = &dev->stats;
+
+
+	uint8_t				*datap;
+	uint16_t				fc;
+	struct sk_buff			*skb;
+
+	/* Don't forget the status, time, and data_len fields are in host order */
+	/* Figure out how big the frame is */
+	fc = le16_to_cpu(hdr->frame_ctl);
+	switch ( WLAN_GET_FC_FTYPE(fc) )
+	{
+	case WLAN_FTYPE_DATA:
+		if ( WLAN_GET_FC_TODS(fc) && WLAN_GET_FC_FROMDS(fc) ) {
+			hdrlen = WLAN_HDR_A4_LEN;
+		} else {
+			hdrlen = WLAN_HDR_A3_LEN;
+		}
+		datalen = len;
+		break;
+	case WLAN_FTYPE_MGMT:
+		hdrlen = WLAN_HDR_A3_LEN;
+		datalen = len;
+		break;
+	case WLAN_FTYPE_CTL:
+		switch ( WLAN_GET_FC_FSTYPE(fc) )
+		{
+		case WLAN_FSTYPE_PSPOLL:
+		case WLAN_FSTYPE_RTS:
+		case WLAN_FSTYPE_CFEND:
+		case WLAN_FSTYPE_CFENDCFACK:
+			hdrlen = 16;
+			break;
+		case WLAN_FSTYPE_CTS:
+		case WLAN_FSTYPE_ACK:
+			hdrlen = 10;
+			break;
+		}
+		datalen = 0;
+		break;
+	default:
+		printk("unknown frm: fc=0x%04x\n", fc);
+		return;
+	}
+
+	/* Allocate an ind message+framesize skb */
+	skblen = sizeof(p80211msg_lnxind_wlansniffrm_t) +
+	  hdrlen + datalen;
+
+	/* sanity check the length */
+	if ( skblen >
+		(sizeof(p80211msg_lnxind_wlansniffrm_t) +
+		WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN) ) {
+		printk("overlen frm: len=%d\n",
+			skblen - sizeof(p80211msg_lnxind_wlansniffrm_t));
+	}
+
+	if ( (skb = dev_alloc_skb(skblen)) == NULL ) {
+		printk("alloc_skb failed trying to allocate %d bytes\n", skblen);
+		return;
+	}
+
+	/* only prepend the prism header if in the right mode */
+	if (dev->ndev->type != ARPHRD_IEEE80211_PRISM) {
+	  skb_put(skb, skblen - sizeof(p80211msg_lnxind_wlansniffrm_t));
+	  datap = skb->data;
+	} else {
+	  skb_put(skb, skblen);
+	  datap = skb->data + sizeof(p80211msg_lnxind_wlansniffrm_t);
+	  msg = (p80211msg_lnxind_wlansniffrm_t*)skb->data;
+
+	  /* Initialize the message members */
+	  msg->msgcode = DIDmsg_lnxind_wlansniffrm;
+	  msg->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t);
+	  strcpy(msg->devname, dev->ndev->name);
+
+	  msg->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
+	  msg->hosttime.status = 0;
+	  msg->hosttime.len = 4;
+	  msg->hosttime.data = jiffies;
+
+	  msg->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
+	  msg->mactime.status = 0;
+	  msg->mactime.len = 4;
+	  msg->mactime.data = rxdesc->time;
+
+	  msg->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
+	  msg->channel.status = P80211ENUM_msgitem_status_no_value;
+	  msg->channel.len = 4;
+	  msg->channel.data = 0;
+
+	  msg->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
+	  msg->rssi.status = P80211ENUM_msgitem_status_no_value;
+	  msg->rssi.len = 4;
+	  msg->rssi.data = 0;
+
+	  msg->sq.did = DIDmsg_lnxind_wlansniffrm_sq;
+	  msg->sq.status = P80211ENUM_msgitem_status_no_value;
+	  msg->sq.len = 4;
+	  msg->sq.data = 0;
+
+	  msg->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
+	  msg->signal.status = 0;
+	  msg->signal.len = 4;
+	  msg->signal.data = rxdesc->signal;
+
+	  msg->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
+	  msg->noise.status = 0;
+	  msg->noise.len = 4;
+	  msg->noise.data = rxdesc->silence;
+
+	  msg->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
+	  msg->rate.status = 0;
+	  msg->rate.len= 4;
+	  msg->rate.data = rxdesc->rate / 5; /* set to 802.11 units */
+
+	  msg->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
+	  msg->istx.status = 0;
+	  msg->istx.len = 4;
+	  msg->istx.data = P80211ENUM_truth_false;
+
+	  msg->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
+	  msg->frmlen.status = 0;
+	  msg->frmlen.len = 4;
+	  msg->frmlen.data = hdrlen + datalen;
+	}
+
+	/* Copy the 802.11 header to the skb (ctl frames may be less than a full header) */
+	memcpy( datap, &(hdr->frame_ctl), hdrlen);
+
+	/* If any, copy the data from the card to the skb */
+	if ( datalen > 0 )
+	{
+		hermes_bap_pread(hw, IRQ_BAP, datap + hdrlen, (datalen+1)&~1,
+				       rxfid, HERMES_RX_DATA_OFF);
+
+		/* check for unencrypted stuff if WEP bit set. */
+		if (*(datap+1) & 0x40) // wep set
+		  if ((*(datap+hdrlen) == 0xaa) && (*(datap+hdrlen+1) == 0xaa))
+		    *(datap+1) &= 0xbf; // clear wep; it's the 802.2 header!
+	}
+
+       /* pass it up via the PF_PACKET interface */
+       {
+	   skb->dev = dev->ndev;
+	   skb->dev->last_rx = jiffies;
+
+	   skb->mac.raw = skb->data ;
+	   skb->ip_summed = CHECKSUM_NONE;
+	   skb->pkt_type = PACKET_OTHERHOST;
+	   skb->protocol = htons(ETH_P_80211_RAW);  /* XXX ETH_P_802_2? */
+
+	   stats->rx_packets++;
+	   stats->rx_bytes += skb->len;
+
+	   netif_rx(skb);
+       }
+
+	return;
+}
+
 /********************************************************************/
 /* Module initialization                                            */
 /********************************************************************/
@@ -4193,6 +4639,7 @@
 static int __init init_orinoco(void)
 {
 	printk(KERN_DEBUG "%s\n", version);
+	suppress_linkstatus_copy = suppress_linkstatus;
 	return 0;
 }

diff -ur linux-2.6.9/drivers/net/wireless/orinoco.h linux-2.6.9-orinoco/drivers/net/wireless/orinoco.h
--- linux-2.6.9/drivers/net/wireless/orinoco.h	2004-10-20 15:26:41.000000000 -0400
+++ linux-2.6.9-orinoco/drivers/net/wireless/orinoco.h	2004-10-20 15:10:12.000000000 -0400
@@ -20,6 +20,21 @@
 /* To enable debug messages */
 //#define ORINOCO_DEBUG		3

+#ifndef ETH_P_ECONET
+#define ETH_P_ECONET   0x0018    /* needed for 2.2.x kernels */
+#endif
+
+#define ETH_P_80211_RAW        (ETH_P_ECONET + 1)
+
+#ifndef ARPHRD_IEEE80211
+#define ARPHRD_IEEE80211 801     /* kernel 2.4.6 */
+#endif
+
+#ifndef ARPHRD_IEEE80211_PRISM  /* kernel 2.4.18 */
+#define ARPHRD_IEEE80211_PRISM 802
+#endif
+
+
 #define WIRELESS_SPY		// enable iwspy support

 #define ORINOCO_MAX_KEY_SIZE	14
@@ -30,6 +45,159 @@
 	char data[ORINOCO_MAX_KEY_SIZE];
 } __attribute__ ((packed));

+#define WLAN_DEVNAMELEN_MAX 16
+
+/* message data item for INT, BOUNDEDINT, ENUMINT */
+typedef struct p80211item_uint32
+{
+	uint32_t		did		__attribute__ ((packed));
+	uint16_t		status	__attribute__ ((packed));
+	uint16_t		len		__attribute__ ((packed));
+	uint32_t		data	__attribute__ ((packed));
+} __attribute__ ((packed)) p80211item_uint32_t;
+
+typedef struct p80211msg
+{
+	uint32_t	msgcode		__attribute__ ((packed));
+	uint32_t	msglen		__attribute__ ((packed));
+	uint8_t	devname[WLAN_DEVNAMELEN_MAX]	__attribute__ ((packed));
+} __attribute__ ((packed)) p80211msg_t;
+
+#define DIDmsg_lnxind_wlansniffrm 0x0041
+#define DIDmsg_lnxind_wlansniffrm_hosttime 0x1041
+#define DIDmsg_lnxind_wlansniffrm_mactime 0x2041
+#define DIDmsg_lnxind_wlansniffrm_channel 0x3041
+#define DIDmsg_lnxind_wlansniffrm_rssi 0x4041
+#define DIDmsg_lnxind_wlansniffrm_sq 0x5041
+#define DIDmsg_lnxind_wlansniffrm_signal 0x6041
+#define DIDmsg_lnxind_wlansniffrm_noise 0x7041
+#define DIDmsg_lnxind_wlansniffrm_rate 0x8041
+#define DIDmsg_lnxind_wlansniffrm_istx 0x9041
+#define DIDmsg_lnxind_wlansniffrm_frmlen 0xA041
+
+typedef struct p80211msg_lnxind_wlansniffrm
+{
+	uint32_t		msgcode;
+	uint32_t		msglen;
+	uint8_t		    devname[WLAN_DEVNAMELEN_MAX];
+	p80211item_uint32_t	hosttime;
+	p80211item_uint32_t	mactime;
+	p80211item_uint32_t	channel;
+	p80211item_uint32_t	rssi;
+	p80211item_uint32_t	sq;
+	p80211item_uint32_t	signal;
+	p80211item_uint32_t	noise;
+	p80211item_uint32_t	rate;
+	p80211item_uint32_t	istx;
+	p80211item_uint32_t	frmlen;
+} __attribute__ ((packed)) p80211msg_lnxind_wlansniffrm_t;
+
+#define P80211ENUM_truth_false			0
+#define P80211ENUM_truth_true			1
+#define P80211ENUM_resultcode_success		1
+#define P80211ENUM_resultcode_invalid_parameters	2
+#define P80211ENUM_resultcode_not_supported	3
+#define P80211ENUM_resultcode_timeout		4
+#define P80211ENUM_resultcode_too_many_req	5
+#define P80211ENUM_resultcode_refused		6
+#define P80211ENUM_resultcode_bss_already	7
+#define P80211ENUM_resultcode_invalid_access	8
+#define P80211ENUM_resultcode_invalid_mibattribute	9
+#define P80211ENUM_resultcode_cant_set_readonly_mib	10
+#define P80211ENUM_resultcode_implementation_failure	11
+#define P80211ENUM_resultcode_cant_get_writeonly_mib	12
+#define P80211ENUM_msgitem_status_data_ok		0
+#define P80211ENUM_msgitem_status_no_value		1
+#define P80211ENUM_msgitem_status_invalid_itemname	2
+#define P80211ENUM_msgitem_status_invalid_itemdata	3
+#define P80211ENUM_msgitem_status_missing_itemdata	4
+#define P80211ENUM_msgitem_status_incomplete_itemdata	5
+#define P80211ENUM_msgitem_status_invalid_msg_did	6
+#define P80211ENUM_msgitem_status_invalid_mib_did	7
+#define P80211ENUM_msgitem_status_missing_conv_func	8
+#define P80211ENUM_msgitem_status_string_too_long	9
+#define P80211ENUM_msgitem_status_data_out_of_range	10
+#define P80211ENUM_msgitem_status_string_too_short	11
+#define P80211ENUM_msgitem_status_missing_valid_func	12
+#define P80211ENUM_msgitem_status_unknown		13
+#define P80211ENUM_msgitem_status_invalid_did		14
+#define P80211ENUM_msgitem_status_missing_print_func	15
+
+#define WLAN_GET_FC_FTYPE(n)	(((n) & 0x0C) >> 2)
+#define WLAN_GET_FC_FSTYPE(n)	(((n) & 0xF0) >> 4)
+#define WLAN_GET_FC_TODS(n) 	(((n) & 0x0100) >> 8)
+#define WLAN_GET_FC_FROMDS(n)	(((n) & 0x0200) >> 9)
+
+/*--- Sizes -----------------------------------------------*/
+#define WLAN_ADDR_LEN			6
+#define WLAN_CRC_LEN			4
+#define WLAN_BSSID_LEN			6
+#define WLAN_BSS_TS_LEN			8
+#define WLAN_HDR_A3_LEN			24
+#define WLAN_HDR_A4_LEN			30
+#define WLAN_SSID_MAXLEN		32
+#define WLAN_DATA_MAXLEN		2312
+
+/*--- Frame Control Field -------------------------------------*/
+/* Frame Types */
+#define WLAN_FTYPE_MGMT			0x00
+#define WLAN_FTYPE_CTL			0x01
+#define WLAN_FTYPE_DATA			0x02
+
+/* Frame subtypes */
+/* Management */
+#define WLAN_FSTYPE_ASSOCREQ		0x00
+#define WLAN_FSTYPE_ASSOCRESP		0x01
+#define WLAN_FSTYPE_REASSOCREQ		0x02
+#define WLAN_FSTYPE_REASSOCRESP		0x03
+#define WLAN_FSTYPE_PROBEREQ		0x04
+#define WLAN_FSTYPE_PROBERESP		0x05
+#define WLAN_FSTYPE_BEACON		0x08
+#define WLAN_FSTYPE_ATIM		0x09
+#define WLAN_FSTYPE_DISASSOC		0x0a
+#define WLAN_FSTYPE_AUTHEN		0x0b
+#define WLAN_FSTYPE_DEAUTHEN		0x0c
+
+/* Control */
+#define WLAN_FSTYPE_PSPOLL		0x0a
+#define WLAN_FSTYPE_RTS			0x0b
+#define WLAN_FSTYPE_CTS			0x0c
+#define WLAN_FSTYPE_ACK			0x0d
+#define WLAN_FSTYPE_CFEND		0x0e
+#define WLAN_FSTYPE_CFENDCFACK		0x0f
+
+/* Data */
+#define WLAN_FSTYPE_DATAONLY		0x00
+#define WLAN_FSTYPE_DATA_CFACK		0x01
+#define WLAN_FSTYPE_DATA_CFPOLL		0x02
+#define WLAN_FSTYPE_DATA_CFACK_CFPOLL	0x03
+#define WLAN_FSTYPE_NULL		0x04
+#define WLAN_FSTYPE_CFACK		0x05
+#define WLAN_FSTYPE_CFPOLL		0x06
+#define WLAN_FSTYPE_CFACK_CFPOLL	0x07
+
+/*----------------------------------------------------------------*/
+/* Magic number, a quick test to see we're getting the desired struct */
+
+#define P80211_IOCTL_MAGIC	(0x4a2d464dUL)
+
+/*================================================================*/
+/* Types */
+
+/*----------------------------------------------------------------*/
+/* A ptr to the following structure type is passed as the third */
+/*  argument to the ioctl system call when issuing a request to */
+/*  the p80211 module. */
+
+typedef struct p80211ioctl_req
+{
+	char 	name[WLAN_DEVNAMELEN_MAX] __attribute__ ((packed));
+	void	*data 		__attribute__ ((packed));
+	uint32_t	magic 	__attribute__ ((packed));
+	uint16_t	len 	__attribute__ ((packed));
+	uint32_t	result 	__attribute__ ((packed));
+} __attribute__ ((packed)) p80211ioctl_req_t;
+
 struct orinoco_private {
 	void *card;	/* Pointer to card dependent structure */
 	int (*hard_reset)(struct orinoco_private *);
@@ -90,6 +258,9 @@
 	/* Configuration dependent variables */
 	int port_type, createibss;
 	int promiscuous, mc_count;
+
+	uint16_t		presniff_port_type;
+	uint16_t		presniff_wepflags;
 };

 #ifdef ORINOCO_DEBUG
@@ -141,4 +312,12 @@
 	spin_unlock_irqrestore(&priv->lock, *flags);
 }

+/*================================================================*/
+/* Function Declarations */
+
+struct ieee802_11_hdr;
+
+void orinoco_int_rxmonitor( struct orinoco_private *dev, uint16_t rxfid, int len,
+                            struct hermes_rx_descriptor *rxdesc, struct ieee802_11_hdr *hdr);
+
 #endif /* _ORINOCO_H */

Attachment: signature.asc
Description: OpenPGP digital signature


Reply to: