Skip to content

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