misc fixes, see CHANGES.

This commit is contained in:
solomon 2003-02-12 23:43:10 +00:00
parent 02927f0c3b
commit b0f068adaa
7 changed files with 99 additions and 46 deletions

View File

@ -41,6 +41,12 @@
* Intersil Corporation as part of PRISM(R) chipset product development.
*
* --------------------------------------------------------------------
- A series of patches from Pavel Kankovsky, somewhat tweaked. :)
- Properly set skb->mac.raw in non-monitor mode
- Enhancments to the p80211 frame conversion code
- Handle A4 frames.
- Don't issue linkstatus notifications in monitor mode
- Supress Linkstatus messages in monitor mode
- hfa384x.h updates for latest firmware.
-pre9
- ZyXEL ZyAir B200 Wireless USB widget ID added (Paul Lacatus)

2
THANKS
View File

@ -97,6 +97,8 @@ Tom Prado <tprado@charter.net>
Olivier Bornet <Olivier.Bornet@puck.ch>
Ryan Veety <ryan@ryanspc.com>
Michael Hackett <mhackett@kanayo.com>
Pavel Kankovsky <kan@dcit.cz>
[Many, many more. If I've overlooked you and you want to be listed here,
send me e-mail and I'll fix it. I _know_ a bunch of linux-wlan contributors

View File

@ -282,6 +282,7 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *
netdevice_t *dev = wlandev->netdev;
UINT16 fc;
UINT payload_length;
UINT payload_offset;
UINT8 daddr[WLAN_ETHADDR_LEN];
UINT8 saddr[WLAN_ETHADDR_LEN];
p80211_hdr_t *w_hdr;
@ -292,9 +293,10 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *
int foo;
DBFENTER;
payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN;
payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN;
payload_offset = WLAN_HDR_A3_LEN;
w_hdr = (p80211_hdr_t *) skb->data;
/* setup some vars for convenience */
@ -309,14 +311,27 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *
memcpy(daddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN);
memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN);
} else {
WLAN_LOG_ERROR0("HDR_A4 detected! A4 currently not supported.\n");
return 1;
payload_offset = WLAN_HDR_A4_LEN;
payload_length -= ( WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN );
if (payload_length < 0 ) {
WLAN_LOG_ERROR0("A4 frame too short!\n");
return 1;
}
memcpy(daddr, w_hdr->a4.a3, WLAN_ETHADDR_LEN);
memcpy(saddr, w_hdr->a4.a4, WLAN_ETHADDR_LEN);
}
/* perform de-wep if necessary.. */
if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && WLAN_GET_FC_ISWEP(fc) && (wlandev->hostwep & HOSTWEP_DECRYPT)) {
if ((foo = wep_decrypt(wlandev, skb->data + WLAN_HDR_A3_LEN +4, payload_length-8, -1, skb->data+WLAN_HDR_A3_LEN, skb->data + WLAN_HDR_A3_LEN + payload_length - 4))) {
if (payload_length <= 8) {
WLAN_LOG_ERROR1("WEP frame too short (%u).\n",
skb->len);
return 1;
}
if ((foo = wep_decrypt(wlandev, skb->data + payload_offset + 4,
payload_length - 8, -1,
skb->data + payload_offset,
skb->data + payload_offset + payload_length - 4))) {
/* de-wep failed, drop skb. */
WLAN_LOG_WARNING1("Host de-WEP failed, dropping frame (%d).\n", foo);
wlandev->rx.decrypt_err++;
@ -333,14 +348,16 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *
wlandev->rx.decrypt++;
}
e_hdr = (wlan_ethhdr_t *) (skb->data + WLAN_HDR_A3_LEN);
e_hdr = (wlan_ethhdr_t *) (skb->data + payload_offset);
e_llc = (wlan_llc_t *) (skb->data + WLAN_HDR_A3_LEN);
e_snap = (wlan_snap_t *) (skb->data + WLAN_HDR_A3_LEN + sizeof(wlan_llc_t));
e_llc = (wlan_llc_t *) (skb->data + payload_offset);
e_snap = (wlan_snap_t *) (skb->data + payload_offset + sizeof(wlan_llc_t));
/* Test for the various encodings */
if ( memcmp(daddr, e_hdr->daddr, WLAN_ETHADDR_LEN) == 0 &&
memcmp(saddr, e_hdr->saddr, WLAN_ETHADDR_LEN) == 0 ) {
if ( (payload_length >= sizeof(wlan_ethhdr_t)) &&
( e_llc->dsap != 0xaa || e_llc->ssap != 0xaa ) &&
((memcmp(daddr, e_hdr->daddr, WLAN_ETHADDR_LEN) == 0) ||
(memcmp(saddr, e_hdr->saddr, WLAN_ETHADDR_LEN) == 0))) {
WLAN_LOG_DEBUG1(3, "802.3 ENCAP len: %d\n", payload_length);
/* 802.3 Encapsulated */
/* Test for an overlength frame */
@ -352,11 +369,12 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *
}
/* Chop off the 802.11 header. it's already sane. */
skb_pull(skb, WLAN_HDR_A3_LEN);
skb_pull(skb, payload_offset);
/* chop off the 802.11 CRC */
skb_trim(skb, skb->len - WLAN_CRC_LEN);
} else if ((e_llc->dsap == 0xaa) &&
} else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) &&
(e_llc->dsap == 0xaa) &&
(e_llc->ssap == 0xaa) &&
(e_llc->ctl == 0x03) &&
(((memcmp( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)==0) &&
@ -377,7 +395,7 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *
}
/* chop 802.11 header from skb. */
skb_pull(skb, WLAN_HDR_A3_LEN);
skb_pull(skb, payload_offset);
/* create 802.3 header at beginning of skb. */
e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN);
@ -388,9 +406,10 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *
/* chop off the 802.11 CRC */
skb_trim(skb, skb->len - WLAN_CRC_LEN);
} else if ( e_llc->dsap == 0xaa &&
e_llc->ssap == 0xaa &&
e_llc->ctl == 0x03 ) {
} else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) &&
(e_llc->dsap == 0xaa) &&
(e_llc->ssap == 0xaa) &&
(e_llc->ctl == 0x03) ) {
WLAN_LOG_DEBUG1(3, "802.1h/RFC1042 len: %d\n", payload_length);
/* it's an 802.1h frame || (an RFC1042 && protocol is not in STT) */
/* build a DIXII + RFC894 */
@ -404,7 +423,7 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *
}
/* chop 802.11 header from skb. */
skb_pull(skb, WLAN_HDR_A3_LEN);
skb_pull(skb, payload_offset);
/* chop llc header from skb. */
skb_pull(skb, sizeof(wlan_llc_t));
@ -436,7 +455,7 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *
}
/* Chop off the 802.11 header. */
skb_pull(skb, WLAN_HDR_A3_LEN);
skb_pull(skb, payload_offset);
/* create 802.3 header at beginning of skb. */
e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN);
@ -450,6 +469,7 @@ int skb_p80211_to_ether( wlandevice_t *wlandev, UINT32 ethconv, struct sk_buff *
}
skb->protocol = eth_type_trans(skb, dev);
skb->mac.raw = (unsigned char *) e_hdr; /* new MAC header */
DBFEXIT;
return 0;

View File

@ -3812,6 +3812,8 @@ void hfa384x_int_rx(wlandevice_t *wlandev)
UINT16 rxfid;
hfa384x_rx_frame_t rxdesc;
int result;
int hdrlen;
UINT16 fc;
struct sk_buff *skb = NULL;
UINT8 *datap;
@ -3846,14 +3848,6 @@ void hfa384x_int_rx(wlandevice_t *wlandev)
HFA384x_RXSTATUS_ISUNDECR(rxdesc.status)))
goto done;
#if 0
printk(KERN_DEBUG"rxf(%d): ",rxlen);
for (i=0; i<pb->p80211frmlen; i++) {
printk("%x ",pb->p80211buf[i]);
}
printk("\n");
#endif
/* Now handle frame based on port# */
switch( HFA384x_RXSTATUS_MACPORT_GET(rxdesc.status) )
{
@ -3885,9 +3879,16 @@ printk("\n");
}
}
fc = ieee2host16(rxdesc.frame_control);
if ( WLAN_GET_FC_TODS(fc) && WLAN_GET_FC_FROMDS(fc) ) {
hdrlen = WLAN_HDR_A4_LEN;
} else {
hdrlen = WLAN_HDR_A3_LEN;
}
/* Allocate the buffer, note CRC (aka FCS). pballoc */
/* assumes there needs to be space for one */
skb = dev_alloc_skb(hfa384x2host_16(rxdesc.data_len) + WLAN_HDR_A3_LEN + WLAN_CRC_LEN + 2); /* a little extra */
skb = dev_alloc_skb(hfa384x2host_16(rxdesc.data_len) + hdrlen + WLAN_CRC_LEN + 2); /* a little extra */
if ( ! skb ) {
WLAN_LOG_ERROR0("alloc_skb failed.\n");
@ -3897,12 +3898,19 @@ printk("\n");
skb->dev = wlandev->netdev;
/* theoretically align the IP header on a 32-bit word. */
skb_reserve(skb, 2);
if ( hdrlen == WLAN_HDR_A3_LEN )
skb_reserve(skb, 2);
/* Copy the 802.11 hdr to the buffer */
datap = skb_put(skb, WLAN_HDR_A3_LEN);
memcpy(datap, &rxdesc.frame_control, WLAN_HDR_A3_LEN);
/* Snag the A4 address if present */
if (hdrlen == WLAN_HDR_A4_LEN) {
datap = skb_put(skb, WLAN_ADDR_LEN);
memcpy(datap, &rxdesc.address4, WLAN_HDR_A3_LEN);
}
/* we can convert the data_len as we passed the original on */
rxdesc.data_len = hfa384x2host_16(rxdesc.data_len);
@ -3925,6 +3933,7 @@ printk("\n");
/* the prism2 cards don't return the FCS */
datap = skb_put(skb, WLAN_CRC_LEN);
memset (datap, 0xff, WLAN_CRC_LEN);
skb->mac.raw = skb->data;
prism2sta_ev_rx(wlandev, skb);
goto done;

View File

@ -3945,6 +3945,8 @@ void hfa384x_usbin_rx(wlandevice_t *wlandev, hfa384x_usbin_t *usbin)
int result;
p80211_hdr_t *w_hdr;
struct sk_buff *skb = NULL;
int hdrlen;
UINT16 fc;
UINT8 *datap;
DBFENTER;
@ -3955,18 +3957,6 @@ void hfa384x_usbin_rx(wlandevice_t *wlandev, hfa384x_usbin_t *usbin)
usbin->rxfrm.desc.time =
hfa384x2host_32(usbin->rxfrm.desc.time);
#if 0
{
int i;
printk(KERN_DEBUG"rxf(%d): ", usbin->rxfrm.desc.data_len);
for (i=0; i<64; i++) {
printk("%x ",((UINT8*)usbin)[i]);
}
printk("\n");
}
#endif
/* Now handle frame based on port# */
switch( HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status))
{
@ -4000,9 +3990,16 @@ printk("\n");
}
}
fc = ieee2host16(usbin->rxfrm.desc.frame_control);
if ( WLAN_GET_FC_TODS(fc) && WLAN_GET_FC_FROMDS(fc) ) {
hdrlen = WLAN_HDR_A4_LEN;
} else {
hdrlen = WLAN_HDR_A3_LEN;
}
/* Allocate the buffer, note CRC (aka FCS). pballoc */
/* assumes there needs to be space for one */
skb = dev_alloc_skb(hfa384x2host_16(usbin->rxfrm.desc.data_len) + WLAN_HDR_A3_LEN + WLAN_CRC_LEN + 2); /* a litlte extra */
skb = dev_alloc_skb(hfa384x2host_16(usbin->rxfrm.desc.data_len) + hdrlen + WLAN_CRC_LEN + 2); /* a litlte extra */
if ( ! skb ) {
WLAN_LOG_DEBUG0(1, "alloc_skb failed.\n");
@ -4013,12 +4010,19 @@ printk("\n");
skb->dev->last_rx = jiffies;
/* theoretically align the IP header on a 32-bit word. */
skb_reserve(skb, 2);
if ( hdrlen == WLAN_HDR_A3_LEN )
skb_reserve(skb, 2);
/* Copy the 802.11 hdr to the buffer */
datap = skb_put(skb, WLAN_HDR_A3_LEN);
memcpy(datap, w_hdr, WLAN_HDR_A3_LEN);
/* Snag the A4 address if present */
if (hdrlen == WLAN_HDR_A4_LEN) {
datap = skb_put(skb, WLAN_ADDR_LEN);
memcpy(datap, &usbin->rxfrm.desc.address4, WLAN_HDR_A3_LEN);
}
/* we can convert the data_len as we passed the original on */
usbin->rxfrm.desc.data_len = hfa384x2host_16(usbin->rxfrm.desc.data_len);
@ -4032,6 +4036,7 @@ printk("\n");
/* the prism2 series does not return the CRC */
datap = skb_put(skb, WLAN_CRC_LEN);
memset (datap, 0xff, WLAN_CRC_LEN);
skb->mac.raw = skb->data;
prism2sta_ev_rx(wlandev, skb);

View File

@ -2853,6 +2853,7 @@ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
}
WLAN_LOG_INFO0("monitor mode disabled\n");
msg->resultcode.data = P80211ENUM_resultcode_success;
result = 0;
goto exit;
@ -2962,6 +2963,11 @@ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
result);
goto failed;
}
if (wlandev->netdev->type = ARPHRD_ETHER) {
WLAN_LOG_INFO0("monitor mode enabled\n");
}
/* Set the driver state */
/* Do we want the prism2 header? */
if ((msg->prismheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->prismheader.data == P80211ENUM_truth_true)) {

View File

@ -68,6 +68,7 @@
#include <asm/io.h>
#include <linux/delay.h>
#include <asm/byteorder.h>
#include <linux/if_arp.h>
#include <wlan/wlan_compat.h>
@ -1979,10 +1980,13 @@ void prism2sta_linkstatus_defer(void *data)
hw->join_ap = 2;
hw->join_retries = 60;
WLAN_LOG_INFO0("linkstatus=CONNECTED\n");
{
/* Don't call this in monitor mode */
if ( wlandev->netdev->type == ARPHRD_ETHER ) {
UINT16 portstatus;
int result;
WLAN_LOG_INFO0("linkstatus=CONNECTED\n");
/* For non-usb devices, we can use the sync versions */
/* Collect the BSSID, and set state to allow tx */
@ -2034,7 +2038,8 @@ void prism2sta_linkstatus_defer(void *data)
}
else
{
WLAN_LOG_INFO0("linkstatus=DISCONNECTED (unhandled)\n");
if (wlandev->netdev->type == ARPHRD_ETHER)
WLAN_LOG_INFO0("linkstatus=DISCONNECTED (unhandled)\n");
}
break;