summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Greear <greearb@candelatech.com>2011-06-01 06:49:10 +0000
committerDavid S. Miller <davem@davemloft.net>2011-06-01 21:18:03 -0700
commita3bcc23e890a6d49d6763d9eb073d711de2e0469 (patch)
treec4156e932f081dc14a514d5ab23cd43e590029cd
parent41be5a4a3668810bf3687a76c2b017bd437039e0 (diff)
downloadlinux-a3bcc23e890a6d49d6763d9eb073d711de2e0469.tar.gz
linux-a3bcc23e890a6d49d6763d9eb073d711de2e0469.tar.bz2
linux-a3bcc23e890a6d49d6763d9eb073d711de2e0469.zip
af-packet: Add flag to distinguish VID 0 from no-vlan.
Currently, user-space cannot determine if a 0 tcp_vlan_tci means there is no VLAN tag or the VLAN ID was zero. Add flag to make this explicit. User-space can check for TP_STATUS_VLAN_VALID || tp_vlan_tci > 0, which will be backwards compatible. Older could would have just checked for tp_vlan_tci, so it will work no worse than before. Signed-off-by: Ben Greear <greearb@candelatech.com> Acked-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/if_packet.h1
-rw-r--r--net/packet/af_packet.c15
2 files changed, 13 insertions, 3 deletions
diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h
index 72bfa5a034dd..6d66ce1791a9 100644
--- a/include/linux/if_packet.h
+++ b/include/linux/if_packet.h
@@ -70,6 +70,7 @@ struct tpacket_auxdata {
#define TP_STATUS_COPY 0x2
#define TP_STATUS_LOSING 0x4
#define TP_STATUS_CSUMNOTREADY 0x8
+#define TP_STATUS_VLAN_VALID 0x10 /* auxdata has valid tp_vlan_tci */
/* Tx ring - header status */
#define TP_STATUS_AVAILABLE 0x0
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 925f715686a5..ba248d93399a 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -798,7 +798,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
getnstimeofday(&ts);
h.h2->tp_sec = ts.tv_sec;
h.h2->tp_nsec = ts.tv_nsec;
- h.h2->tp_vlan_tci = vlan_tx_tag_get(skb);
+ if (vlan_tx_tag_present(skb)) {
+ h.h2->tp_vlan_tci = vlan_tx_tag_get(skb);
+ status |= TP_STATUS_VLAN_VALID;
+ } else {
+ h.h2->tp_vlan_tci = 0;
+ }
hdrlen = sizeof(*h.h2);
break;
default:
@@ -1725,8 +1730,12 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
aux.tp_snaplen = skb->len;
aux.tp_mac = 0;
aux.tp_net = skb_network_offset(skb);
- aux.tp_vlan_tci = vlan_tx_tag_get(skb);
-
+ if (vlan_tx_tag_present(skb)) {
+ aux.tp_vlan_tci = vlan_tx_tag_get(skb);
+ aux.tp_status |= TP_STATUS_VLAN_VALID;
+ } else {
+ aux.tp_vlan_tci = 0;
+ }
put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux);
}