Binary files orinoco-cvs-pure/.orinoco.c.swp and orinoco-cvs/.orinoco.c.swp differ Common subdirectories: orinoco-cvs-pure/CVS and orinoco-cvs/CVS diff -u --new-file orinoco-cvs-pure/orinoco.c orinoco-cvs/orinoco.c --- orinoco-cvs-pure/orinoco.c 2004-02-26 14:04:18.000000000 -0500 +++ orinoco-cvs/orinoco.c 2004-02-26 14:34:53.000000000 -0500 @@ -430,6 +430,7 @@ * o Fix recognition of Intersil x.x.1 firmware (Pavel Roskin). * o Don't let unprivileged users use dump_recs (Pavel Roskin). * o RF monitor mode support (Pavel Roskin). + * o Prism2 and Prism2AVS header support, FCS byte support (Mike Kershaw) * * TODO * o Handle de-encapsulation within network layer, provide 802.11 @@ -486,6 +487,7 @@ #include "hermes_rid.h" #include "orinoco.h" #include "ieee802_11.h" +#include "prism2header.h" /********************************************************************/ /* Module information */ @@ -1133,7 +1135,7 @@ * * Call context: interrupt */ -static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, int len) +static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, struct hermes_rx_descriptor *rxdesc, int len) { u32 hdrlen = 30; /* return full header by default */ u32 datalen = 0; @@ -1144,6 +1146,11 @@ struct orinoco_private *priv = dev->priv; 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}; err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr), rxfid, HERMES_802_11_OFFSET); @@ -1196,7 +1203,19 @@ goto drop; } - skb = dev_alloc_skb(hdrlen + datalen); + /* Handle allocation for different custom headers */ + 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 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); @@ -1204,13 +1223,100 @@ goto drop; } + skb_put(skb, skballoclen); + + /* WARNING: Right now we build just prism2, not AVS! */ + /* 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 = rxdesc->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 = rxdesc->signal; + + prism2hdr->noise.did = DIDmsg_lnxind_wlansniffrm_noise; + prism2hdr->noise.status = 0; + prism2hdr->noise.len = 4; + prism2hdr->noise.data = rxdesc->silence; + + prism2hdr->rate.did = DIDmsg_lnxind_wlansniffrm_rate; + prism2hdr->rate.status = 0; + prism2hdr->rate.len = 4; + prism2hdr->rate.data = rxdesc->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 = P80211ENUM_truth_false; + + 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(rxdesc->time) * 1000; + prism2avshdr->hosttime = __cpu_to_be64(jiffies); + prism2avshdr->phytype = htonl(4); /* 802.11b */ + prism2avshdr->channel = htonl(0); + prism2avshdr->datarate = htonl(rxdesc->rate); + prism2avshdr->antenna = htonl(0); + prism2avshdr->priority = htonl(0); + prism2avshdr->ssi_type = htonl(3); /* ssi raw */ + prism2avshdr->ssi_signal = htonl(rxdesc->signal); + prism2avshdr->ssi_noise = htonl(rxdesc->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), &(hdr.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), + err = hermes_bap_pread(hw, IRQ_BAP, datap + hdrlen, (datalen + 1) & ~1, rxfid, HERMES_802_2_OFFSET); if (err) { @@ -1220,6 +1326,10 @@ } } + /* 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; @@ -1298,7 +1408,7 @@ /* Handle monitor frames */ if (port == 7) { - orinoco_rx_monitor(dev, rxfid, length); + orinoco_rx_monitor(dev, rxfid, &desc, length); return; } @@ -2075,9 +2185,16 @@ } } - if (priv->iw_mode == IW_MODE_MONITOR && dev->type != ARPHRD_IEEE80211) { + /* Is this the nicest way of doing this? - dragorn */ + if (priv->iw_mode == IW_MODE_MONITOR && dev->type == ARPHRD_ETHER) { /* Enable monitor mode */ - dev->type = ARPHRD_IEEE80211; + + /* Set the link type */ + if (priv->prism2header) + dev->type = ARPHRD_IEEE80211_PRISM; + else + dev->type = ARPHRD_IEEE80211; + err = hermes_docmd_wait(hw, HERMES_CMD_MONITOR | HERMES_MONITOR_ENABLE, 0, NULL); @@ -2085,7 +2202,8 @@ return err; } - if (priv->iw_mode != IW_MODE_MONITOR && dev->type == ARPHRD_IEEE80211) { + /* Again, best way to test? Do we ever use anything other than ARPHRD_ETHER for normal mode? */ + if (priv->iw_mode != IW_MODE_MONITOR && dev->type != ARPHRD_ETHER) { /* Disable monitor mode */ dev->type = ARPHRD_ETHER; err = hermes_docmd_wait(hw, @@ -2653,6 +2771,10 @@ priv->wep_on = 0; priv->tx_key = 0; + /* Don't turn on the rfmon fancy stuff by default */ + priv->prism2header = 0; + priv->fcsbytes = 0; + err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); if (err == -EIO) { /* Try workaround for old Symbol firmware bug */ @@ -4369,6 +4491,60 @@ } #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 -EINPROGRESS; /* Call commit handler */ +} + +/* 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 -EINPROGRESS; /* Call commit handler */ +} + /* Commit handler, called after set operations */ static int orinoco_ioctl_commit(struct net_device *dev, struct iw_request_info *info, @@ -4461,6 +4637,12 @@ { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_ibssport" }, + { SIOCIWFIRSTPRIV + 0x8, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_prismheader" }, + { SIOCIWFIRSTPRIV + 0x9, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "set_fcsbytes" }, { SIOCIWLASTPRIV, 0, 0, "dump_recs" }, }; @@ -4538,6 +4720,8 @@ (iw_handler) orinoco_ioctl_getpreamble, /* SIOCIWFIRSTPRIV + 5 */ (iw_handler) orinoco_ioctl_setibssport, /* SIOCIWFIRSTPRIV + 6 */ (iw_handler) orinoco_ioctl_getibssport, /* SIOCIWFIRSTPRIV + 7 */ + (iw_handler) orinoco_ioctl_setprism2header, /* SIOCIWFIRSTPRIV + 8 */ + (iw_handler) orinoco_ioctl_setfcsbytes, /* SIOCIWFIRSTPRIV + 9 */ [SIOCIWLASTPRIV - SIOCIWFIRSTPRIV] (iw_handler) orinoco_debug_dump_recs, }; diff -u --new-file orinoco-cvs-pure/orinoco.h orinoco-cvs/orinoco.h --- orinoco-cvs-pure/orinoco.h 2004-02-26 14:04:18.000000000 -0500 +++ orinoco-cvs/orinoco.h 2004-02-26 11:25:12.000000000 -0500 @@ -123,6 +123,11 @@ u32 scan_mode; /* Type of scan done */ char * scan_result; /* Result of previous scan */ int scan_len; /* Lenght of result */ + + /* rfmon format */ + int prism2header; /* Attach no header, prism2, or prism2_avs to rfmon packets */ + int fcsbytes; /* Attach a bogus 4-byte FCS to packets */ + }; #ifdef ORINOCO_DEBUG diff -u --new-file orinoco-cvs-pure/prism2header.h orinoco-cvs/prism2header.h --- orinoco-cvs-pure/prism2header.h 1969-12-31 19:00:00.000000000 -0500 +++ orinoco-cvs/prism2header.h 2004-02-26 14:24:04.000000000 -0500 @@ -0,0 +1,100 @@ +#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_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 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 */