diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index d3b59d7..5f17fef 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -446,7 +446,7 @@ static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, * Note: called only from the BH handler context, * so we don't need to lock the hashes. */ -static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, +static void __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, struct in6_addr *saddr, struct in6_addr *daddr, struct udp_table *udptable) { @@ -460,8 +460,9 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, dif = inet6_iif(skb); sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); if (!sk) { - kfree_skb(skb); - goto out; + spin_unlock(&hslot->lock); + consume_skb(skb); + return; } sk2 = sk; @@ -483,9 +484,8 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, else sk_add_backlog(sk, skb); bh_unlock_sock(sk); -out: + spin_unlock(&hslot->lock); - return 0; } static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, @@ -568,9 +568,11 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, /* * Multicast receive code */ - if (ipv6_addr_is_multicast(daddr)) - return __udp6_lib_mcast_deliver(net, skb, + if (ipv6_addr_is_multicast(daddr)) { + __udp6_lib_mcast_deliver(net, skb, saddr, daddr, udptable); + return 0; + } /* Unicast */