X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fbridge%2Fbr_input.c;h=0ee79a726d91f3159e293282013dd7fad395760e;hb=982286d1b8e438f595cdc9304cc4c185c7b90a39;hp=3a8a015c92e0d49a29d7e0b4e686fb78135529b7;hpb=c2f828977ba5d17c13debba374ea252d18e5ccfb;p=linux-2.6 diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 3a8a015c92..0ee79a726d 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -122,10 +122,15 @@ static inline int is_link_local(const unsigned char *dest) struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb) { const unsigned char *dest = eth_hdr(skb)->h_dest; + int (*rhook)(struct sk_buff *skb); if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) goto drop; + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + return NULL; + if (unlikely(is_link_local(dest))) { /* Pause frames shouldn't be passed up by driver anyway */ if (skb->protocol == htons(ETH_P_PAUSE)) @@ -143,9 +148,9 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb) switch (p->state) { case BR_STATE_FORWARDING: - - if (br_should_route_hook) { - if (br_should_route_hook(&skb)) + rhook = rcu_dereference(br_should_route_hook); + if (rhook != NULL) { + if (rhook(skb)) return skb; dest = eth_hdr(skb)->h_dest; }