IP校验和字段是用来检验数据传输正确性的。在发送数据时,为了计算IP数据报的校验和,按如下步骤:
(1) 把IP数据报的校验和字段置为0;
(2) 把首部看成以16位为单位的数字组成,依次进行二进制反码求和;
(3) 把得到的结果存入校验和字段中。
在接收方,要验证数据的正确性,按如下步骤:
(1) 把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括检验和字段;
(2) 检查计算出的校验和的结果是否为0;
(3) 如果等于零,说明检验和正确,否则,检验和是错误的,协议栈会抛弃这个数据包。
在一般的协议栈中,这个检验和算法的实现大多为C语言写的,因为C语言不光移植
性好,而且执行效率也高,算法如下:
unsigned short checksum(unsigned short *buf,int nword)
{
unsigned long sum;
for(sum = 0; nword>0; nword--)
Sum+=*buf++;
sum = (sum>>16)+(sum&0xffff);
sum+ = (sum>>16);
return ~sum;
}
举个例子:
IP头数据:
01000101 (17664)
00000000
00000000 01001110
10010101 01010110
00000000 00000000
10000000
00100011
11000110 01100000
00001010 01101000 00000100 00011010
00001010 01101000 00000101 11111111
我们是要运行checksum函数,把返回的sum结果填到checksum字段。
基本过程就是,将IP头部(包括可选项)以32位为单位进行进位加法运算,将得到的结果的低16位和高16相加,然后最终结果取反即我们的checksum。
然后接收方可进行校验。
以上参考:
http://hi.baidu.com/zengzhaonong/blog/item/c933102403bc1530c89559fb.html
下面看看如何在python中实现:
#!usr/bin/python
import readpcapfile
import struct
def IP_headchecksum(IP_head):
checksum = 0
headlen = len(IP_head)
i=0
while i
temp = struct.unpack('!H',IP_head[i:i+2])[0]
checksum = checksum+temp
i = i+2
checksum = (checksum>>16) + (checksum&0xffff)
checksum = checksum+(checksum>>16)
return ~checksum
packet_data =
readpcapfile.rdpcap('C:\\Python25\\code\\pcap\\PcapReader\\pcap\\test_ether.pcap')
# get the first packet of IP field (20 bytes)
tem = packet_data[0][1][14:34]
result = IP_headchecksum(tem)
print result
结果是-65536,是65535的补码。
其中的IP数据包用到了以前写的读取pcap文件的模块。