diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/bridge/br_forward.c | 14 | ||||
| -rw-r--r-- | net/bridge/br_input.c | 2 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 2 |
3 files changed, 13 insertions, 5 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index d61e6f741125..8347916efe88 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
| @@ -19,6 +19,10 @@ | |||
| 19 | #include <linux/netfilter_bridge.h> | 19 | #include <linux/netfilter_bridge.h> |
| 20 | #include "br_private.h" | 20 | #include "br_private.h" |
| 21 | 21 | ||
| 22 | static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb, | ||
| 23 | void (*__packet_hook)(const struct net_bridge_port *p, | ||
| 24 | struct sk_buff *skb)); | ||
| 25 | |||
| 22 | /* Don't forward packets to originating port or forwarding diasabled */ | 26 | /* Don't forward packets to originating port or forwarding diasabled */ |
| 23 | static inline int should_deliver(const struct net_bridge_port *p, | 27 | static inline int should_deliver(const struct net_bridge_port *p, |
| 24 | const struct sk_buff *skb) | 28 | const struct sk_buff *skb) |
| @@ -94,14 +98,18 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | |||
| 94 | } | 98 | } |
| 95 | 99 | ||
| 96 | /* called with rcu_read_lock */ | 100 | /* called with rcu_read_lock */ |
| 97 | void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | 101 | void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0) |
| 98 | { | 102 | { |
| 99 | if (should_deliver(to, skb)) { | 103 | if (should_deliver(to, skb)) { |
| 100 | __br_forward(to, skb); | 104 | if (skb0) |
| 105 | deliver_clone(to, skb, __br_forward); | ||
| 106 | else | ||
| 107 | __br_forward(to, skb); | ||
| 101 | return; | 108 | return; |
| 102 | } | 109 | } |
| 103 | 110 | ||
| 104 | kfree_skb(skb); | 111 | if (!skb0) |
| 112 | kfree_skb(skb); | ||
| 105 | } | 113 | } |
| 106 | 114 | ||
| 107 | static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb, | 115 | static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb, |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 53b39851d87d..08a72e63fb8e 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
| @@ -90,7 +90,7 @@ int br_handle_frame_finish(struct sk_buff *skb) | |||
| 90 | 90 | ||
| 91 | if (skb) { | 91 | if (skb) { |
| 92 | if (dst) | 92 | if (dst) |
| 93 | br_forward(dst->dst, skb); | 93 | br_forward(dst->dst, skb, skb2); |
| 94 | else | 94 | else |
| 95 | br_flood_forward(br, skb, skb2); | 95 | br_flood_forward(br, skb, skb2); |
| 96 | } | 96 | } |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index fef0384e3c0b..bfb8feb310a6 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -252,7 +252,7 @@ extern void br_deliver(const struct net_bridge_port *to, | |||
| 252 | struct sk_buff *skb); | 252 | struct sk_buff *skb); |
| 253 | extern int br_dev_queue_push_xmit(struct sk_buff *skb); | 253 | extern int br_dev_queue_push_xmit(struct sk_buff *skb); |
| 254 | extern void br_forward(const struct net_bridge_port *to, | 254 | extern void br_forward(const struct net_bridge_port *to, |
| 255 | struct sk_buff *skb); | 255 | struct sk_buff *skb, struct sk_buff *skb0); |
| 256 | extern int br_forward_finish(struct sk_buff *skb); | 256 | extern int br_forward_finish(struct sk_buff *skb); |
| 257 | extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); | 257 | extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); |
| 258 | extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, | 258 | extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, |
