9b1536
diff --git a/pcap-linux.c b/pcap-linux.c
9b1536
index 0bfc77a..8cf531b 100644
9b1536
--- a/pcap-linux.c
9b1536
+++ b/pcap-linux.c
9b1536
@@ -368,6 +368,12 @@ static void pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
9b1536
     const u_char *bytes);
9b1536
 #endif
9b1536
 
9b1536
+#ifdef TP_STATUS_VLAN_TPID_VALID
9b1536
+#define VLAN_TPID(hdr, hv)	(((hv)->tp_vlan_tpid || ((hdr)->tp_status & TP_STATUS_VLAN_TPID_VALID)) ? (hv)->tp_vlan_tpid : ETH_P_8021Q)
9b1536
+#else
9b1536
+#define VLAN_TPID(hdr, hv)	ETH_P_8021Q
9b1536
+#endif
9b1536
+
9b1536
 /*
9b1536
  * Wrap some ioctl calls
9b1536
  */
9b1536
@@ -1656,7 +1662,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
9b1536
 			memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
9b1536
 
9b1536
 			tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
9b1536
-			tag->vlan_tpid = htons(ETH_P_8021Q);
9b1536
+			tag->vlan_tpid = htons(VLAN_TPID(aux, aux));
9b1536
 			tag->vlan_tci = htons(aux->tp_vlan_tci);
9b1536
 
9b1536
                         /* store vlan tci to bpf_aux_data struct for userland bpf filter */
9b1536
@@ -4242,7 +4248,8 @@ static int pcap_handle_packet_mmap(
9b1536
 		unsigned int tp_sec,
9b1536
 		unsigned int tp_usec,
9b1536
 		int tp_vlan_tci_valid,
9b1536
-		__u16 tp_vlan_tci)
9b1536
+		__u16 tp_vlan_tci,
9b1536
+		__u16 tp_vlan_tpid)
9b1536
 {
9b1536
 	struct pcap_linux *handlep = handle->priv;
9b1536
 	unsigned char *bp;
9b1536
@@ -4350,7 +4357,7 @@ static int pcap_handle_packet_mmap(
9b1536
 		memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
9b1536
 
9b1536
 		tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
9b1536
-		tag->vlan_tpid = htons(ETH_P_8021Q);
9b1536
+		tag->vlan_tpid = htons(tp_vlan_tpid);
9b1536
 		tag->vlan_tci = htons(tp_vlan_tci);
9b1536
 
9b1536
 		pcaphdr.caplen += VLAN_TAG_LEN;
9b1536
@@ -4410,6 +4417,7 @@ pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
9b1536
 				h.h1->tp_sec,
9b1536
 				h.h1->tp_usec,
9b1536
 				0,
9b1536
+				0,
9b1536
 				0);
9b1536
 		if (ret == 1) {
9b1536
 			pkts++;
9b1536
@@ -4488,7 +4496,8 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
9b1536
 #else
9b1536
 				h.h2->tp_vlan_tci != 0,
9b1536
 #endif
9b1536
-				h.h2->tp_vlan_tci);
9b1536
+				h.h2->tp_vlan_tci,
9b1536
+				VLAN_TPID(h.h2, h.h2));
9b1536
 		if (ret == 1) {
9b1536
 			pkts++;
9b1536
 			handlep->packets_read++;
9b1536
@@ -4583,7 +4592,8 @@ pcap_read_linux_mmap_v3(pcap_t *handle, int max_packets, pcap_handler callback,
9b1536
 #else
9b1536
 					tp3_hdr->hv1.tp_vlan_tci != 0,
9b1536
 #endif
9b1536
-					tp3_hdr->hv1.tp_vlan_tci);
9b1536
+					tp3_hdr->hv1.tp_vlan_tci,
9b1536
+					VLAN_TPID(tp3_hdr, &tp3_hdr->hv1));
9b1536
 			if (ret == 1) {
9b1536
 				pkts++;
9b1536
 				handlep->packets_read++;