diff -urN dist/orinoco-0.13e/hermes.c orinoco-monitor/hermes.c
--- dist/orinoco-0.13e/hermes.c	2003-05-12 16:22:27.000000000 +1000
+++ orinoco-monitor/hermes.c	2003-05-13 13:26:02.000000000 +1000
@@ -183,6 +183,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 -urN dist/orinoco-0.13e/hermes.h orinoco-monitor/hermes.h
--- dist/orinoco-0.13e/hermes.h	2003-05-12 16:22:27.000000000 +1000
+++ orinoco-monitor/hermes.h	2003-05-07 16:54:45.000000000 +1000
@@ -33,6 +33,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
  */
@@ -148,6 +152,14 @@
 #define		HERMES_MONITOR_ENABLE		(0x000b)
 #define		HERMES_MONITOR_DISABLE		(0x000f)
 
+/*--------------------------------------------------------------------
+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
  */
@@ -171,6 +183,7 @@
 #define	HERMES_RXSTAT_BADCRC		(0x0001)
 #define	HERMES_RXSTAT_UNDECRYPTABLE	(0x0002)
 #define	HERMES_RXSTAT_MACPORT		(0x0700)
+#define HERMES_RXSTAT_GET_MACPORT(s)	(((s) & HERMES_RXSTAT_MACPORT) >> 8)
 #define HERMES_RXSTAT_PCF		(0x1000)	/* Frame was received in CF period */
 #define	HERMES_RXSTAT_MSGTYPE		(0xE000)
 #define	HERMES_RXSTAT_1042		(0x2000)	/* RFC-1042 frame */
@@ -286,6 +299,7 @@
 #define HERMES_32BIT_REGSPACING	1
 
 	u16 inten; /* Which interrupts should be enabled? */
+ 	u8 port_enabled[HERMES_NUMPORTS_MAX];
 
 #ifdef HERMES_DEBUG_BUFFER
 	struct hermes_debug_entry dbuf[HERMES_DEBUG_BUFSIZE];
@@ -339,12 +353,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 -urN dist/orinoco-0.13e/orinoco.c orinoco-monitor/orinoco.c
--- dist/orinoco-0.13e/orinoco.c	2003-05-12 16:22:27.000000000 +1000
+++ orinoco-monitor/orinoco.c	2003-05-13 13:27:31.000000000 +1000
@@ -1673,6 +1673,7 @@
 	struct header_struct hdr;
 	struct ethhdr *eh;
 	int err;
+	struct ieee802_11_hdr hdr80211;
 
 	rxfid = hermes_read_regn(hw, RXFID);
 
@@ -1689,6 +1690,8 @@
 	
 	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);
@@ -1699,7 +1702,7 @@
 		stats->rx_errors++;
 		goto drop;
 	}
-
+sniffing:
 	/* For now we ignore the 802.11 header completely, assuming
            that the card's firmware has handled anything vital */
 
@@ -1729,81 +1732,111 @@
 		stats->rx_errors++;
 		goto drop;
 	}
+	/* Now handle frame based on port# */
+	switch (HERMES_RXSTAT_GET_MACPORT(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 packets from the card, which
+		 * has an IO granularity of 16 bits */
+		skb = dev_alloc_skb(length+ETH_HLEN+2+1);
+		if (!skb) {
+			printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
+			       dev->name);
+			goto drop;
+		}
 
-	/* 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
-	   packets from the card, which has an IO granularity of 16
-	   bits */  
-	skb = dev_alloc_skb(length+ETH_HLEN+2+1);
-	if (!skb) {
-		printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
-		       dev->name);
-		goto drop;
-	}
-
-	skb_reserve(skb, 2); /* This way the IP header is aligned */
-
-	/* Handle decapsulation
-	 * In most cases, the firmware tell us about SNAP frames.
-	 * For some reason, the SNAP frames sent by LinkSys APs
-	 * are not properly recognised by most firmwares.
-	 * So, check ourselves */
-	if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
-	   ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
-	   is_ethersnap(&hdr)) {
-		/* These indicate a SNAP within 802.2 LLC within
-		   802.11 frame which we'll need to de-encapsulate to
-		   the original EthernetII frame. */
+		skb_reserve(skb, 2); /* This way the IP header is aligned */
 
-		if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */
-			stats->rx_length_errors++;
+		/* Handle decapsulation In most cases, the firmware
+		 * tell us about SNAP frames.  For some reason, the
+		 * SNAP frames sent by LinkSys APs are not properly
+		 * recognised by most firmwares.  So, check ourselves
+		 * */
+		if (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
+		    ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
+		    is_ethersnap(&hdr)) {
+			/* These indicate a SNAP within 802.2 LLC
+			 * within 802.11 frame which we'll need to
+			 * de-encapsulate to the original EthernetII
+			 * frame. */
+
+			if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */
+				stats->rx_length_errors++;
+				goto drop;
+			}
+			
+			/* Remove SNAP header, reconstruct EthernetII frame */
+			data_len = length - ENCAPS_OVERHEAD;
+			data_off = HERMES_802_3_OFFSET + sizeof(hdr);
+			
+			eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
+			
+			memcpy(eh, &hdr, 2 * ETH_ALEN);
+			eh->h_proto = hdr.ethertype;
+		} else {
+			/* All other cases indicate a genuine 802.3 frame.  No
+			   decapsulation needed.  We just throw the whole
+			   thing in, and hope the protocol layer can deal with
+			   it as 802.3 */
+			data_len = length;
+			data_off = HERMES_802_3_OFFSET;
+			/* FIXME: we re-read from the card data we already read here */
+		}
+		
+		p = skb_put(skb, data_len);
+		err = hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len),
+				       rxfid, data_off);
+		if (err) {
+			printk(KERN_ERR "%s: error %d reading frame. "
+			       "Frame dropped.\n", dev->name, err);
+			stats->rx_errors++;
+			goto drop;
+		}
+		
+		dev->last_rx = jiffies;
+		skb->dev = dev;
+		skb->protocol = eth_type_trans(skb, dev);
+		skb->ip_summed = CHECKSUM_NONE;
+		
+		/* Process the wireless stats if needed */
+		orinoco_stat_gather(dev, skb, &desc);
+		
+		/* Pass the packet to the networking stack */
+		netif_rx(skb);
+		stats->rx_packets++;
+		stats->rx_bytes += length;
+		
+		return;
+		
+	case 7:
+		if (status & HERMES_RXSTAT_BADCRC) {
+                        printk(KERN_DEBUG "%s: Received monitor frame: "
+			       "BADCRC set\n", dev->name);
 			goto drop;
 		}
 
-		/* Remove SNAP header, reconstruct EthernetII frame */
-		data_len = length - ENCAPS_OVERHEAD;
-		data_off = HERMES_802_3_OFFSET + sizeof(hdr);
+		err = hermes_bap_pread(hw, IRQ_BAP, &hdr80211,
+				       sizeof(hdr80211), 
+				       rxfid, HERMES_RX_80211HDR_OFF);
 
-		eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
+		if (err) {
+			printk(KERN_ERR "%s: error %d reading monitor frame. "
+			       "Frame dropped.\n", dev->name, err);
+			stats->rx_errors++;
+			goto drop;
+		}
 
-		memcpy(eh, &hdr, 2 * ETH_ALEN);
-		eh->h_proto = hdr.ethertype;
-	} else {
-		/* All other cases indicate a genuine 802.3 frame.  No
-		   decapsulation needed.  We just throw the whole
-		   thing in, and hope the protocol layer can deal with
-		   it as 802.3 */
-		data_len = length;
-		data_off = HERMES_802_3_OFFSET;
-		/* FIXME: we re-read from the card data we already read here */
-	}
+		orinoco_int_rxmonitor(dev, rxfid, length,
+				      &desc, &hdr80211);
+                break;
 
-	p = skb_put(skb, data_len);
-	err = hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len),
-			       rxfid, data_off);
-	if (err) {
-		printk(KERN_ERR "%s: error %d reading frame. "
-		       "Frame dropped.\n", dev->name, err);
-		stats->rx_errors++;
-		goto drop;
+	default:
+		printk("Received frame on unsupported port=%d\n",
+		       HERMES_RXSTAT_GET_MACPORT(status));
+		break;
 	}
-
-	dev->last_rx = jiffies;
-	skb->dev = dev;
-	skb->protocol = eth_type_trans(skb, dev);
-	skb->ip_summed = CHECKSUM_NONE;
-	
-	/* Process the wireless stats if needed */
-	orinoco_stat_gather(dev, skb, &desc);
-
-	/* Pass the packet to the networking stack */
-	netif_rx(skb);
-	stats->rx_packets++;
-	stats->rx_bytes += length;
-
-	return;
-
  drop:	
 	stats->rx_dropped++;
 
@@ -3598,6 +3631,159 @@
 	return 0;
 }
 
+static int orinoco_wlansniff(struct net_device *dev, struct iwreq *wrq)
+{
+	struct orinoco_private *priv = dev->priv;
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	u16 word;
+	int *parms = (int *) wrq->u.name;
+	int enable = parms[0] > 0;
+	unsigned long flags;
+
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
+
+	switch (enable) {
+	case 0:
+		/* Confirm that we're in monitor mode */
+		if (dev->type == ARPHRD_ETHER)
+			err = -EFAULT;
+
+		/* Disable monitor mode */
+		word =	HERMES_CMD_MONITOR | (HERMES_MONITOR_DISABLE << 8);
+		err = hermes_docmd_wait(hw, word, 0, NULL);
+		if (err)
+			break;
+
+		/* Disable port 0 */
+		err = hermes_disable_port(hw, 0);
+		if (err)
+			break;
+
+		/* Clear the driver state */
+		dev->type = ARPHRD_ETHER;
+
+		/* Restore the wepflags */   /*Orinoco doesn't like this*/
+#if 0
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFWEPFLAGS_INTERSIL, 
+					   priv->presniff_wepflags);
+		if (err)
+			break;
+#endif /* 0 */
+
+		/* Set the port to its prior type and enable (if necessary) */
+		if (priv->presniff_port_type != 0) {
+			word = priv->presniff_port_type;
+			err = hermes_write_wordrec(hw, USER_BAP, 
+						   HERMES_RID_CNFPORTTYPE,
+						   word);
+			if (err)
+				break;
+			
+			/* Enable the port */
+			err = hermes_enable_port(hw, 0);
+			if (err)
+				break;
+		}
+
+		break;
+
+	case 1:
+		/* 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);
+		/* Disable the port (if enabled), only check Port 0 */
+		if (hw->port_enabled[0]) {
+			/* Save macport 0 state */
+			err = hermes_read_wordrec(hw, USER_BAP,
+						  HERMES_RID_CNFPORTTYPE,
+						  &(priv->presniff_port_type));
+			if (err)
+				break;
+		    
+			/* Save the wepflags state */
+			err = hermes_read_wordrec(hw, USER_BAP,
+						  HERMES_RID_CNFWEPFLAGS_INTERSIL,
+						  &(priv->presniff_wepflags));
+			if (err)
+				break;
+			err = hermes_disable_port(hw, 0);
+			if (err)
+				break;
+		} else {
+			priv->presniff_port_type = 0;
+		}
+
+		/* Set the channel we wish to sniff  */
+		if ((parms[1] > 0) && (parms[1] < 15)) {
+			word = parms[1];
+			err = hermes_write_wordrec(hw, USER_BAP, 
+						   HERMES_RID_CNFOWNCHANNEL,
+						   word);
+		} else {
+			err = -EFAULT;
+		}
+
+		if (err)
+			break;
+
+		/* Set the port type to pIbss */
+		word = HFA384x_PORTTYPE_IBSS;
+		err = hermes_write_wordrec(hw, USER_BAP, 
+					   HERMES_RID_CNFPORTTYPE, word);
+		if (err)
+			break;
+
+#if 0
+		if ( (msg->keepwepflags.status == P80211ENUM_msgitem_status_data_ok) && 
+		     (msg->keepwepflags.data != 1)) {
+			/* Set the wepflags for no decryption */
+			/* Orinoco doesn't like this */
+			word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT | 
+				HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
+			err = hermes_write_wordrec(hw, USER_BAP, 
+						   HERMES_RID_CNFWEPFLAGS_INTERSIL,
+						   word); /*won't work with the bits above */
+		}
+		if (err)
+			break;
+#endif /* 0 */
+		/* Enable the port */
+		err = hermes_enable_port(hw, 0);
+		if (err)
+			break;
+
+		/* Enable monitor mode */
+		word =	HERMES_CMD_MONITOR | (HERMES_MONITOR_ENABLE << 8);
+		err = hermes_docmd_wait(hw, word, 0, NULL);
+		if (err)
+			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:
+		BUG();
+		break;
+	}
+
+	orinoco_unlock(priv, &flags);
+	return err;
+}
+
 static int
 orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
@@ -3830,6 +4016,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" },
 			};
 
@@ -3924,6 +4113,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)
@@ -4171,6 +4370,191 @@
 
 }
 
+/*----------------------------------------------------------------
+* orinoco_int_rxmonitor
+*
+* 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
+*
+* Side effects:
+*	Allocates an skb and passes it up via the PF_PACKET interface.
+* Call context:
+*	interrupt
+----------------------------------------------------------------*/
+void orinoco_int_rxmonitor(struct net_device *dev, u16 rxfid,
+			   int len, struct hermes_rx_descriptor *rxdesc,
+			   struct ieee802_11_hdr *hdr)
+{
+	struct orinoco_private *priv = dev->priv;
+	hermes_t *hw = &priv->hw;
+	u32 hdrlen = 0;
+	u32 datalen = 0;
+	u32 skblen = 0;
+	p80211msg_lnxind_wlansniffrm_t *msg;
+	struct net_device_stats *stats = &priv->stats;
+	u8 *datap;
+	u16 fc;
+	struct sk_buff *skb;
+
+	/* Don't forget the status, time, and data_len fields are in
+	 * little-endian order */
+	/* Figure out how big the frame is */
+	fc = le16_to_cpu(hdr->frame_ctl);
+	switch (fc & IEEE802_11_FCTL_FTYPE) {
+	case IEEE802_11_FTYPE_DATA:
+		if ((fc & IEEE802_11_FCTL_TODS)
+		    && (fc & IEEE802_11_FCTL_FROMDS))
+			hdrlen = WLAN_HDR_A4_LEN;
+		else
+			hdrlen = WLAN_HDR_A3_LEN;
+		datalen = len;
+		break;
+	case IEEE802_11_FTYPE_MGMT:
+		hdrlen = WLAN_HDR_A3_LEN;
+		datalen = len;
+		break;
+	case IEEE802_11_FTYPE_CTL:
+		switch (fc & IEEE802_11_FCTL_STYPE) {
+		case IEEE802_11_STYPE_PSPOLL:
+		case IEEE802_11_STYPE_RTS:
+		case IEEE802_11_STYPE_CFEND:
+		case IEEE802_11_STYPE_CFENDACK:
+			hdrlen = 16;
+			break;
+		case IEEE802_11_STYPE_CTS:
+		case IEEE802_11_STYPE_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->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->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 = 0;
+	  
+		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;
+	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                                            */
 /********************************************************************/
diff -urN dist/orinoco-0.13e/orinoco.h orinoco-monitor/orinoco.h
--- dist/orinoco-0.13e/orinoco.h	2003-05-12 16:22:27.000000000 +1000
+++ orinoco-monitor/orinoco.h	2003-05-13 13:27:02.000000000 +1000
@@ -37,6 +37,16 @@
 /* To enable debug messages */
 //#define ORINOCO_DEBUG		3
 
+#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
+
 #if (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10)
 #error "orinoco driver requires Wireless extensions v10 or later."
 #endif /* (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10) */
@@ -55,6 +65,67 @@
 				HERMES_EV_INFDROP )
 
 
+#define WLAN_DEVNAMELEN_MAX 16
+
+/* message data item for INT, BOUNDEDINT, ENUMINT */
+typedef struct p80211item_uint32 {
+	u32 did;
+	u16 status;
+	u16 len;
+	u32 data;
+} __attribute__ ((packed)) p80211item_uint32_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 {
+	u32 msgcode;
+	u32 msglen;
+	u8 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_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
+
+/*--- Sizes -----------------------------------------------*/
+#define WLAN_CRC_LEN			4
+#define WLAN_HDR_A3_LEN			24
+#define WLAN_HDR_A4_LEN			30
+#define WLAN_DATA_MAXLEN		2312
+
 struct orinoco_private {
 	void *card;	/* Pointer to card dependent structure */
 	int (*hard_reset)(struct orinoco_private *);
@@ -116,6 +187,9 @@
 	/* Configuration dependent variables */
 	int port_type, createibss;
 	int promiscuous, mc_count;
+
+	u16 presniff_port_type;
+	u16 presniff_wepflags;
 };
 
 #ifdef ORINOCO_DEBUG