Chinaunix

标题: IP头校验和的计算 [打印本页]

作者: guhan010    时间: 2007-11-05 18:03
标题: IP头校验和的计算
怎么个计算方法?
我查了一下,但是理解上有点问题.

大家给详细解释下下。
是不是把数据中每个16相加,然后赋值给一个32位数.
然后对该32位数高位+低位(16位),
然后求反呢?

unsigned short csum(unsigned char *addr, int count)
{
           /* Compute Internet Checksum for "count" bytes
            *         beginning at location "addr".
            */

       register long sum = 0;
 
       while( count > 1 )  {
           /*  This is the inner loop */
               sum += * (unsigned short) addr++;
               count -= 2;
       }
 
           /*  Add left-over byte, if any */
       if( count > 0 )
               sum += * (unsigned char *) addr;
 
           /*  Fold 32-bit sum to 16 bits */
       while (sum>>16)
           sum = (sum & 0xffff) + (sum >> 16);
 
       return ~sum;
}





USHORT ip_checksum(USHORT* buffer, int size)
{
unsigned long cksum = 0;

// Sum all the words together, adding the final byte if size is odd

while (size > 1) {
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size) {
cksum += *(UCHAR*)buffer;
}

// Do a little shuffling

cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);

// Return the bitwise complement of the resulting mishmash

return (USHORT)(~cksum);
}




两个的实现上,有什么区别呢?

[ 本帖最后由 guhan010 于 2007-11-5 18:06 编辑 ]
作者: guhan010    时间: 2007-11-06 08:45
拜托大家给我详细解释解释啊.
作者: foolishx    时间: 2007-11-06 11:13
你也真够可以的,呵呵,到网上查一下就知道了。好多解释的呢。

大概就是把这个IP报文拆分成若干个16BIT的单元(不够用0补齐),然后把这些单元当做一个无符号整数进行相加,最后取反。就是这个道理。

取反的主要目的是当对方收到这个报文之后,再用同样的方法进行求和,如果和为0,说明没有差错。
作者: guhan010    时间: 2007-11-06 11:48
不是啊,主要是生成的32位处理的时候,为什么,高位加低位要两次呢?
作者: win_hate    时间: 2007-11-06 12:50
原帖由 guhan010 于 2007-11-6 11:48 发表
不是啊,主要是生成的32位处理的时候,为什么,高位加低位要两次呢?


高 16 位加低 16 位可能有进位,所以多加一次。
作者: foolishx    时间: 2007-11-06 12:52
对于cksum最后那两步
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);

的解释是这样子的:
在IP报文中,存放校验和的那个空间也只有16位,所以,如果cksum的值超过了这个范围的话,也应该用计算校验和的方法进行16BIT相加。这样说你应该明白了吧?




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2