ip分组格式如下,注意图中的为bit。
协议号
协议号 | 协议 | 协议号 | 协议 |
00 | IP | 22 | XNS-IDP |
01 | ICMP | 27 | RDP |
02 | IGMP | 29 | ISO-TP4 |
03 | GGP | 36 | XTP |
04 | IP-ENCAP | 37 | DDP |
05 | ST | 39 | IDPR-CMTP |
06 | TCP | 73 | RSPF |
08 | EGP | 81 | VMTP |
12 | PUP | 89 | OSPFIGP |
17 | UDP | 94 | IPIP |
20 | HMP | 98 | ENCAP |
前4个bit为版本号,也就是半个字节;后面4个bit是头部长度,通常头部长度是5个字长,注意不是字节,字长对于不同的CPU不同,这里是以32个bit为单位,也就是4个字节,所以通过头部也就是20个字节(所以有的地方就把0x45合起来叫做协议版本);8bit的TOS,也就是1字节,定义分组数据的优先级,根据RFC1122的定义,IP优先级使用最高3比特,可以定义8个服务等级,第3到第5比特由RFC791定义,称为DTR位,后来RFC1349又扩展到第6位,最后1比特必须为0 ,IETF已经决定从IP头部中去掉还未广泛使用的TOS字节,并重新定义它,这个字节中的6位已经分配给区分服务代码指针(DSCP),一般为00;16bit是数据报的长度,也就是2个字节,其中包括头部的长度,与HLen不同的是,它的技术是以字节而不是字长,最大长度为256²,也就是65535; 每一个IP封包都有一个16bit的唯一识别码,当程序产生的数据要通过网络传送时都会被拆散成封包形式发送,当封包要进行重组的时候这个ID就是依据了; 这是当封包在传输过程中进行最佳组合时使用的3个bit的识别记号 , 标志字段中的最高位为保留分段,当此值为0的时候表示目前未被使用,标志字段中的最低位为MF(More Fragment),MF=1即表示后面“还有分片”的数据报。MF=0表示这已是若干数据报片中的最后一个, 标志字段中间的一位记为DF(Don't Fragment),意思是不能分”,只有当DF=0时才允许分片; 偏移量占13位,片偏移指出:较长的分组在分片后,某片在原分组中的相对位置,也就是说,相对用户数据字段的起点,该片从何处开始,片偏移以8个字节为偏移单位,这就是说,每个分片的长度一定是8字节(64位)的整数倍,(看上面图片所示);1个字节的TTL生存期,默认值为64;协议一个字节,用于识别IP分组应被传送到的最高协议层(看上面表格); checksum 校验和, 这个字段只检验数据报的首部,但不包括数据部分;其次是原地址和目的地址,这个不用解释了;最后,在头部最后有多个选项,有没有这些选项需通过检查头部的长度字段HLen来得知,请参看如下
选项(Options)+填充(Padding)
这两个选项较少使用,只有某些特殊的封包需要特定的控制才会利用到。共32位。这些选项通常包括:
◆安全和处理限制:用于军事领域
◆记录路径:让每个路由器都记下它的IP地址
◆时间戳:让每个路由器都记下它的IP地址和时间
◆宽松的源站选路:为数据报指定一系列必须经过的IP地址
◆严格的源站选路:与宽松的源站选路类似,但是要求只能经过指定的这些地址,不能经过其他的地址。
以上这些选项很少被使用,而且并非所有的主机和路由器都支持这些选项。选项字段一直都是以32位作为界限,在必要的时候插入值为0的填充字节。这样就保证IP首部始终是32位的整数倍(这是首部长度字段所要求的)。
附:校验和计算方法
http://blog.csdn.net/zhangyang0402/article/details/3924108
一、首先区别下面两个概念:
(1)one's complement:正数=原码,负数=反码 (2)two's complement:就是通常所指的补码
二、计算ip首部校验和
1.发送IP数据报计算checksum
(1)将校验和字段置为0; (2)对首部中(一般为20B)每个16位字进行二进制反码求和; (3)将(2)中得到的和再取反码,即得checksum,写入校验和字段中。 抓个IP数据包,取IP数据报报头部分(20B),数据如下:45 00 00 30 80 4c 40 00 80 06 b5 2e d3 43 11 7b cb 51 15 3d
下面我来计算一下校验和:
(1)将校验和字段置为0: 将b5 2e置为00 00,即变成: 45 00 00 30 80 4c 40 00 80 06 00 00 d3 43 11 7b cb 51 15 3d(2)反码求和
4500+0030+804c+4000+8006+0000+d343+117b+cb51+153d=34ace 将将进位(3)加到低16位(4ace)上:0003+4ace=4ad1(3)取反码
将4ad1取反得:checksum=b52e 2.接收IP数据报检验IP校验和 (1)对首部中每个16 bit进行二进制反码求和; (2)将(1)中得到的和再取反码 ,看是否为0.接收到的IP数据报首部:
45 00 00 30 80 4c 40 00 80 06 b5 2e d3 43 11 7b cb 51 15 3d 下面来验证下: (1)反码求和4500+0030+804c+4000+8006+b52e+d343+117b+cb51+153d=3fffc
0003+fffc=ffff(2)取反码:~ffff=0 正确
三、求IP数据报首部校验码代码已将IP首部校验和0xb52e置为0x0000
#includevoid main() { int buff[10]={0x4500,0x0030,0x804c,0x4000,0x8006,0x0000,0xd343,0x117b,0xcb51,0x153d}; int checksum=0,i=0; for(i=0;i<10;i++) { checksum+=buff[i]; } printf("checksum=%x/n",checksum); checksum=(checksum>>16)+(checksum & 0xffff); checksum+=(checksum>>16); checksum=0xffff-checksum; printf("checksum=%04x/n",checksum); }