aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_input.c')
-rw-r--r--net/bridge/br_input.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 4b34207419b1..480330151898 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -17,6 +17,7 @@
17#include <linux/etherdevice.h> 17#include <linux/etherdevice.h>
18#include <linux/netfilter_bridge.h> 18#include <linux/netfilter_bridge.h>
19#include <linux/export.h> 19#include <linux/export.h>
20#include <linux/rculist.h>
20#include "br_private.h" 21#include "br_private.h"
21 22
22/* Hook for brouter */ 23/* Hook for brouter */
@@ -34,6 +35,20 @@ static int br_pass_frame_up(struct sk_buff *skb)
34 brstats->rx_bytes += skb->len; 35 brstats->rx_bytes += skb->len;
35 u64_stats_update_end(&brstats->syncp); 36 u64_stats_update_end(&brstats->syncp);
36 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
48 skb = br_handle_vlan(br, br_get_vlan_info(br), skb);
49 if (!skb)
50 return NET_RX_DROP;
51
37 indev = skb->dev; 52 indev = skb->dev;
38 skb->dev = brdev; 53 skb->dev = brdev;
39 54
@@ -50,13 +65,17 @@ int br_handle_frame_finish(struct sk_buff *skb)
50 struct net_bridge_fdb_entry *dst; 65 struct net_bridge_fdb_entry *dst;
51 struct net_bridge_mdb_entry *mdst; 66 struct net_bridge_mdb_entry *mdst;
52 struct sk_buff *skb2; 67 struct sk_buff *skb2;
68 u16 vid = 0;
53 69
54 if (!p || p->state == BR_STATE_DISABLED) 70 if (!p || p->state == BR_STATE_DISABLED)
55 goto drop; 71 goto drop;
56 72
73 if (!br_allowed_ingress(p->br, nbp_get_vlan_info(p), skb, &vid))
74 goto drop;
75
57 /* insert into forwarding database after filtering to avoid spoofing */ 76 /* insert into forwarding database after filtering to avoid spoofing */
58 br = p->br; 77 br = p->br;
59 br_fdb_update(br, p, eth_hdr(skb)->h_source); 78 br_fdb_update(br, p, eth_hdr(skb)->h_source, vid);
60 79
61 if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) && 80 if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) &&
62 br_multicast_rcv(br, p, skb)) 81 br_multicast_rcv(br, p, skb))
@@ -91,7 +110,8 @@ int br_handle_frame_finish(struct sk_buff *skb)
91 skb2 = skb; 110 skb2 = skb;
92 111
93 br->dev->stats.multicast++; 112 br->dev->stats.multicast++;
94 } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) { 113 } else if ((dst = __br_fdb_get(br, dest, vid)) &&
114 dst->is_local) {
95 skb2 = skb; 115 skb2 = skb;
96 /* Do not forward the packet since it's local. */ 116 /* Do not forward the packet since it's local. */
97 skb = NULL; 117 skb = NULL;
@@ -119,8 +139,10 @@ drop:
119static int br_handle_local_finish(struct sk_buff *skb) 139static int br_handle_local_finish(struct sk_buff *skb)
120{ 140{
121 struct net_bridge_port *p = br_port_get_rcu(skb->dev); 141 struct net_bridge_port *p = br_port_get_rcu(skb->dev);
142 u16 vid = 0;
122 143
123 br_fdb_update(p->br, p, eth_hdr(skb)->h_source); 144 br_vlan_get_tag(skb, &vid);
145 br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid);
124 return 0; /* process further */ 146 return 0; /* process further */
125} 147}
126 148