diff options
author | Phil Sutter <phil@nwl.cc> | 2013-08-02 05:37:39 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-02 17:58:32 -0400 |
commit | 0f75b09c798ed00c30d7d5551b896be883bc2aeb (patch) | |
tree | 9fc3da6d33d9ce15c1566e30f7bf13bfcefbc58c /net | |
parent | d27fc78208b53ccdfd6a57d4ac44a459ca66806f (diff) |
af_packet: when sending ethernet frames, parse header for skb->protocol
This may be necessary when the SKB is passed to other layers on the go,
which check the protocol field on their own. An example is a VLAN packet
sent out using AF_PACKET on a bridge interface. The bridging code checks
the SKB size, accounting for any VLAN header only if the protocol field
is set accordingly.
Note that eth_type_trans() sets skb->dev to the passed argument, so this
can be skipped in packet_snd() for ethernet frames, as well.
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 | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 4cb28a7f639b..71db35ecba39 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -88,6 +88,7 @@ | |||
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> | ||
91 | 92 | ||
92 | #ifdef CONFIG_INET | 93 | #ifdef CONFIG_INET |
93 | #include <net/inet_common.h> | 94 | #include <net/inet_common.h> |
@@ -2005,6 +2006,9 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
2005 | if (unlikely(err)) | 2006 | if (unlikely(err)) |
2006 | return err; | 2007 | return err; |
2007 | 2008 | ||
2009 | if (dev->type == ARPHRD_ETHER) | ||
2010 | skb->protocol = eth_type_trans(skb, dev); | ||
2011 | |||
2008 | data += dev->hard_header_len; | 2012 | data += dev->hard_header_len; |
2009 | to_write -= dev->hard_header_len; | 2013 | to_write -= dev->hard_header_len; |
2010 | } | 2014 | } |
@@ -2324,6 +2328,13 @@ static int packet_snd(struct socket *sock, | |||
2324 | 2328 | ||
2325 | sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); | 2329 | sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); |
2326 | 2330 | ||
2331 | if (dev->type == ARPHRD_ETHER) { | ||
2332 | skb->protocol = eth_type_trans(skb, dev); | ||
2333 | } else { | ||
2334 | skb->protocol = proto; | ||
2335 | skb->dev = dev; | ||
2336 | } | ||
2337 | |||
2327 | if (!gso_type && (len > dev->mtu + reserve + extra_len)) { | 2338 | if (!gso_type && (len > dev->mtu + reserve + extra_len)) { |
2328 | /* Earlier code assumed this would be a VLAN pkt, | 2339 | /* Earlier code assumed this would be a VLAN pkt, |
2329 | * double-check this now that we have the actual | 2340 | * double-check this now that we have the actual |
@@ -2338,8 +2349,6 @@ static int packet_snd(struct socket *sock, | |||
2338 | } | 2349 | } |
2339 | } | 2350 | } |
2340 | 2351 | ||
2341 | skb->protocol = proto; | ||
2342 | skb->dev = dev; | ||
2343 | skb->priority = sk->sk_priority; | 2352 | skb->priority = sk->sk_priority; |
2344 | skb->mark = sk->sk_mark; | 2353 | skb->mark = sk->sk_mark; |
2345 | 2354 | ||