阅读:1910回复:8
校验和的调整问题
以前一直是全算校验和。但看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的算法只适用于偶偏移和偶长度. |
|
最新喜欢:baoyib...
|
沙发#
发布于:2003-07-03 21:05
靠....折腾半天.....1631的算法是错误的。*(在GOOGLE)讨论区看到的。
|
|
|
板凳#
发布于:2003-07-03 21:18
恭喜你,碰到这么幸福的问题 :D :D :D
|
|
|
地板#
发布于:2003-07-03 21:45
靠....折腾半天.....1631的算法是错误的。*(在GOOGLE)讨论区看到的。 呵呵!!!!! |
|
地下室#
发布于:2003-07-04 02:19
不是吧.各位老大别光看笑话啊.给我调整算法啊。
|
|
|
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? |
|
6楼#
发布于:2003-07-04 17:11
我也遇到计算校验和的问题,楼主说的“以前一直是全算校验和”是不是指的计算tcp,ip头部校验和啊?我正被这个问题搞得教头兰额,能帮我看看么? 虽然已经重复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是对的。 |
|
|
7楼#
发布于:2003-07-07 22:13
那么我在调用函数CheckSum时,第二个参数是(PacketLen-34)对么?
|
|
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的问题吧,如果能给些建议非常感谢! |
|