diff options
author | Vlad Yasevich <vyasevic@redhat.com> | 2013-02-13 07:00:11 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-02-13 19:41:46 -0500 |
commit | 85f46c6baef1486ce20e13dd7cdea5dd15be2a90 (patch) | |
tree | aab52d4f01320337bfc59358d26fc856e717a8f2 /net/bridge | |
parent | a37b85c9fbd1dc69fbec3985763f373203eaf9e3 (diff) |
bridge: Verify that a vlan is allowed to egress on given port
When bridge forwards a frame, make sure that a frame is allowed
to egress on that port.
Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_forward.c | 1 | ||||
-rw-r--r-- | net/bridge/br_input.c | 10 | ||||
-rw-r--r-- | net/bridge/br_private.h | 10 | ||||
-rw-r--r-- | net/bridge/br_vlan.c | 20 |
4 files changed, 41 insertions, 0 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 02015a505d2a..35b0671f135d 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -31,6 +31,7 @@ static inline int should_deliver(const struct net_bridge_port *p, | |||
31 | const struct sk_buff *skb) | 31 | const struct sk_buff *skb) |
32 | { | 32 | { |
33 | return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) && | 33 | return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) && |
34 | br_allowed_egress(p->br, nbp_get_vlan_info(p), skb) && | ||
34 | p->state == BR_STATE_FORWARDING); | 35 | p->state == BR_STATE_FORWARDING); |
35 | } | 36 | } |
36 | 37 | ||
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 4ef3f6b17bd0..787d7dad6b7e 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -35,6 +35,16 @@ static int br_pass_frame_up(struct sk_buff *skb) | |||
35 | brstats->rx_bytes += skb->len; | 35 | brstats->rx_bytes += skb->len; |
36 | u64_stats_update_end(&brstats->syncp); | 36 | u64_stats_update_end(&brstats->syncp); |
37 | 37 | ||
38 | /* Bridge is just like any other port. Make sure the | ||
39 | * packet is allowed except in promisc modue when someone | ||
40 | * may be running packet capture. | ||
41 | */ | ||
42 | if (!(brdev->flags & IFF_PROMISC) && | ||
43 | !br_allowed_egress(br, br_get_vlan_info(br), skb)) { | ||
44 | kfree_skb(skb); | ||
45 | return NET_RX_DROP; | ||
46 | } | ||
47 | |||
38 | indev = skb->dev; | 48 | indev = skb->dev; |
39 | skb->dev = brdev; | 49 | skb->dev = brdev; |
40 | 50 | ||
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index ed7c764ee9da..f0f24610d111 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -554,6 +554,9 @@ static inline void br_mdb_uninit(void) | |||
554 | #ifdef CONFIG_BRIDGE_VLAN_FILTERING | 554 | #ifdef CONFIG_BRIDGE_VLAN_FILTERING |
555 | extern bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | 555 | extern bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, |
556 | struct sk_buff *skb); | 556 | struct sk_buff *skb); |
557 | extern bool br_allowed_egress(struct net_bridge *br, | ||
558 | const struct net_port_vlans *v, | ||
559 | const struct sk_buff *skb); | ||
557 | extern int br_vlan_add(struct net_bridge *br, u16 vid); | 560 | extern int br_vlan_add(struct net_bridge *br, u16 vid); |
558 | extern int br_vlan_delete(struct net_bridge *br, u16 vid); | 561 | extern int br_vlan_delete(struct net_bridge *br, u16 vid); |
559 | extern void br_vlan_flush(struct net_bridge *br); | 562 | extern void br_vlan_flush(struct net_bridge *br); |
@@ -598,6 +601,13 @@ static inline bool br_allowed_ingress(struct net_bridge *br, | |||
598 | return true; | 601 | return true; |
599 | } | 602 | } |
600 | 603 | ||
604 | static inline bool br_allowed_egress(struct net_bridge *br, | ||
605 | const struct net_port_vlans *v, | ||
606 | const struct sk_buff *skb) | ||
607 | { | ||
608 | return true; | ||
609 | } | ||
610 | |||
601 | static inline int br_vlan_add(struct net_bridge *br, u16 vid) | 611 | static inline int br_vlan_add(struct net_bridge *br, u16 vid) |
602 | { | 612 | { |
603 | return -EOPNOTSUPP; | 613 | return -EOPNOTSUPP; |
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 8b4bcd8ff46e..d8690bfe63d4 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c | |||
@@ -89,6 +89,26 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
89 | return false; | 89 | return false; |
90 | } | 90 | } |
91 | 91 | ||
92 | /* Called under RCU. */ | ||
93 | bool br_allowed_egress(struct net_bridge *br, | ||
94 | const struct net_port_vlans *v, | ||
95 | const struct sk_buff *skb) | ||
96 | { | ||
97 | u16 vid; | ||
98 | |||
99 | if (!br->vlan_enabled) | ||
100 | return true; | ||
101 | |||
102 | if (!v) | ||
103 | return false; | ||
104 | |||
105 | br_vlan_get_tag(skb, &vid); | ||
106 | if (test_bit(vid, v->vlan_bitmap)) | ||
107 | return true; | ||
108 | |||
109 | return false; | ||
110 | } | ||
111 | |||
92 | /* Must be protected by RTNL */ | 112 | /* Must be protected by RTNL */ |
93 | int br_vlan_add(struct net_bridge *br, u16 vid) | 113 | int br_vlan_add(struct net_bridge *br, u16 vid) |
94 | { | 114 | { |