patch-2.3.6 linux/net/ipv4/udp.c

Next file: linux/net/ipv4/utils.c
Previous file: linux/net/ipv4/tcp_ipv4.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.5/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
@@ -5,7 +5,7 @@
  *
  *		The User Datagram Protocol (UDP).
  *
- * Version:	$Id: udp.c,v 1.67 1999/05/27 00:37:50 davem Exp $
+ * Version:	$Id: udp.c,v 1.69 1999/06/09 11:15:31 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -173,7 +173,7 @@
 	return 0;
 }
 
-/* Shared by v4/v6 tcp. */
+/* Shared by v4/v6 udp. */
 unsigned short udp_good_socknum(void)
 {
 	int result;
@@ -763,7 +763,10 @@
 	/* 4.1.3.4. It's configurable by the application via setsockopt() */
 	/* (MAY) and it defaults to on (MUST). */
 
-	err = ip_build_xmit(sk,sk->no_check ? udp_getfrag_nosum : udp_getfrag,
+	err = ip_build_xmit(sk,
+			    (sk->no_check == UDP_CSUM_NOXMIT ?
+			     udp_getfrag_nosum :
+			     udp_getfrag),
 			    &ufh, ulen, &ipc, rt, msg->msg_flags);
 
 out:
@@ -1093,6 +1096,33 @@
 }
 #endif
 
+static int udp_checksum_verify(struct sk_buff *skb, struct udphdr *uh,
+			       unsigned short ulen, u32 saddr, u32 daddr,
+			       int full_csum_deferred)
+{
+	if (!full_csum_deferred) {
+		if (uh->check) {
+			if (skb->ip_summed == CHECKSUM_HW &&
+			    udp_check(uh, ulen, saddr, daddr, skb->csum))
+				return -1;
+			if (skb->ip_summed == CHECKSUM_NONE &&
+			    udp_check(uh, ulen, saddr, daddr,
+				      csum_partial((char *)uh, ulen, 0)))
+				return -1;
+		}
+	} else {
+		if (uh->check == 0)
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+		else if (skb->ip_summed == CHECKSUM_HW) {
+			if (udp_check(uh, ulen, saddr, daddr, skb->csum))
+				return -1;
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+		} else if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+			skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
+	}
+	return 0;
+}
+
 /*
  *	All we need to do is get the socket, and then do a checksum. 
  */
@@ -1134,25 +1164,18 @@
 	}
 	skb_trim(skb, ulen);
 
-#ifndef CONFIG_UDP_DELAY_CSUM
-	if (uh->check &&
-	    (((skb->ip_summed==CHECKSUM_HW)&&udp_check(uh,ulen,saddr,daddr,skb->csum)) ||
-	     ((skb->ip_summed==CHECKSUM_NONE) &&
-	      (udp_check(uh,ulen,saddr,daddr, csum_partial((char*)uh, ulen, 0)))))) 
-		goto csum_error;
+	if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) {
+		int defer;
+
+#ifdef CONFIG_UDP_DELAY_CSUM
+		defer = 1;
 #else
-	if (uh->check==0)
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	else if (skb->ip_summed==CHECKSUM_HW) {
-		if (udp_check(uh,ulen,saddr,daddr,skb->csum)) 
-			goto csum_error;
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	} else if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-		skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
+		defer = 0;
 #endif
-
-	if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
+		if (udp_checksum_verify(skb, uh, ulen, saddr, daddr, defer))
+			goto csum_error;
 		return udp_v4_mcast_deliver(skb, uh, saddr, daddr);
+	}
 
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
 	if (IPCB(skb)->redirport)
@@ -1179,6 +1202,15 @@
 		kfree_skb(skb);
 		return(0);
   	}
+	if (udp_checksum_verify(skb, uh, ulen, saddr, daddr,
+#ifdef CONFIG_UDP_DELAY_CSUM
+				1
+#else
+				(sk->no_check & UDP_CSUM_NORCV) != 0
+#endif
+		))
+		goto csum_error;
+
 	udp_deliver(sk, skb);
 	return 0;
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)