解析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的更多相关文章

  1. 如何设置IPv4和IPv6报文的DSCP值——网络测试仪实操

    一.操作说明 在QoS测试中,经常要设置不同优先级的报文,来验证被测设备对于优先级的调度.所以,我们就要了解如何设置IPv6和IPv6报文中的DSCP(大部分使用DSCP值,也会用到TOS值) 这里我 ...

  2. IP数据报、TCP报文、UDP报文格式

    总是记不得TCP/IP协议的各个协议格式,特在此做个记录,好方便回顾. 信息来自众多网络大神们的总结,我再结合自己的理解整理所得. ================================== ...

  3. ipv4枯竭和ipv6的启用

    IPv4是Internet Protocol version 4的缩写,中文翻译为互联网通信协议(TCP/IP协议)第四版,通常简称为网际协议版本4. IPv4使用32位(4字节)地址,因此地址空间中 ...

  4. spring-boot 使用Aop通知打印控制器请求报文和返回报文

    一.简介 开发过程中我们往往需要写许多例如: @GetMapping("/id/get") public Result getById( String id) throws Exc ...

  5. HTTP的请求报文与响应报文

    报文: 简单来说,报文就是也就是HTTP报文,作用是在各个系统之间进行和响应时用来交换与传输的数据单元,即站点一次性要发送的数据块,这些数据块以一些文本形式的元信息开头,这些信息描述了报文的内容及含义 ...

  6. 【转】非教育网中IPv4网络访问IPv6资源

    1. 背景知识 随着个人电脑.移动终端.乃至物联网的不断发展,有很大的IP地址需求.由于IPv4协议设计时没有料到日后网络会如此发达,IPv4网络中的IP数量相对今天的需求来说,显得捉襟见肘.加上IP ...

  7. 重温Http协议--请求报文和响应报文

    http协议是位于应用层的协议,我们在日常浏览网页比如在导航网站请求百度首页的时候,会先通过http协议把请求做一个类似于编码的工作,发送给百度的服务器,然后在百度服务器响应请求时把相应的内容再通过h ...

  8. 科普:什么是IPV4?什么是IPV6?

    IPv4是Internet Protocol version 4(网际协议版本4)的英文简称,而中文简称为“网协版4”. 目前的全球因特网所采用的协议族是TCP/IP协议族.IP是TCP/IP协议族中 ...

  9. HTTP请求报文与响应报文

    http://docs.telerik.com/fiddler/KnowledgeBase/HTTP HTTP请求报文与响应报文 HTTP http://www.w3.org/Protocols/rf ...

随机推荐

  1. 51nod1276(xjb)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1276 题意:中文题诶- 思路:xjb 通过画图可以发现对于当前 ...

  2. 阿里巴巴开源性能监控神器Arthas初体验

    如果问性能测试中最难的是哪部分,相信很多人会说“性能调优”.确实是这样,性能调优是一个非常复杂.技术含量很高的工作.涉及到的知识面很广.以我多年从业经验来看,在企业里,大多数的性能调优都是由开发架构师 ...

  3. PJzhang:最基本的正则表达式实例

    猫宁!!! 参考链接: https://www.cnblogs.com/fozero/p/7868687.html http://tool.oschina.net/regex/# http://too ...

  4. redis集群模式

    1 弊端和优势 弊端:相比单机模式,集群模式会在节点之间同步数据,会降低20%-30%的性能,同时增加架构复杂性,提高硬件成本和学习成本. 优势:增加冗余,避免单点故障.单机模式如果要重启,必然会丢失 ...

  5. scrapy框架中选择器的用法

    scrapy框架中选择器的用法 Scrapy提取数据有自己的一套机制,被称作选择器(selectors),通过特定的Xpath或者CSS表达式来选择HTML文件的某个部分Xpath是专门在XML文件中 ...

  6. 牛客网Java刷题知识点之方法覆盖(方法重写)和方法重载的区别

    不多说,直接上干货! https://www.nowcoder.com/ta/review-java/review?query=&asc=true&order=&page=6 ...

  7. web移动端滑动插件

    1.slip只有6.3k可以说是非常小了,主要是通过css3里面的transform来改变的位置,控制的是父容器,使用也非常简单,具体信息移步slip.js.一个简单的demo如下 <!DOCT ...

  8. DBAplus社群线上分享----Sharding-Sphere之Proxy初探

    功能 Cobar Mycat Heisenberg Shark TDDL Sharding-JDBC 是否开源 开源 开源 开源 开源 部分开源 开源 架构模型 Proxy架构 Proxy架构 Pro ...

  9. asp.net,监听输入框值的即时变化onpropertychange、oninput

    作者:自由天堂发布站点:WEB六零零 网页设计制作原文地址:http://www.web600.net/html/editor/JavaScript/201001131529.html 要达到的效果 ...

  10. 借助sass的Maps功能使得响应式代码更有条理

    原文来自这里 本文综合了原文(by Jonathan Suh)以及笔者自己的理解. Introduction 众所周知,写代码与写维护性高的代码是两回事.而涉及到响应式,代码又特别容易变的杂乱.借助s ...