Ip校验是针对ip头部的,即仅校验ip头部,而对于ip数据部分的校验,则交由相应的四次协议来保证, ip 头部中校验和字段为16bit。
计算原理如下:
1.把校验和字段设置为0
2.计算ip头部中所有16bit的字之和
3.将2中得到的和按位取反,得到校验和。
对于ip层协议来说,其校验和只要计算ip头即可,那相对的,对于四层协议来说,其校验和则需要计算四层头部与四层数据。
tcp校验需要将ip伪首部、tcp报头、tcp数据分为16位的字,然后进行累加(如果总长度为奇数个字节,则在最后增添一个位都为0的字节 ),最后对累加的和进行按位取反即可。
Ip伪首部包括源ip地址(4字节)、目的ip地址(4字节)、协议号(两字节)、tcp包长(2字节) ,共14字节。
Udp校验与tcp校验基本上是一致的。
udp校验需要将ip伪首部、udp报头、udp数据分为16位的字,然后进行累加(如果总长度为奇数个字节,则在最后增添一个位都为0的字节 ),最后对累加的和进行按位取反即可。
Ip伪首部包括源ip地址(4字节)、目的ip地址(4字节)、协议号(两字节)、tcp包长(2字节) ,共14字节。
以上就是ip、tcp、udp的校验和的计算原理,如果是我们自己写相应的校验和函数,问题也不是太大,只要根据其计算原理即可。
而在linux中,关于ip、tcp、udp的校验,都有相应的接口函数。
Ip校验和的计算接口函数为:
__inline__ void ip_send_check(struct iphdr *iph)
我们只要传递一个ip头部指针,即可计算该ip头部的checksum,并进行设置checksum操作。
而对于tcp、udp的校验和计算,由于多了一个ip伪首部、协议号、tcp/udp长度的计算,因此需要两个接口函数:
__wsum csum_partial(const void *buff, int len, __wsum sum)
__sum16 csum_tcpudp_magic (__be32 saddr, __be32 daddr, unsigned short len,
unsigned short proto, __wsum sum)
其中csum_partial是计算udp/tcp数据的checksum(即整个tcp或者整个udp头部与数据部分的校验和)
而csum_tcpudp_magic则是将ip伪首部、协议号、tcp/udp长度、以及上述csum_partial计算的udp/tcp数据的checksum,计算udp/tcp最终的checksum。
本文主要是记录tcp、udp、ip校验的原理,以及相应的接口函数,本身没有给出其校验和实现。