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);