From e6a1f3b8211852f9393d8bd4a9d73593e7318412 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 12 Jul 2007 02:53:44 -0400 Subject: [PATCH] Clean up handling of ethernet frames in the tx path Use more standard definitions for ethernet frames. Fix peeking beyond the end of skb for pathologically short frames. Signed-off-by: Pavel Roskin --- at76_usb.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/at76_usb.c b/at76_usb.c index cbf4bda..d843771 100644 --- a/at76_usb.c +++ b/at76_usb.c @@ -3636,6 +3636,7 @@ static int at76_tx(struct sk_buff *skb, struct net_device *netdev) struct ieee80211_hdr_3addr *i802_11_hdr = (struct ieee80211_hdr_3addr *)tx_buffer->packet; u8 *payload = i802_11_hdr->payload; + struct ethhdr *eh = (struct ethhdr *)skb->data; if (netif_queue_stopped(netdev)) { err("%s: %s called while netdev is stopped", netdev->name, @@ -3653,7 +3654,7 @@ static int at76_tx(struct sk_buff *skb, struct net_device *netdev) return 0; } - if (skb->len < 2 * ETH_ALEN) { + if (skb->len < ETH_HLEN) { err("%s: %s: skb too short (%d)", priv->netdev->name, __func__, skb->len); dev_kfree_skb(skb); @@ -3662,36 +3663,34 @@ static int at76_tx(struct sk_buff *skb, struct net_device *netdev) at76_ledtrig_tx_activity(); /* tell the ledtrigger we send a packet */ - /* we can get rid of memcpy, if we set netdev->hard_header_len - to 8 + IEEE80211_3ADDR_LEN, because then we have enough space - at76_dbg(DBG_TX, "skb->data - skb->head = %d", skb->data - skb->head); */ + /* we can get rid of memcpy if we set netdev->hard_header_len to + reserve enough space, but we would need to keep the skb around */ - if (ntohs(*(__be16 *)(skb->data + 2 * ETH_ALEN)) <= 1518) { + if (ntohs(eh->h_proto) <= ETH_DATA_LEN) { /* this is a 802.3 packet */ - if (skb->data[2 * ETH_ALEN + 2] == rfc1042sig[0] && - skb->data[2 * ETH_ALEN + 2 + 1] == rfc1042sig[1]) { + if (skb->len >= ETH_HLEN + sizeof(rfc1042sig) + && skb->data[ETH_HLEN] == rfc1042sig[0] + && skb->data[ETH_HLEN + 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 = IEEE80211_3ADDR_LEN + skb->len - - 2 * ETH_ALEN - 2; + memcpy(payload, skb->data + ETH_HLEN, + skb->len - ETH_HLEN); + wlen = IEEE80211_3ADDR_LEN + skb->len - ETH_HLEN; } else { err("%s: %s: no support for non-SNAP 802.2 packets " "(DSAP 0x%02x SSAP 0x%02x cntrl 0x%02x)", priv->netdev->name, __func__, - skb->data[2 * ETH_ALEN + 2], - skb->data[2 * ETH_ALEN + 2 + 1], - skb->data[2 * ETH_ALEN + 2 + 2]); + skb->data[ETH_HLEN], skb->data[ETH_HLEN + 1], + skb->data[ETH_HLEN + 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 = IEEE80211_3ADDR_LEN + sizeof(rfc1042sig) + - skb->len - 2 * ETH_ALEN; + memcpy(payload + sizeof(rfc1042sig), &eh->h_proto, + skb->len - offsetof(struct ethhdr, h_proto)); + wlen = IEEE80211_3ADDR_LEN + sizeof(rfc1042sig) + skb->len - + offsetof(struct ethhdr, h_proto); } /* make wireless header */ @@ -3702,13 +3701,13 @@ static int at76_tx(struct sk_buff *skb, struct net_device *netdev) IW_MODE_INFRA ? IEEE80211_FCTL_TODS : 0)); if (priv->iw_mode == IW_MODE_ADHOC) { - memcpy(i802_11_hdr->addr1, skb->data, ETH_ALEN); /* destination */ - memcpy(i802_11_hdr->addr2, skb->data + ETH_ALEN, ETH_ALEN); /* source */ + memcpy(i802_11_hdr->addr1, eh->h_dest, ETH_ALEN); + memcpy(i802_11_hdr->addr2, eh->h_source, ETH_ALEN); memcpy(i802_11_hdr->addr3, priv->bssid, ETH_ALEN); } else if (priv->iw_mode == IW_MODE_INFRA) { memcpy(i802_11_hdr->addr1, priv->bssid, ETH_ALEN); - memcpy(i802_11_hdr->addr2, skb->data + ETH_ALEN, ETH_ALEN); /* source */ - memcpy(i802_11_hdr->addr3, skb->data, ETH_ALEN); /* destination */ + memcpy(i802_11_hdr->addr2, eh->h_source, ETH_ALEN); + memcpy(i802_11_hdr->addr3, eh->h_dest, ETH_ALEN); } i802_11_hdr->duration_id = cpu_to_le16(0); -- cgit v1.2.3