12.6 如何手动计算ip_sum
https://scz.617.cn/network/200611071801.txt
A: W. Richard Stevens
static unsigned short int in_cksum ( unsigned short int addr, unsigned int len ) { unsigned int nleft = len; unsigned int sum = 0; unsigned short int w = addr; unsigned short int answer = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while ( nleft > 1 )
{
sum += *w++;
nleft -= 2;
}
/*
* 4mop up an odd byte, if necessary
*/
if ( 1 == nleft )
{
*( unsigned char * )( &answer ) = *( unsigned char * )w ;
sum += answer;
}
/*
* 4add back carry outs from top 16 bits to low 16 bits
*/
/*
* add hi 16 to low 16
*/
sum = ( sum >> 16 ) + ( sum & 0xffff );
/*
* add carry
*/
sum += ( sum >> 16 );
/*
* truncate to 16 bits
*/
answer = ~sum;
return( answer );
} / end of in_cksum /
A: xjojox@netexpert 2006-11-07 18:01
以如下IP首部为例:
45 00 00 34 1F CF 40 00 40 06 3C A9 DA F6 BC FD DA 1E 6C 39 ~~~~~ 做如下运算:
45 00
00 34
1F CF
40 00
40 06
3C A9(这个字段不要参与运算)
DA F6
BC FD
DA 1E
+ 6C 39
03 C3 53
将进位加回:
C3 53
+ 03
C3 56
求反码得校验和:
3C A9
D: 2009-11-05 16:28 刘昶
将进位加回:
C3 53
+ 03
C3 56
这一步可能仍有进位,还需要将这个进位加回。最极端的情况是:
FF FF
+ FF FF
01 FF FE
此时的进位最多是1,将32-bits表示的结果右移16位之后加回去即可,不会再次产生 进位:
FF FE
+ 01
FF FF
这个算法基于一个假设,最开始的短整型累加和不会超过0xFFFFFFFF。就IP报文来说 这是可以保证的。即使每一个短整型都是0xFFFF也无所谓,因为ip_len本身是短整型, 限制了IP报文的总字节数,0xFFFF * ( 0xFFFF / 2 ) + 0xFF = 0x7FFE8100。下面 是一种更接近真实的极端情况:
FF FF
FF FF
\
... (0x7FFF个0xFFFF累加,最后再加一个0xFF)
/
FF FF
FF FF
+ FF
7F FE 81 00
将进位加回:
81 00
+ 7F FE
01 00 FE
再次将进位加回:
00 FE
+ 01
00 FF
求反码得校验和:
FF 00