ip校验和 及 udp校验和 的计算方法
来源:互联网 发布:益盟高点画线源码 编辑:程序博客网 时间:2024/05/29 02:02
一、ip校验和的计算:
计算方法:
1. ip包头(共20个字节)按照每16个bit作为一个值依次进行相加
2. 将计算结果的进位加到低16位上
3. 将结果取反
ip包头的内存内容
eg:
45 00 00 20 0F B8 00 00
80 11 00 00 C0 A8 0A 9F
C0 A8 0A C7
将 0x4500 0x0020 0x0FB8 0x0000 0x8011 0x0000 0xC0A8 0x0A9F 0xC0A8 0x0AC7 依次相加 所得结果为0x26B9F 然后将 0x0002 + 0x6B9F = 0x6BA1
然后将 0x6BA1 取反得 0x945E
要注意两点:
1 在给ip_header计算校验和之前 首先把ip_header的checksum字段置为02 计算得到checksum之后 赋值时要转换为网络字节序: ip_header.checksum = htons(checksum); struct ip_header //小端模式__LITTLE_ENDIAN { unsigned char ihl:4; //ip header length unsigned char version:4; //version u_char tos; //type of service u_short tot_len; //total length u_short id; //identification u_short frag_off; //fragment offset u_char ttl; //time to live u_char protocol; //protocol type u_short check; //check sum u_int saddr; //source address u_int daddr; //destination address }; // 计算ip数据包的checksum// 将20个字节的ip数据包每16位组成一个字 依次相加 设所得结果为 0x34ACE// 将 进位的3与 0x4ACE相加 得 0x4AD1// 将 0x4AD1取反得到checksumu_short get_ip_checksum(char* ip_hdr){ char* ptr_data = ip_hdr; u_long tmp = 0; u_long sum = 0; for (int i=0; i<20; i+=2) { tmp += (u_char)ptr_data[i] << 8; tmp += (u_char)ptr_data[i+1]; sum += tmp; tmp = 0; } u_short lWord = sum & 0x0000FFFF; u_short hWord = sum >> 16; u_short checksum = lWord + hWord; checksum = ~checksum; return checksum; }
二、udp校验和
// udp的checksum计算是用到的结构体// udp中, 参与计算checksum的数据包括三部分: 亚头部 + UDP头部 + 数据部分// 亚头部: 4 byte源ip地址 + 4 byte目的ip地址 + 0x00 + 1 byte协议 + UDP 长度(2byte)(udp包头长度+数据长度)// UDP包头: 2 byte源端口 + 2 byte目的端口 + 2 byte UDP包长(此处是udp包头自带的值不用变) + 0x0000 (checksum)// 数据部分// 计算方法同get_ip_checksum一样typedef struct udp_check_subhdr // udp计算checksum时的 亚头部: 4 byte源ip地址 + 4 byte目的ip地址 + 0x00 + 1 byte协议 + UDP 长度(2byte){ u_long src_ip; u_long dst_ip; char mbz; // must be zero char protocol; u_short len; // 这里的长度是指 udp packet中 udp头部和数据部分的总长度} udp_check_subhdr;// pudp_pkt: udp的整个packet// pkt_len: 整个packet的长度(以太网数据帧头 ip头 udp头)u_short get_udp_checksum(char* pudp_pkt, int pkt_len) { ether_header *eth_hdr = (ether_header *)pudp_pkt; ip_header *ip_hdr = (ip_header*)( pudp_pkt+sizeof(ether_header) ); udphdr *udp_hdr = (udphdr*)( (char*)ip_hdr+sizeof(ip_header) ); u_short udp_part_len = pkt_len-sizeof(ether_header)-sizeof(ip_header); // 亚包头中的len: =udp包头长度+数据长度(udp包总长度-ethernet包头长度-ip包头长度); udp_check_subhdr udp_subhdr; udp_subhdr.protocol = ip_hdr->protocol; udp_subhdr.dst_ip = ip_hdr->daddr; udp_subhdr.src_ip = ip_hdr->saddr; udp_subhdr.mbz = 0x00; udp_subhdr.len = htons(udp_part_len); int subhdr_len = sizeof(udp_check_subhdr); int buf_size = udp_part_len + subhdr_len; // 亚包头 + udp包头 + 数据部分的总长度 if (pkt_len < buf_size) return 0; u_char* buffer = (u_char*)malloc(buf_size); memset(buffer, 0x00, buf_size); memcpy(buffer, (char*)&udp_subhdr, subhdr_len); memcpy(buffer + subhdr_len, (char*)udp_hdr, udp_part_len); unsigned char* ptr_data = buffer; u_long tmp = 0; u_long sum = 0; for (int i=0; i<buf_size; i+=2) { tmp += (u_char)ptr_data[i] << 8; tmp += (u_char)ptr_data[i+1]; sum += tmp; tmp = 0; } u_short lWord = sum & 0x0000FFFF; u_short hWord = sum >> 16; u_short checksum = lWord + hWord; checksum = ~checksum; return checksum; }
最后: ip校验和还有udp校验和的查看是在接收端查看的,从源端查看是没有计算的值(ip校验和是0x00 udp校验和不清楚什么意义) 用pcap发送自定义数据包时 调用pcap_sendpacket时是直接发送定义好的数据包 就是将定义好的包直接通过网卡发送 不会经过电脑上的ip层和链路层 所以 校验和要自己计算
从两个网页处学到计算方法:
http://www.360doc.com/content/12/0511/15/621500_210332306.shtml
http://blog.csdn.net/maeom/article/details/6065203
*注: 仅作为笔记之用 如有错误或不妥之处还望指正。
0 0
- ip校验和 及 udp校验和 的计算方法
- ip校验和及udp校验和的计算方法
- ip校验和计算方法
- TCP/IP 中校验和的计算方法
- 校验和的计算方法
- Tcp、Udp 校验和与ip校验和的概念
- IP/UDP/TCP/ICMP的校验和
- IP/TCP/UDP校验和的计算
- IP和TCP包头校验和计算方法
- IP和TCP包头校验和计算方法
- IP和TCP包头校验和计算方法
- IP和TCP包头校验和的计算方法
- UDP的校验和
- ip首部校验和的计算方法(c语言实现)
- IP首部校验和(ICMP报文的校验和)的计算方法
- udp头部及校验和
- 关于UDP和IP报校验和
- IP,TCP,UDP,ICMP校验和的区别和计算
- Spring中的AOP——在Advice方法中获取目标方法的参数
- Linux 配置nexus
- tomcat分析
- 如何使我们的薪资15k?
- 如何将自己薪资提升到15K
- ip校验和 及 udp校验和 的计算方法
- 月薪15k意味着什么
- 如何月薪15K
- vb.net ファイル操作クラス
- 循环更新表字段
- 深入解析JavaScript编程中的this关键字使用
- sql 添加注释
- 在IT行业中,如何拿到15K的月薪?
- Paint 画笔的一些属性