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

Next file: linux/net/netlink/af_netlink.c
Previous file: linux/net/ipv6/tcp_ipv6.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.123/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
@@ -7,7 +7,7 @@
  *
  *	Based on linux/ipv4/udp.c
  *
- *	$Id: udp.c,v 1.35 1998/09/07 00:13:57 davem Exp $
+ *	$Id: udp.c,v 1.36 1998/10/03 09:38:54 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -332,32 +332,22 @@
   	struct sk_buff *skb;
   	int copied, err;
 
-	/*
-	 *	Check any passed addresses
-	 */
-	 
-  	if (addr_len) 
+  	if (addr_len)
   		*addr_len=sizeof(struct sockaddr_in6);
   
-	/*
-	 *	From here the generic datagram does a lot of the work. Come
-	 *	the finished NET3, it will do _ALL_ the work!
-	 */
+	if (flags & MSG_ERRQUEUE)
+		return ipv6_recv_error(sk, msg, len);
 
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
 		goto out;
-  
+
  	copied = skb->len - sizeof(struct udphdr);
   	if (copied > len) {
   		copied = len;
   		msg->msg_flags |= MSG_TRUNC;
   	}
 
-  	/*
-  	 *	FIXME : should use udp header size info value 
-  	 */
-  	 
 #ifndef CONFIG_UDP_DELAY_CSUM
 	err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), 
 				      msg->msg_iov, copied);
@@ -395,7 +385,7 @@
 #endif
 	if (err)
 		goto out_free;
-	
+
 	sk->stamp=skb->stamp;
 
 	/* Copy the address. */
@@ -445,26 +435,25 @@
 
 	sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, dev->ifindex);
    
-	if (sk == NULL) {
-		if (net_ratelimit())
-			printk(KERN_DEBUG "icmp for unknown sock\n");
+	if (sk == NULL)
 		return;
-	}
 
-	if (icmpv6_err_convert(type, code, &err)) {
-		if(sk->bsdism && sk->state!=TCP_ESTABLISHED)
-			return;
-		
-		sk->err = err;
-		sk->error_report(sk);
-	} else {
-		sk->err_soft = err;
-	}
+	if (!icmpv6_err_convert(type, code, &err) &&
+	    !sk->net_pinfo.af_inet6.recverr)
+		return;
+
+	if (sk->bsdism && sk->state!=TCP_ESTABLISHED)
+		return;
+
+	if (sk->net_pinfo.af_inet6.recverr)
+		ipv6_icmp_error(sk, skb, err, uh->dest, ntohl(info), (u8 *)(uh+1));
+
+	sk->err = err;
+	sk->error_report(sk);
 }
 
 static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
 {
-
 	if (sock_queue_rcv_skb(sk,skb)<0) {
 		udp_stats_in6.UdpInErrors++;
 		ipv6_statistics.Ip6InDiscards++;
@@ -768,6 +757,11 @@
 	       
 		udh.uh.dest = sin6->sin6_port;
 		daddr = &sin6->sin6_addr;
+
+		/* Otherwise it will be difficult to maintain sk->dst_cache. */
+		if (sk->state == TCP_ESTABLISHED &&
+		    !ipv6_addr_cmp(daddr, &sk->net_pinfo.af_inet6.daddr))
+			daddr = &sk->net_pinfo.af_inet6.daddr;
 	} else {
 		if (sk->state != TCP_ESTABLISHED)
 			return(-ENOTCONN);
@@ -785,6 +779,7 @@
 		sin.sin_addr.s_addr = daddr->s6_addr32[3];
 		sin.sin_port = udh.uh.dest;
 		msg->msg_name = (struct sockaddr *)(&sin);
+		msg->msg_namelen = sizeof(sin);
 
 		return udp_sendmsg(sk, msg, ulen);
 	}
@@ -806,7 +801,7 @@
 		udh.daddr = daddr;
 
 	udh.uh.source = sk->sport;
-	udh.uh.len = len < 0x1000 ? htons(len) : 0;
+	udh.uh.len = len < 0x10000 ? htons(len) : 0;
 	udh.uh.check = 0;
 	udh.iov = msg->msg_iov;
 	udh.wcheck = 0;

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