aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Roskin <proski@gnu.org>2007-07-12 02:53:44 -0400
committerGuido Guenther <agx@bogon.sigxcpu.org>2007-07-15 12:19:07 -0400
commite6a1f3b8211852f9393d8bd4a9d73593e7318412 (patch)
tree4733a53918de374ebe0a50bff038d3124603498c
parent12caae4237e5ac72b85265b0fef483f4797a4730 (diff)
[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 <proski@gnu.org>
-rw-r--r--at76_usb.c43
1 files 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);