`
xitong
  • 浏览: 6197483 次
文章分类
社区版块
存档分类
最新评论

TCP校验值的伪头以及校验值计算

 
阅读更多

tcp层的校验值难道还需要ip层的元数据也就是ip头吗?如果一切都是理想的显然不需要,因为这违背了分层隔离的原则,下层一定不能依赖上层,但是上层可以访问下层,还好tcp使用ip信息正是这一点。按照封包原则,封装到TCP层的时候,ip信息还没有封装上去,但是校验值却需要马上进行计算,所以必须手工构造一个伪头部来表示ip层的信息,怎么构造呢?在数据到tcp层的时候其实用户肯定知道数据发往何处,源地址和目的地址都有,只不过是还没有封装到数据上罢了,简单的例子就是在socket程序中,connect或者accept或者recvfrom以及sendto都会保留有地址信息,另外伪头中还将保留有传输层协议信息,所有这一切都是为了使得通信更加安全和缜密,试想如果一个中间人截获了一个icmp包,然后改为了udp包或发生什么,该udp不是随意的而是精心构造的,但是加入了伪头部如此之行为得逞就困难多了,因为伪头部中有协议字段,除此之外,任何错误的投递,错误的数据长度以及错误的协议都会被检测到。看一下伪头吧:

struct psd_head

{

__u32 saddr; // 源网络层地址

__u32 daddr; // 目的网络层地址

__u8 mbz; //赋0

__u8 ptcl; // 传输层协议

__u16 tcpudpl; //传输层长度

};

以下是一个简单的校验和校验码的计算函数

void tcpv4_check_addr( __u16 * ppkgdata )

{

char * indata;

__u16 ippktlen, udppktlen,tcppktlen,wd;

__u32 ipheadlen;

__u32 sum,i,pl,el;

struct psd_head psd;

struct iphdr * ipd;

struct tcphdr * tcpd;

struct udphdr * udpd;

__u16 * databegin;

indata = (char *)ppkgdata; //从MAC开始的整个帧

ipheadlen = 14 + (indata[14]&0x0f)*4 ; //MAC和ip头的长度和

databegin = (__u16 *)(indata + ipheadlen); //ip数据

ipd = (struct iphdr *)(indata + 14); //MAC数据

tcpd = (struct tcphdr *)(indata + ipheadlen); //ip数据

ippktlen = htons(ipd->tot_len); //ip头和ip数据的总长度

if(ipd->protocol == 0x6){

tcppktlen = ippktlen +14 - ipheadlen; //tcp头和tcp数据的总长度

tcpd->check = 0;

psd.saddr = ipd->saddr; //构造伪头部

psd.daddr = ipd->daddr;

psd.mbz=0;

psd.ptcl = 0x06; //ip的下一个头

psd.tcpudpl = htons(tcppktlen);

sum = 0;

wd = tcppktlen/2; //每次数据前移16位而不是一个字节

for(i=0;i<wd><p>sum += *databegin;</p> <p>databegin++;</p> <p>}</p> <p>el = tcppktlen - wd*2;</p> <p>if(el != 0)</p> <p>sum += (*databegin&amp;0xff);</p> <p>wd = sizeof(struct psd_head)/2;</p> <p>databegin = (__u16 *) &amp;psd.saddr;</p> <p>for(i=0;i<wd><p>sum += *databegin;</p> <p>databegin++;</p> <p>}//下面这个表达式就是高低16分别相加,sum/65536就是高16位:sum </p> <p>pl = (sum + sum/65536)&amp;0xffff;</p> <p>sum = 0xffff^pl; </p> <p>tcpd-&gt;check = (__u16)sum; //检验和的计算很简单,就是将数据相加并且回卷之后取反</p> <p>}</p> <p>return;</p> <p>}</p> <p>以上的算法再清晰不过了,甚至将tcp,ip头部的偏移怎么计算都表达了出来,但是这个函数并不适用于实际情况,因为在高负载网络环境下,特别是NAT或者数据过滤网关环境下,校验和的计算是一个很频繁的过程,因此上述函数的c语言本质将很影响效率,取而代之的是用汇编实现,正如linux内核中的那样:</p> <p>static inline __sum16 csum_fold(__wsum sum)</p> <p>{</p> <p>__asm__(</p> <p>"addl %1, %0 ;/n"</p> <p>"adcl $0xffff, %0 ;/n"</p> <p>: "=r" (sum)</p> <p>: "r" ((__force u32)sum </p> <p>"" ((__force u32)sum &amp; 0xffff0000)</p> <p>);</p> <p>return (__force __sum16)(~(__force u32)sum &gt;&gt; 16);</p> <p>}</p> <p>static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, __wsum sum)</p> <p>{</p> <p>__asm__(</p> <p>"addl %1, %0 ;/n"</p> <p>"adcl %2, %0 ;/n"</p> <p>"adcl %3, %0 ;/n"</p> <p>"adcl $0, %0 ;/n"</p> <p>: "=r" (sum)</p> <p>: "g" (daddr), "g"(saddr), "g"((len + proto) </p> <p>return sum;</p> <p>}</p> <p>static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, __wsum sum)</p> <p>{</p> <p>return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));</p> <p>}</p> <p>别看一个小小的计算校验和,它本质上影响了网络传输的效率,如果用tcpv4_check_addr这个函数计算校验和,效率慢了10倍之多,但是用汇编取而代之的话,效率虽然由于额外吸收而有所下降,但是数量级并没有改变。</p> </wd></p></wd>

分享到:
评论

相关推荐

    计算机网络课程设计发送TCP数据包.doc

    计算校验和的子函数 在填充数据包的过程中,需要调用计算校验和的函数checksum两次,分别用于校验IP头 和TCP头部(加上伪头部),其实现代码如下: USHORT checksum(USHORT *buffer, int size) { unsigned long ...

    CODESYS ST语言实现MODBUS CRC校验

    MODBUS库有许多,但要想自己调度MODBUS通讯,就需要自己计算CRC,该文介绍CRC的ST语言实现。

    单片机的TCP.doc

    " "TCP/IP协议的最底层IP层,很多定义都是16位或32位的,例如源IP地址 " "(32位)目的IP地址(32位),校验值(16位),特别是较验值,是以1" "6位为单位进行计算的,这样使得能够处理16位、32位运算的CPU,比如8...

    ModBus TCP Test.zip

    MODBUS/TCP 使MODBUS_RTU协议运行于以太网,MODBUS TCP使用TCP/IP和以太网在站点间传送MODBUS报文,MODBUS TCP结合了以太网物理网络和网络标准TCP/IP以及以MODBUS作为应用协议标准的数据表示方法。MODBUS TCP通信...

    USR-TCP232-Test

    USR-TCP232-Test ,串口转网络调试助手:TCP/IP网络调试助手...5. 支持追加校验功能,和校验,累加和取反校验,固定值。 6. 可以将接收到的数据存入文件,可以通过文件输入数据到发送区。 7. 支持接收结果自动换行显示

    USR-TCP232-Test-V1.3

    【软件关键特点】: 1. 有人串口调试助手和网络调试助手...5. 支持追加校验功能,和校验,累加和取反校验,固定值。 6. 可以将接收到的数据存入文件,可以通过文件输入数据到发送区。 7. 支持接收结果自动换行显示

    计算机网络课程设计--数据包发送和接受程序的实现.doc

    校验和:该字段长度为16位,校验和的校验范围包括伪头部,TCP报头以及应用层来 的数据。其计算方法与IP协议头部校验和的计算方法一样。伪头部为12B,它本身并不是 TCP数据包的真头部,只是在计算校验和时,临时和...

    网际校验和算法VC源码

    校验和算法描述:为保证网络上传输的数据的可靠性,在许多协议中都设置了校验和项,例如:IPv4、ICMPv4、IGMPV4、ICMPv6、UDP和TCP 等等。计算这些校验和的算法称为网际校验和算法,简单来说就是:把被校验的数据16...

    TCP串口调试软件

    用于TCP,串口代码调试让您爱不释手的专业串口调试软件,使用完全免费! 本软件可以在Win95/98、Win2000、WinNT、WinXP下面运行.软件功能主要为: 1.接收从串口进来的数据并在窗口显示. 2.所接收到的数据数据显示方式...

    TCP拦截和网络地址转换

    TCP拦截和网络地址转换 本书将讨论与访问表相关的技术,而非访问表本身。这些技术提供了控制网络中数据流 量的附加功能。这些功能特性会使读者能够加强进出网络报文的附加功能。通过智能地对数 据本身进行操作,...

    GET计算机网络作业七及解答.doc

    报头长度总是4的倍数个字节 " " D.TCP校验和伪首部中IP分组头的协议字段为1 7 " " 6.滑动窗口的作用是( )。 " " A.流量控制 B.拥塞控制 " " C.路由控制 D.过失控制 " " 7.在TCP中,发送方的窗口大小取决于( )...

    TCP/IP症状和原因

    对OSPF,校验通配符掩码5) 检查应用到接口上的distribute list6)验证邻居的IP配置7) 如果路由被再发布,验证度量值8) 验证路由被正常的再发布  没有构成相邻关系 1) 用show ip protocol neighbors列表已构成...

    STM32F407上实现Modbus协议,包括多种CRC校验算法,读取智能电表数据示例程序

    STM32F407ZET上实现Modbus协议,包括多种CRC校验算法,读取智能电表数据示例程序,STM32CubeMX、Keil5工程源码。

    USBHID调试软件PortHelper.rar

    并支持HIDUSB设备(3)网络通信支持TCP/UDP协议,并支持服务器功能(4)提供8051/ATMEGA16生成代码的功能(5)提供进制转换、数码管字型码定制、汉字字模制作等功能(6)增加校验值计算功能,方便数据调试(7)收发数据支持...

    PortHelper 单片机 网络 蓝牙 硬件 多功能调试助手 socket调试

    (1)支持串口、USB、网络数据收发 (2)USB通信支持CH372USB芯片,并支持HIDUSB设备 (3)网络通信支持TCP/UDP协议,并支持服务器功能 ...(6)增加校验值计算功能,方便数据调试 (7)收发数据支持中文 (8)添加字符串编码功能

    开发通讯程序时经常用到的小软件

    开发通讯程序时经常用到的小软件.crc小软件,这是一款在Windows下用来计算和校验字符串CRC值或者文件CRC值的工具,支持CRC16、CRC32校验。SocketTool调试软件是一款网络TCP/UDP通信调试工具,本工具集功能强大与简单...

    Wireshark-v2.6.1

    Wireshark(前称Ethereal)是一款免费开源的网络嗅探抓包工具,世界上最流行的网络协议分析器!...它的强大特性:例如包含有强显示过滤器语言和查看TCP会话重构流的能力,支持上百种协议和媒体类型。

    计算机网络复习题终极版

    计算机网络复习题 (答案仅供参考) ...33. 计算 TCP 校验和时要用到“伪首部” ,该“伪首部”不包括( C ) A. 源 IP 地址 B. 目标 IP 地址 C. TCP 首部长度 D. TCP 长度 34 .以下用于多播管理的是( A )

    基于Qt+C++开发的跨平台多功能串口调试工具+源码+开发文档说明(毕业设计&课设&项目开发)

    基于Qt+C++开发的跨平台多功能串口调试工具+源码+开发文档...计算数据校验码的功能(校验和、异或值) 自动保存配置 数据保存的功能 发送数据添加结尾 \r\n、 \r、 \n 拖放文件到程序中自动更新内容到发送输入框 ....

    一个 smol tcp/ip 堆栈

    它的设计反目标包括复杂的编译时计算,例如宏或类型技巧,甚至以性能下降为代价。smoltcp并不需要在所有堆分配,被广泛记载,和稳定的锈1.40和更高编译。在环回模式下针对 Linux TCP 堆栈进行测试时,smoltcp实现了~...

Global site tag (gtag.js) - Google Analytics