Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Nov 2000 12:09:36 +0200
From:      Ruslan Ermilov <ru@FreeBSD.org>
To:        Jonathan Lemon <jlemon@FreeBSD.org>
Cc:        net@FreeBSD.org
Subject:   Delayed checksums commit broke UDP checksum calculation
Message-ID:  <20001116120936.A45755@sunbay.com>

next in thread | raw e-mail | index | archive | help

--mP3DRpeJDSE+ciuQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi!

RFC768> If the computed checksum is zero, it is transmitted as all ones
RFC768> (the equivalent in one's complement arithmetic).  An all zero
RFC768> transmitted checksum value means that the transmitter generated
RFC768> no checksum.

This (0x0000 -> 0xFFFF) apparently got broken in udp_usrreq.c,v 1.65.

--- udp_usrreq.c	1999/12/22 19:13:24	1.64
+++ udp_usrreq.c	2000/03/27 19:14:23	1.65
@@ -688,11 +700,14 @@ udp_output(inp, m, addr, control, p)
 	ui->ui_dport = inp->inp_fport;
-	ui->ui_ulen = ui->ui_len;
+	ui->ui_ulen = htons((u_short)len + sizeof(struct udphdr));
 
 	/*
-	 * Stuff checksum and output datagram.
+	 * Set up checksum and output datagram.
 	 */
-	ui->ui_sum = 0;
 	if (udpcksum) {
-	    if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
-		ui->ui_sum = 0xffff;
+        	ui->ui_sum = in_pseudo(ui->ui_src.s_addr, ui->ui_dst.s_addr,
+		    htons((u_short)len + sizeof(struct udphdr) + IPPROTO_UDP));
+		m->m_pkthdr.csum_flags = CSUM_UDP;
+		m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
+	} else {
+		ui->ui_sum = 0;
 	}


The attached patch should fix this.
Comments?

-- 
Ruslan Ermilov		Oracle Developer/DBA,
ru@sunbay.com		Sunbay Software AG,
ru@FreeBSD.org		FreeBSD committer,
+380.652.512.251	Simferopol, Ukraine

http://www.FreeBSD.org	The Power To Serve
http://www.oracle.com	Enabling The Information Age

--mP3DRpeJDSE+ciuQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=p

Index: ip_output.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.116
diff -u -p -r1.116 ip_output.c
--- ip_output.c	2000/11/01 01:59:28	1.116
+++ ip_output.c	2000/11/16 10:05:06
@@ -974,6 +974,8 @@ in_delayed_cksum(struct mbuf *m)
 	ip = mtod(m, struct ip *);
 	offset = IP_VHL_HL(ip->ip_vhl) << 2 ;
 	csum = in_cksum_skip(m, ip->ip_len, offset);
+	if (m->m_pkthdr.csum_flags & CSUM_UDP && csum == 0)
+		csum = 0xffff;			/* per RFC768 */
 	offset += m->m_pkthdr.csum_data;	/* checksum offset */
 
 	if (offset + sizeof(u_short) > m->m_len) {

--mP3DRpeJDSE+ciuQ--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001116120936.A45755>