aboutsummaryrefslogtreecommitdiff
path: root/at76_usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'at76_usb.c')
-rw-r--r--at76_usb.c88
1 files changed, 31 insertions, 57 deletions
diff --git a/at76_usb.c b/at76_usb.c
index d843771..a4d10f8 100644
--- a/at76_usb.c
+++ b/at76_usb.c
@@ -5252,87 +5252,61 @@ static void at76_dbg_dumpbuf(const char *tag, const u8 *buf, int size)
pr_debug("\n");
}
-/* 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).
- */
+/* Convert the 802.11 header into an ethernet-style header, make skb
+ * ready for consumption by netif_rx() */
static void at76_ieee80211_to_eth(struct sk_buff *skb, int iw_mode)
{
struct ieee80211_hdr_3addr *i802_11_hdr;
struct ethhdr *eth_hdr_p;
u8 *src_addr;
u8 *dest_addr;
- __be16 proto = 0;
- int build_ethhdr = 1;
i802_11_hdr = (struct ieee80211_hdr_3addr *)skb->data;
dbg("%s: ENTRY skb len %d data %s", __func__,
skb->len, hex2str(skb->data, 64));
- skb_pull(skb, IEEE80211_3ADDR_LEN);
+ /* That would be the ethernet header if the hardware converted
+ * the frame for us. Make sure the source and the destination
+ * match the 802.11 header. Which hardware does it? */
+ eth_hdr_p = (struct ethhdr *)skb_pull(skb, IEEE80211_3ADDR_LEN);
- src_addr = iw_mode == IW_MODE_ADHOC ? i802_11_hdr->addr2
- : i802_11_hdr->addr3;
dest_addr = i802_11_hdr->addr1;
+ if (iw_mode == IW_MODE_ADHOC)
+ src_addr = i802_11_hdr->addr2;
+ else
+ src_addr = i802_11_hdr->addr3;
- eth_hdr_p = (struct ethhdr *)skb->data;
if (!compare_ether_addr(eth_hdr_p->h_source, src_addr) &&
!compare_ether_addr(eth_hdr_p->h_dest, dest_addr)) {
- /* An ethernet frame is encapsulated within the data portion.
- * Just use its header instead. */
- skb_pull(skb, ETH_HLEN);
- build_ethhdr = 0;
- } else if (!memcmp(skb->data, snapsig, sizeof(snapsig))) {
- /* SNAP frame - collapse it */
- skb_pull(skb, sizeof(rfc1042sig) + 2);
- proto = *(__be16 *)(skb->data - 2);
+ /* Yes, we already have an ethernet header */
+ skb_reset_mac_header(skb);
} else {
-#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) */
- proto = htons(skb->len);
-#else /* IEEE_STANDARD */
- /* Unfortunately, it appears no actual 802.11 implementations
- * follow any standards specs. They all appear to put a
- * 16-bit ethertype after the 802.11 header instead, so we take
- * 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 = *(__be16 *)(skb->data);
- skb_pull(skb, 2);
-#endif /* IEEE_STANDARD */
- }
-
- skb_set_mac_header(skb, -ETH_HLEN);
- eth_hdr_p = (struct ethhdr *)skb_mac_header(skb);
-
- if (build_ethhdr) {
+ u16 len;
+
+ /* Need to build an ethernet header */
+ if (!memcmp(skb->data, snapsig, sizeof(snapsig))) {
+ /* SNAP frame - decapsulate, keep proto */
+ skb_push(skb, offsetof(struct ethhdr, h_proto) -
+ sizeof(rfc1042sig));
+ len = 0;
+ } else {
+ /* 802.3 frame, proto is length */
+ len = skb->len;
+ skb_push(skb, ETH_HLEN);
+ }
+
+ skb_reset_mac_header(skb);
+ eth_hdr_p = eth_hdr(skb);
/* This needs to be done in this order (eth_hdr_p->h_dest may
* overlap src_addr) */
memcpy(eth_hdr_p->h_source, src_addr, ETH_ALEN);
memcpy(eth_hdr_p->h_dest, dest_addr, ETH_ALEN);
- /* make an 802.3 header (proto = length) */
- eth_hdr_p->h_proto = proto;
+ if (len)
+ eth_hdr_p->h_proto = htons(len);
}
- if (ntohs(eth_hdr_p->h_proto) > 1518) {
- skb->protocol = eth_hdr_p->h_proto;
- } else if (*(unsigned short *)skb->data == 0xFFFF) {
- /* Magic hack for Novell IPX-in-802.3 packets */
- skb->protocol = htons(ETH_P_802_3);
- } else {
- /* Assume it's an 802.2 packet (it should be, and we have no
- * good way to tell if it isn't) */
- skb->protocol = htons(ETH_P_802_2);
- }
+ skb->protocol = eth_type_trans(skb, skb->dev);
dbg("%s: EXIT skb da %s sa %s proto 0x%04x len %d data %s",
__func__, mac2str(eth_hdr(skb)->h_dest),