checksum计算方法.doc_第1页
checksum计算方法.doc_第2页
checksum计算方法.doc_第3页
checksum计算方法.doc_第4页
checksum计算方法.doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

ICMP,IP,UDP,TCP报头部分都有checksum(检验和)字段。ICMP和IP报头校验和的计算都很简单,使用RFC1071中给出的方法即可完成(如下)。/计算校验和USHORT checksum(USHORT *buffer,int size)unsigned long cksum=0;while(size1)cksum+=*buffer+;size-=sizeof(USHORT);if(size)cksum+=*(UCHAR *)buffer;/将32位数转换成16while (cksum16)cksum=(cksum16)+(cksum & 0xffff);return (USHORT) (cksum);UDP/TCP报头中的校验和的计算比较复杂的,要用到 UDP/TCP伪首部:先要填充伪首部各个字段,然后再将UDP/TCP报头以后(包括报头)的数据附加到伪首部的后面,再对位首部使用上述校验和计算,所得到的值才是UDP/TCP报头部分的校验和。位首部可以用如下的结构体表示:typedef structULONG sourceip; /源IP地址ULONG destip; /目的IP地址BYTE mbz; /置空(0)BYTE ptcl; /协议类型USHORT plen; /TCP/UDP数据包的长度(即从TCP/UDP报头算起到数据包结束的长度 单位:字节)Psd_Header;这个过程是一个很繁琐的过程,计算过几次后再也忍受不了做这样重复的工作,于是写了一个通用的计算函数。这个函数使用起来我感觉非常方便:先封装好你的数据包(完整的,包括以太头),然后将数据包的首地址作为参数,调用该函数即可。函数将帮你完成IP报头以及UDP/TCP报头部分校验和的计算。/-/ PacketCheckSum/ 计算数据包的校验和/ 参数:packet-待处理数据(将封装好的数据包的指针)/-void PacketCheckSum(unsigned char packet)Dlc_Header *pdlc_header=NULL; /以太头指针Ip_Header *pip_header=NULL; /IP头指针unsigned short attachsize=0; /传输层协议头以及附加数据的总长度pdlc_header=(Dlc_Header *)packet;/判断ethertype,如果不是IP包则不予处理if(ntohs(pdlc_header-ethertype)!=00800) return;pip_header=(Ip_Header *)(packet+14);/TCP包if(006=pip_header-proto)Tcp_Header *ptcp_header=NULL; /TCP头指针Tcp_Psd_Header *ptcp_psd_header=NULL;ptcp_header=(Tcp_Header *)(packet+14+(pip_header-ver_len)&15)*4);attachsize=ntohs(pip_header-total_len)-(pip_header-ver_len)&15)*4;ptcp_psd_header=(Tcp_Psd_Header *)malloc(attachsize+sizeof(Tcp_Psd_Header);if(!ptcp_psd_header) return;memset(ptcp_psd_header,0,attachsize+sizeof(Tcp_Psd_Header);/填充伪TCP头ptcp_psd_header-destip=pip_header-destIP;ptcp_psd_header-sourceip=pip_header-sourceIP;ptcp_psd_header-mbz=0;ptcp_psd_header-ptcl=006;ptcp_psd_header-tcpl=htons(attachsize);/计算TCP校验和ptcp_header-chksum=0;memcpy(unsigned char *)ptcp_psd_header+sizeof(Tcp_Psd_Header),(unsigned char *)ptcp_header,attachsize);ptcp_header-chksum=checksum(unsigned short *)ptcp_psd_header,attachsize+sizeof(Tcp_Psd_Header);/计算ip头的校验和pip_header-checksum=0;pip_header-checksum=checksum(unsigned short *)pip_header,20);return;/UDP包if(011=pip_header-proto)Udp_Header *pudp_header=NULL; /UDP头指针Udp_Psd_Header *pudp_psd_header=NULL;pudp_header=(Udp_Header *)(packet+14+(pip_header-ver_len)&15)*4);attachsize=ntohs(pip_header-total_len)-(pip_header-ver_len)&15)*4;pudp_psd_header=(Udp_Psd_Header *)malloc(attachsize+sizeof(Udp_Psd_Header);if(!pudp_psd_header) return;memset(pudp_psd_header,0,attachsize+sizeof(Udp_Psd_Header);/填充伪UDP头pudp_psd_header-destip=pip_header-destIP;pudp_psd_header-sourceip=pip_header-sourceIP;pudp_psd_header-mbz=0;pudp_psd_header-ptcl=011;pudp_psd_header-udpl=htons(attachsize);/计算UDP校验和pudp_header-chksum=0;memcpy(unsigned char *)pudp_psd_header+sizeof(Udp_Psd_Header),(unsigned char *)pudp_header,attachsize);pudp_header-chksum=checksum(unsigned short *)pudp_psd_header,attachsize+sizeof(Udp_Psd_Header);/计算ip头的校验和pip_header-checksum=0;pip_header-checksum=checksum(unsigned short *)pip_header,20);return;return;需要几个头文件,以及库:#include #include #include “packet.h”#pragma comment(lib,”ws2_32.lib”)如果要自己填充IP数据报,那么计算Checksum是必不可少的一步,算法如下。按16位一组,取补码相加,然后对和取补码USHORT Checksum(USHORT *buffer, int size)unsigned long cksum=0;while(size 1)cksum+=*buffer+;size -=sizeof(USHORT);if(size)cksum += *(UCHAR*)buffer;cksum = (cksum 16) + (cksum & 0xffff);cksum += (cksum 16);return (USHORT)(cksum);此算法根据linux中快速计算ip数据包的chksum算法改写而成,运算速度快,使用方便。此算法也可以应用到其他计算chksum的地方,但是要注意计算条件要求:数据长度是4的倍数。几年前改写而成,这里共享出来。/* ip_fast_csum Compute the IPv4 header checksum efficiently.* iph: ipv4 header* ihl: length of header / 4*/*static inline unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)unsigned int sum;_asm_ _volatile_( “movl (%1), %0 ;n” “subl $4, %2 ;n” “jbe 2f ;n” “addl 4(%1), %0 ;n” “adcl 8(%1), %0 ;n” “adcl 12(%1), %0 ;n”“1: adcl 16(%1), %0 ;n” “lea 4(%1), %1 ;n” “decl %2 ;n” “jne 1b ;n” “adcl $0, %0 ;n” “movl %0, %2 ;n” “shrl $16, %0 ;n” “addw %w2, %w0 ;n” “adcl $0, %0 ;n” “notl %0 ;n”“2: ;n”: “=r” (sum), “=r” (iph), “=r” (ihl): “1 (iph), “2 (ihl): “memory”);return(sum);*/*jonathan 改写于linux; linux的code 见上 */static unsigned shortip_fast_csum( IN unsigned char* iph, IN unsigned int ihl)unsigned int cksum = 0;_asm push eax push ebx push ecx mov ebx , dword ptr iph mov edx, ihl mov eax, dword ptr ebx sub edx, 004 jbe EXIT add eax, dword ptr ebx + 4 adc eax, dword ptr ebx + 8 adc eax, dword ptr ebx + 12BEGIN: adc eax, dword ptr ebx + 16 lea ebx, dword ptr ebx + 4 dec edx jne BEGIN adc eax, 000 mov edx, eax shr eax, 010 add ax, dx adc eax, 000 not eaxEXIT: mov cksum , eax pop ecx pop ebx pop eaxreturn (unsigned short)cksum;UDP checksum计算方法:/*For udp checksum, sophie add, 20100524*/struct fake_head u_int sIp4; u_int dIp4; u_int len; u_short reserved1; u_char reserved2; u_char nextHead;u_short in_cksum_v6 (u_char *mdata, u_int len, u_int ck) u_int sum = 0; int i; if (len % 2) return 0; for (i = 0; i len; i = i + 2) sum += (mdatai 16) sum = (sum 16) + (sum & 0xffff); return (sum & 0xffff);u_short udp_check_sum_v6(char *udp, const struct in6_addr *sIp, const struct in6_addr *dIp, u_short payload_length, u_char next_protocol) u_short *pFakeHead = NULL; struct fake_head fakeHead; u_int i,ck = 0; struct udphdr *udpHdr; udpHdr = (struct udphdr *)udp; memcpy(char *)fakeHead.sIp, (char *)sIp, 16); memcpy(char *)fakeHead.

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论