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