报文校验和计算

计算校验和算法

IP、ICMP、UDP和TCP头都有检验和字段,大小都是16bit,算法基本上是一样的。
发送报文时计算校验和
1、把校验和字段设置为0;
2、把需要校验的数据看成以16位为单位的数字组成,依次进行二进制反码求和;
3、把得到的结果存入校验和字段中。

接收数据时计算检验和
1、把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段;
2、检查结果是否为0;
3、如果等于0,校验和正确;否则,校验和错误,丢弃数据包。

作用范围不同
IP校验和只校验20个字节的IP报头。
ICMP校验和覆盖整个报文(ICMP报头+ICMP数据)。
UDP和TCP校验和不仅覆盖整个报文,还有12个字节的IP伪首部,包括源IP地址(4字节)、目的IP地址(4字节)、协议(2字节)、TCP/UDP包长(2字节)。UDP和TCP报文长度可以是奇数字节,所以在计算校验和时需要在最后增加填充字节0(填充字节只是为了计算校验和,可以不被传送)。

计算tcp校验和代码案例

源IP 10.16.0.9->0x0a100009

目的IP 172.18.0.4->0xac120004

tcp协议是6->0x0006

tcp报文占40字节->0x0028

把tcp校验和e450改成0000,否则结果是0,该场景用于接收端确认校验和是否正确。

#include <stdio.h>

#define data_len 26

unsigned short getChecksum(unsigned short *data) {
    unsigned long sum = 0;
    int i;
    for (i = 0; i < data_len; i++) {
        sum += *data;
        data++;
        sum = (sum >> 16) + (sum & 0xffff);
    }
    return ~sum;
}

int main() {
    unsigned short data[data_len] = {0x0a10, 0x0009, 0xac12, 0x0004, 0x0006, 0x0028, 
    0xa33e, 0x19f2, 0xab45, 0xfbdc, 0x0000, 0x0000, 0xa002, 0x6a40, 0x0000, 0x0000, 0x0204, 0x0550, 0x0402, 0x080a, 0x04c6, 0xda8a, 0x0000, 0x0000, 0x0103, 0x0307};
    printf("%x\t", getChecksum(data));
}

结果是0xe450。

参考资料

https://blog.csdn.net/oceanstudy123/article/details/121677774

https://blog.csdn.net/stone_Yu/article/details/81611067

 

posted on 2023-10-30 08:42  王景迁  阅读(572)  评论(0)    收藏  举报

导航