2005-02-26 18:16:23

by Eric Gaumer

[permalink] [raw]
Subject: [PATCH] orinoco rfmon

Could anyone elaborate on the status of this patch? I've had 344 days of uptime on a PPC
powerbook using it on 2.4.22 and about 3 months of solid use on 2.6.

If the code looks problematic could someone point out possible deficiencies so we can work
toward a satisfactory resolution? I didn't write the code but I'm willing do what I have to
in order to get this (wireless scanning) into the official tree.



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 */



--
"Education is what remains after one has forgotten everything he learned in school."
- Albert Einstein


Attachments:
signature.asc (256.00 B)
OpenPGP digital signature

2005-02-26 19:59:53

by Alexey Dobriyan

[permalink] [raw]
Subject: Re: [PATCH] orinoco rfmon

On Saturday 26 February 2005 20:10, Eric Gaumer wrote:

> If the code looks problematic could someone point out possible
> deficiencies so we can work toward a satisfactory resolution? I didn't
> write the code but I'm willing do what I have to in order to get this
> (wireless scanning) into the official tree.

Uhhh... Started to comment line-by-line but then realized it would take too
much time.

* Read Documentaion/CodingStyle.
* Indent code with tabs where it is already indented with tabs.
* Brackets around a single number in #define's are useless.
* Use u8, u16, u32 (not uint*_t) where the code already uses them.
* Comments are supposed to be anonymous.
* Use appropriate KERN_* constant in printk()'s.
* Don't pack simple types (uint32_t, ...)
* Common convention is to return 0 on success, negative number on error.
Positive return values don't fit well into this scheme. If possible
follow it.

Oh, and the type p80211item_uint32_t when in fact it is a 12-bytes long
structure ...

Alexey

2005-02-26 22:49:46

by Eric Gaumer

[permalink] [raw]
Subject: Re: [PATCH] orinoco rfmon

Alexey Dobriyan wrote:
> On Saturday 26 February 2005 20:10, Eric Gaumer wrote:
>
>
>>If the code looks problematic could someone point out possible
>>deficiencies so we can work toward a satisfactory resolution? I didn't
>>write the code but I'm willing do what I have to in order to get this
>>(wireless scanning) into the official tree.
>
>
> Uhhh... Started to comment line-by-line but then realized it would take too
> much time.
>
> * Read Documentaion/CodingStyle.
> * Indent code with tabs where it is already indented with tabs.
> * Brackets around a single number in #define's are useless.
> * Use u8, u16, u32 (not uint*_t) where the code already uses them.
> * Comments are supposed to be anonymous.
> * Use appropriate KERN_* constant in printk()'s.
> * Don't pack simple types (uint32_t, ...)
> * Common convention is to return 0 on success, negative number on error.
> Positive return values don't fit well into this scheme. If possible
> follow it.
>
> Oh, and the type p80211item_uint32_t when in fact it is a 12-bytes long
> structure ...
>
> Alexey

What is the difference between u* and uint*_t ? Both are derived from the same basic data type.

typedef unsigned char __u8;
typedef __u8 uint8_t;

And...

typedef unsigned char u8;

--
"Education is what remains after one has forgotten everything he learned in school."
- Albert Einstein


Attachments:
signature.asc (256.00 B)
OpenPGP digital signature

2005-02-27 04:28:33

by David Gibson

[permalink] [raw]
Subject: Re: [PATCH] orinoco rfmon

On Sat, Feb 26, 2005 at 10:10:15AM -0800, Eric Gaumer wrote:
> Could anyone elaborate on the status of this patch? I've had 344 days of
> uptime on a PPC
> powerbook using it on 2.4.22 and about 3 months of solid use on 2.6.
>
> If the code looks problematic could someone point out possible deficiencies
> so we can work
> toward a satisfactory resolution? I didn't write the code but I'm willing
> do what I have to
> in order to get this (wireless scanning) into the official tree.

This looks like the ancient version of the monitor patch - which
includes importing a lot of needless junk from the linux-wlan-ng
tree. A cleaned up version of monitor has been merged in the orinoco
CVS tree for ages now, but unfortunately that's long overdue for a
merge with mainline. I'm trying to get that merge done - I just don't
have much time or energy for the orinoco driver these days. One stack
of patches which gets part of the way went to Jeff Garzik last week.
We'll see how we go.

In the meantime go to http://savannah.nongnu.org/projects/orinoco for
access to the driver CVS. You probably want to get the "for_linus"
branch of CVS if you're planning to work with 2.6.

--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist. NOT _the_ _other_ _way_
| _around_!
http://www.ozlabs.org/people/dgibson


Attachments:
(No filename) (1.33 kB)
signature.asc (189.00 B)
Digital signature
Download all attachments

2005-02-28 00:51:06

by Eric Gaumer

[permalink] [raw]
Subject: Re: [PATCH] orinoco rfmon

David Gibson wrote:
>
> This looks like the ancient version of the monitor patch - which
> includes importing a lot of needless junk from the linux-wlan-ng
> tree. A cleaned up version of monitor has been merged in the orinoco
> CVS tree for ages now, but unfortunately that's long overdue for a
> merge with mainline. I'm trying to get that merge done - I just don't
> have much time or energy for the orinoco driver these days. One stack
> of patches which gets part of the way went to Jeff Garzik last week.
> We'll see how we go.
>
> In the meantime go to http://savannah.nongnu.org/projects/orinoco for
> access to the driver CVS. You probably want to get the "for_linus"
> branch of CVS if you're planning to work with 2.6.
>

Thanks David, the CVS code works great with the small excpetion of the following change to
get it to build.

diff -Nru orinoco-cvs/orinoco_cs.c orinoco-build/orinoco_cs.c
--- orinoco-cvs/orinoco_cs.c 2005-02-26 22:21:55.000000000 -0800
+++ orinoco-build/orinoco_cs.c 2005-02-27 15:00:07.698368136 -0800
@@ -428,7 +428,7 @@
SET_MODULE_OWNER(dev);
card->node.major = card->node.minor = 0;

- SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+ dev->name[0] = '\0';
/* Tell the stack we exist */
if (register_netdev(dev) != 0) {
printk(KERN_ERR PFX "register_netdev() failed\n");


What's the deal with the broken firmware for monitor mode?

* v0.15rc1 -> v0.15rc2 - 28 Jul 2004 - Pavel Roskin & David Gibson
* o orinoco_pci saves PCI registers on suspend (Simon Huggins).
* o Monitor mode disabled on Agere 8.xx firmware - it's broken.

I have 8.4 but things seem fine (used this card in monitor mode for over a year without
problems).

I just disabled the check for broken firmware and things seem fine (better than the original
patch I posted). The iwlist command now works. Could the buggy firmware be generalized a bit
too much? Perhaps only certain versions > 8 are buggy?


--
"Education is what remains after one has forgotten everything he learned in school."
- Albert Einstein


Attachments:
signature.asc (256.00 B)
OpenPGP digital signature

2005-02-28 01:03:20

by David Gibson

[permalink] [raw]
Subject: Re: [PATCH] orinoco rfmon

On Sun, Feb 27, 2005 at 04:45:46PM -0800, Eric Gaumer wrote:
> David Gibson wrote:
> >
> >This looks like the ancient version of the monitor patch - which
> >includes importing a lot of needless junk from the linux-wlan-ng
> >tree. A cleaned up version of monitor has been merged in the orinoco
> >CVS tree for ages now, but unfortunately that's long overdue for a
> >merge with mainline. I'm trying to get that merge done - I just don't
> >have much time or energy for the orinoco driver these days. One stack
> >of patches which gets part of the way went to Jeff Garzik last week.
> >We'll see how we go.
> >
> >In the meantime go to http://savannah.nongnu.org/projects/orinoco for
> >access to the driver CVS. You probably want to get the "for_linus"
> >branch of CVS if you're planning to work with 2.6.
> >
>
> Thanks David, the CVS code works great with the small excpetion of the
> following change to
> get it to build.
>
> diff -Nru orinoco-cvs/orinoco_cs.c orinoco-build/orinoco_cs.c
> +++ orinoco-build/orinoco_cs.c 2005-02-27 15:00:07.698368136 -0800
> @@ -428,7 +428,7 @@
> SET_MODULE_OWNER(dev);
> card->node.major = card->node.minor = 0;
>
> - SET_NETDEV_DEV(dev, &handle_to_dev(handle));
> + dev->name[0] = '\0';
> /* Tell the stack we exist */
> if (register_netdev(dev) != 0) {
> printk(KERN_ERR PFX "register_netdev() failed\n");
>
>
> What's the deal with the broken firmware for monitor mode?
>
> * v0.15rc1 -> v0.15rc2 - 28 Jul 2004 - Pavel Roskin & David Gibson
> * o orinoco_pci saves PCI registers on suspend (Simon Huggins).
> * o Monitor mode disabled on Agere 8.xx firmware - it's broken.
>
> I have 8.4 but things seem fine (used this card in monitor mode for over a
> year without
> problems).
>
> I just disabled the check for broken firmware and things seem fine (better
> than the original
> patch I posted). The iwlist command now works. Could the buggy firmware be
> generalized a bit
> too much? Perhaps only certain versions > 8 are buggy?

Possibly, but I don't really have the means to find out in more
detail. The trouble is that when it falls over, it falls over very
badly, which is why we disable this rather than just letting the user
risk it. Pavel knows more of the details on this one.

--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist. NOT _the_ _other_ _way_
| _around_!
http://www.ozlabs.org/people/dgibson


Attachments:
(No filename) (2.45 kB)
signature.asc (189.00 B)
Digital signature
Download all attachments

2005-02-28 07:45:00

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH] orinoco rfmon

On Sat, Feb 26, 2005 at 02:45:49PM -0800, Eric Gaumer wrote:
> What is the difference between u* and uint*_t ? Both are derived from the
> same basic data type.
>
> typedef unsigned char __u8;
> typedef __u8 uint8_t;
>
> And...
>
> typedef unsigned char u8;

Don't use the uint*_t types, they are not correct. See the lkml
archives for why this is true.

Use the u8 for when you are in the kernel, and __u8 when you need it for
a variable that crosses the userspace/kernelspace barrier.

thanks,

greg k-h

2005-02-28 07:52:33

by Eric Gaumer

[permalink] [raw]
Subject: Re: [PATCH] orinoco rfmon

Greg KH wrote:
> On Sat, Feb 26, 2005 at 02:45:49PM -0800, Eric Gaumer wrote:
>
>>What is the difference between u* and uint*_t ? Both are derived from the
>>same basic data type.
>>
>>typedef unsigned char __u8;
>>typedef __u8 uint8_t;
>>
>>And...
>>
>>typedef unsigned char u8;
>
>
> Don't use the uint*_t types, they are not correct. See the lkml
> archives for why this is true.
>
> Use the u8 for when you are in the kernel, and __u8 when you need it for
> a variable that crosses the userspace/kernelspace barrier.
>
> thanks,
>

Thanks, I'll dig up those archives.


--
"Education is what remains after one has forgotten everything he learned in school."
- Albert Einstein


Attachments:
signature.asc (256.00 B)
OpenPGP digital signature

2005-02-28 20:02:26

by Pavel Roskin

[permalink] [raw]
Subject: Re: [PATCH] orinoco rfmon

Hello!

>> I just disabled the check for broken firmware and things seem fine (better
>> than the original
>> patch I posted). The iwlist command now works. Could the buggy firmware be
>> generalized a bit
>> too much? Perhaps only certain versions > 8 are buggy?
>
>Possibly, but I don't really have the means to find out in more
>detail. The trouble is that when it falls over, it falls over very
>badly, which is why we disable this rather than just letting the user
>risk it. Pavel knows more of the details on this one.
>
Try AirSnort with scanning enabled - it will bring the firmware down in
a few minutes.

--
Regards,
Pavel Roskin