3.2 ICMPv4 报文和报文类型
3.2 ICMPv4 报文和报文类型
1. ICMPv4 报头
ICMPv4 是基于IP协议的。所以在 ICMPv4 的报文外面,还有一层 IP 报文格式。

ICMPv4 报头struct icmphdr由 类型(8位)、代码(8位)、校验和(16位)和可变部分(32位)组成。

struct icmphdr {
__u8 type;
__u8 code;
__sum16 checksum;
union {
struct {
__be16 id;
__be16 sequence;
} echo;
__be32 gateway;
struct {
__be16 __unused;
__be16 mtu;
} frag;
__u8 reserved[4];
} un;
};
在 ICMPv4 的报头中,type和code的组合构成了 ICMPv4 的各种报文类型。其它的字段则是不同的报文类型所携带的私有属性。下面将通过type和code的不同组合,先来整体的了解以下,icmp所能传达的信息。
2. ICMPv4报文类型

在这张图中,报文类型分为2类:查询和差错。
查询报文,顾名思义,它并不是发生了错误而产生,它是为了在网路中获取数据。最常用的就是 Type 0 和 Type 8 ping服务。
差错报文,当网路中发生错误信息时,将被发送出去。最常用的就是Type 3不可达差错和Type 11 超时差错。
ICMPv4 有一个结构体struct icmp_control 来描述ICMPv4处理函数。
struct icmp_control {
bool (*handler)(struct sk_buff *skb); //处理函数
short error; // 用来标记是否是错误信息
};
在文章开头提到,ICMPv4信息,有2个作用,一个是信息消息,一个是错误消息,在ICMPv4中,error注册为1的为错误消息。(ICMPv6则用bit位来表示)
在ICMPv4中记录消息类型处理的数组是icmp_pointers[NR_ICMP_TYPES + 1] 详见附录1.
以下是每个服务所对应的处理函数:
| typeID | 消息类型 | 处理函数 | 错误消息 | 信息消息 |
|---|---|---|---|---|
| 0 | ICMP_ECHOREPLY | ping_rcv | x | ✔ |
| 3 | ICMP_DEST_UNREACH | icmp_unreach | ✔ | x |
| 4 | ICMP_SOURCE_QUENCH | icmp_unreach | ✔ | x |
| 5 | ICMP_REDIRECT | icmp_redirect | ✔ | x |
| 8 | ICMP_ECHO | icmp_echo | x | ✔ |
| 11 | ICMP_TIME_EXCEEDED | icmp_unreach | ✔ | x |
| 12 | ICMP_PARAMETERPROB | icmp_unreach | ✔ | x |
| 13 | ICMP_TIMESTAMP | icmp_timestamp | x | ✔ |
| 14 | ICMP_TIMESTAMPREPLY | icmp_discard | x | ✔ |
| 15 | ICMP_INFO_REQUEST(作废) | icmp_discard | x | ✔ |
| 16 | ICMP_INFO_REPLY(作废) | icmp_discard | x | ✔ |
| 17 | ICMP_ADDRESS | icmp_discard | x | ✔ |
| 18 | ICMP_ADDRESSREPLY | icmp_discard | x | ✔ |
处理函数进行归纳有:
- 查询处理:
ping_rcv()\icmp_echo()\icmp_timestamp() - 差错处理:
icmp_unreach()\icmp_redirect() - 不做处理:
icmp_discard()
他们的功能如下:
ping_rcv负责处理接收ping应答(ICMP_ECHOREPLY)。icmp_echo处理回应ping请求。(ICMP_ECHO)icmp_timestamp用来处理ICMP时间戳请求(ICMP_TIMESTAMP)。icmp_unreach消息不可达的消息类型。在很多情况下都会发送(ICMP_DEST_UNREACH).icmp_redirect处理重定向消息(ICMP_REDIRECT)。icmp_discard这是一个空处理函数。用于不存在的消息类型和不需要做任何处理的消息。
下文我们将对如何接收一个ICMPv4报文做出描述。
3. 附录
附录1. ICMP消息处理数组:
static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
[ICMP_ECHOREPLY] = {
.handler = ping_rcv,
},
[1] = {
.handler = icmp_discard,
.error = 1,
},
[2] = {
.handler = icmp_discard,
.error = 1,
},
[ICMP_DEST_UNREACH] = {
.handler = icmp_unreach,
.error = 1,
},
[ICMP_SOURCE_QUENCH] = {
.handler = icmp_unreach,
.error = 1,
},
[ICMP_REDIRECT] = {
.handler = icmp_redirect,
.error = 1,
},
[6] = {
.handler = icmp_discard,
.error = 1,
},
[7] = {
.handler = icmp_discard,
.error = 1,
},
[ICMP_ECHO] = {
.handler = icmp_echo,
},
[9] = {
.handler = icmp_discard,
.error = 1,
},
[10] = {
.handler = icmp_discard,
.error = 1,
},
[ICMP_TIME_EXCEEDED] = {
.handler = icmp_unreach,
.error = 1,
},
[ICMP_PARAMETERPROB] = {
.handler = icmp_unreach,
.error = 1,
},
[ICMP_TIMESTAMP] = {
.handler = icmp_timestamp,
},
[ICMP_TIMESTAMPREPLY] = {
.handler = icmp_discard,
},
[ICMP_INFO_REQUEST] = {
.handler = icmp_discard,
},
[ICMP_INFO_REPLY] = {
.handler = icmp_discard,
},
[ICMP_ADDRESS] = {
.handler = icmp_discard,
},
[ICMP_ADDRESSREPLY] = {
.handler = icmp_discard,
},
};
浙公网安备 33010602011771号