shithub: riscv

Download patch

ref: 4971db9e32dadf72dff6df6293774df2a4f57a89
parent: 39fb26df70b6d8878953ff18046cdc12817a2e42
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Jun 14 16:48:21 EDT 2018

udp: fix udp checksum

we did not apply the special case to store 0xFFFF (-0)
in the checksum field when the checksum calculation
returned zero. we survived this for v4 as RFC768 states:

> If the computed checksum is zero, it is transmitted as
> all ones (the equivalent in one's complement arithmetic).
>
> An all zero transmitted checksum value means that the
> transmitter generated no checksum (for debuging or for
> higher level protocols that don't care).

for ipv6 however, the checksum is not optional and receivers
would drop packets with a zero checksum.

--- a/sys/src/9/ip/udp.c
+++ b/sys/src/9/ip/udp.c
@@ -190,6 +190,7 @@
 	Fs *f;
 	int version;
 	Routehint *rh;
+	ushort csum;
 
 	upriv = c->p->priv;
 	f = c->p->f;
@@ -260,8 +261,10 @@
 		hnputs(uh4->udplen, ptcllen);
 		uh4->udpcksum[0] = 0;
 		uh4->udpcksum[1] = 0;
-		hnputs(uh4->udpcksum,
-		       ptclcsum(bp, UDP4_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP4_PHDR_SZ));
+		csum = ptclcsum(bp, UDP4_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP4_PHDR_SZ);
+		if(csum == 0)
+			csum = 0xffff;	/* -0 */
+		hnputs(uh4->udpcksum, csum);
 		uh4->vihl = IP_VER4;
 		ipoput4(f, bp, 0, c->ttl, c->tos, rh);
 		break;
@@ -294,8 +297,10 @@
 		hnputs(uh6->udplen, ptcllen);
 		uh6->udpcksum[0] = 0;
 		uh6->udpcksum[1] = 0;
-		hnputs(uh6->udpcksum,
-		       ptclcsum(bp, UDP6_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP6_PHDR_SZ));
+		csum = ptclcsum(bp, UDP6_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP6_PHDR_SZ);
+		if(csum == 0)
+			csum = 0xffff;	/* -0 */
+		hnputs(uh6->udpcksum, csum);
 		memset(uh6, 0, 8);
 		uh6->viclfl[0] = IP_VER6;
 		hnputs(uh6->len, ptcllen);