patch-2.1.89 linux/net/ipv6/udp.c

Next file: linux/net/ipx/af_ipx.c
Previous file: linux/net/ipv6/sysctl_net_ipv6.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.88/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
@@ -300,10 +300,8 @@
 int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, int len,
 		  int noblock, int flags, int *addr_len)
 {
-  	int copied = 0;
-  	int truesize;
   	struct sk_buff *skb;
-  	int err;
+  	int copied, err;
 
 	/*
 	 *	Check any passed addresses
@@ -318,16 +316,13 @@
 	 */
 	 	
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
-	if(skb==NULL)
-  		return err;
+	if (!skb)
+		goto out;
   
- 	truesize=ntohs(((struct udphdr *)skb->h.raw)->len) - sizeof(struct udphdr);
-  	
-  	copied=truesize;
-
-  	if(copied>len) {
-  		copied=len;
-  		msg->msg_flags|=MSG_TRUNC;
+ 	copied = ntohs(((struct udphdr *)skb->h.raw)->len) - sizeof(struct udphdr);
+  	if (copied > len) {
+  		copied = len;
+  		msg->msg_flags |= MSG_TRUNC;
   	}
 
   	/*
@@ -337,7 +332,7 @@
 	err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), 
 				      msg->msg_iov, copied);
 	if (err)
-		return err; 
+		goto out_free;
 	
 	sk->stamp=skb->stamp;
 
@@ -346,7 +341,6 @@
 		struct sockaddr_in6 *sin6;
 	  
 		sin6 = (struct sockaddr_in6 *) msg->msg_name;
-		
 		sin6->sin6_family = AF_INET6;
 		sin6->sin6_port = skb->h.uh->source;
 
@@ -361,9 +355,12 @@
 				datagram_recv_ctl(sk, msg, skb);
 		}
   	}
-	
-  	skb_free_datagram(sk, skb);
-  	return(copied);
+	err = copied;
+
+out_free:
+	skb_free_datagram(sk, skb);
+out:
+	return err;
 }
 
 void udpv6_err(int type, int code, unsigned char *buff, __u32 info,
@@ -409,7 +406,7 @@
 	return 0;
 }
 
-static int __inline__ inet6_mc_check(struct sock *sk, struct in6_addr *addr)
+static __inline__ int inet6_mc_check(struct sock *sk, struct in6_addr *addr)
 {
 	struct ipv6_mc_socklist *mc;
 		
@@ -457,6 +454,7 @@
 {
 	struct sock *sk, *sk2;
 
+	SOCKHASH_LOCK();
 	sk = udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)];
 	sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr);
 	if(sk) {
@@ -465,7 +463,7 @@
 					       uh->dest, saddr,
 					       uh->source, daddr))) {
 			struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC);
-			if(sock_queue_rcv_skb(sk, buff) < 0) {
+			if (buff && sock_queue_rcv_skb(sk2, buff) < 0) {
 				buff->sk = NULL;
 				kfree_skb(buff);
 			}
@@ -475,6 +473,7 @@
 		skb->sk = NULL;
 		kfree_skb(skb);
 	}
+	SOCKHASH_UNLOCK();
 }
 
 int udpv6_rcv(struct sk_buff *skb, struct device *dev,

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov