brian@amc-gw.amc.com (Brian Crowley) (01/30/91)
I wonder if someone can't give me some pointers on what I feel should be a simple operation, but one that I just can't seem to get a handle on. I am building an IP packet for transmission over an Ethernet Network. No problem building the packet, big problems getting the IP header checksum to come out correctly! According to the RFC in front of me, the IP header checksum is calculated by treating the IP header as a sequence of 16-bit values, which are added together using one's complement arithmetic, and then the one's complement of the result is used as the checksum. To test my algorithm, I pulled some IP packets off our local network and ran the IP headers through. Alas, the results of my program do not match the checksums stored in the packets! Would some kind soul please send me their algorithm to accomplish this feat? A "C" code fragment, a written algorithm, any help you can give would be appreciated. --------------------------------------------------------------------------- |Brian Crowley | DNS: brian@amc.com | |Applied Microsystems Corp. | UUCP: uunet!amc-gw!brian | |Redmond, WA | ATT: 206-882-2000 Ext. 328 | ---------------------------------------------------------------------------
zweig@cs.uiuc.edu (Johnny Zweig) (01/30/91)
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
kasten@EUROPA.INTERLAN.COM (Frank Kastenholz) (01/30/91)
Brian, look at: RFC 1071 Braden, R.T.; Borman, D.A.; Partridge, C. Computing the Internet checksum. 1988 September; 24 p. (Format: TXT=54941 bytes) (Updated by RFC 1141) Frank Kastenholz Racal Interlan
braden@VENERA.ISI.EDU (01/31/91)
I suggest you look at RFC-1071, republished in CCR April 89. Bob Braden