aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r--net/ipv6/udp.c92
1 files changed, 70 insertions, 22 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index ee1cc3f8599f..bd4b9df8f614 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -34,6 +34,7 @@
34#include <linux/ipv6.h> 34#include <linux/ipv6.h>
35#include <linux/icmpv6.h> 35#include <linux/icmpv6.h>
36#include <linux/init.h> 36#include <linux/init.h>
37#include <linux/module.h>
37#include <linux/skbuff.h> 38#include <linux/skbuff.h>
38#include <asm/uaccess.h> 39#include <asm/uaccess.h>
39 40
@@ -50,8 +51,6 @@
50#include <linux/seq_file.h> 51#include <linux/seq_file.h>
51#include "udp_impl.h" 52#include "udp_impl.h"
52 53
53DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
54
55static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) 54static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
56{ 55{
57 return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); 56 return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
@@ -121,6 +120,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
121 struct inet_sock *inet = inet_sk(sk); 120 struct inet_sock *inet = inet_sk(sk);
122 struct sk_buff *skb; 121 struct sk_buff *skb;
123 unsigned int ulen, copied; 122 unsigned int ulen, copied;
123 int peeked;
124 int err; 124 int err;
125 int is_udplite = IS_UDPLITE(sk); 125 int is_udplite = IS_UDPLITE(sk);
126 126
@@ -131,7 +131,8 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
131 return ipv6_recv_error(sk, msg, len); 131 return ipv6_recv_error(sk, msg, len);
132 132
133try_again: 133try_again:
134 skb = skb_recv_datagram(sk, flags, noblock, &err); 134 skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
135 &peeked, &err);
135 if (!skb) 136 if (!skb)
136 goto out; 137 goto out;
137 138
@@ -164,6 +165,9 @@ try_again:
164 if (err) 165 if (err)
165 goto out_free; 166 goto out_free;
166 167
168 if (!peeked)
169 UDP6_INC_STATS_USER(UDP_MIB_INDATAGRAMS, is_udplite);
170
167 sock_recv_timestamp(msg, sk, skb); 171 sock_recv_timestamp(msg, sk, skb);
168 172
169 /* Copy the address. */ 173 /* Copy the address. */
@@ -200,13 +204,17 @@ try_again:
200 err = ulen; 204 err = ulen;
201 205
202out_free: 206out_free:
207 lock_sock(sk);
203 skb_free_datagram(sk, skb); 208 skb_free_datagram(sk, skb);
209 release_sock(sk);
204out: 210out:
205 return err; 211 return err;
206 212
207csum_copy_err: 213csum_copy_err:
208 UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); 214 lock_sock(sk);
209 skb_kill_datagram(sk, skb, flags); 215 if (!skb_kill_datagram(sk, skb, flags))
216 UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite);
217 release_sock(sk);
210 218
211 if (flags & MSG_DONTWAIT) 219 if (flags & MSG_DONTWAIT)
212 return -EAGAIN; 220 return -EAGAIN;
@@ -251,13 +259,14 @@ static __inline__ void udpv6_err(struct sk_buff *skb,
251 struct inet6_skb_parm *opt, int type, 259 struct inet6_skb_parm *opt, int type,
252 int code, int offset, __be32 info ) 260 int code, int offset, __be32 info )
253{ 261{
254 return __udp6_lib_err(skb, opt, type, code, offset, info, udp_hash); 262 __udp6_lib_err(skb, opt, type, code, offset, info, udp_hash);
255} 263}
256 264
257int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) 265int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
258{ 266{
259 struct udp_sock *up = udp_sk(sk); 267 struct udp_sock *up = udp_sk(sk);
260 int rc; 268 int rc;
269 int is_udplite = IS_UDPLITE(sk);
261 270
262 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) 271 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
263 goto drop; 272 goto drop;
@@ -265,7 +274,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
265 /* 274 /*
266 * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c). 275 * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c).
267 */ 276 */
268 if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { 277 if ((is_udplite & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) {
269 278
270 if (up->pcrlen == 0) { /* full coverage was set */ 279 if (up->pcrlen == 0) { /* full coverage was set */
271 LIMIT_NETDEBUG(KERN_WARNING "UDPLITE6: partial coverage" 280 LIMIT_NETDEBUG(KERN_WARNING "UDPLITE6: partial coverage"
@@ -289,13 +298,13 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
289 if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { 298 if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
290 /* Note that an ENOMEM error is charged twice */ 299 /* Note that an ENOMEM error is charged twice */
291 if (rc == -ENOMEM) 300 if (rc == -ENOMEM)
292 UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag); 301 UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, is_udplite);
293 goto drop; 302 goto drop;
294 } 303 }
295 UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); 304
296 return 0; 305 return 0;
297drop: 306drop:
298 UDP6_INC_STATS_BH(UDP_MIB_INERRORS, up->pcflag); 307 UDP6_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite);
299 kfree_skb(skb); 308 kfree_skb(skb);
300 return -1; 309 return -1;
301} 310}
@@ -361,10 +370,21 @@ static int __udp6_lib_mcast_deliver(struct sk_buff *skb, struct in6_addr *saddr,
361 while ((sk2 = udp_v6_mcast_next(sk_next(sk2), uh->dest, daddr, 370 while ((sk2 = udp_v6_mcast_next(sk_next(sk2), uh->dest, daddr,
362 uh->source, saddr, dif))) { 371 uh->source, saddr, dif))) {
363 struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC); 372 struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC);
364 if (buff) 373 if (buff) {
365 udpv6_queue_rcv_skb(sk2, buff); 374 bh_lock_sock_nested(sk2);
375 if (!sock_owned_by_user(sk2))
376 udpv6_queue_rcv_skb(sk2, buff);
377 else
378 sk_add_backlog(sk2, buff);
379 bh_unlock_sock(sk2);
380 }
366 } 381 }
367 udpv6_queue_rcv_skb(sk, skb); 382 bh_lock_sock_nested(sk);
383 if (!sock_owned_by_user(sk))
384 udpv6_queue_rcv_skb(sk, skb);
385 else
386 sk_add_backlog(sk, skb);
387 bh_unlock_sock(sk);
368out: 388out:
369 read_unlock(&udp_hash_lock); 389 read_unlock(&udp_hash_lock);
370 return 0; 390 return 0;
@@ -477,7 +497,12 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
477 497
478 /* deliver */ 498 /* deliver */
479 499
480 udpv6_queue_rcv_skb(sk, skb); 500 bh_lock_sock_nested(sk);
501 if (!sock_owned_by_user(sk))
502 udpv6_queue_rcv_skb(sk, skb);
503 else
504 sk_add_backlog(sk, skb);
505 bh_unlock_sock(sk);
481 sock_put(sk); 506 sock_put(sk);
482 return 0; 507 return 0;
483 508
@@ -523,6 +548,7 @@ static int udp_v6_push_pending_frames(struct sock *sk)
523 struct inet_sock *inet = inet_sk(sk); 548 struct inet_sock *inet = inet_sk(sk);
524 struct flowi *fl = &inet->cork.fl; 549 struct flowi *fl = &inet->cork.fl;
525 int err = 0; 550 int err = 0;
551 int is_udplite = IS_UDPLITE(sk);
526 __wsum csum = 0; 552 __wsum csum = 0;
527 553
528 /* Grab the skbuff where UDP header space exists. */ 554 /* Grab the skbuff where UDP header space exists. */
@@ -538,7 +564,7 @@ static int udp_v6_push_pending_frames(struct sock *sk)
538 uh->len = htons(up->len); 564 uh->len = htons(up->len);
539 uh->check = 0; 565 uh->check = 0;
540 566
541 if (up->pcflag) 567 if (is_udplite)
542 csum = udplite_csum_outgoing(sk, skb); 568 csum = udplite_csum_outgoing(sk, skb);
543 else 569 else
544 csum = udp_csum_outgoing(sk, skb); 570 csum = udp_csum_outgoing(sk, skb);
@@ -554,7 +580,7 @@ out:
554 up->len = 0; 580 up->len = 0;
555 up->pending = 0; 581 up->pending = 0;
556 if (!err) 582 if (!err)
557 UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, up->pcflag); 583 UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, is_udplite);
558 return err; 584 return err;
559} 585}
560 586
@@ -578,7 +604,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
578 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; 604 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
579 int err; 605 int err;
580 int connected = 0; 606 int connected = 0;
581 int is_udplite = up->pcflag; 607 int is_udplite = IS_UDPLITE(sk);
582 int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); 608 int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
583 609
584 /* destination address check */ 610 /* destination address check */
@@ -748,7 +774,7 @@ do_udp_sendmsg:
748 if (final_p) 774 if (final_p)
749 ipv6_addr_copy(&fl.fl6_dst, final_p); 775 ipv6_addr_copy(&fl.fl6_dst, final_p);
750 776
751 if ((err = __xfrm_lookup(&dst, &fl, sk, 1)) < 0) { 777 if ((err = __xfrm_lookup(&dst, &fl, sk, XFRM_LOOKUP_WAIT)) < 0) {
752 if (err == -EREMOTE) 778 if (err == -EREMOTE)
753 err = ip6_dst_blackhole(sk, &dst, &fl); 779 err = ip6_dst_blackhole(sk, &dst, &fl);
754 if (err < 0) 780 if (err < 0)
@@ -988,6 +1014,10 @@ struct proto udpv6_prot = {
988 .hash = udp_lib_hash, 1014 .hash = udp_lib_hash,
989 .unhash = udp_lib_unhash, 1015 .unhash = udp_lib_unhash,
990 .get_port = udp_v6_get_port, 1016 .get_port = udp_v6_get_port,
1017 .memory_allocated = &udp_memory_allocated,
1018 .sysctl_mem = sysctl_udp_mem,
1019 .sysctl_wmem = &sysctl_udp_wmem_min,
1020 .sysctl_rmem = &sysctl_udp_rmem_min,
991 .obj_size = sizeof(struct udp6_sock), 1021 .obj_size = sizeof(struct udp6_sock),
992#ifdef CONFIG_COMPAT 1022#ifdef CONFIG_COMPAT
993 .compat_setsockopt = compat_udpv6_setsockopt, 1023 .compat_setsockopt = compat_udpv6_setsockopt,
@@ -1007,9 +1037,27 @@ static struct inet_protosw udpv6_protosw = {
1007}; 1037};
1008 1038
1009 1039
1010void __init udpv6_init(void) 1040int __init udpv6_init(void)
1041{
1042 int ret;
1043
1044 ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP);
1045 if (ret)
1046 goto out;
1047
1048 ret = inet6_register_protosw(&udpv6_protosw);
1049 if (ret)
1050 goto out_udpv6_protocol;
1051out:
1052 return ret;
1053
1054out_udpv6_protocol:
1055 inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
1056 goto out;
1057}
1058
1059void udpv6_exit(void)
1011{ 1060{
1012 if (inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP) < 0) 1061 inet6_unregister_protosw(&udpv6_protosw);
1013 printk(KERN_ERR "udpv6_init: Could not register protocol\n"); 1062 inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
1014 inet6_register_protosw(&udpv6_protosw);
1015} 1063}