前言
这是几年前写的一份txt,大概内容忘了,应该是求证icmp的校验和
文字部分(流程)
发送端
1)将发送的IP头部中的检验和字段设置为0,然后以16位为一个间隔,将IP头部分成许多个16位的字段
2)将第1步获得的所有字段进行二进制相加求和
3)把最终结果取反,也就是0置位1,1置位0,就得到检验和,再将该值填充到IP头部。
接收端
把接收到的IP头部分成16位的间隔
所有字段进行二进制相加求和
结果取反
如果结果为0,说明校验正确
接收方进行校验时,也是对每16位进行二进制反码求和。
接收方计算校验和时的首部与发送方计算校验和时的首部相比,多了一个发送方计算出来的校验和。
因此,如果首部在传输过程中没有发生差错,那么接收方计算的结果应该为全一,因为接收方计算除校验和以外的部分得到值是校验和的反码,再加多出来的校验和当然是全一了。
代码部分
unsigned short checksum(unsigned short *buffer, int size)
{
unsigned long cksum=0;
while(size >1) {
cksum+=*buffer++;
size-=sizeof(unsigned short);
}
if(size) cksum+=*(unsigned short*)buffer;
cksum=(cksum >> 16)+(cksum&0xffff);
cksum+=(cksum >>16);
return (unsigned short)(~cksum);
}
unsigned short checksum(unsigned short *buffer, int size)
{
unsigned long cksum=0; //初始化要校验的校验和
while(size >1) { //将IP首部的内容以16位为单位相加
cksum+=*buffer++;
size-=sizeof(unsigned short);
}
if(size) cksum+=*(unsigned short*)buffer;
cksum=(cksum >> 16)+(cksum&0xffff); //高16位移位到低16位,低16位相加
cksum+=(cksum >>16); //再次移位相加避免进位
return (unsigned short)(~cksum); //返回取反值
}
测试
第一段ICMP包的16进制数值为以下的值,其中00B8为校验和。
4500 003C A5D0 0000 8001 0000
C0A8 0009 C0A8 00B8
第二段ICMP包的16进制数值为以下的值,其中00B8为校验和。
4500 003C A5D0 0000 8001 12DF
C0A8 0009 C0A8 00B8
计算过程如下
4500+003C+A5D0+0000+8001+0000+C0A8+0009+C0A8+00B8=2 ED1E
0002+ED1E
0002+ED1E=ED20 = 1110 1101 0010 0000
~ED20 = 0001 0010 1101 1111 =12DF
4500+003C+A5D0+0000+8001+12DF+C0A8+0009+C0A8+00B8=2 FFFD
0002+FFFD
0002+FFFD=FFFF =1111 1111 1111 1111
~FFFF = 0000 0000 0000 0000
Comments | NOTHING