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
[-- Attachment #1 --]
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
[-- Attachment #2 --]
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) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001116120936.A45755>
