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.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 88e4aa9cb1f9..f3ac1e858ee1 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -98,9 +98,10 @@ int br_handle_frame_finish(struct sk_buff *skb)
98 } 98 }
99 99
100 if (skb) { 100 if (skb) {
101 if (dst) 101 if (dst) {
102 dst->used = jiffies;
102 br_forward(dst->dst, skb, skb2); 103 br_forward(dst->dst, skb, skb2);
103 else 104 } else
104 br_flood_forward(br, skb, skb2); 105 br_flood_forward(br, skb, skb2);
105 } 106 }
106 107
@@ -139,21 +140,22 @@ static inline int is_link_local(const unsigned char *dest)
139 * Return NULL if skb is handled 140 * Return NULL if skb is handled
140 * note: already called with rcu_read_lock 141 * note: already called with rcu_read_lock
141 */ 142 */
142struct sk_buff *br_handle_frame(struct sk_buff *skb) 143rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
143{ 144{
144 struct net_bridge_port *p; 145 struct net_bridge_port *p;
146 struct sk_buff *skb = *pskb;
145 const unsigned char *dest = eth_hdr(skb)->h_dest; 147 const unsigned char *dest = eth_hdr(skb)->h_dest;
146 br_should_route_hook_t *rhook; 148 br_should_route_hook_t *rhook;
147 149
148 if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) 150 if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
149 return skb; 151 return RX_HANDLER_PASS;
150 152
151 if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) 153 if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
152 goto drop; 154 goto drop;
153 155
154 skb = skb_share_check(skb, GFP_ATOMIC); 156 skb = skb_share_check(skb, GFP_ATOMIC);
155 if (!skb) 157 if (!skb)
156 return NULL; 158 return RX_HANDLER_CONSUMED;
157 159
158 p = br_port_get_rcu(skb->dev); 160 p = br_port_get_rcu(skb->dev);
159 161
@@ -163,14 +165,16 @@ struct sk_buff *br_handle_frame(struct sk_buff *skb)
163 goto drop; 165 goto drop;
164 166
165 /* If STP is turned off, then forward */ 167 /* If STP is turned off, then forward */
166 if (p->br->stp_enabled == BR_NO_STP) 168 if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0)
167 goto forward; 169 goto forward;
168 170
169 if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, 171 if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
170 NULL, br_handle_local_finish)) 172 NULL, br_handle_local_finish)) {
171 return NULL; /* frame consumed by filter */ 173 return RX_HANDLER_CONSUMED; /* consumed by filter */
172 else 174 } else {
173 return skb; /* continue processing */ 175 *pskb = skb;
176 return RX_HANDLER_PASS; /* continue processing */
177 }
174 } 178 }
175 179
176forward: 180forward:
@@ -178,8 +182,10 @@ forward:
178 case BR_STATE_FORWARDING: 182 case BR_STATE_FORWARDING:
179 rhook = rcu_dereference(br_should_route_hook); 183 rhook = rcu_dereference(br_should_route_hook);
180 if (rhook) { 184 if (rhook) {
181 if ((*rhook)(skb)) 185 if ((*rhook)(skb)) {
182 return skb; 186 *pskb = skb;
187 return RX_HANDLER_PASS;
188 }
183 dest = eth_hdr(skb)->h_dest; 189 dest = eth_hdr(skb)->h_dest;
184 } 190 }
185 /* fall through */ 191 /* fall through */
@@ -194,5 +200,5 @@ forward:
194drop: 200drop:
195 kfree_skb(skb); 201 kfree_skb(skb);
196 } 202 }
197 return NULL; 203 return RX_HANDLER_CONSUMED;
198} 204}