aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/skbuff.h2
-rw-r--r--net/core/datagram.c9
-rw-r--r--net/ipv4/udp.c5
-rw-r--r--net/ipv6/udp.c4
4 files changed, 13 insertions, 7 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index d39f53ef66bb..17b3f70fbbc3 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1549,7 +1549,7 @@ extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
1549 int hlen, 1549 int hlen,
1550 struct iovec *iov); 1550 struct iovec *iov);
1551extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb); 1551extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
1552extern void skb_kill_datagram(struct sock *sk, struct sk_buff *skb, 1552extern int skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
1553 unsigned int flags); 1553 unsigned int flags);
1554extern __wsum skb_checksum(const struct sk_buff *skb, int offset, 1554extern __wsum skb_checksum(const struct sk_buff *skb, int offset,
1555 int len, __wsum csum); 1555 int len, __wsum csum);
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 029b93e246b4..fbd6c76436d0 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)
217 * This function currently only disables BH when acquiring the 217 * This function currently only disables BH when acquiring the
218 * sk_receive_queue lock. Therefore it must not be used in a 218 * sk_receive_queue lock. Therefore it must not be used in a
219 * context where that lock is acquired in an IRQ context. 219 * context where that lock is acquired in an IRQ context.
220 *
221 * It returns 0 if the packet was removed by us.
220 */ 222 */
221 223
222void skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags) 224int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
223{ 225{
226 int err = 0;
227
224 if (flags & MSG_PEEK) { 228 if (flags & MSG_PEEK) {
229 err = -ENOENT;
225 spin_lock_bh(&sk->sk_receive_queue.lock); 230 spin_lock_bh(&sk->sk_receive_queue.lock);
226 if (skb == skb_peek(&sk->sk_receive_queue)) { 231 if (skb == skb_peek(&sk->sk_receive_queue)) {
227 __skb_unlink(skb, &sk->sk_receive_queue); 232 __skb_unlink(skb, &sk->sk_receive_queue);
228 atomic_dec(&skb->users); 233 atomic_dec(&skb->users);
234 err = 0;
229 } 235 }
230 spin_unlock_bh(&sk->sk_receive_queue.lock); 236 spin_unlock_bh(&sk->sk_receive_queue.lock);
231 } 237 }
232 238
233 kfree_skb(skb); 239 kfree_skb(skb);
240 return err;
234} 241}
235 242
236EXPORT_SYMBOL(skb_kill_datagram); 243EXPORT_SYMBOL(skb_kill_datagram);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index d0283b7fcec5..f50de5d5218d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -899,9 +899,8 @@ out:
899 return err; 899 return err;
900 900
901csum_copy_err: 901csum_copy_err:
902 UDP_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); 902 if (!skb_kill_datagram(sk, skb, flags))
903 903 UDP_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
904 skb_kill_datagram(sk, skb, flags);
905 904
906 if (noblock) 905 if (noblock)
907 return -EAGAIN; 906 return -EAGAIN;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 77ab31b99232..87bccec9882a 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -207,8 +207,8 @@ out:
207 return err; 207 return err;
208 208
209csum_copy_err: 209csum_copy_err:
210 UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); 210 if (!skb_kill_datagram(sk, skb, flags))
211 skb_kill_datagram(sk, skb, flags); 211 UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
212 212
213 if (flags & MSG_DONTWAIT) 213 if (flags & MSG_DONTWAIT)
214 return -EAGAIN; 214 return -EAGAIN;