[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20070302141418.1daa9047@freekitty>
Date: Fri, 2 Mar 2007 14:14:18 -0800
From: Stephen Hemminger <shemminger@...ux-foundation.org>
To: David Miller <davem@...emloft.net>
Cc: bridge@...ux-foundation.org, netdev@...r.kernel.org
Subject: [RFC 2/2] bridge: per device promiscious taps
Part of the next set of bridge patches includes this.
It allows packet capture by interface on a bridge:
tcpdump -i eth0
will work as expected.
@@ -128,34 +125,45 @@ static inline int is_link_local(const un
int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
+ struct sk_buff *skb2 = NULL;
const unsigned char *dest = eth_hdr(skb)->h_dest;
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
goto err;
if (unlikely(is_link_local(dest))) {
skb->pkt_type = PACKET_HOST;
return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
NULL, br_handle_local_finish) != 0;
}
+
+ if (unlikely(p->dev->promiscuity > 1))
+ skb2 = skb_clone(skb, GFP_ATOMIC);
- if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) {
+ switch (p->state) {
+ case BR_STATE_FORWARDING:
if (br_should_route_hook) {
- if (br_should_route_hook(pskb))
+ if (br_should_route_hook(pskb)) {
+ kfree_skb(skb2);
return 0;
+ }
skb = *pskb;
dest = eth_hdr(skb)->h_dest;
}
if (!compare_ether_addr(p->br->dev->dev_addr, dest))
skb->pkt_type = PACKET_HOST;
+ /* fall thru */
+ case BR_STATE_LEARNING:
NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
br_handle_frame_finish);
- return 1;
+ break;
+
+ default:
+ kfree_skb(skb);
}
-err:
- kfree_skb(skb);
- return 1;
+ if (likely(!skb2))
+ return 1;
+
+ *pskb = skb2;
+ return 0;
}
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists