diff options
author | Phil Sutter <phil@nwl.cc> | 2013-08-02 11:37:39 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-02 14:58:32 -0700 |
commit | 0f75b09c798ed00c30d7d5551b896be883bc2aeb (patch) | |
tree | 9fc3da6d33d9ce15c1566e30f7bf13bfcefbc58c /net/packet | |
parent | d27fc78208b53ccdfd6a57d4ac44a459ca66806f (diff) | |
download | linux-0f75b09c798ed00c30d7d5551b896be883bc2aeb.tar.gz linux-0f75b09c798ed00c30d7d5551b896be883bc2aeb.tar.bz2 linux-0f75b09c798ed00c30d7d5551b896be883bc2aeb.zip |
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/packet')
-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 @@ #include <linux/virtio_net.h> #include <linux/errqueue.h> #include <linux/net_tstamp.h> +#include <linux/if_arp.h> #ifdef CONFIG_INET #include <net/inet_common.h> @@ -2005,6 +2006,9 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, if (unlikely(err)) return err; + if (dev->type == ARPHRD_ETHER) + skb->protocol = eth_type_trans(skb, dev); + data += dev->hard_header_len; to_write -= dev->hard_header_len; } @@ -2324,6 +2328,13 @@ static int packet_snd(struct socket *sock, sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); + if (dev->type == ARPHRD_ETHER) { + skb->protocol = eth_type_trans(skb, dev); + } else { + skb->protocol = proto; + skb->dev = dev; + } + if (!gso_type && (len > dev->mtu + reserve + extra_len)) { /* Earlier code assumed this would be a VLAN pkt, * double-check this now that we have the actual @@ -2338,8 +2349,6 @@ static int packet_snd(struct socket *sock, } } - skb->protocol = proto; - skb->dev = dev; skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; |