Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!zaphod.mps.ohio-state.edu!julius.cs.uiuc.edu!zweig From: zweig@cs.uiuc.edu (Johnny Zweig) Newsgroups: comp.protocols.tcp-ip Subject: Re: IP Header Checksum Calculation Message-ID: <1991Jan30.061814.7382@julius.cs.uiuc.edu> Date: 30 Jan 91 06:18:14 GMT References: <5212@amc-gw.amc.com> Sender: news@julius.cs.uiuc.edu (USENet News) Reply-To: zweig@cs.uiuc.edu Organization: U of Illinois, Dept. of Computer Science, Systems Research Group Lines: 56 Here is the C++ code from my working IP checksum calculation routine: Word16 IPChecksum( octet * datagram, int length ) { // Add all the 16-bit words (in HOST byte-order!) inside a 32-bit word, // so that the carries can all be added in at the end of the // calculation. Notice that, regardless of host byte order, if we // assign the sum to an int16, the byte with the lower address will // be the one with the high order bits (i.e. we never switched them, // even though the host might have regarded the high order // bits as low order when doing the sum -- the end-around carry // takes care of everything!), so casting a pointer to an int16 // as an octet * will cause the assignment to a Word16 to do the // Right Thing. (See RFC 1071 for lots about checksum-computation.) int32 sum = 0; int16 tmp; Word16 num; int16 * foo = (int16 *)datagram; // Add in a 32-bit int (won't overflow): while ( length > 1 ) { sum += *foo++; length -= 2; } // Add left-over byte, if any if ( length > 0 ) { int16 holder; // Make it an int16 so alignment is right char * holderarray = (char*) & holder; holderarray[0] = *foo; holderarray[1] = 0x00; sum += holder; // To make sure there is a zero after that last byte! } // Fold 32-bit sum to 16 bits (while-loop since may have to add twice // if the first addition causes overflow out of lo-order 16 bits) while ( sum >> 16 ) sum = ( sum & 0x0000ffff ) + ( sum >> 16 ); tmp = sum; tmp = ~tmp; num.equals((octet *) &tmp); // Here, then, we've basically casted from octet * to int16 * // and back to octet *; it ends up with the right byte order return( num ); } The class Word16 has operations equals(octet *) and val() which assign from a network-byte-order value pointed to by the point, and return a host byte order value from the word. Octet is just unsigned char, int16 is probably unsigned short int, etc. -Johnny Checksum