david@dcl-cs.UUCP (04/07/87)
I'm posting this on behalf of a project student so if anyone has any thoughts on it, could they channel them through me. Thanks. -- INTERNET HEADER CHECKSUM I am having a no doubt trivial problem calculating the header checksum within an internet packet and would be grateful if someone could enlighten me as to my mistake. To calculate the checksum I take each 16-bits within the header ( starting with the version/IHL octet and ending with the octet immediately preceding the data portion of the Internet packet). To each of these I take the 16-bit one's complement and add them all up giving an unsigned 16-bit value. This is then one's complemented to give me the header checksum which is placed in the internet header checksum field (as per the IP spec). When calculating the checksum the checksum field is taken as containing zero. I have applied this procedure to packets taken directly from the network, the final checksum is nothing like what it should be, however, the value before taking the final one's complement is sometimes 7 sometimes 8 lower than what is in the checksum field of the packet read. Any clues? Thanks. -- janet: david@uk.ac.lancs.comp Department of Computing arpa: david@comp.lancs.ac.uk University of Lancaster uucp: ...!mcvax!ukc!dcl-cs!david Bailrigg, Lancaster, LA1 4YR, UK
hans@umd5.UUCP (04/08/87)
In article <328@dcl-csvax.comp.lancs.ac.uk> david@comp.lancs.ac.uk (David Coffield) writes: > >INTERNET HEADER CHECKSUM > >I am having a no doubt trivial problem calculating the header checksum >within an internet packet and would be grateful if someone could enlighten >me as to my mistake. > > ... > > >I have applied this procedure to packets taken directly from the network, >the final checksum is nothing like what it should be, however, the value >before taking the final one's complement is sometimes 7 sometimes 8 lower >than what is in the checksum field of the packet read. > >Any clues? Thanks. >-- You are probably using twos complement addition instead of one's complement addition when computing the sum. The difference lies in what happens to the carry when doing addition: in two's complement it is ignored, in one's com- plement it is added to the sum. For example the sum of the 16-bit octal numbers 07776 and 3 works as follows: Two's complement: 07776 is -2, -2 plus 3 gives 1 07776 + 00003 = 00001 plus carry (which gets ignored) One's complement: 07776 is -1, -1 plus 3 gives 2 07776 + 00003 = 00001 plus carry 00001 + carry = 00002 If you are working on a 32-bit machine, you can just add all the numbers, and then add the two 16-bit fields of the result (plus any carry you get from that addition). There is an additional problem with simulating one's complement in this fashion: If the result is zero, it will usually be minus zero (i.e. 07777) and not plus zero. One's complement hardware usually works by subtracting the complement instead of adding, in which case you get minus zero results only if you start out with a minus zero. I don't know if you have to worry about this special case in IP header checksums.
ron@brl-sem.ARPA (Ron Natalie <ron>) (04/09/87)
In article <328@dcl-csvax.comp.lancs.ac.uk>, david@comp.lancs.ac.uk (David Coffield) writes: > > To calculate the checksum I take each 16-bits within the header > ( starting with the version/IHL octet and ending with the octet immediately > preceding the data portion of the Internet packet). To each of these > I take the 16-bit one's complement and add them all up giving an > unsigned 16-bit value. This is then one's complemented to give me > the header checksum which is placed in the internet header checksum field > (as per the IP spec). You read the spec wrong. The checksum is the ones complement of the ones complement sum of all the values. The ones complement sum is not the twos complement sum of all the numbers ones complemented. When a ones complement number reaches the value 0xFFFF (-0) it must be incremented to 0 (+0) before adding another number to it. In assembler this is easy (if you don't already have ones complement instructions already), if the carry bit it set after an addition, add one to the result. A crude C function would look like this.... (assuming, 16 bit shorts, and > 16 bit longs, I know, silly assumption, but I'm just doing this for illustration) unsigned short header[N]; long tmpsum; int i; short sum; for(i = 0, tmpsum = 0; i < N; i++) { tmpsum += header[i]; if(tmpsum & 0x10000L) tmpsum = (tmpsum & 0xFFFF) + 1; } sum = ~tmpsum; -Ron
henry@utzoo.UUCP (Henry Spencer) (04/12/87)
> To calculate the checksum I take each 16-bits within the header ... > To each of these > I take the 16-bit one's complement and add them all up giving an > unsigned 16-bit value. This is then one's complemented to give me > the header checksum ... (as per the IP spec). The problem is that you have misunderstooding the meaning of the term "one's-complement addition". This does not mean adding the complements of the numbers. One's-complement addition is addition done by treating the 16-bit lumps as numbers in the obsolete one's-complement number representation, rather than the two's-complement representation that most modern computers use. See any good book on digital systems design for the details of what one's-complement representation is all about. The simple way to fake one's-complement addition on a two's-complement machine is to do a regular add and then add the carry to the result; on a 32-bit machine it's often better to do a 32-bit sum of all the 16-bit values and then add the top 16 bits to the bottom 16 (repeating this until the top 16 are zero). -- "We must choose: the stars or Henry Spencer @ U of Toronto Zoology the dust. Which shall it be?" {allegra,ihnp4,decvax,pyramid}!utzoo!henry