概述
ICMP经常被认为是 IP层的一个组成部分。它传递差错报文以及其他需要注意的信息。ICMP报文通常被 IP层或更高层协议( TCP或UDP)使用。一些 ICMP报文把差错报文返回给用户进程。
ICMP报文在IP数据报内部传输结构如下图:

ICMP报文格式如下图所示:

从上图可知ICMP报文类型字段可以有 15个不同的值,以描述特定类型的 ICMP报文。某些 ICMP报文还使用代码字段的值来进一步描述不同的条件。
检验和字段覆盖整个ICMP报文。
ICMP报文类型
各种类型的ICMP报文如下图所示:

不同类型由报文中的类型字段和代码字段来共同决定。
当发送一份ICMP差错报文时,报文始终包含IP的首部和产生ICMP差错报文的IP数据报的前8个字节。这样接收ICMP差错报文的模块就会把它与某个特定的协议和用户进程联系起来。
以下情况不会产生ICMP差错报文:
- ICMP差错报文(不过,ICMP查询报文可能产生ICMP差错报文)
- 目的地址是广播地址或多播地址的IP数据报
- 作为链路层广播的数据报
- 不是IP分片的第一片
- 源地址不是单个主机的数据报。这就是说,源地址不能为零地址、环回地址、广播地址或多播地址。
这些规则是为了防止过去允许 ICMP差错报文对广播分组响应所带来的广播风暴。
ICMP地址掩码请求与应答
ICMP地址掩码请求用于无盘系统在引导过程中获取自己的子网掩码。系统广播它的ICMP请求报文。无盘系统获取子网掩码的另一个方法是 BOOTP协议。
ICMP地址掩码请求和应答报文格式如下图所示:

ICMP报文中的标识符和序列号字段由发送端任意选择设定,这些值在应答中将被返回。这样,发送端就可以把应答与请求进行匹配。
ICMP时间戳请求与应答
ICMP时间戳请求允许系统向另一个系统查询当前的时间。返回的建议值是自午夜开始计算的毫秒数,协调的统一时间。这种ICMP报文的好处是它提供了毫秒级的分辨率,而利用其他方法从别的主机获取的时间(如某些 Unix系统提供的rdate命令)只能提供秒级的分辨率。由于返回的时间是从午夜开始计算的,因此调用者必须通过其他方法获知当时的日期,这是它的一个缺陷
ICMP时间戳请求和应答报文格式如图所示:

请求端填写发起时间戳,然后发送报文。应答系统收到请求报文时填写接收时间戳,在发送应答时填写发送时间戳。
实际上,大多数的实现把后面两个字段都设成相同的值
ICMP端口不可达差错
它是ICMP目的不可到达报文中的一种,一个ICMP端口不可达差错是立刻返回的。ICMP报文是在主机之间交换的,而不用目的端口号。
ICMP的一个规则是, ICMP差错报文必须包括生成该差错报文的数据报IP首部(包含任何选项),还必须至少包括跟在该 IP首部后面的前 8个字节。
ICMP报文的4.4BSD处理
于ICMP覆盖的范围很广,从致命差错到信息差错,因此即使在一个给定的系统实现中,对每个ICMP报文的处理都是不相同的。
下图给出的是4.4BSD系统对每个可能的ICMP报文的处理方法:

如果最后一列标明是“内核”,那么 ICMP就由内核来处理。如果最后一列指明是“用户进程”,那么报文就被传送到所有在内核中登记的用户进程,以读取收到的 ICMP报文。如果不存在任何这样的用户进程,那么报文就悄悄地被丢弃