2010-04-05 77 views
3
unsigned short /* this function generates header checksums */ 
csum (unsigned short *buf, int nwords) 
{ 
    unsigned long sum; 
    for (sum = 0; nwords > 0; nwords--) // add words(16bits) together 
    { 
     sum += *buf++; 
    } 
    sum = (sum >> 16) + (sum & 0xffff); //add carry over 
    sum += (sum >> 16);     //MY question: what exactly does this step do??? add possible left-over 
             //byte? But hasn't it already been added in the loop (if 
             //any)? 
    return ((unsigned short) ~sum); 
} 
  1. 我nwords承担16位的字的数量问题,而不是8位字节(如果有奇数个字节,nword四舍五入到下一个大),是正确的吗?说ip_hdr总共有27个字节,那么nword将是14而不是13,对不对?
  2. 总和=(总和>> 16)+(总和& 0xffff)是加进位16位补全
  3. sum + =(sum >> 16);这一步的目的是什么?添加剩余字节?但是,循环中已经添加了剩余的字节?

谢谢!关于IP校验码

+0

可以格式化你的代码一点,好吗? – WhirlWind 2010-04-05 19:19:24

+0

有人需要清理它。 :( – Rev316 2010-04-05 19:19:37

+0

'ip_hdr'不能是27个字节,它们必须是4个字节长的倍数,并且长度必须在20到60个字节之间 - '(4 * ip_hdr-> ip_ihl)',因为'ip_ihl'是一个四位的字段 – Alnitak 2014-11-06 08:46:22

回答

0

你是对的。步骤3将总和(32位长)压缩成16位无符号短路,这是校验和的长度。这是出于性能目的,允许一个计算校验和而不跟踪溢出直到结束。它在步骤2和步骤3都执行此操作,因为它可能已经从步骤2溢出。然后它仅返回反转的低16位和。

这是一个有点清晰: http://www.sysnet.ucsd.edu/~cfleizac/iptcphdr.html

+0

这里的假设是一个long的长度是32位,而一个short的长度是16位,但是有一些平台的两个都不是真的 – 2010-04-05 22:29:38

+0

是的,但这不是平台无关的代码;它在内核中,你知道尺寸是什么,所以这是一个合理的假设。 – WhirlWind 2010-04-06 00:07:44

+0

你可以看到BSD源使用类似的“不可移植”声明:http://fxr.watson.org/fxr/source /netinet/in_cksum.c – WhirlWind 2010-04-06 00:16:39