struct iphdr *iphdr;
        struct ipv6hdr *ipv6hdr;
        struct udphdr *udphdr;
+       struct vlan_ethhdr *vhdr;
+       __be16 proto;
 
        /* check for ethernet header */
        if (!pskb_may_pull(skb, *header_len + ETH_HLEN))
                return false;
        ethhdr = (struct ethhdr *)skb->data;
+       proto = ethhdr->h_proto;
        *header_len += ETH_HLEN;
 
        /* check for initial vlan header */
-       if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
+       if (proto == htons(ETH_P_8021Q)) {
                if (!pskb_may_pull(skb, *header_len + VLAN_HLEN))
                        return false;
-               ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN);
+
+               vhdr = (struct vlan_ethhdr *)skb->data;
+               proto = vhdr->h_vlan_encapsulated_proto;
                *header_len += VLAN_HLEN;
        }
 
        /* check for ip header */
-       switch (ntohs(ethhdr->h_proto)) {
-       case ETH_P_IP:
+       switch (proto) {
+       case htons(ETH_P_IP):
                if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr)))
                        return false;
                iphdr = (struct iphdr *)(skb->data + *header_len);
                        return false;
 
                break;
-       case ETH_P_IPV6:
+       case htons(ETH_P_IPV6):
                if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr)))
                        return false;
                ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len);
        *header_len += sizeof(*udphdr);
 
        /* check for bootp port */
-       if ((ntohs(ethhdr->h_proto) == ETH_P_IP) &&
+       if ((proto == htons(ETH_P_IP)) &&
            (ntohs(udphdr->dest) != 67))
                return false;
 
-       if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) &&
+       if ((proto == htons(ETH_P_IPV6)) &&
            (ntohs(udphdr->dest) != 547))
                return false;