diff options
author | David S. Miller <davem@davemloft.net> | 2013-08-07 20:11:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-07 20:11:00 -0400 |
commit | 09effa67a18d893fc4e6f81a3659fc9efef1445e (patch) | |
tree | 9342bde8059a3fe16a5a902f5deca5b25272e09c /net/packet/af_packet.c | |
parent | 16dda493312b15898025177c109a55aef84288ff (diff) |
packet: Revert recent header parsing changes.
This reverts commits:
0f75b09c798ed00c30d7d5551b896be883bc2aeb
cbd89acb9eb257ed3b2be867142583fdcf7fdc5b
c483e02614551e44ced3fe6eedda8e36d3277ccc
Amongst other things, it's modifies the SKB header
to pull the ethernet headers off via eth_type_trans()
on the output path which is bogus.
It's causing serious regressions for people.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 53 |
1 files changed, 24 insertions, 29 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 0c0f6c9a90e7..4cb28a7f639b 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -88,7 +88,6 @@ | |||
88 | #include <linux/virtio_net.h> | 88 | #include <linux/virtio_net.h> |
89 | #include <linux/errqueue.h> | 89 | #include <linux/errqueue.h> |
90 | #include <linux/net_tstamp.h> | 90 | #include <linux/net_tstamp.h> |
91 | #include <linux/if_arp.h> | ||
92 | 91 | ||
93 | #ifdef CONFIG_INET | 92 | #ifdef CONFIG_INET |
94 | #include <net/inet_common.h> | 93 | #include <net/inet_common.h> |
@@ -1924,7 +1923,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
1924 | __be16 proto, unsigned char *addr, int hlen) | 1923 | __be16 proto, unsigned char *addr, int hlen) |
1925 | { | 1924 | { |
1926 | union tpacket_uhdr ph; | 1925 | union tpacket_uhdr ph; |
1927 | int to_write, offset, len, tp_len, nr_frags, len_max, max_frame_len; | 1926 | int to_write, offset, len, tp_len, nr_frags, len_max; |
1928 | struct socket *sock = po->sk.sk_socket; | 1927 | struct socket *sock = po->sk.sk_socket; |
1929 | struct page *page; | 1928 | struct page *page; |
1930 | void *data; | 1929 | void *data; |
@@ -1947,6 +1946,10 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
1947 | tp_len = ph.h1->tp_len; | 1946 | tp_len = ph.h1->tp_len; |
1948 | break; | 1947 | break; |
1949 | } | 1948 | } |
1949 | if (unlikely(tp_len > size_max)) { | ||
1950 | pr_err("packet size is too long (%d > %d)\n", tp_len, size_max); | ||
1951 | return -EMSGSIZE; | ||
1952 | } | ||
1950 | 1953 | ||
1951 | skb_reserve(skb, hlen); | 1954 | skb_reserve(skb, hlen); |
1952 | skb_reset_network_header(skb); | 1955 | skb_reset_network_header(skb); |
@@ -2002,25 +2005,10 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
2002 | if (unlikely(err)) | 2005 | if (unlikely(err)) |
2003 | return err; | 2006 | return err; |
2004 | 2007 | ||
2005 | if (dev->type == ARPHRD_ETHER) | ||
2006 | skb->protocol = eth_type_trans(skb, dev); | ||
2007 | |||
2008 | data += dev->hard_header_len; | 2008 | data += dev->hard_header_len; |
2009 | to_write -= dev->hard_header_len; | 2009 | to_write -= dev->hard_header_len; |
2010 | } | 2010 | } |
2011 | 2011 | ||
2012 | max_frame_len = dev->mtu + dev->hard_header_len; | ||
2013 | if (skb->protocol == htons(ETH_P_8021Q)) | ||
2014 | max_frame_len += VLAN_HLEN; | ||
2015 | |||
2016 | if (size_max > max_frame_len) | ||
2017 | size_max = max_frame_len; | ||
2018 | |||
2019 | if (unlikely(tp_len > size_max)) { | ||
2020 | pr_err("packet size is too long (%d > %d)\n", tp_len, size_max); | ||
2021 | return -EMSGSIZE; | ||
2022 | } | ||
2023 | |||
2024 | offset = offset_in_page(data); | 2012 | offset = offset_in_page(data); |
2025 | len_max = PAGE_SIZE - offset; | 2013 | len_max = PAGE_SIZE - offset; |
2026 | len = ((to_write > len_max) ? len_max : to_write); | 2014 | len = ((to_write > len_max) ? len_max : to_write); |
@@ -2059,7 +2047,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2059 | struct net_device *dev; | 2047 | struct net_device *dev; |
2060 | __be16 proto; | 2048 | __be16 proto; |
2061 | bool need_rls_dev = false; | 2049 | bool need_rls_dev = false; |
2062 | int err; | 2050 | int err, reserve = 0; |
2063 | void *ph; | 2051 | void *ph; |
2064 | struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name; | 2052 | struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name; |
2065 | int tp_len, size_max; | 2053 | int tp_len, size_max; |
@@ -2092,6 +2080,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2092 | if (unlikely(dev == NULL)) | 2080 | if (unlikely(dev == NULL)) |
2093 | goto out; | 2081 | goto out; |
2094 | 2082 | ||
2083 | reserve = dev->hard_header_len; | ||
2084 | |||
2095 | err = -ENETDOWN; | 2085 | err = -ENETDOWN; |
2096 | if (unlikely(!(dev->flags & IFF_UP))) | 2086 | if (unlikely(!(dev->flags & IFF_UP))) |
2097 | goto out_put; | 2087 | goto out_put; |
@@ -2099,6 +2089,9 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2099 | size_max = po->tx_ring.frame_size | 2089 | size_max = po->tx_ring.frame_size |
2100 | - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); | 2090 | - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); |
2101 | 2091 | ||
2092 | if (size_max > dev->mtu + reserve) | ||
2093 | size_max = dev->mtu + reserve; | ||
2094 | |||
2102 | do { | 2095 | do { |
2103 | ph = packet_current_frame(po, &po->tx_ring, | 2096 | ph = packet_current_frame(po, &po->tx_ring, |
2104 | TP_STATUS_SEND_REQUEST); | 2097 | TP_STATUS_SEND_REQUEST); |
@@ -2331,20 +2324,22 @@ static int packet_snd(struct socket *sock, | |||
2331 | 2324 | ||
2332 | sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); | 2325 | sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); |
2333 | 2326 | ||
2334 | if (dev->type == ARPHRD_ETHER) { | ||
2335 | skb->protocol = eth_type_trans(skb, dev); | ||
2336 | if (skb->protocol == htons(ETH_P_8021Q)) | ||
2337 | reserve += VLAN_HLEN; | ||
2338 | } else { | ||
2339 | skb->protocol = proto; | ||
2340 | skb->dev = dev; | ||
2341 | } | ||
2342 | |||
2343 | if (!gso_type && (len > dev->mtu + reserve + extra_len)) { | 2327 | if (!gso_type && (len > dev->mtu + reserve + extra_len)) { |
2344 | err = -EMSGSIZE; | 2328 | /* Earlier code assumed this would be a VLAN pkt, |
2345 | goto out_free; | 2329 | * double-check this now that we have the actual |
2330 | * packet in hand. | ||
2331 | */ | ||
2332 | struct ethhdr *ehdr; | ||
2333 | skb_reset_mac_header(skb); | ||
2334 | ehdr = eth_hdr(skb); | ||
2335 | if (ehdr->h_proto != htons(ETH_P_8021Q)) { | ||
2336 | err = -EMSGSIZE; | ||
2337 | goto out_free; | ||
2338 | } | ||
2346 | } | 2339 | } |
2347 | 2340 | ||
2341 | skb->protocol = proto; | ||
2342 | skb->dev = dev; | ||
2348 | skb->priority = sk->sk_priority; | 2343 | skb->priority = sk->sk_priority; |
2349 | skb->mark = sk->sk_mark; | 2344 | skb->mark = sk->sk_mark; |
2350 | 2345 | ||