diff options
Diffstat (limited to 'at76_usb.c')
-rw-r--r-- | at76_usb.c | 88 |
1 files changed, 31 insertions, 57 deletions
@@ -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), |