diff options
-rw-r--r-- | net/bridge/br_netfilter.c | 16 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_vlan.c | 21 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtables.c | 15 |
3 files changed, 34 insertions, 18 deletions
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 7f9ce9600ef3..47c2dabe8669 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -64,22 +64,24 @@ static int brnf_filter_pppoe_tagged __read_mostly = 0; | |||
64 | 64 | ||
65 | static inline __be16 vlan_proto(const struct sk_buff *skb) | 65 | static inline __be16 vlan_proto(const struct sk_buff *skb) |
66 | { | 66 | { |
67 | return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; | 67 | if (vlan_tx_tag_present(skb)) |
68 | return skb->protocol; | ||
69 | else if (skb->protocol == htons(ETH_P_8021Q)) | ||
70 | return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; | ||
71 | else | ||
72 | return 0; | ||
68 | } | 73 | } |
69 | 74 | ||
70 | #define IS_VLAN_IP(skb) \ | 75 | #define IS_VLAN_IP(skb) \ |
71 | (skb->protocol == htons(ETH_P_8021Q) && \ | 76 | (vlan_proto(skb) == htons(ETH_P_IP) && \ |
72 | vlan_proto(skb) == htons(ETH_P_IP) && \ | ||
73 | brnf_filter_vlan_tagged) | 77 | brnf_filter_vlan_tagged) |
74 | 78 | ||
75 | #define IS_VLAN_IPV6(skb) \ | 79 | #define IS_VLAN_IPV6(skb) \ |
76 | (skb->protocol == htons(ETH_P_8021Q) && \ | 80 | (vlan_proto(skb) == htons(ETH_P_IPV6) && \ |
77 | vlan_proto(skb) == htons(ETH_P_IPV6) &&\ | ||
78 | brnf_filter_vlan_tagged) | 81 | brnf_filter_vlan_tagged) |
79 | 82 | ||
80 | #define IS_VLAN_ARP(skb) \ | 83 | #define IS_VLAN_ARP(skb) \ |
81 | (skb->protocol == htons(ETH_P_8021Q) && \ | 84 | (vlan_proto(skb) == htons(ETH_P_ARP) && \ |
82 | vlan_proto(skb) == htons(ETH_P_ARP) && \ | ||
83 | brnf_filter_vlan_tagged) | 85 | brnf_filter_vlan_tagged) |
84 | 86 | ||
85 | static inline __be16 pppoe_proto(const struct sk_buff *skb) | 87 | static inline __be16 pppoe_proto(const struct sk_buff *skb) |
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c index 87b53b3a921d..cc11d6b8e507 100644 --- a/net/bridge/netfilter/ebt_vlan.c +++ b/net/bridge/netfilter/ebt_vlan.c | |||
@@ -39,8 +39,6 @@ static bool | |||
39 | ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par) | 39 | ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par) |
40 | { | 40 | { |
41 | const struct ebt_vlan_info *info = par->matchinfo; | 41 | const struct ebt_vlan_info *info = par->matchinfo; |
42 | const struct vlan_hdr *fp; | ||
43 | struct vlan_hdr _frame; | ||
44 | 42 | ||
45 | unsigned short TCI; /* Whole TCI, given from parsed frame */ | 43 | unsigned short TCI; /* Whole TCI, given from parsed frame */ |
46 | unsigned short id; /* VLAN ID, given from frame TCI */ | 44 | unsigned short id; /* VLAN ID, given from frame TCI */ |
@@ -48,9 +46,20 @@ ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
48 | /* VLAN encapsulated Type/Length field, given from orig frame */ | 46 | /* VLAN encapsulated Type/Length field, given from orig frame */ |
49 | __be16 encap; | 47 | __be16 encap; |
50 | 48 | ||
51 | fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame); | 49 | if (vlan_tx_tag_present(skb)) { |
52 | if (fp == NULL) | 50 | TCI = vlan_tx_tag_get(skb); |
53 | return false; | 51 | encap = skb->protocol; |
52 | } else { | ||
53 | const struct vlan_hdr *fp; | ||
54 | struct vlan_hdr _frame; | ||
55 | |||
56 | fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame); | ||
57 | if (fp == NULL) | ||
58 | return false; | ||
59 | |||
60 | TCI = ntohs(fp->h_vlan_TCI); | ||
61 | encap = fp->h_vlan_encapsulated_proto; | ||
62 | } | ||
54 | 63 | ||
55 | /* Tag Control Information (TCI) consists of the following elements: | 64 | /* Tag Control Information (TCI) consists of the following elements: |
56 | * - User_priority. The user_priority field is three bits in length, | 65 | * - User_priority. The user_priority field is three bits in length, |
@@ -59,10 +68,8 @@ ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
59 | * (CFI) is a single bit flag value. Currently ignored. | 68 | * (CFI) is a single bit flag value. Currently ignored. |
60 | * - VLAN Identifier (VID). The VID is encoded as | 69 | * - VLAN Identifier (VID). The VID is encoded as |
61 | * an unsigned binary number. */ | 70 | * an unsigned binary number. */ |
62 | TCI = ntohs(fp->h_vlan_TCI); | ||
63 | id = TCI & VLAN_VID_MASK; | 71 | id = TCI & VLAN_VID_MASK; |
64 | prio = (TCI >> 13) & 0x7; | 72 | prio = (TCI >> 13) & 0x7; |
65 | encap = fp->h_vlan_encapsulated_proto; | ||
66 | 73 | ||
67 | /* Checking VLAN Identifier (VID) */ | 74 | /* Checking VLAN Identifier (VID) */ |
68 | if (GET_BITMASK(EBT_VLAN_ID)) | 75 | if (GET_BITMASK(EBT_VLAN_ID)) |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index bcc102e3be4d..a1dcf83f0d58 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -124,16 +124,23 @@ ebt_dev_check(const char *entry, const struct net_device *device) | |||
124 | #define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg)) | 124 | #define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg)) |
125 | /* process standard matches */ | 125 | /* process standard matches */ |
126 | static inline int | 126 | static inline int |
127 | ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h, | 127 | ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb, |
128 | const struct net_device *in, const struct net_device *out) | 128 | const struct net_device *in, const struct net_device *out) |
129 | { | 129 | { |
130 | const struct ethhdr *h = eth_hdr(skb); | ||
131 | __be16 ethproto; | ||
130 | int verdict, i; | 132 | int verdict, i; |
131 | 133 | ||
134 | if (vlan_tx_tag_present(skb)) | ||
135 | ethproto = htons(ETH_P_8021Q); | ||
136 | else | ||
137 | ethproto = h->h_proto; | ||
138 | |||
132 | if (e->bitmask & EBT_802_3) { | 139 | if (e->bitmask & EBT_802_3) { |
133 | if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO)) | 140 | if (FWINV2(ntohs(ethproto) >= 1536, EBT_IPROTO)) |
134 | return 1; | 141 | return 1; |
135 | } else if (!(e->bitmask & EBT_NOPROTO) && | 142 | } else if (!(e->bitmask & EBT_NOPROTO) && |
136 | FWINV2(e->ethproto != h->h_proto, EBT_IPROTO)) | 143 | FWINV2(e->ethproto != ethproto, EBT_IPROTO)) |
137 | return 1; | 144 | return 1; |
138 | 145 | ||
139 | if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN)) | 146 | if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN)) |
@@ -213,7 +220,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, | |||
213 | base = private->entries; | 220 | base = private->entries; |
214 | i = 0; | 221 | i = 0; |
215 | while (i < nentries) { | 222 | while (i < nentries) { |
216 | if (ebt_basic_match(point, eth_hdr(skb), in, out)) | 223 | if (ebt_basic_match(point, skb, in, out)) |
217 | goto letscontinue; | 224 | goto letscontinue; |
218 | 225 | ||
219 | if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 0) | 226 | if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 0) |