nicol
驱动大牛
驱动大牛
  • 注册日期2001-11-28
  • 最后登录2009-07-30
  • 粉丝0
  • 关注0
  • 积分45分
  • 威望5点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
阅读:1910回复:8

校验和的调整问题

楼主#
更多 发布于:2003-07-03 19:50
以前一直是全算校验和。但看RFC文档.那里提供了一个校验和的调整算法.
在测试过程中。发现始终不对.
参见RFC3022.
同时在RFC1631中也提到一个算法
两个算发最大的不同.在一个先做反运算.一个先做与运算.
但结果肯定不一样.而且测试结果.......好象都不对....
大家用的什么算法?

RFC[3022]
Void checksumadjust(unsigned char *chksum, unsigned char *optr, int olen,
unsigned char *nptr, int nlen)
/assuming:unsigned char is 8 bits, long is 32 bits.
- chksum points to the chksum in the packet
- optr points to the old data in the packet
- nptr points to the new data in the packet */
{
   long x,old,new;
x=chksum[0]*256+chksum[1];
x=x&0xFFFF;
while(olen)
{
   old = optr[0]*256+optr[1];
optr+=2;
x-=old&oxffff;
if(x<=0 ){ x--; x&=0xffff;}
olen-=2;
}
while(nlen)
{
new=nptr[0]*256+nptr[1];
nptr+=2;
x+= new& 0xffff;
  if(x & 0x10000){ x++; x&=0xffff;}
nlen-=2;
}
x=x& 0xffff;
chksum[0]=x/256;
chksum[1]=x&0xff;
}


RFC[1631]
   void checksumadjust(unsigned char *chksum, unsigned char *optr,
   int olen, unsigned char *nptr, int nlen)
   /* assuming: unsigned char is 8 bits, long is 32 bits.
     - chksum points to the chksum in the packet
     - optr points to the old data in the packet
     - nptr points to the new data in the packet
   */
   {
     long x, old, new;
     x=chksum[0]*256+chksum[1];
     x=~x;
     while (olen) {
       if (olen==1) {
         old=optr[0]*256+optr[1];
         x-=old & 0xff00;
         if (x<=0) { x--; x&=0xffff; }
         break;
       }
       else {
         old=optr[0]*256+optr[1]; optr+=2;
         x-=old & 0xffff;
         if (x<=0) { x--; x&=0xffff; }
         olen-=2;
       }
     }
     while (nlen) {
       if (nlen==1) {
         new=nptr[0]*256+nptr[1];
         x+=new & 0xff00;
         if (x & 0x10000) { x++; x&=0xffff; }
         break;
       }
       else {
         new=nptr[0]*256+nptr[1]; nptr+=2;
         x+=new & 0xffff;
         if (x & 0x10000) { x++; x&=0xffff; }
         nlen-=2;
       }
     }
     x=~x;
     chksum[0]=x/256; chksum[1]=x & 0xff;
   }


在RFC的文档中说明:3022的算法只适用于偶偏移和偶长度.

最新喜欢:

baoyibao99baoyib...
==寂寞骆驼==
nicol
驱动大牛
驱动大牛
  • 注册日期2001-11-28
  • 最后登录2009-07-30
  • 粉丝0
  • 关注0
  • 积分45分
  • 威望5点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-07-03 21:05
靠....折腾半天.....1631的算法是错误的。*(在GOOGLE)讨论区看到的。
==寂寞骆驼==
antspower
驱动中牛
驱动中牛
  • 注册日期2002-10-17
  • 最后登录2010-08-03
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值2点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2003-07-03 21:18
恭喜你,碰到这么幸福的问题 :D :D :D
放弃瘟草,现吃李草
Gong_XG
驱动太牛
驱动太牛
  • 注册日期2002-10-01
  • 最后登录2010-11-25
  • 粉丝0
  • 关注0
  • 积分313分
  • 威望46点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-07-03 21:45
靠....折腾半天.....1631的算法是错误的。*(在GOOGLE)讨论区看到的。


呵呵!!!!!
nicol
驱动大牛
驱动大牛
  • 注册日期2001-11-28
  • 最后登录2009-07-30
  • 粉丝0
  • 关注0
  • 积分45分
  • 威望5点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2003-07-04 02:19
不是吧.各位老大别光看笑话啊.给我调整算法啊。
==寂寞骆驼==
lucy_huiminz
驱动小牛
驱动小牛
  • 注册日期2002-06-18
  • 最后登录2009-02-11
  • 粉丝0
  • 关注0
  • 积分30分
  • 威望6点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2003-07-04 12:54
我也遇到计算校验和的问题,楼主说的“以前一直是全算校验和”是不是指的计算tcp,ip头部校验和啊?我正被这个问题搞得教头兰额,能帮我看看么?


1、ip包头进行校验和计算时,输入CheckSum的参数addr应该是ip包头内容,而且将其中的checksum两个字节
      置0;

2、tcp包头进行校验和计算时,输入CheckSum的参数addr应该是tcp伪头部+tcp包头内容+数据,而且将其中
      的checksum两个字节置0;

      2.1      其中:psd_header为tcp伪头部结构,PacketLen为得到的包的总长度,34是以太网头长度+ip头长度

                                                                  psd_header.saddr=htonl(p_ip->sourceIP) ;
                                                                  psd_header.daddr=htonl(p_ip->destIP );
                                                                  psd_header.mbz=0;
                                                                  psd_header.ptcl=6;
                                                                  psd_header.tcpl=htons((unsigned short)(PacketLen-34));

                 整个包中是不是包括以太网尾呢?我是不是应该总长度减去38呢?
    
      2.2      tcp包头内容+数据是不是整个包去掉以太网头和ip头?

3、如果我收到一个包不把tcp包头的checksum两字节置0,直接按照上述办法计算checksum,是不是得到的值
      应该为0?
antspower
驱动中牛
驱动中牛
  • 注册日期2002-10-17
  • 最后登录2010-08-03
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值2点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2003-07-04 17:11
我也遇到计算校验和的问题,楼主说的“以前一直是全算校验和”是不是指的计算tcp,ip头部校验和啊?我正被这个问题搞得教头兰额,能帮我看看么?


1、ip包头进行校验和计算时,输入CheckSum的参数addr应该是ip包头内容,而且将其中的checksum两个字节
      置0;

2、tcp包头进行校验和计算时,输入CheckSum的参数addr应该是tcp伪头部+tcp包头内容+数据,而且将其中
      的checksum两个字节置0;

      2.1      其中:psd_header为tcp伪头部结构,PacketLen为得到的包的总长度,34是以太网头长度+ip头长度

                                                                  psd_header.saddr=htonl(p_ip->sourceIP) ;
                                                                  psd_header.daddr=htonl(p_ip->destIP );
                                                                  psd_header.mbz=0;
                                                                  psd_header.ptcl=6;
                                                                  psd_header.tcpl=htons((unsigned short)(PacketLen-34));

                 整个包中是不是包括以太网尾呢?我是不是应该总长度减去38呢?
    
      2.2      tcp包头内容+数据是不是整个包去掉以太网头和ip头?

3、如果我收到一个包不把tcp包头的checksum两字节置0,直接按照上述办法计算checksum,是不是得到的值
      应该为0?


虽然已经重复N次了!,但是决定在重复一次
1.你的说法是对的。
2。你的说法也是对的。但是;
2。1,错在TCP/IP协议中,包中已经包含足够多的信息。你为什么不
用IP包中自带的数据,你的方法虽然也是对的,但是为什么把简单的问题复杂话,而且也不安全。IP包的长度是,HTONS(iphdr->tot_length)
ip头的长度包括可选部分为:(iphdr->hdrlen)<<2

                                                                  psd_header.saddr=htonl(p_ip->sourceIP) ;//??为什么要
//转顺序
                                                                  psd_header.daddr=htonl(p_ip->destIP ); //????
                                                                  psd_header.mbz=0;
                                                                  psd_header.ptcl=6;
                                                                  psd_header.tcpl=htons((unsigned short)(PacketLen-34));
//psd_header.tcpl = HTONS(HTONS(iphdr->tot_length)-
(iphdr->hdrlen)<<2)
2。2是对的。
放弃瘟草,现吃李草
lucy_huiminz
驱动小牛
驱动小牛
  • 注册日期2002-06-18
  • 最后登录2009-02-11
  • 粉丝0
  • 关注0
  • 积分30分
  • 威望6点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2003-07-07 22:13
那么我在调用函数CheckSum时,第二个参数是(PacketLen-34)对么?
guitar_string
驱动牛犊
驱动牛犊
  • 注册日期2003-06-04
  • 最后登录2004-06-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2003-07-10 09:17
IP CHECKSUM CALCULATION

The IP Header Checksum is computed on the header fields only.
Before starting the calculation, the checksum fields (octets 11 and 12)
are made equal to zero.

In the example code,
u16 buff[] is an array containing all octets in the header with octets 11 and 12 equal to zero.
u16 len_ip_header is the length (number of octets) of the header.



/*
**************************************************************************
Function: ip_sum_calc
Description: Calculate the 16 bit IP sum.
***************************************************************************
*/
typedef unsigned short u16;
typedef unsigned long u32;

u16 ip_sum_calc(u16 len_ip_header, u16 buff[])
{
u16 word16;
u32 sum=0;
u16 i;
    
// make 16 bit words out of every two adjacent 8 bit words in the packet
// and add them up
for (i=0;i<len_ip_header;i=i+2){
word16 =((buff<<8)&0xFF00)+(buff[i+1]&0xFF);
sum = sum + (u32) word16;
}

// take only 16 bits out of the 32 bit sum
while (sum>>16)
 sum = (sum & 0xFFFF)+(sum >> 16);

// one\'s complement the result
sum = ~sum;

return ((u16) sum);
}


不用加分了,各位大侠看看guitar_string的问题吧,如果能给些建议非常感谢!
游客

返回顶部