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,
},
};