File libpcap-use-tpid.patch of Package libpcap.2975

From: Atzm Watanabe <atzm@atzm.org>
Date: Tue, 25 Mar 2014 19:04:25 +0900
Subject: pcap-linux: Obtain VLAN TPID from the kernel when available
Patch-mainline: libpcap-1.7.2
Git-commit: 235734c4eb94a8dffd6fe7ca6c0c18e04fb390c1
References: bsc#874131

The VLAN TPID was hardcoded in pcap-linux.c but recent Linux kernel
supports 802.1ad Q-in-Q.
Since Linux 3.14, kernel gives the TPID value to the userspace when
available.
---
 pcap-linux.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/pcap-linux.c b/pcap-linux.c
index 65513e929c97..434cda0eb992 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -1658,7 +1658,12 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
 			memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
 
 			tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
-			tag->vlan_tpid = htons(ETH_P_8021Q);
+#if defined(TP_STATUS_VLAN_TPID_VALID)
+			if (aux->tp_vlan_tpid || (aux->tp_status & TP_STATUS_VLAN_TPID_VALID))
+				tag->vlan_tpid = htons(aux->tp_vlan_tpid);
+			else
+#endif
+				tag->vlan_tpid = htons(ETH_P_8021Q);
 			tag->vlan_tci = htons(aux->tp_vlan_tci);
 
 			packet_len += VLAN_TAG_LEN;
@@ -4179,7 +4184,8 @@ static int pcap_handle_packet_mmap(
 		unsigned int tp_sec,
 		unsigned int tp_usec,
 		int tp_vlan_tci_valid,
-		__u16 tp_vlan_tci)
+		__u16 tp_vlan_tci,
+		__u16 tp_vlan_tpid)
 {
 	struct pcap_linux *handlep = handle->priv;
 	unsigned char *bp;
@@ -4279,7 +4285,7 @@ static int pcap_handle_packet_mmap(
 		memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
 
 		tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
-		tag->vlan_tpid = htons(ETH_P_8021Q);
+		tag->vlan_tpid = htons(tp_vlan_tpid);
 		tag->vlan_tci = htons(tp_vlan_tci);
 
 		pcaphdr.caplen += VLAN_TAG_LEN;
@@ -4339,6 +4345,7 @@ pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
 				h.h1->tp_sec,
 				h.h1->tp_usec,
 				0,
+				0,
 				0);
 		if (ret == 1) {
 			pkts++;
@@ -4417,7 +4424,12 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
 #else
 				h.h2->tp_vlan_tci != 0,
 #endif
-				h.h2->tp_vlan_tci);
+				h.h2->tp_vlan_tci,
+#if defined(TP_STATUS_VLAN_TPID_VALID)
+				(h.h2->tp_vlan_tpid || (h.h2->tp_status & TP_STATUS_VLAN_TPID_VALID)) ? h.h2->tp_vlan_tpid : ETH_P_8021Q);
+#else
+				ETH_P_8021Q);
+#endif
 		if (ret == 1) {
 			pkts++;
 			handlep->packets_read++;
@@ -4512,7 +4524,12 @@ pcap_read_linux_mmap_v3(pcap_t *handle, int max_packets, pcap_handler callback,
 #else
 					tp3_hdr->hv1.tp_vlan_tci != 0,
 #endif
-					tp3_hdr->hv1.tp_vlan_tci);
+					tp3_hdr->hv1.tp_vlan_tci,
+#if defined(TP_STATUS_VLAN_TPID_VALID)
+					(tp3_hdr->hv1.tp_vlan_tpid || (tp3_hdr->tp_status & TP_STATUS_VLAN_TPID_VALID)) ? tp3_hdr->hv1.tp_vlan_tpid : ETH_P_8021Q);
+#else
+					ETH_P_8021Q);
+#endif
 			if (ret == 1) {
 				pkts++;
 				handlep->packets_read++;
-- 
2.5.0