diff options
Diffstat (limited to 'net/bridge/br_forward.c')
| -rw-r--r-- | net/bridge/br_forward.c | 19 | 
1 files changed, 15 insertions, 4 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index d61e6f74112..7a241c39698 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -12,6 +12,7 @@   */  #include <linux/err.h> +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/netdevice.h>  #include <linux/skbuff.h> @@ -19,6 +20,11 @@  #include <linux/netfilter_bridge.h>  #include "br_private.h" +static int deliver_clone(const struct net_bridge_port *prev, +			 struct sk_buff *skb, +			 void (*__packet_hook)(const struct net_bridge_port *p, +					       struct sk_buff *skb)); +  /* Don't forward packets to originating port or forwarding diasabled */  static inline int should_deliver(const struct net_bridge_port *p,  				 const struct sk_buff *skb) @@ -94,17 +100,22 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)  }  /* called with rcu_read_lock */ -void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) +void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)  {  	if (should_deliver(to, skb)) { -		__br_forward(to, skb); +		if (skb0) +			deliver_clone(to, skb, __br_forward); +		else +			__br_forward(to, skb);  		return;  	} -	kfree_skb(skb); +	if (!skb0) +		kfree_skb(skb);  } -static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb, +static int deliver_clone(const struct net_bridge_port *prev, +			 struct sk_buff *skb,  			 void (*__packet_hook)(const struct net_bridge_port *p,  					       struct sk_buff *skb))  {  |