
1.4.4 ICMP协议
ICMP协议是网络层的一个协议,用于探测网络是否连通、主机是否可达、路由是否可用等。简单来说,它是用来查询诊断网络的。
虽然和IP协议同处网络层,但ICMP报文却是作为IP数据报的数据,然后加上IP报头后再发送出去的,如图1-13所示。

图1-13
IP首部的长度为20字节。ICMP报文作为IP数据报的数据部分,当IP首部的协议字段取值1时其数据部分是ICMP报文。ICMP报文格式如图1-14所示。

图1-14
其中,最上面的(0、8、16、31)指的是比特位,所以前3个字段(类型、代码、校验和)一共占了32个比特(类型占8位,代码占8位,检验和占16位),即4字节。所有ICMP报文前4字节的格式都是一样的,即任何ICMP报文都含有类型、代码和校验和这3个字段,8位类型和8位代码字段一起决定了ICMP报文的种类。紧接着后面4字节取决于ICMP报文种类。前面8字节就是ICMP报文的首部,后面的ICMP数据部分的内容和长度也取决于ICMP报文种类。16位的检验和字段是对包括选项数据在内的整个ICMP数据报文的检验和,其计算方法和IP头部检验和的计算方法一样。
ICMP报文可分为2大类别:差错报告报文和查询报文。每一条(或称每一种)ICMP报文要么属于差错报告报文,要么属于查询报文,如图1-15所示。

图1-15
1.ICMP差错报告报文
我们从图1-15中可以发现属于差错报告报文的ICMP报文很多,为了归纳方便,根据其类型的不同,可以将这些差错报告报文分为5种类型:目的不可达(类型为3)、源端被关闭(类型为4)、重定向(类型为5)、超时(类型为11)和参数问题(类型为12)。
代码字段不同的取值进一步表明了该类型ICMP报文的具体情况,比如类型为3的ICMP报文都是表明目的不可达,但目的不可达的原因可用代码字段进一步说明,比如代码为0表示网络不可达、代码为1表示主机不可达等。
ICMP协议规定,ICMP差错报文必须包括产生该差错报文的源数据报的IP首部,还必须包括跟在该IP(源IP)首部后面的前8个字节,这样ICMP差错报文的IP数据报长度=本IP首部(20字节)+本ICMP首部(8字节)+源IP首部(20字节)+源IP数据报的IP首部后的8个字节=56字节。ICMP差错报文如图1-16所示。

图1-16
如图1-17所示为一个具体的UDP端口不可达的差错报文。

图1-17
从图1-17中可看到,IP数据报的长度是56字节。为了让读者更清晰地了解这五大类差错报告报文格式,我们用图形来表示每一类报文。
(1)ICMP目的不可达报文
目的不可达也称终点不可达,可分为网络不可达、主机不可达、协议不可达、端口不可达、需要分片但DF比特已置为1,以及源站选路失败等16种报文,其代码字段分别置为0至15。当出现以上16种情况时就向源站发送目的不可达报文。该类报文格式如图1-18所示。
(2)ICMP源端被关闭报文
也称源站抑制,当路由器或主机由于拥塞而丢弃数据报时,就向源站发送源站抑制报文,使源站知道应当将数据报的发送速率放慢。该类报文格式如图1-19所示。
(3)ICMP重定向报文
当IP数据报应该被发送到另一个路由器时,收到该数据报的当前路由器就要发送ICMP重定向差错报文给IP数据报的发送端。重定向一般用来让具有很少选路信息的主机逐渐建立更完善的路由表。ICMP重定向报文只能有路由器产生。该类报文格式如图1-20所示。

图1-18

图1-19

图1-20
(4)ICMP超时报文
当路由器收到生存时间为零的数据报时,除丢弃该数据报外,还要向源站发送超时报文。当目的站在预先规定的时间内不能收到一个数据报的全部数据报片时,就将已收到的数据报片都丢弃,并向源站发送时间超时报文。该类报文格式如图1-21所示。

图1-21
(5)ICMP参数问题
当路由器或目的主机收到的数据报的首部中的字段的值不正确时,就丢弃该数据报,并向源站发送参数问题报文。该类报文格式如图1-22所示。

图1-22
2.ICMP查询报文
根据功能的不同,ICMP查询报文可以分为4大类:请求回显(Echo)或应答、请求时间戳(Timestamp)或应答、请求地址掩码(Address Mask)或应答、请求路由器或通告。种类由类型和代码字段决定,其类型和代码,如表1-3所示。
表1-3 ICMP查询报文的种类

关于回显请求和应答,Echo的中文翻译为回声,有的文献用回送或回显,本书用回显。请求回显的含义就好比请求对方回复一个应答。Linux或Windows下有个ping命令,值得注意的是,Linux下ping命令产生的ICMP报文大小是64字节(56+8=64,56是ICMP报文数据部分长度,8是ICMP报头部分长度),而Windows(如XP)下ping命令产生的ICMP报文大小是40字节(32+8=40)。该命令就是本机向一个目的主机发送一个请求回显(类型Type=8)的ICMP报文,如果途中没有异常(例如被路由器丢弃、目标不回应ICMP或传输失败),则目标返回一个回显应答的ICMP报文(类型Type=0),表明这台主机存在。
为了让读者更清晰地了解这四类查询报文格式,用图表示每一类报文,如图1-23~图1-27所示。
(1)ICMP请求回显和应答报文格式

图1-23
(2)ICMP时间戳请求和应答报文格式

图1-24
(3)ICMP地址掩码请求和应答报文格式

图1-25
(4)ICMP路由器请求报文和通告报文格式

图1-26

图1-27
【例1.1】 抓包查看来自Windows的ping包。
(1)启动VMware下的虚拟机XP,设置网络连接方式为NAT,则虚拟机XP会连接到虚拟交换机VMnet8上。
(2)在Windows 7安装并打开抓包软件Wireshark,选择要捕获网络数据报的网卡是VMware Virtual Ethernet Adapter for VMnet8,如图1-28所示。

图1-28
双击图1-28中选中的网卡,就开始在该网卡上捕获数据。此时在虚拟机XP(192.168.80.129)下ping宿主机(192.168.80.1),可以在Wireshark下看到捕获到的ping包,如图1-29所示为回显请求,可以看到ICMP报文的数据部分是32字节,如果加上ICMP报头(8字节),则为40字节。

图1-29
如图1-30所示为回显应答,ICMP报文的数据部分长度依然是32字节。

图1-30
【例1.2】 抓包查看来自Linux的ping包。
(1)启动VMware下的虚拟机Linux,设置网络连接方式为NAT,则虚拟机Linux会连接到虚拟交换机VMnet8上。
(2)在Windows 7安装并打开抓包软件Wireshark,选择要捕获网络数据报的网卡是VMware Virtual Ethernet Adapter for VMnet8,图片可以参考例1.1。
在虚拟机Linux(192.168.80.128)下ping宿主机(192.168.80.1),可以在Wireshark下看到捕获到的ping包,如图1-31所示为回显请求,可以看到ICMP报文的数据部分是56字节,如果加上ICMP报头(8字节),则为64字节。

图1-31
如图1-32所示为回显应答,ICMP报文的数据部分长度依然是56字节。

图1-32