aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/datagram.c9
-rw-r--r--net/ipv4/udp.c5
-rw-r--r--net/ipv6/udp.c4
3 files changed, 12 insertions, 6 deletions
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 029b93e246b..fbd6c76436d 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -217,20 +217,27 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb)
* This function currently only disables BH when acquiring the
* sk_receive_queue lock. Therefore it must not be used in a
* context where that lock is acquired in an IRQ context.
+ *
+ * It returns 0 if the packet was removed by us.
*/
-void skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
+int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
{
+ int err = 0;
+
if (flags & MSG_PEEK) {
+ err = -ENOENT;
spin_lock_bh(&sk->sk_receive_queue.lock);
if (skb == skb_peek(&sk->sk_receive_queue)) {
__skb_unlink(skb, &sk->sk_receive_queue);
atomic_dec(&skb->users);
+ err = 0;
}
spin_unlock_bh(&sk->sk_receive_queue.lock);
}
kfree_skb(skb);
+ return err;
}
EXPORT_SYMBOL(skb_kill_datagram);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index d0283b7fcec..f50de5d5218 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -899,9 +899,8 @@ out:
return err;
csum_copy_err:
- UDP_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
-
- skb_kill_datagram(sk, skb, flags);
+ if (!skb_kill_datagram(sk, skb, flags))
+ UDP_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
if (noblock)
return -EAGAIN;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 77ab31b9923..87bccec9882 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -207,8 +207,8 @@ out:
return err;
csum_copy_err:
- UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
- skb_kill_datagram(sk, skb, flags);
+ if (!skb_kill_datagram(sk, skb, flags))
+ UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
if (flags & MSG_DONTWAIT)
return -EAGAIN;