I've read a function that does it pretty good, but i can't "translate" it into a human form so i can do it manually.
here's the code:
Code:
unsigned short checksum(unsigned short *ptr, int length){
register int sum = 0;
u_short answer = 0;
register u_short *w = ptr;
register int nleft = len;
while(nleft > 1){
sum += *w++;
nleft -= 2;
}
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}
In theory, the IP checksum is the 16 bit one's complement of the one's complement sum of all 16 bit words in the header, as you may know, not all the IP fields are exactly 16-bit long, so we have to remove and place to sort them in 16 bit words.
We have the following IP packet:
Code:
TS: 18:45:33.398596
IP: 172.16.10.99 > 172.16.10.12
Offset: Hexadecimal dump : Char dump :
------:-----------------------------------------:-----------------
0x0000: 4500 003c 1c46 4000 4006 b1e6 ac10 0a63 E..<.F@.@......c
0x0010: ac10 0a0c ..
Fine, now let's analyze it:
The first byte (45) correspond to the two first fields of the IP header, which are IP Version and Internet Header Length (IHL), so, this values tell us that the IP version used is "4", and the IHL is 5 (which actually is 20, because this field is measured in 32-bit multiples).
The second byte (00) correspond to the Type Of Service IP field (ToS), which means that NORMAL PRECEDENCE is set in this packet.
The next two bytes (003C) correspond to the Total length field of the IP header, which tell us that the total length of the packet is 60 (0x16^3 + 0x16^2 + 3x16^1 + Cx16^0 = 60).
The next two bytes (1C46) correspond to the Identification field, which in this packet is 7238 (1x16^3 + Cx16^2 + 4x16^1 + 6x16^0 = 7238).
The next two bytes (4000) correspond to the flags and fragment offset IP header fields, which are divided in 3 bits for the flags and 13 for the fragment offset. Treating the flags field in 3-bit words, it's value is actually 4 (Don't Fragment), and the value for the fragment offset is obviously zero (000).
The next byte (40) correspond to the Time To Live field (TTL), which actually is 64 (4x16^1 + 0x16^0 = 64).
The next byte (06) correspond to the IP protocol field, which is set to 6, so the packet contains a TCP segment on it's payload.
The next two bytes (B1E6) correspond to the IP header checksum of the packet, we'll calculate this "manually" later, so for us, this fields value is actually zero because we're gonna calculate it just as the "sender" did. When receiving, the calculation used is a different method.
Phew... the next four bytes (ac10 0a63) correspond to the Source IP address field, which is "172.16.10.99", and the next four bytes (ac10 0a0c) correspond to the Destination IP address field, which is "172.16.10.12".
Right, we need to sort all of these fields in 16-bit words and convert them into binary, so, it will be like this:
HEX BINARY
4500 0100010100000000
003c 0000000000111100
1c46 0001110001000110
4000 0100000000000000
4006 0100000000000110
0000 0000000000000000 <- The checksum is set to zero.
ac10 1010110000010000
0a63 0000101001100011
ac10 1010110000010000
0a0c 0000101000001100
Okay, let's add all this numbers one by one:
4500 0100010100000000
003c 0000000000111100
453C 0100010100111100 <-- This is the 1st result.
453C 0100010100111100 <-- First result plus next 16-bit word.
1c46 0001110001000110
6182 0110000110000010 <-- This is the 2nd result.
6182 0110000110000010 <-- Second result plus next 16-bit word.
4000 0100000000000000
A182 1010000110000010 <-- This is the 3rd result.
A182 1010000110000010 <-- Third result plus next 16-bit word.
4006 0100000000000110
E188 1110000110001000 <-- This is the 4th result.
..E188 1110000110001000 <--Fourth result plus next 16-bit word.
..AC10 1010110000010000
18D98 11000110110011000 <-- here we see one odd bit (carry), but we have to keep the checksum in "16-bit" words, so we add that odd bit to the result.
18D98 11000110110011000
.8D99 1000110110011001 <--This is the 5th result.
8D99 1000110110011001 <-- Fifth result plus next 16-bit word.
0A63 0000101001100011
97FC 1001011111111100 <--This is the 6th result.
..97FC 1001011111111100 <-- Sixth result plus next 16-bit word.
..AC10 1010110000010000
1440C 10100010000001100 <-- Again, there is a carry, so we add it.
1440C 10100010000001100
.440D 0100010000001101 <-- This is the 7th result.
440D 0100010000001101 <-- Seventh result plus next 16-bit word
0A0C 0000101000001100
4E19 0100111000011001 <-- Last result.
Here we're not done yet, we have to apply now the last binary operation, which is the one's complement, and the result (the checksum itself) will be:
4E19 0100111000011001
B1E6 1011000111100110 <-- The IP header checksum.
Easy, huh?
No comments:
Post a Comment