解析IPV4报文 和IPV6 报文的 checksum
解析IPV4报文和IPV6报文的checksum的算法:
校验和(checksum)算法,简单的说就是16位累加的反码运算:
计算函数如下:
我们在计算时是主机字节序,计算的结果封装成IP包时是网络字节序,注意这两者之间的区别,我们在从IP包里读取要转化为主机字节序,往IP包里存入时要转化为网络字节序在存入。
UINT32 Checksum(UINT32 cksum, VOID *pBuffer, UINT32 size)
{
INT8 num = 0;
UINT8 *p = (UINT8 *)pBuffer;
if ((NULL == pBuffer) || (0 == size))
{
return cksum;
}
while (size > 1)
{
cksum += ((UINT16)p[num] << 8 & 0xff00) | (UINT16)p[num + 1] & 0x00FF;
2个字节累加,先取网络字节序低位左移8位(变成主机字节序高位),与(加)上 网络字节序中的高位(主机字节序地位),即网络字节序要先变成主机字节序在进行累加,
size -= 2;
num += 2;
}
if (size > 0)
如果长度为奇数
{
cksum += ((UINT16)p[num] << 8) & 0xFFFF;
如果总的字节数为奇数,则最后一个字节单独相加
num += 1;
}
while (cksum >> 16)
{
cksum = (cksum & 0xFFFF) + (cksum >> 16);
累加完毕将结果中高16位再加到低16位上,重复这一过程直到高16位为全0
}
return cksum;
}
注意:UINT32 cksum的类型,这里是4个字节的,防止在累加的过程中,数据溢出,(例如0xFF累加时就会内存溢出)
详细的计算过程和原理如下
一:
ip头的计算:
直接对头部数据进行累加(不包括原来的checksum值):
1、ipv4包头
ipHeadLen = (pIpHeader->ver_ihl & 0x0F) << 2;
在ipv4头中,版本类型和头长度加在一起是1个字节(8位),各占4位,版本类型在前,长度在后,所以要取长度只能取低4位,
pIpHeader->chksum = 0;
因为不包括原来的checksum值,所以在每次计算前先把checksum的值置0,然后计算
sum = Checksum(0, (VOID *)pIpHeader, ipHeadLen);
对整个ip包头的累加
pIpHeader->chksum = HTONS((UINT16)(~sum));
结果为计算值的反码,(别忘转化为网络字节序)
2、ipv6包头
在ipv6中已经省略了checksum部分,但在后面的部分要有的,比如TCP/UDP包,别高兴的太早
二、
TCP/UDP报文的计算(举例UDP):
这里的checksum包含两部分,一部分是伪头的累加,还有一部分是UDP包的累加(不包括原来的checksum值)
伪头有分ipv4和ipv6两种,分别包含如下几部分,这里做下比较
|
IPV4 |
IPV6 |
|
|
目的地址 |
4字节(32位) |
16字节(128位) |
|
源地址 |
4字节(32位) |
16字节(128位) |
|
协议类型 |
1字节(8位)(Protocol) |
1字节(8位)(next header) |
|
(TCP/UDP)长度 |
2字节(16位) |
2字节(16位) |
1、 ipv4类型的:
第一部分,伪头部分的计算:
sum = 0;
udpLen = sizeof(UDP_HEADER_T) + dhcpLen;
UDP的长度= UDP的包头长度+ UDP的数据长度
sum += udpLen;
或者,下面也是一样的,这里就是网络字节序和主机字节序的区别了,上面的是(主机字节序)直接累加,下面的是网络字节序,一定要变成主机字节序后累加
pUdpHeader->len = HTONS(udpLen);
主机字节序转化为网络字节序,存入数据包中,一定要注意,我们做的所有累加也是网络字节序,这里一定要搞清楚,以防混淆搞错了
sum += (pUdpHeader->len >> 8 & 0x00FF);
2个字节的累加,先取网络字节序的高位,右移8位,变成主机字节序的低位,累加
sum += (pUdpHeader->len << 8 & 0xFF00);
在取网络字节序的低位,左移8位,变成主机字节序的高位,累加
sum = Checksum(sum, (VOID *)&pIpHeader->saddr, 4);
sum = Checksum(sum, (VOID *)&pIpHeader->daddr, 4);
对4位的地址进行累加
sum += ((UINT16)pIpHeader->proto & 0x00FF);
对1位的协议类型进行累加
伪头部分计算完成
第二部分,UDP数据包的计算
pUdpHeader->chksum = 0;
注意:每次计算前别忘先把checksum的值置0,然后计算
sum = Checksum(sum, (VOID *)pUdpHeader, udpLen);
对整个UDP包的累加
pUdpHeader->chksum = HTONS((UINT16)(~sum));
结果为计算值的反码,(别忘转化为网络字节序)
UDP数据包部分计算完成
2、 ipv6类型的:
第一部分,伪头部分的计算:
sum = 0;
udpLen = sizeof(UDP_HEADER_T) + dhcpLen;
sum += udpLen;
或者
pUdpHeader->len = HTONS(udpLen);
sum += (pUdpHeader->len >> 8 & 0x00FF);
sum += (pUdpHeader->len << 8 & 0xFF00);
sum = Checksum(sum, (VOID *)&pIpHeader->saddr, 16);
sum = Checksum(sum, (VOID *)&pIpHeader->daddr, 16);
对16位的地址进行累加
sum += ((UINT16)pIpHeader->proto & 0x00FF);
伪头部分计算完成
第二部分,UDP数据包的计算
pUdpHeader->chksum = 0;
注意:每次计算前别忘先把checksum的值置0,然后计算
sum = Checksum(sum, (VOID *)pUdpHeader, udpLen);
对整个UDP包的累加
pUdpHeader->chksum = HTONS((UINT16)(~sum));
结果为计算值的反码,(别忘转化为网络字节序)
UDP数据包部分计算完成
解析IPV4报文 和IPV6 报文的 checksum的更多相关文章
- 如何设置IPv4和IPv6报文的DSCP值——网络测试仪实操
一.操作说明 在QoS测试中,经常要设置不同优先级的报文,来验证被测设备对于优先级的调度.所以,我们就要了解如何设置IPv6和IPv6报文中的DSCP(大部分使用DSCP值,也会用到TOS值) 这里我 ...
- IP数据报、TCP报文、UDP报文格式
总是记不得TCP/IP协议的各个协议格式,特在此做个记录,好方便回顾. 信息来自众多网络大神们的总结,我再结合自己的理解整理所得. ================================== ...
- ipv4枯竭和ipv6的启用
IPv4是Internet Protocol version 4的缩写,中文翻译为互联网通信协议(TCP/IP协议)第四版,通常简称为网际协议版本4. IPv4使用32位(4字节)地址,因此地址空间中 ...
- spring-boot 使用Aop通知打印控制器请求报文和返回报文
一.简介 开发过程中我们往往需要写许多例如: @GetMapping("/id/get") public Result getById( String id) throws Exc ...
- HTTP的请求报文与响应报文
报文: 简单来说,报文就是也就是HTTP报文,作用是在各个系统之间进行和响应时用来交换与传输的数据单元,即站点一次性要发送的数据块,这些数据块以一些文本形式的元信息开头,这些信息描述了报文的内容及含义 ...
- 【转】非教育网中IPv4网络访问IPv6资源
1. 背景知识 随着个人电脑.移动终端.乃至物联网的不断发展,有很大的IP地址需求.由于IPv4协议设计时没有料到日后网络会如此发达,IPv4网络中的IP数量相对今天的需求来说,显得捉襟见肘.加上IP ...
- 重温Http协议--请求报文和响应报文
http协议是位于应用层的协议,我们在日常浏览网页比如在导航网站请求百度首页的时候,会先通过http协议把请求做一个类似于编码的工作,发送给百度的服务器,然后在百度服务器响应请求时把相应的内容再通过h ...
- 科普:什么是IPV4?什么是IPV6?
IPv4是Internet Protocol version 4(网际协议版本4)的英文简称,而中文简称为“网协版4”. 目前的全球因特网所采用的协议族是TCP/IP协议族.IP是TCP/IP协议族中 ...
- HTTP请求报文与响应报文
http://docs.telerik.com/fiddler/KnowledgeBase/HTTP HTTP请求报文与响应报文 HTTP http://www.w3.org/Protocols/rf ...
随机推荐
- [Xcode 实际操作]九、实用进阶-(18)图像人脸识别:对图片中的人像进行面部检测
目录:[Swift]Xcode实际操作 本文将演示对图片中的人像,进行面部检测. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit //导入 ...
- 在虚拟机中设置NAT模式实现主机和虚拟机的通信
1.打开虚拟机,对几个节点进行网络连接的设置.虚拟机设置/网络连接,选择“NAT模式” 2.编辑—>虚拟网络编辑器来查看NAT模式中所用到的网段. 从上图可以看出,NAT中的子网IP是192.1 ...
- PAT甲级——1123 Is It a Complete AVL Tree (完全AVL树的判断)
嫌排版乱的话可以移步我的CSDN:https://blog.csdn.net/weixin_44385565/article/details/89390802 An AVL tree is a sel ...
- Map集合的四种常用遍历方式整理
1.Map集合简介:map集合是一个key—value型的数据结构,存储的数据具有查询速度快速的特点,但由于是无序的,所以没有顺序可言.在遍历时没有办法像简单的list或数组一样. 2.代码: pac ...
- A.走方格
链接:https://ac.nowcoder.com/acm/contest/368/A 题意: 在一个n*n的方格中,你只能斜着走. 你还有一次上下左右走的机会 给你一个起点(sx,sy),和终点( ...
- SNMP4J 总结
一.SNMP4J介绍 SNMP4J是一个用Java来实现SNMP(简单网络管理协议)协议的开源项目.它支持以命令行的形式进行管理与响应.SNMP4J是纯面向对象设计与SNMP++(用C++实现SNMP ...
- (转载)Unity 优化总结
Unity 优化总结 2017-03-10 | 发布 大海明月 zengfeng75@qq.com | 分类 Unity | 标签 Unity 优化 相关文档 UGUI 降低填充率技巧两则 U ...
- Aop第一节
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...
- 60分钟课程: 用egg.js实现增删改查,文件上传和restfulApi, webpack react es6 (一)
今天开始我将写nodejs框架egg.js, react 实现的增删改查,文件上传等常用的b/s场景,这个将分3部分来写. 会让你在60分钟内快速 入口并应用~ 你应该用es6, node,或是ph ...
- 用vue.js实现购物车功能
购物车是电商必备的功能,可以让用户一次性购买多个商品,常见的购物车实现方式有如下几种: 1. 用户更新购物车里的商品后,页面自动刷新. 2. 使用局部刷新功能,服务器端返回整个购物车的页面html 3 ...