diff -u -r --new-file orinoco-0.15rc2/orinoco.c orinoco-0.15rc2-dragorn/orinoco.c
--- orinoco-0.15rc2/orinoco.c	2004-07-28 02:06:45.000000000 -0400
+++ orinoco-0.15rc2-dragorn/orinoco.c	2005-02-04 17:15:29.000000000 -0500
@@ -447,6 +447,11 @@
  *	o Numerous trivial cleanups, mainly arising from long-overdue
  *	  merge with mainline.
  *
+ * v0.15rc2-dragorn (dragorn@kismetwireless.net)
+ *  o Restored missing Prism2 and Prism2_AVS functionality for per-packet
+ *    statistics
+ *  o Optional FCS bytes support
+ *
  * TODO
  *	o Handle de-encapsulation within network layer, provide 802.11
  *	  headers (patch from Thomas 'Dent' Mirlacher)
@@ -505,6 +510,8 @@
 #include "orinoco.h"
 #include "ieee802_11.h"
 
+#include "prism2header.h"
+
 /********************************************************************/
 /* Module information                                               */
 /********************************************************************/
@@ -1169,9 +1176,20 @@
 	struct orinoco_private *priv = netdev_priv(dev);
 	struct net_device_stats *stats = &priv->stats;
 	hermes_t *hw = &priv->hw;
+	int skballoclen;
+	uint8_t *datap;
+	p80211msg_lnxind_wlansniffrm_t *prism2hdr;
+	prism2_avs_80211_v1_header *prism2avshdr;
+	uint8_t fcsquad[4] = {0xFF, 0xFF, 0xFF, 0xFF};
+	struct ieee802_11_hdr hdr;
 
 	len = le16_to_cpu(desc->data_len);
 
+	/* Try to grab a standard headers size from the bap.  If this doesn't
+	 * work then we couldn't have done anything anyhow */
+	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), rxfid,
+						   HERMES_802_11_OFFSET);
+
 	/* Determine the size of the header and the data */
 	fc = le16_to_cpu(desc->frame_ctl);
 	switch (fc & IEEE802_11_FCTL_FTYPE) {
@@ -1214,7 +1232,19 @@
 		goto drop;
 	}
 
-	skb = dev_alloc_skb(hdrlen + datalen);
+	/* Handle allocation for different custom packet headers (dragorn) */
+	if (priv->prism2header == 1 && dev->type == ARPHRD_IEEE80211_PRISM)
+		skballoclen = hdrlen + datalen + sizeof(p80211msg_lnxind_wlansniffrm_t);
+	else if (priv->prism2header == 2 && dev->type == ARPHRD_IEEE80211_PRISM)
+		skballoclen = hdrlen + datalen + sizeof(prism2_avs_80211_v1_header);
+	else
+		skballoclen = hdrlen + datalen;
+
+	/* Handle optional FCS bytes */
+	if (priv->fcsbytes)
+		skballoclen = skballoclen + 4;
+
+	skb = dev_alloc_skb(skballoclen);
 	if (!skb) {
 		printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
 		       dev->name);
@@ -1222,22 +1252,110 @@
 		goto drop;
 	}
 
+	skb_put(skb, skballoclen); 
+
+	/* Do we build a custom header?  Only attach it if we're in the right linktype */
+	if (priv->prism2header == 1 && dev->type == ARPHRD_IEEE80211_PRISM) {
+		datap = skb->data + sizeof(p80211msg_lnxind_wlansniffrm_t);
+		prism2hdr = (p80211msg_lnxind_wlansniffrm_t *) skb->data;
+
+		/* Initialize the message members */
+		prism2hdr->msgcode = DIDmsg_lnxind_wlansniffrm;
+		prism2hdr->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t);
+		strcpy(prism2hdr->devname, priv->ndev->name);
+
+		prism2hdr->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
+		prism2hdr->hosttime.status = 0;
+		prism2hdr->hosttime.len = 4;
+		prism2hdr->hosttime.data = jiffies;
+
+		prism2hdr->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
+		prism2hdr->mactime.status = 0;
+		prism2hdr->mactime.len = 4;
+		prism2hdr->mactime.data = desc->time;
+
+		prism2hdr->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
+		prism2hdr->channel.status = P80211ENUM_msgitem_status_no_value;
+		prism2hdr->channel.len = 4;
+		prism2hdr->channel.data = 0;
+
+		prism2hdr->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
+		prism2hdr->rssi.status = P80211ENUM_msgitem_status_no_value;
+		prism2hdr->rssi.len = 4;
+		prism2hdr->rssi.data = 0;
+
+		prism2hdr->sq.did = DIDmsg_lnxind_wlansniffrm_sq;
+		prism2hdr->sq.status = P80211ENUM_msgitem_status_no_value;
+		prism2hdr->sq.len = 4;
+		prism2hdr->sq.data = 0;
+
+		prism2hdr->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
+		prism2hdr->signal.status = 0;
+		prism2hdr->signal.len = 4;
+		prism2hdr->signal.data = desc->signal;
+
+		prism2hdr->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
+		prism2hdr->noise.status = 0;
+		prism2hdr->noise.len = 4;
+		prism2hdr->noise.data = desc->silence;
+
+		prism2hdr->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
+		prism2hdr->rate.status = 0;
+		prism2hdr->rate.len = 4;
+		prism2hdr->rate.data = desc->rate / 5; /* set to 802.11 units */
+
+		prism2hdr->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
+		prism2hdr->istx.status = 0;
+		prism2hdr->istx.len = 4;
+		prism2hdr->istx.data = 0;
+
+		prism2hdr->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
+		prism2hdr->frmlen.status = 0;
+		prism2hdr->frmlen.len = 4;
+		prism2hdr->frmlen.data = hdrlen + datalen;
+	} else if (priv->prism2header == 2 && dev->type == ARPHRD_IEEE80211_PRISM) {
+		datap = skb->data + sizeof(prism2_avs_80211_v1_header);
+		prism2avshdr = (prism2_avs_80211_v1_header *) skb->data;
+
+		prism2avshdr->version = htonl(P80211CAPTURE_VERSION);
+		prism2avshdr->length = htonl(sizeof(prism2_avs_80211_v1_header));
+		prism2avshdr->mactime = __cpu_to_be64(desc->time) * 1000;
+		prism2avshdr->hosttime = __cpu_to_be64(jiffies);
+		prism2avshdr->phytype = htonl(4); /* 802.11b */
+		prism2avshdr->channel = htonl(0);
+		prism2avshdr->datarate = htonl(desc->rate);
+		prism2avshdr->antenna = htonl(0);
+		prism2avshdr->priority = htonl(0);
+		prism2avshdr->ssi_type = htonl(3); /* ssi raw */
+		prism2avshdr->ssi_signal = htonl(desc->signal);
+		prism2avshdr->ssi_noise = htonl(desc->silence);
+		prism2avshdr->preamble = htonl(0); /* Unknown */
+		prism2avshdr->encoding = htonl(1); /* CCK */
+	} else {
+		datap = skb->data;
+	}
+
 	/* Copy the 802.11 header to the skb */
-	memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen);
+	memcpy(datap, &(hdr.frame_ctl), hdrlen);
 	skb->mac.raw = skb->data;
 
 	/* If any, copy the data from the card to the skb */
 	if (datalen > 0) {
-		err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
-				       ALIGN(datalen, 2), rxfid,
-				       HERMES_802_2_OFFSET);
+		err = hermes_bap_pread(hw, IRQ_BAP, datap + hdrlen,
+							   (datalen + 1) & ~1, rxfid,
+							   HERMES_802_2_OFFSET);
 		if (err) {
 			printk(KERN_ERR "%s: error %d reading monitor frame\n",
-			       dev->name, err);
+				   dev->name, err);
 			goto drop;
 		}
 	}
 
+	/* Attach the FCS if requested */
+	if (priv->fcsbytes)
+		memcpy(skb->data + skballoclen - 4, fcsquad, 4);
+
+
 	skb->dev = dev;
 	skb->ip_summed = CHECKSUM_NONE;
 	skb->pkt_type = PACKET_OTHERHOST;
@@ -1245,6 +1363,9 @@
 	
 	dev->last_rx = jiffies;
 	stats->rx_packets++;
+	/* Should this really be += datalen since thats how many bytes we really
+	 * got?  I don't know that I trust ANY of these stats in rfmon since it's 
+	 * a funny link type so we'll leave it for now.  (dragorn) */
 	stats->rx_bytes += skb->len;
 
 	netif_rx(skb);
@@ -2225,13 +2346,23 @@
 		}
 	}
 
-	if (priv->iw_mode == IW_MODE_MONITOR) {
-		/* Enable monitor mode */
-		dev->type = ARPHRD_IEEE80211;
+	/* Enable monitor mode if we're not already in it */
+	if (priv->iw_mode == IW_MODE_MONITOR && dev->type != ARPHRD_IEEE80211 &&
+		dev->type != ARPHRD_IEEE80211_PRISM) {
+		
+		/* Set the link type */
+		if (priv->prism2header)
+			dev->type = ARPHRD_IEEE80211_PRISM;
+		else
+			dev->type = ARPHRD_IEEE80211;
+
 		err = hermes_docmd_wait(hw, HERMES_CMD_TEST | 
 					    HERMES_TEST_MONITOR, 0, NULL);
-	} else {
-		/* Disable monitor mode */
+	}
+
+	/* Disable monitor mode if we're not already out of it */
+	if (priv->iw_mode != IW_MODE_MONITOR &&
+		(dev->type == ARPHRD_IEEE80211 || dev->type == ARPHRD_IEEE80211_PRISM)) {
 		dev->type = ARPHRD_ETHER;
 		err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
 					    HERMES_TEST_STOP, 0, NULL);
@@ -2830,6 +2961,11 @@
 	priv->wep_on = 0;
 	priv->tx_key = 0;
 
+	/* Turn on rfmon fancy stuff by default so that we look like the
+	 * old drivers did (dragorn) */
+	priv->prism2header = 1;
+	priv->fcsbytes = 1;
+
 	/* Make the hardware available, as long as it hasn't been
 	 * removed elsewhere (e.g. by PCMCIA hot unplug) */
 	spin_lock_irq(&priv->lock);
@@ -4672,6 +4808,62 @@
 }
 #endif	/* WIRELESS_EXT > 13 */
 
+/* Set the prism2 headers */
+static int orinoco_ioctl_setprism2header(struct net_device *dev,
+										 struct iw_request_info *info,
+										 void *wrqu,
+										 char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+	int val = *( (int *) extra );
+	unsigned long flags;
+
+	if (orinoco_lock(priv, &flags) != 0)
+		return -EBUSY;
+
+	/* Only allow legal values: 0 off, 1 prism2, 2 prism2avs */
+	if (val < 0 || val > 2)
+		return -EINVAL;
+
+	/* If we're in rfmon, update the linktype appropriately */
+	if (priv->iw_mode == IW_MODE_MONITOR && 
+		dev->type != ARPHRD_IEEE80211_PRISM && val) {
+		printk(KERN_DEBUG "setting type ieee80211_prism\n");
+		dev->type = ARPHRD_IEEE80211_PRISM;
+	} else if (priv->iw_mode == IW_MODE_MONITOR && 
+			   dev->type != ARPHRD_IEEE80211 && val == 0) {
+		printk(KERN_DEBUG "setting type ieee80211\n");
+		dev->type = ARPHRD_IEEE80211;
+	}
+
+	priv->prism2header = val;
+
+	orinoco_unlock(priv, &flags);
+	return 0;
+}
+
+/* Set if we append trailing FCS bytes */
+static int orinoco_ioctl_setfcsbytes(struct net_device *dev,
+									 struct iw_request_info *info,
+									 void *wrqu,
+									 char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+	int val = *( (int *) extra );
+	unsigned long flags;
+
+	if (orinoco_lock(priv, &flags) != 0)
+		return -EBUSY;
+
+	if (val < 0 || val > 1)
+		return -EINVAL;
+
+	priv->fcsbytes = val;
+
+	orinoco_unlock(priv, &flags);
+	return 0;
+}
+
 /* Commit handler, called after set operations */
 static int orinoco_ioctl_commit(struct net_device *dev,
 				struct iw_request_info *info,
@@ -4793,6 +4985,12 @@
 	{ SIOCIWFIRSTPRIV + 0x9, 0,
 	  IW_PRIV_TYPE_BYTE | MAX_RID_LEN,
 	  "get_rid" },
+	{ SIOCIWFIRSTPRIV + 0x10,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	  0, "set_prismheader" },
+	{ SIOCIWFIRSTPRIV + 0x12,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	  0, "set_fcsbytes" },
 };
 
 #if WIRELESS_EXT > 12
@@ -4870,7 +5068,9 @@
 	(iw_handler) orinoco_ioctl_setibssport,		/* SIOCIWFIRSTPRIV + 6 */
 	(iw_handler) orinoco_ioctl_getibssport,		/* SIOCIWFIRSTPRIV + 7 */
 	(iw_handler) NULL,				/* SIOCIWFIRSTPRIV + 8 */
-	(iw_handler) orinoco_ioctl_getrid		/* SIOCIWFIRSTPRIV + 9 */
+	(iw_handler) orinoco_ioctl_getrid,		/* SIOCIWFIRSTPRIV + 9 */
+	(iw_handler) orinoco_ioctl_setprism2header, /* SIOCIWFIRSTPRIV + 10 */
+	(iw_handler) orinoco_ioctl_setfcsbytes,	 /* SIOCIWFIRSTPRIV + 12 */
 };
 
 static const struct iw_handler_def	orinoco_handler_def =
diff -u -r --new-file orinoco-0.15rc2/orinoco.h orinoco-0.15rc2-dragorn/orinoco.h
--- orinoco-0.15rc2/orinoco.h	2004-07-28 02:06:45.000000000 -0400
+++ orinoco-0.15rc2-dragorn/orinoco.h	2005-02-04 17:15:33.000000000 -0500
@@ -140,6 +140,11 @@
 	u32	scan_mode;		/* Type of scan done */
 	char *	scan_result;		/* Result of previous scan */
 	int	scan_len;		/* Lenght of result */
+
+	/* rfmon additions */
+	int prism2header; /* Attach no header (0), prism2 (1), or prism2_avs (2) */
+	int fcsbytes; /* Attach a bogus 4-byte FCS to frames to make this look like
+					the old drivers and like the original wlan-ng monitor return */
 };
 
 #ifdef ORINOCO_DEBUG
diff -u -r --new-file orinoco-0.15rc2/prism2header.h orinoco-0.15rc2-dragorn/prism2header.h
--- orinoco-0.15rc2/prism2header.h	1969-12-31 19:00:00.000000000 -0500
+++ orinoco-0.15rc2-dragorn/prism2header.h	2005-02-04 17:15:37.000000000 -0500
@@ -0,0 +1,98 @@
+#ifndef _PRISM2HEADER_H
+#define _PRISM2HEADER_H
+
+#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_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 P80211CAPTURE_VERSION     0x80211001
+typedef struct {
+    uint32_t version;
+    uint32_t length;
+    uint64_t mactime;
+    uint64_t hosttime;
+    uint32_t phytype;
+    uint32_t channel;
+    uint32_t datarate;
+    uint32_t antenna;
+    uint32_t priority;
+    uint32_t ssi_type;
+    int32_t ssi_signal;
+    int32_t ssi_noise;
+    uint32_t preamble;
+    uint32_t encoding;
+} prism2_avs_80211_v1_header;
+
+#endif /* _PRISM2HEADER_H */
