Linux icmp功能分析之一 icmp协议相关的格式
ICMP协议是网络层中一个非常重要的协议,其全称为Internet Control Message Protocol(因特网控制报文协议),ICMP协议弥补了IP的缺限,它使用IP协议进行信息传递,向数据包中的源端节点提供发生在网络层的错误信息 反馈。
在实现中,路由器会使用该协议来报告问题,而主机则会使用该机制来测试目的站是否可达。该报文的最终目的地不是一个应用程序或者目的设备上的用户,而是目的设备上的网际协议软件,一般icmp报文的接收是linux内核里的icmp接收模块来处理的,而icmp请求报文的发送即可以是内核里相关子系统也可以是应用层的程序发送(比如ping应用)。
1、 ICMP报文的格式
各种ICMP报文的前32bits都是三个长度固定的字段,为8bit的type字段、8bit的code字段、16bit的校验和字段(包括icmp数据字段的校验和),而对于不同类型的icmp报文,其余下字段的含义则是不同的。
a) type类型
icmp类型目前有40个,下面几个是比较常用的,也是目前linux支持的类型。
0 回显应答(ECHO-REPLY)
3 不可到达
4 源站抑制
5 重定向
8 回显请求(ECHO-REQUEST)
11 数据报超时
12 参数失灵
13 时间戳请求
14 时间戳应答
15 信息请求(已不再使用)
16 信息应答(已不再使用)
17 地址掩码请求(已不再使用)
18 地址掩码应答(已不再使用)
对于 以上类型,比较重要的有:回显请求与应答(type 0、8)、不可到达(3)、源站抑制(4)、路由重定向(5)、时间戳请求与应答(13、14)
2、 主要的ICMP格式
a) 回显请求与应答
其中type值表示是一个回显请求或应答,code值为0,而identifier在linux的实现为进程pid(因为ping请求是应用程序,通过该值能够确认是机器上的哪一个应用程序执行的ping操作,能够对进行的接收数据进行匹配操作),而sequence则为一个计数器,主要是为每一个回显请求数据包设置序列值。Option是可选数据,其大小是可变的。
TYPE(8/0) | CODE(0) | Checksum |
identifier | Sequence | |
Option |
b) 目的站不可达
TYPE(3) | CODE(0-15) | Checksum |
Not used (must set 0) | ||
Option |
由于目的站不可达的原因很多,所以需要用code来进行进一步细分。对于option字段,其值为ip头部(包括可选项)加上原始ip数据部分的前8个字节。
而code的定义如下:
#define ICMP_NET_UNREACH0 /* Network Unreachable */
#define ICMP_HOST_UNREACH1 /* Host Unreachable */
#define ICMP_PROT_UNREACH2 /* Protocol Unreachable */
#define ICMP_PORT_UNREACH3 /* Port Unreachable */
#define ICMP_FRAG_NEEDED4 /* Fragmentation Needed/DF set */
#define ICMP_SR_FAILED5 /* Source Route failed */
#define ICMP_NET_UNKNOWN6
#define ICMP_HOST_UNKNOWN7
#define ICMP_HOST_ISOLATED8
#define ICMP_NET_ANO9
#define ICMP_HOST_ANO10
#define ICMP_NET_UNR_TOS11
#define ICMP_HOST_UNR_TOS12
#define ICMP_PKT_FILTERED13 /* Packet filtered */
#define ICMP_PREC_VIOLATION14 /* Precedence violation */
#define ICMP_PREC_CUTOFF15 /* Precedence cut off */
#define NR_ICMP_UNREACH15 /* instead of hardcoding immediate value */
c)重定向
TYPE(5) | CODE(0-3) | Checksum |
Route’s ip | ||
Option |
对于option字段,其值为ip头部(包括可选项)加上原始ip数据部分的前8个字节。
第二个32bits代表路由器的wan側地址。
Code类型如下:
#defineICMP_REDIR_NET 0 /* Redirect Net */
#defineICMP_REDIR_HOST 1 /* Redirect Host */
#defineICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */
#defineICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */
重定向报文仅限于在直接连接到同一网络上的路由器与主机间交互。
d)数据包超时
因为每一个ip数据包都有一个ttl计数器,即跳数计数器,当数据包中的ttl的值为0时,就丢弃数据包,并发送一个数据包超时的icmp 报文。下面即是icmp 数据包超时报文的格式
TYPE(11) | CODE(0-1) | Checksum |
Not used(must set 0) | ||
Option |
对于option字段,其值为ip头部(包括可选项)加上原始ip数据部分的前8个字节。
对于命令traceroute(windows 下为tracert),即是根据ttl来实现查找到目的站点所有跳点的ip地址的。即先发送3个ttl为1的数据包,根据接收到的icmp 数据包超时报文获取到第一个下一跳地址;然后再发送3个ttl为的数据包,根据接收到的数据包超时报文获取到第二个下一跳地址;依此类推直到找到所有的跳点地址或者已经到了ttl的max值还没有到目的站点则程序返回。
基本上这4个icmp报文是最重要的了。
3、 linux中icmp相关的数据结构
#defineICMP_ECHOREPLY 0 /* Echo Reply */
#defineICMP_DEST_UNREACH 3 /* Destination Unreachable */
#defineICMP_SOURCE_QUENCH 4 /* Source Quench */
#defineICMP_REDIRECT 5 /* Redirect (change route) */
#defineICMP_ECHO 8 /* Echo Request */
#defineICMP_TIME_EXCEEDED 11 /* Time Exceeded */
#defineICMP_PARAMETERPROB 12 /* Parameter Problem */
#defineICMP_TIMESTAMP 13 /* Timestamp Request */
#defineICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */
#defineICMP_INFO_REQUEST 15 /* Information Request */
#defineICMP_INFO_REPLY 16 /* Information Reply */
#defineICMP_ADDRESS 17 /* Address Mask Request */
#defineICMP_ADDRESSREPLY 18 /* Address Mask Reply */
#defineNR_ICMP_TYPES 18
/*Codes for UNREACH. */
#defineICMP_NET_UNREACH 0 /* Network Unreachable */
#defineICMP_HOST_UNREACH 1 /* Host Unreachable */
#defineICMP_PROT_UNREACH 2 /* Protocol Unreachable */
#defineICMP_PORT_UNREACH 3 /* Port Unreachable */
#defineICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */
#defineICMP_SR_FAILED 5 /* Source Route failed */
#defineICMP_NET_UNKNOWN 6
#defineICMP_HOST_UNKNOWN 7
#defineICMP_HOST_ISOLATED 8
#defineICMP_NET_ANO 9
#defineICMP_HOST_ANO 10
#defineICMP_NET_UNR_TOS 11
#defineICMP_HOST_UNR_TOS 12
#defineICMP_PKT_FILTERED 13 /* Packet filtered */
#defineICMP_PREC_VIOLATION 14 /* Precedence violation */
#defineICMP_PREC_CUTOFF 15 /* Precedence cut off */
#defineNR_ICMP_UNREACH 15 /* instead of hardcoding immediate value */
/*Codes for REDIRECT. */
#defineICMP_REDIR_NET 0 /* Redirect Net */
#defineICMP_REDIR_HOST 1 /* Redirect Host */
#defineICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */
#defineICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */
/*Codes for TIME_EXCEEDED. */
#defineICMP_EXC_TTL 0 /* TTL count exceeded */
#defineICMP_EXC_FRAGTIME 1 /* Fragment Reass time exceeded */
Icmp头部定义:
structicmphdr {
__u8 type;
__u8 code;
__sum16 checksum;
union {
struct {
__be16 id;
__be16 sequence;
} echo;
__be32 gateway;
struct {
__be16 __unused;
__be16 mtu;
} frag;
} un;
};
在该数据结构中,前32bits的定义是一样的,而后面32bits的定义,因回显请求与应答、重定向等报文定义不同而有不同的含义。
发送icmp报文相关的数据结构。
structicmp_bxm {
struct sk_buff *skb;//接收到的icmp报文
int offset;//选项数据在icmp数据中的偏移量
int data_len;//icmp数据报文长度
struct {
struct icmphdr icmph;/icmp头部/
__be32 times[3];
} data;
int head_len;//icmp头部长度
struct ip_options replyopts;//存储的接收icmp报文的选项数据,待发送时使用
unsigned char optbuf[40];
};