micro patch for udp

David Mosberger-Tang (davidm@cs.arizona.edu)
Wed, 10 Jan 1996 16:17:55 -0700


OK, I finally *did* get sick of not being able to NFS mount the
Cabrio's in our department when it works just fine at home. Turns out
that the UDP checksum is wrong if the destination host has an ip
address with a last byte of >= 128 (in network byteorder, this means
that bit 31 is set... :-) The following patch fixes the problem (and
also makes the "bad checksum" error message look a little nicer). It
should apply to 1.3.52 but I don't recall recent changes to UDP, so
other kernel versions probably work, too.

The exact reason why the checksum was wrong is that the call:

ufh->uh.check = csum_tcpudp_magic(saddr, ufh->daddr,
ntohs(ufh->uh.len),
IPPROTO_UDP, ufh->wcheck);

resulted in ufh->daddr being sign extended because the second argument
to csum_tcpudp_magic() is an "unsigned long" argument.

Cheers,
--david

--- net/ipv4/udp.c~ Wed Jan 10 11:56:38 1996
+++ net/ipv4/udp.c Wed Jan 10 16:02:03 1996
@@ -216,10 +216,10 @@
struct udpfakehdr
{
struct udphdr uh;
- int daddr;
- int other;
+ __u32 daddr;
+ __u32 other;
const char *from;
- int wcheck;
+ __u32 wcheck;
};

/*
@@ -645,8 +645,8 @@
/* the network is concered, anyway) as per 4.1.3.4 (MUST). */

NETDEBUG(printk("UDP: bad checksum. From %08X:%d to %08X:%d ulen %d\n",
- ntohl(saddr),ntohs(uh->source),
- ntohl(daddr),ntohs(uh->dest),
+ (__u32) ntohl(saddr),ntohs(uh->source),
+ (__u32) ntohl(daddr),ntohs(uh->dest),
ulen));
udp_statistics.UdpInErrors++;
kfree_skb(skb, FREE_WRITE);