问题由来
在网络测试中,经常遇到需要构建报文的时候,构建报文就要计算udp和tcp报头的检验和值。
校验和计算算法
报文中udp和tcp头的检验和计算方式是:对数据 (伪首部 + tcp或者udp头(检验和字段设置为0))每2个字节进行整数累积加运行得到总和,如果总和大于ffff,再进行高2个字节和低2个字节的相加,最终得到16位的整数,对该整数按位取反,就能够得到相应的校验和。
这里的数据中包括伪首部,伪首部是由下面的数据组成的。
源ip地址、目的ip地址、00、IP头的协议字段(udp为16进制11、tcp为16进制06)、2个字节的tcp或者udp头部和数据的总长度
也就是说最终计算校验和的数据如下:
源ip地址、目的ip地址、00、IP头的协议字段(udp为16进制11、tcp为16进制06)、2个字节的tcp或者udp头部和数据的总长度、checksum设置为0后的udp或者tcp头数据、tcp报文的数据部分
Tcp头检验和的tcl实现
proc tcp_checksum_calculate {srcip dstip tcpsegment} {
#Produce pseudo tcp header hex
#source ip and destination ip hex
set byteshex ""
foreach ip [list $srcip $dstip] {
foreach byte [split $ip "."] {
append byteshex [format %02x $byte]
}
}
#protocol---tcp:06
append byteshex 0006
#tcp header length + tcp data length, hex
set tcplen [format %04x [expr [string length $tcpsegment] / 2]]
append byteshex $tcplen
#Process tcp data hex
#if tcp data is odd, append 0 byte at the end
if {[expr 0x$tcplen % 2] == 1} { append tcpsegment 00}
#Replace tcp checksum hex into 000
set tcpsegment [string replace $tcpsegment 32 35 0000]
#All the hex data need produce checksum
append byteshex $tcpsegment
#Calculate checksum
set sum_hex [checksum_calculate $byteshex]
return $sum_hex
}
Udp头的检验和的tcl实现
proc udp_checksum_calculate {srcip dstip udpsegment} {
#Produce pseudo udp header hex
#source ip and destination ip hex
set byteshex ""
foreach ip [list $srcip $dstip] {
foreach byte [split $ip "."] {
append byteshex [format %02x $byte]
}
}
#protocol---udp:11
append byteshex 0011
#udp header length + udp data length, hex
set udplen [format %04x [expr [string length $udpsegment] / 2]]
append byteshex $udplen
#Process udp data hex
#if udp data is odd, append 0 byte at the end
if {[expr 0x$udplen % 2] == 1} { append udpsegment 00}
#Replace udp checksum hex into 000
set udpsegment [string replace $udpsegment 12 15 0000]
#All the hex data need produce checksum
append byteshex $udpsegment
#Calculate checksum
set sum_hex [checksum_calculate $byteshex]
return $sum_hex
}