From owner-freebsd-net Wed Mar 7 7:47:10 2001 Delivered-To: freebsd-net@freebsd.org Received: from whizzo.transsys.com (whizzo.TransSys.COM [144.202.42.10]) by hub.freebsd.org (Postfix) with ESMTP id A727737B71A; Wed, 7 Mar 2001 07:47:06 -0800 (PST) (envelope-from louie@whizzo.transsys.com) Received: from whizzo.transsys.com (localhost.transsys.com [127.0.0.1]) by whizzo.transsys.com (8.11.2/8.11.0) with ESMTP id f27Fl6a00528; Wed, 7 Mar 2001 10:47:06 -0500 (EST) (envelope-from louie@whizzo.transsys.com) Message-Id: <200103071547.f27Fl6a00528@whizzo.transsys.com> X-Mailer: exmh version 2.3.1 01/18/2001 with nmh-1.0.4 To: Ruslan Ermilov Cc: Jonathan Lemon , Jonathan Lemon , net@FreeBSD.ORG X-Image-URL: http://www.transsys.com/louie/images/louie-mail.jpg From: "Louis A. Mamakos" Subject: Re: Delayed checksums commit broke UDP checksum calculation References: <20001116120936.A45755@sunbay.com> <20001116091954.A19895@prism.flugsvamp.com> <20010307123156.A19829@sunbay.com> <200103071440.f27EeYa99809@whizzo.transsys.com> <20010307164822.E97252@sunbay.com> <200103071458.f27EwWa99960@whizzo.transsys.com> <20010307171956.B36537@sunbay.com> In-reply-to: Your message of "Wed, 07 Mar 2001 17:19:56 +0200." <20010307171956.B36537@sunbay.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Wed, 07 Mar 2001 10:47:06 -0500 Sender: owner-freebsd-net@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org > In two's complement arithmetics, yes. What matters here is how the > the real checkers are implemented. For BSD-derived implementations, > this does not matter. I don't know if others really exist. RFC 1624 > is pretty clear on this topic. The usual Internet principle is in place > (from RFC 791): "In general, an implementation must be conservative in > its sending behavior, and liberal in its receiving behavior. That is, > it must be careful to send well-formed datagrams, but must accept any > datagram that it can interpret (e.g., not object to technical errors > where the meaning is still clear)." > To be CONSERVATIVE, the implementation MUST NOT transmit all-zero > computed TCP checksum as all-ones; while they are certainly equivalent > in two's complement arithmetics, but RFC 793 does not grant us to do > this conversion (as opposed to RFC 768), and there may an implementation > exist that computes checksums from scratch using the "shift-and-add-carry" > algorithm to compute the two's complement sum on a non-two's-complement > hardware, and compare the result with what stored in the checksum field. > In this case, +0 and -0 will differ. I disagree on your conservative interpretation of the spec. Here's the text from RFC 793, on TCP, and what it has to say about the checksum computation: Checksum: 16 bits The checksum field is the 16 bit one's complement of the one's complement sum of all 16 bit words in the header and text. If a segment contains an odd number of header and text octets to be checksummed, the last octet is padded on the right with zeros to form a 16 bit word for checksum purposes. The pad is not transmitted as part of the segment. While computing the checksum, the checksum field itself is replaced with zeros. The checksum also covers a 96 bit pseudo header conceptually prefixed to the TCP header. This pseudo header contains the Source Address, the Destination Address, the Protocol, and TCP length. This gives the TCP protection against misrouted segments. This information is carried in the Internet Protocol and is transferred across the TCP/Network interface in the arguments or results of calls by the TCP on the IP. +--------+--------+--------+--------+ | Source Address | +--------+--------+--------+--------+ | Destination Address | +--------+--------+--------+--------+ | zero | PTCL | TCP Length | +--------+--------+--------+--------+ The TCP Length is the TCP header length plus the data length in octets (this is not an explicitly transmitted quantity, but is computed), and it does not count the 12 octets of the pseudo header. For the sake of illustration, assume that you're computing a checksum over segment which contains all zeros. This will produce a sum with a value of zero. When you take the 16 bit one's complement of this value, you end up with 0xFFFF which is supposed to be put into the checksum field. For other segments which you're computing the checksum over, a properly implemented 1's complement arithemetic sum will produce a normalized +0 (0x0000) rather than a negative zero (0xFFFF). So when you get to the step of taking the 1's complement (the logical NOT operation), you'll never start with 0xFFFF to produce a 0x0000 result. Of course the problem is that all these modern systems apparently don't have high-fidelity emulation of 1's complement add operations and are computing a -0 value along the way. > To be LIBERAL, the implementation SHOULD verify checksums by computing > the checksum using the value stored in the checksum field, and comparing > the result with zero, as opposed to computing the checksum from scratch > and comparing with the value stored in the checksum field. But computing a checksum with either 0xffff or 0x0000 WILL produce the same result if you are implementing the Internet 1's complement checksum algorithm correctly. I can assure you that the stack I wrote in 1981, which ran on a 1's complement-based CPU sent TCP checksums with value 0xFFFF in the packet header, and it works Just Fine. I don't see how reading that section of the TCP protocol spec would lead you to believe otherwise. louie To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-net" in the body of the message