diff options
author | Phil Sutter <phil@nwl.cc> | 2013-08-02 05:37:40 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-02 17:58:32 -0400 |
commit | cbd89acb9eb257ed3b2be867142583fdcf7fdc5b (patch) | |
tree | 7dfaa72d8f217853bb840407a86a9d6b46146525 /net | |
parent | 0f75b09c798ed00c30d7d5551b896be883bc2aeb (diff) |
af_packet: fix for sending VLAN frames via packet_mmap
Since tpacket_fill_skb() parses the protocol field in ethernet frames'
headers, it's easy to see if any passed frame is a VLAN one and account
for the extended size.
But as the real protocol does not turn up before tpacket_fill_skb()
runs which in turn also checks the frame length, move the max frame
length calculation into the function.
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/packet/af_packet.c | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 71db35ecba39..2b1470de9e16 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -1924,7 +1924,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
1924 | __be16 proto, unsigned char *addr, int hlen) | 1924 | __be16 proto, unsigned char *addr, int hlen) |
1925 | { | 1925 | { |
1926 | union tpacket_uhdr ph; | 1926 | union tpacket_uhdr ph; |
1927 | int to_write, offset, len, tp_len, nr_frags, len_max; | 1927 | int to_write, offset, len, tp_len, nr_frags, len_max, max_frame_len; |
1928 | struct socket *sock = po->sk.sk_socket; | 1928 | struct socket *sock = po->sk.sk_socket; |
1929 | struct page *page; | 1929 | struct page *page; |
1930 | void *data; | 1930 | void *data; |
@@ -1947,10 +1947,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
1947 | tp_len = ph.h1->tp_len; | 1947 | tp_len = ph.h1->tp_len; |
1948 | break; | 1948 | break; |
1949 | } | 1949 | } |
1950 | if (unlikely(tp_len > size_max)) { | ||
1951 | pr_err("packet size is too long (%d > %d)\n", tp_len, size_max); | ||
1952 | return -EMSGSIZE; | ||
1953 | } | ||
1954 | 1950 | ||
1955 | skb_reserve(skb, hlen); | 1951 | skb_reserve(skb, hlen); |
1956 | skb_reset_network_header(skb); | 1952 | skb_reset_network_header(skb); |
@@ -2013,6 +2009,18 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
2013 | to_write -= dev->hard_header_len; | 2009 | to_write -= dev->hard_header_len; |
2014 | } | 2010 | } |
2015 | 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 | |||
2016 | offset = offset_in_page(data); | 2024 | offset = offset_in_page(data); |
2017 | len_max = PAGE_SIZE - offset; | 2025 | len_max = PAGE_SIZE - offset; |
2018 | len = ((to_write > len_max) ? len_max : to_write); | 2026 | len = ((to_write > len_max) ? len_max : to_write); |
@@ -2051,7 +2059,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2051 | struct net_device *dev; | 2059 | struct net_device *dev; |
2052 | __be16 proto; | 2060 | __be16 proto; |
2053 | bool need_rls_dev = false; | 2061 | bool need_rls_dev = false; |
2054 | int err, reserve = 0; | 2062 | int err; |
2055 | void *ph; | 2063 | void *ph; |
2056 | struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name; | 2064 | struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name; |
2057 | int tp_len, size_max; | 2065 | int tp_len, size_max; |
@@ -2084,8 +2092,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2084 | if (unlikely(dev == NULL)) | 2092 | if (unlikely(dev == NULL)) |
2085 | goto out; | 2093 | goto out; |
2086 | 2094 | ||
2087 | reserve = dev->hard_header_len; | ||
2088 | |||
2089 | err = -ENETDOWN; | 2095 | err = -ENETDOWN; |
2090 | if (unlikely(!(dev->flags & IFF_UP))) | 2096 | if (unlikely(!(dev->flags & IFF_UP))) |
2091 | goto out_put; | 2097 | goto out_put; |
@@ -2093,9 +2099,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2093 | size_max = po->tx_ring.frame_size | 2099 | size_max = po->tx_ring.frame_size |
2094 | - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); | 2100 | - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); |
2095 | 2101 | ||
2096 | if (size_max > dev->mtu + reserve) | ||
2097 | size_max = dev->mtu + reserve; | ||
2098 | |||
2099 | do { | 2102 | do { |
2100 | ph = packet_current_frame(po, &po->tx_ring, | 2103 | ph = packet_current_frame(po, &po->tx_ring, |
2101 | TP_STATUS_SEND_REQUEST); | 2104 | TP_STATUS_SEND_REQUEST); |