aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2010-10-20 09:56:01 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-21 04:26:49 -0400
commit13937911f93ef52ae652f4652761aea6a58d3193 (patch)
tree04fd08dd8678f71b0e91239e5fbea43e55d3c23b /net/bridge
parent53c90536e96218ed6d60e7ea7a69a92b68805cdf (diff)
ebtables: Allow filtering of hardware accelerated vlan frames.
An upcoming commit will allow packets with hardware vlan acceleration information to be passed though more parts of the network stack, including packets trunked through the bridge. This adds support for matching and filtering those packets through ebtables. Signed-off-by: Jesse Gross <jesse@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_netfilter.c16
-rw-r--r--net/bridge/netfilter/ebt_vlan.c21
-rw-r--r--net/bridge/netfilter/ebtables.c15
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
65static inline __be16 vlan_proto(const struct sk_buff *skb) 65static 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
85static inline __be16 pppoe_proto(const struct sk_buff *skb) 87static 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
39ebt_vlan_mt(const struct sk_buff *skb, struct xt_action_param *par) 39ebt_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 */
126static inline int 126static inline int
127ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h, 127ebt_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)