static inline __be16 vlan_proto(const struct sk_buff *skb)
 {
-       return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
+       if (vlan_tx_tag_present(skb))
+               return skb->protocol;
+       else if (skb->protocol == htons(ETH_P_8021Q))
+               return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
+       else
+               return 0;
 }
 
 #define IS_VLAN_IP(skb) \
-       (skb->protocol == htons(ETH_P_8021Q) && \
-        vlan_proto(skb) == htons(ETH_P_IP) &&  \
+       (vlan_proto(skb) == htons(ETH_P_IP) && \
         brnf_filter_vlan_tagged)
 
 #define IS_VLAN_IPV6(skb) \
-       (skb->protocol == htons(ETH_P_8021Q) && \
-        vlan_proto(skb) == htons(ETH_P_IPV6) &&\
+       (vlan_proto(skb) == htons(ETH_P_IPV6) && \
         brnf_filter_vlan_tagged)
 
 #define IS_VLAN_ARP(skb) \
-       (skb->protocol == htons(ETH_P_8021Q) && \
-        vlan_proto(skb) == htons(ETH_P_ARP) && \
+       (vlan_proto(skb) == htons(ETH_P_ARP) && \
         brnf_filter_vlan_tagged)
 
 static inline __be16 pppoe_proto(const struct sk_buff *skb)
 
 ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par)
 {
        const struct ebt_vlan_info *info = par->matchinfo;
-       const struct vlan_hdr *fp;
-       struct vlan_hdr _frame;
 
        unsigned short TCI;     /* Whole TCI, given from parsed frame */
        unsigned short id;      /* VLAN ID, given from frame TCI */
        /* VLAN encapsulated Type/Length field, given from orig frame */
        __be16 encap;
 
-       fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
-       if (fp == NULL)
-               return false;
+       if (vlan_tx_tag_present(skb)) {
+               TCI = vlan_tx_tag_get(skb);
+               encap = skb->protocol;
+       } else {
+               const struct vlan_hdr *fp;
+               struct vlan_hdr _frame;
+
+               fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
+               if (fp == NULL)
+                       return false;
+
+               TCI = ntohs(fp->h_vlan_TCI);
+               encap = fp->h_vlan_encapsulated_proto;
+       }
 
        /* Tag Control Information (TCI) consists of the following elements:
         * - User_priority. The user_priority field is three bits in length,
         * (CFI) is a single bit flag value. Currently ignored.
         * - VLAN Identifier (VID). The VID is encoded as
         * an unsigned binary number. */
-       TCI = ntohs(fp->h_vlan_TCI);
        id = TCI & VLAN_VID_MASK;
        prio = (TCI >> 13) & 0x7;
-       encap = fp->h_vlan_encapsulated_proto;
 
        /* Checking VLAN Identifier (VID) */
        if (GET_BITMASK(EBT_VLAN_ID))
 
 #define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
 /* process standard matches */
 static inline int
-ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h,
+ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb,
                 const struct net_device *in, const struct net_device *out)
 {
+       const struct ethhdr *h = eth_hdr(skb);
+       __be16 ethproto;
        int verdict, i;
 
+       if (vlan_tx_tag_present(skb))
+               ethproto = htons(ETH_P_8021Q);
+       else
+               ethproto = h->h_proto;
+
        if (e->bitmask & EBT_802_3) {
-               if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
+               if (FWINV2(ntohs(ethproto) >= 1536, EBT_IPROTO))
                        return 1;
        } else if (!(e->bitmask & EBT_NOPROTO) &&
-          FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
+          FWINV2(e->ethproto != ethproto, EBT_IPROTO))
                return 1;
 
        if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
        base = private->entries;
        i = 0;
        while (i < nentries) {
-               if (ebt_basic_match(point, eth_hdr(skb), in, out))
+               if (ebt_basic_match(point, skb, in, out))
                        goto letscontinue;
 
                if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 0)