diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/datagram.c | 9 | ||||
-rw-r--r-- | net/ipv4/udp.c | 5 | ||||
-rw-r--r-- | net/ipv6/udp.c | 4 |
3 files changed, 12 insertions, 6 deletions
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 | ||
222 | void skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags) | 224 | int 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 | ||
236 | EXPORT_SYMBOL(skb_kill_datagram); | 243 | EXPORT_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 | ||
901 | csum_copy_err: | 901 | csum_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 | ||
209 | csum_copy_err: | 209 | csum_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; |