aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjal2 <jal2>2004-06-12 10:59:59 +0000
committerjal2 <jal2>2004-06-12 10:59:59 +0000
commit49e1a126133143a47513fb98fe441022441e5a2e (patch)
treee761b2b4d8474a927192bdc9aeb2d25e5d66b55c
parent5eb1633e6e463ef48bbf3ebedfeea98d52cc3679 (diff)
- version 0.12beta13version_0_12beta13
- tx data: send correct SNAP header, which should fix bug with WindowsXP as peer - rx data, ieee802_11_hdr: cleaned it up a bit, removed addr4 which is not used by non-APs
-rw-r--r--Makefile4
-rw-r--r--at76c503.c202
-rw-r--r--ieee802_11.h5
3 files changed, 138 insertions, 73 deletions
diff --git a/Makefile b/Makefile
index 774c4c8..b1887d6 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
-#$Id: Makefile,v 1.31 2004/05/31 13:59:27 jal2 Exp $
+#$Id: Makefile,v 1.32 2004/06/12 10:59:59 jal2 Exp $
-VERSION = 0.12beta12
+VERSION = 0.12beta13
CC=gcc
diff --git a/at76c503.c b/at76c503.c
index d9d5087..844161b 100644
--- a/at76c503.c
+++ b/at76c503.c
@@ -1,5 +1,5 @@
/* -*- linux-c -*- */
-/* $Id: at76c503.c,v 1.55 2004/05/31 13:59:27 jal2 Exp $
+/* $Id: at76c503.c,v 1.56 2004/06/12 10:59:59 jal2 Exp $
*
* USB at76c503/at76c505 driver
*
@@ -293,20 +293,6 @@ static int pm_period = 0;
MODULE_PARM(pm_period, "i");
MODULE_PARM_DESC(pm_period, "period of waking up the device in usec");
-struct header_struct {
- /* 802.3 */
- u8 dest[ETH_ALEN];
- u8 src[ETH_ALEN];
- u16 len;
- /* 802.2 */
- u8 dsap;
- u8 ssap;
- u8 ctrl;
- /* SNAP */
- u8 oui[3];
- u16 ethertype;
-} __attribute__ ((packed));
-
#define DEF_RTS_THRESHOLD 1536
#define DEF_FRAG_THRESHOLD 1536
#define DEF_SHORT_RETRY_LIMIT 8
@@ -446,11 +432,11 @@ struct ieee802_11_deauth_frame {
static DECLARE_WAIT_QUEUE_HEAD(wait_queue);
static u8 snapsig[] = {0xaa, 0xaa, 0x03};
-#ifdef COLLAPSE_RFC1042
+//#ifdef COLLAPSE_RFC1042
/* RFC 1042 encapsulates Ethernet frames in 802.2 SNAP (0xaa, 0xaa, 0x03) with
* a SNAP OID of 0 (0x00, 0x00, 0x00) */
static u8 rfc1042sig[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
-#endif /* COLLAPSE_RFC1042 */
+//#endif /* COLLAPSE_RFC1042 */
/* local function prototypes */
static void iwspy_update(struct at76c503 *dev, struct at76c503_rx_buffer *buf);
@@ -3332,11 +3318,55 @@ static void dbg_dumpbuf(const char *tag, const u8 *buf, int size)
printk("\n");
}
+/* A short overview on Ethernet-II, 802.2, 802.3 and SNAP
+ (taken from http://www.geocities.com/billalexander/ethernet.html):
+
+Ethernet Frame Formats:
+
+Ethernet (a.k.a. Ethernet II)
+
+ +---------+---------+---------+----------
+ | Dst | Src | Type | Data...
+ +---------+---------+---------+----------
+
+ <-- 6 --> <-- 6 --> <-- 2 --> <-46-1500->
+
+ Type 0x80 0x00 = TCP/IP
+ Type 0x06 0x00 = XNS
+ Type 0x81 0x37 = Novell NetWare
+
+
+802.3
+
+ +---------+---------+---------+----------
+ | Dst | Src | Length | Data...
+ +---------+---------+---------+----------
+
+ <-- 6 --> <-- 6 --> <-- 2 --> <-46-1500->
+
+802.2 (802.3 with 802.2 header)
+
+ +---------+---------+---------+-------+-------+-------+----------
+ | Dst | Src | Length | DSAP | SSAP |Control| Data...
+ +---------+---------+---------+-------+-------+-------+----------
+
+ <- 1 -> <- 1 -> <- 1 -> <-43-1497->
+
+SNAP (802.3 with 802.2 and SNAP headers)
+
+ +---------+---------+---------+-------+-------+-------+-----------+---------+-----------
+ | Dst | Src | Length | 0xAA | 0xAA | 0x03 | Org Code | Type | Data...
+ +---------+---------+---------+-------+-------+-------+-----------+---------+-----------
+
+ <-- 3 --> <-- 2 --> <-38-1492->
+
+*/
+
/* Convert the 802.11 header on a packet into an ethernet-style header
* (basically, pretend we're an ethernet card receiving ethernet packets)
*
* This routine returns with the skbuff pointing to the actual data (just past
- * the end of the newly-created ethernet header), and the CRC trimmed off.
+ * the end of the newly-created ethernet header).
*/
static void ieee80211_to_eth(struct sk_buff *skb, int iw_mode)
{
@@ -3348,6 +3378,15 @@ static void ieee80211_to_eth(struct sk_buff *skb, int iw_mode)
int build_ethhdr = 1;
i802_11_hdr = (struct ieee802_11_hdr *)skb->data;
+
+#if 0
+ {
+ char dbuf[3*64];
+ dbg_uc("%s: ENTRY skb len %d data %s", __FUNCTION__,
+ skb->len, hex2str(dbuf, skb->data, sizeof(dbuf)/3, ' '));
+ }
+#endif
+
skb_pull(skb, sizeof(struct ieee802_11_hdr));
// skb_trim(skb, skb->len - 4); /* Trim CRC */
@@ -3363,19 +3402,11 @@ static void ieee80211_to_eth(struct sk_buff *skb, int iw_mode)
skb_pull(skb, sizeof(struct ethhdr));
build_ethhdr = 0;
} else if (!memcmp(skb->data, snapsig, sizeof(snapsig))) {
- /* SNAP frame. */
-#ifdef COLLAPSE_RFC1042
- if (!memcmp(skb->data, rfc1042sig, sizeof(rfc1042sig))) {
- /* RFC1042 encapsulated packet. Collapse it to a
- * simple Ethernet-II or 802.3 frame */
- /* NOTE: prism2 doesn't collapse Appletalk frames (why?). */
- skb_pull(skb, sizeof(rfc1042sig)+2);
- proto = *(unsigned short *)(skb->data - 2);
- } else
-#endif /* COLLAPSE_RFC1042 */
- proto = htons(skb->len);
+ /* SNAP frame - collapse it */
+ skb_pull(skb, sizeof(rfc1042sig)+2);
+ proto = *(unsigned short *)(skb->data - 2);
} else {
-#if IEEE_STANDARD
+#ifdef IEEE_STANDARD
/* According to all standards, we should assume the data
* portion contains 802.2 LLC information, so we should give it
* an 802.3 header (which has the same implications) */
@@ -3387,6 +3418,10 @@ static void ieee80211_to_eth(struct sk_buff *skb, int iw_mode)
* that value and make it into an Ethernet-II packet. */
/* Note that this means we can never support non-SNAP 802.2
* frames (because we can't tell when we get one) */
+
+ /* jal: This isn't true. My WRT54G happily sends SNAP.
+ Difficult to speak for all APs, so I don't dare to define
+ IEEE_STANDARD ... */
proto = *(unsigned short *)(skb->data);
skb_pull(skb, 2);
#endif /* IEEE_STANDARD */
@@ -3403,8 +3438,7 @@ static void ieee80211_to_eth(struct sk_buff *skb, int iw_mode)
eth_hdr->h_proto = proto;
}
- /* TODO: check this max length */
- if (ntohs(eth_hdr->h_proto) >= 1536) {
+ if (ntohs(eth_hdr->h_proto) > 1518) {
skb->protocol = eth_hdr->h_proto;
} else if (*(unsigned short *)skb->data == 0xFFFF) {
/* Magic hack for Novell IPX-in-802.3 packets */
@@ -3414,6 +3448,18 @@ static void ieee80211_to_eth(struct sk_buff *skb, int iw_mode)
* good way to tell if it isn't) */
skb->protocol = htons(ETH_P_802_2);
}
+
+#if 0
+ {
+ char dbuf[3*64], da[3*ETH_ALEN], sa[3*ETH_ALEN];
+ dbg_uc("%s: EXIT skb da %s sa %s proto x%04x len %d data %s", __FUNCTION__,
+ hex2str(da, skb->mac.ethernet->h_dest, ETH_ALEN, ':'),
+ hex2str(sa, skb->mac.ethernet->h_source, ETH_ALEN, ':'),
+ ntohs(skb->protocol), skb->len,
+ hex2str(dbuf, skb->data, sizeof(dbuf)/3, ' '));
+ }
+#endif
+
}
/* Adjust the skb to trim the hardware header and CRC, and set up skb->mac,
@@ -3445,21 +3491,15 @@ static void ieee80211_fixup(struct sk_buff *skb, int iw_mode)
skb_pull(skb, sizeof(struct ethhdr));
proto = eth_hdr->h_proto;
} else if (!memcmp(skb->data, snapsig, sizeof(snapsig))) {
- /* SNAP frame */
-#ifdef COLLAPSE_RFC1042
- if (!memcmp(skb->data, rfc1042sig, sizeof(rfc1042sig))) {
- /* RFC1042 encapsulated packet. Treat the SNAP header
- * as part of the HW header and note the protocol. */
- /* NOTE: prism2 doesn't collapse Appletalk frames (why?). */
- skb_pull(skb, sizeof(rfc1042sig) + 2);
- proto = *(unsigned short *)(skb->data - 2);
- } else
-#endif /* COLLAPSE_RFC1042 */
- proto = htons(ETH_P_802_2);
+ /* SNAP frame - collapse it */
+ /* RFC1042/802.1h encapsulated packet. Treat the SNAP header
+ * as part of the HW header and note the protocol. */
+ /* NOTE: prism2 doesn't collapse Appletalk frames (why?). */
+ skb_pull(skb, sizeof(rfc1042sig) + 2);
+ proto = *(unsigned short *)(skb->data - 2);
}
- /* TODO: check this max length */
- if (ntohs(proto) >= 1536) {
+ if (ntohs(proto) > 1518) {
skb->protocol = proto;
} else {
#ifdef IEEE_STANDARD
@@ -3473,7 +3513,7 @@ static void ieee80211_fixup(struct sk_buff *skb, int iw_mode)
* use that (and consider it part of the hardware header). */
/* Note that this means we can never support non-SNAP 802.2
* frames (because we can't tell when we get one) */
- skb->protocol = *(unsigned short *)(skb->data - 2);
+ skb->protocol = *(unsigned short *)skb->data;
skb_pull(skb, 2);
#endif /* IEEE_STANDARD */
}
@@ -3502,13 +3542,9 @@ static struct sk_buff *check_for_rx_frags(struct at76c503 *dev)
excl. the struct at76c503_rx_buffer */
int length = le16_to_cpu(buf->wlength) - dev->rx_data_fcs_len;
- /* where does the data payload start in skb->data ?
- This depends on if addr4 is present or not. */
- u8 *data = ((frame_ctl &
- (IEEE802_11_FCTL_TODS|IEEE802_11_FCTL_FROMDS)) ==
- (IEEE802_11_FCTL_TODS|IEEE802_11_FCTL_FROMDS) ?
- (u8 *)i802_11_hdr + sizeof(struct ieee802_11_hdr) :
- (u8 *)&i802_11_hdr->addr4);
+ /* where does the data payload start in skb->data ? */
+ u8 *data = (u8 *)i802_11_hdr + sizeof(struct ieee802_11_hdr);
+
/* length of payload, excl. the trailing FCS */
int data_len = length - (data - (u8 *)i802_11_hdr);
@@ -3964,23 +4000,51 @@ at76c503_tx(struct sk_buff *skb, struct net_device *netdev)
struct at76c503 *dev = (struct at76c503 *)(netdev->priv);
struct net_device_stats *stats = &dev->stats;
int ret;
- int len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
- int wlen = len + 18;
+ int wlen;
int submit_len;
struct at76c503_tx_buffer *tx_buffer =
(struct at76c503_tx_buffer *)dev->bulk_out_buffer;
struct ieee802_11_hdr *i802_11_hdr =
(struct ieee802_11_hdr *)&(tx_buffer->packet);
+ u8 *payload = tx_buffer->packet + sizeof(struct ieee802_11_hdr);
+
+ if (skb->len < 2*ETH_ALEN) {
+ err("%s: %s: skb too short (%d)", dev->netdev->name,
+ __FUNCTION__, skb->len);
+ dev_kfree_skb(skb);
+ return 0;
+ }
/* we can get rid of memcpy, if we set netdev->hard_header_len
to 8 + sizeof(struct ieee802_11_hdr), because then we have
enough space */
// dbg(DBG_TX, "skb->data - skb->head = %d", skb->data - skb->head);
- /* 18 = sizeof(ieee802_11_hdr) - 2 * ETH_ALEN */
- /* ssap and dsap stay in the data */
- memcpy(&(tx_buffer->packet[18]), skb->data, len);
-
+ if (ntohs(*(u16 *)(skb->data + 2*ETH_ALEN)) <= 1518) {
+ /* this is a 802.3 packet */
+ if (skb->data[2*ETH_ALEN+2] == rfc1042sig[0] &&
+ skb->data[2*ETH_ALEN+2+1] == rfc1042sig[1]) {
+ /* higher layer delivered SNAP header - keep it */
+ memcpy(payload, skb->data + 2*ETH_ALEN+2, skb->len - 2*ETH_ALEN -2);
+ wlen = sizeof(struct ieee802_11_hdr) + skb->len - 2*ETH_ALEN -2;
+ } else {
+ err("%s: %s: no support for non-SNAP 802.2 packets "
+ "(DSAP x%02x SSAP x%02x cntrl x%02x)",
+ dev->netdev->name, __FUNCTION__,
+ skb->data[2*ETH_ALEN+2], skb->data[2*ETH_ALEN+2+1],
+ skb->data[2*ETH_ALEN+2+2]);
+ dev_kfree_skb(skb);
+ return 0;
+ }
+ } else {
+ /* add RFC 1042 header in front */
+ memcpy(payload, rfc1042sig, sizeof(rfc1042sig));
+ memcpy(payload + sizeof(rfc1042sig),
+ skb->data + 2*ETH_ALEN, skb->len - 2*ETH_ALEN);
+ wlen = sizeof(struct ieee802_11_hdr) + sizeof(rfc1042sig) +
+ skb->len - 2*ETH_ALEN;
+ }
+
/* make wireless header */
i802_11_hdr->frame_ctl =
cpu_to_le16(IEEE802_11_FTYPE_DATA |
@@ -3989,14 +4053,13 @@ at76c503_tx(struct sk_buff *skb, struct net_device *netdev)
if(dev->iw_mode == IW_MODE_ADHOC){
memcpy(i802_11_hdr->addr1, skb->data, ETH_ALEN); /* destination */
- memcpy(i802_11_hdr->addr2, netdev->dev_addr, ETH_ALEN); /* source */
+ memcpy(i802_11_hdr->addr2, skb->data+ETH_ALEN, ETH_ALEN); /* source */
memcpy(i802_11_hdr->addr3, dev->bssid, ETH_ALEN);
}else if(dev->iw_mode == IW_MODE_INFRA){
memcpy(i802_11_hdr->addr1, dev->bssid, ETH_ALEN);
- memcpy(i802_11_hdr->addr2, netdev->dev_addr, ETH_ALEN); /* source */
+ memcpy(i802_11_hdr->addr2, skb->data+ETH_ALEN, ETH_ALEN); /* source */
memcpy(i802_11_hdr->addr3, skb->data, ETH_ALEN); /* destination */
}
- memset(i802_11_hdr->addr4, 0, ETH_ALEN);
i802_11_hdr->duration_id = cpu_to_le16(0);
i802_11_hdr->seq_ctl = cpu_to_le16(0);
@@ -4015,14 +4078,17 @@ at76c503_tx(struct sk_buff *skb, struct net_device *netdev)
le16_to_cpu(tx_buffer->padding);
{
- char hbuf[2*24+1], dbuf[2*16] __attribute__((unused));
+ char dbuf[2*48+1] __attribute__((unused));
+ dbg(DBG_TX_DATA_CONTENT, "%s skb->data %s", dev->netdev->name,
+ hex2str(dbuf, skb->data, min(sizeof(dbuf)/2,(size_t)32),'\0'));
dbg(DBG_TX_DATA, "%s tx wlen x%x pad x%x rate %d hdr %s",
dev->netdev->name,
le16_to_cpu(tx_buffer->wlength),
le16_to_cpu(tx_buffer->padding), tx_buffer->tx_rate,
- hex2str(hbuf, (u8 *)i802_11_hdr,sizeof(hbuf)/2,'\0'));
- dbg(DBG_TX_DATA_CONTENT, "%s data %s", dev->netdev->name,
- hex2str(dbuf, (u8 *)i802_11_hdr+24,sizeof(dbuf)/2,'\0'));
+ hex2str(dbuf, (u8 *)i802_11_hdr,
+ min(sizeof(dbuf)/2, sizeof(struct ieee802_11_hdr)),'\0'));
+ dbg(DBG_TX_DATA_CONTENT, "%s payload %s", dev->netdev->name,
+ hex2str(dbuf, payload, sizeof(dbuf)/2,'\0'));
}
/* send stuff */
@@ -4040,7 +4106,7 @@ at76c503_tx(struct sk_buff *skb, struct net_device *netdev)
goto err;
}
- stats->tx_bytes += len;
+ stats->tx_bytes += skb->len;
dev_kfree_skb(skb);
return 0;
@@ -6471,7 +6537,7 @@ int init_new_device(struct at76c503 *dev)
else
dev->rx_data_fcs_len = 4;
- info("$Id: at76c503.c,v 1.55 2004/05/31 13:59:27 jal2 Exp $ compiled %s %s", __DATE__, __TIME__);
+ info("$Id: at76c503.c,v 1.56 2004/06/12 10:59:59 jal2 Exp $ compiled %s %s", __DATE__, __TIME__);
info("firmware version %d.%d.%d #%d (fcs_len %d)",
dev->fw_version.major, dev->fw_version.minor,
dev->fw_version.patch, dev->fw_version.build,
diff --git a/ieee802_11.h b/ieee802_11.h
index cc07b4f..30281ce 100644
--- a/ieee802_11.h
+++ b/ieee802_11.h
@@ -8,17 +8,16 @@ struct ieee802_11_hdr {
u8 addr2[ETH_ALEN];
u8 addr3[ETH_ALEN];
u16 seq_ctl;
- u8 addr4[ETH_ALEN];
} __attribute__ ((packed));
/* max. length of frame body, incl. IV and ICV fields)
see 802.11(1999), section 7.1.2 */
#define IEEE802_11_MAX_DATA_LEN (4+2304+4)
-/* we include addr4 here althrough we'll never handle any packet containing it.
- + 4 at the end for the FCS (Do we get it from the device ???) */
+/* + 4 at the end for the FCS (Do we get it from the device ???) */
#define IEEE802_11_MAX_FRAME_LEN \
(sizeof(struct ieee802_11_hdr) + IEEE802_11_MAX_DATA_LEN + 4)
+
//#define IEEE802_11_HLEN 30
//#define IEEE802_11_FRAME_LEN (IEEE802_11_DATA_LEN + IEEE802_11_HLEN)