icmp报文格式 各种.docx
- 文档编号:5466701
- 上传时间:2023-05-08
- 格式:DOCX
- 页数:64
- 大小:109.92KB
icmp报文格式 各种.docx
《icmp报文格式 各种.docx》由会员分享,可在线阅读,更多相关《icmp报文格式 各种.docx(64页珍藏版)》请在冰点文库上搜索。
icmp报文格式各种
ICMP分析
文档说明:
由于排版的问题,请在“视图”中选择“Web版式”进行阅读。
1ICMP报文的分类和格式
1.1ICMP报文格式概要介绍
ICMP报文是在IP数据报内部被传输的,如下图。
IP首部(有可能有选项)
ICMP报文
这样的一个IP数据报,我们也称它为ICMP数据报。
注意,ICMP数据报和ICMP报文是两个不同的概念,ICMP数据报的数据部分为ICMP报文。
ICMP报文的格式如下图所示。
所有ICMP报文的前4个字节都是一样的,但是剩下的其他字节则互不相同。
078151631
8比特类型
8比特代码
16比特校验和
(不同的类型和代码有不同的内容)
1.2各种类型的ICMP报文的格式
ICMP报文类型可以分为三大类:
ICMP请求报文、ICMP回答报文和ICMP差错报文。
接下来分别介绍它们的格式。
1.2.1ICMP请求和回答报文格式
ICMP请求报文有以下五种类型。
类型
代码
描述
8
0
回显请求
10
0
路由器请求
13
0
时间戳请求
15
0
信息请求(废弃不用)
17
0
地址掩码请求
ICMP回答报文有以下五种类型。
类型
代码
描述
0
0
回显回答
9
0
路由器回答
14
0
时间戳回答
16
0
信息回答(废弃不用)
18
0
地址掩码回答
回显请求和回答报文格式如下。
078151631
类型(0或8)
代码(0)
校验和
标识符
序列号
回显数据
路由器请求报文格式如下,长度为8字节。
078151631
类型(10)
代码(0)
校验和
未用(必须为0)
路由器回答报文格式如下。
078151631
类型(9)
代码(0)
校验和
地址数
地址项长度
(2)
生存时间
路由器地址【1】
优先级【1】
路由器地址【2】
优先级【2】
***
时间戳请求和回答报文格式如下,长度为20字节。
078151631
类型(13或14)
代码(0)
校验和
标识符
序列号
发起时间戳
接收时间戳
传送时间戳
地址掩码请求和回答报文格式如下,长度为12字节。
078151631
类型(17或18)
代码(0)
校验和
标识符
序列号
32比特的子网掩码
1.2.2ICMP差错报文格式
ICMP差错报文分为四类:
ICMP重定向报文、目的不可达差错报文、ICMP源站抑制差错报文、超时差错报文和参数问题差错报文。
1.2.2.1ICMP重定向报文格式
ICMP重定向报文类型为5,代码从0到3总共有4种,如下表。
类型
代码
描述
5
0
对网络重定向
1
对主机重定向
2
对服务类型和网络重定向
3
对服务类型和主机重定向
ICMP重定向报文格式如下。
078151631
类型(5)
代码(0到3)
校验和
应该使用的路由器IP地址
原IP数据报的IP首部(包括选项)+原IP数据报的数据部分的前8个字节
1.2.2.2目的不可达差错报文格式
目的不可达差错报文类型为3,代码从0到15总共有16种,如下表。
类型
代码
描述
3
0
网络不可达
1
主机不可达
2
协议不可达
3
端口不可达
4
需要进行分片但是设置了不分片比特
5
源站选路失败
6
目的网络不认识
7
目的主机不认识
8
源主机被隔离(作废不用)
9
和目的网络的通讯被强制制止
10
和目的主机的通讯被强制制止
11
由于服务类型TOS,网络不可达
12
由于服务类型TOS,主机不可达
13
由于过滤,通信被强制制止
14
主机越权
15
优先权终止生效
目的不可达差错报文的格式如下(代码号为4的除外)。
078151631
类型(3)
代码(0到3,5到15)
校验和
未用(必须为0)
原IP数据报的IP首部(包括选项)+原IP数据报的数据部分的前8个字节
代码号为4的目的不可达差错报文的格式如下。
078151631
类型(3)
代码(4)
校验和
未用(必须为0)
下一站网络的MTU
原IP数据报的IP首部(包括选项)+原IP数据报的数据部分的前8个字节
1.2.2.3ICMP源站抑制差错报文、超时差错报文和参数问题差错报文
类型
代码
描述
4(源站抑制差错报文)
0
源站抑制
11(超时差错报文)
0
传输期间生存时间为0
1
数据报组装期间生存时间为0
12(参数问题差错报文)
0
坏的IP首部(包括各种差错)
1
缺少必须的选项
源站抑制差错报文和超时差错报文的格式如下。
078151631
类型
代码
校验和
未用(必须为0)
原IP数据报的IP首部(包括选项)+原IP数据报的数据部分的前8个字节
参数问题差错报文格式如下。
078151631
类型(12)
代码(0或1)
校验和
指针
未用(必须为0)
原IP数据报的IP首部(包括选项)+原IP数据报的数据部分的前8个字节
2ICMP函数关系图
下图中,蓝色字体的部分为ICMP模块中的函数。
从中可以清晰的看出ICMP模块和上下层函数的接口。
应用程序
相应协议的pr_ctlinput()函数:
协议用此函数来处理来自下层的控制信息
IP和传输层协议
(注:
IP层在ICMP层之下)
rtredirect()函数:
根据“ICMP数据报的源地址、ICMP报文中的推荐下一跳地址、无效数据报的目的地地址”来更新路由表。
pfctlinput()函数:
根据“无效数据报的目的地地址”来通告重定向的所有协议域,使协议有机会把缓存的到目的站的路由作废。
rip_input()函数:
内核把它接收的这些报文传给等待ICMP报文的进程。
有ICMP差错
3ICMP流程图
进程或传输程协议
IP和传输层协议
原IP数据报
应用程序
有ICMP差错
否
片偏移是否为0
是
否
是
是
否
是
是
否
合法
非法
IP层
ICMP报文合法
分用ICMP报文
丢弃报文
是否为除路由器请求报文之外的请求报文
构造ICMP回答报文和ICMP差错报文
是否为广播或多播
否
丢弃报文
丢弃报文
是否有选项
保留某些选项
是否为单播或者环回
构造ICMP请求报文或路由器回答报文
发出ICMP请求报文或路由器回答报文
丢弃报文
注释1:
“保留某些选项”指的是记录路由选项、时间戳选项和安全选项,另外,如果有源路由选项,则要保存其逆转之后的结果。
注释2:
ICMP差错、回答数据报发送到IP层之前有个判断条件“是否为单播或者环回”。
实际上,这个判断条件的一部分是在IP层完成的。
但是为了说明的方便和强调“ICMP差错、回答数据报的目的地址只能为单播或者环回”,把它列在ICMP层。
4ICMP状态机
结束状态
起始状态
初始状态
原IP数据报
ICMP请求报文
ICMP回答报文
ICMP差错报文
进程或者传输层协议
初始状态
事件:
IP层收到ICMP请求报文。
动作:
分用。
事件:
IP层收到ICMP回答报文。
动作:
分用。
事件:
IP层收到ICMP差错报文。
动作:
分用。
原IP数据报
事件1:
原IP数据报的片偏移不为0。
动作1:
释放mbuf。
事件2:
原IP数据报为广播或者多播。
动作2:
释放mbuf。
事件:
原IP数据报有ICMP差错。
动作:
发送ICMP差错报文。
ICMP请求报文
事件:
ICMP模块检查从IP层分用上来的ICMP请求报文,发现其不合法。
动作:
释放mbuf。
事件:
在IP和传输层协议检测到“出错或者需要重定向”的ICMP请求数据报。
动作:
把该数据报传给ICMP模块。
事件:
ICMP模块收到IP层分用上来的不是路由器请求报文的ICMP请求报文。
动作:
构造相应的ICMP回答报文。
事件:
ICMP模块收到IP层分用上来的路由器请求报文。
动作:
上传给路由进程。
ICMP回答报文
事件1:
ICMP模块检查从IP层分用上来的ICMP回答报文,发现其不合法。
动作1:
释放mbuf。
事件2:
发送ICMP回答报文的时候发现其目的地址不是单播或者环回。
动作2:
释放mbuf。
事件:
在IP和传输层协议检测到“出错或者需要重定向”的ICMP回答数据报。
动作:
把该数据报传给ICMP模块。
事件:
ICMP模块收到IP层分用上来的ICMP回答报文。
动作:
上传给相应的进程。
ICMP差错报文
事件1:
ICMP模块检查从IP层分用上来的ICMP差错报文,发现其不合法。
动作1:
释放mbuf。
事件2:
IP层发送ICMP差错报文的时候发现其目的地址不是单播或者环回。
动作2:
释放mbuf。
事件:
在IP和传输层协议检测到“出错或者需要重定向”的ICMP差错数据报。
动作:
把该数据报传给ICMP模块。
事件:
ICMP模块收到IP层分用上来的ICMP差错报文。
动作:
上传给相应的进程或者传输层协议。
进程或者传输层协议
事件:
需要发出ICMP请求报文。
动作:
调用ICMP模块发出ICMP请求报文。
事件:
收到路由器请求报文。
动作:
调用ICMP模块发出路由器回答报文。
注释1:
一个ICMP差错报文不能产生另一个非重定向的ICMP差错报文。
这一点在状态机和流程图中没有表现出来,这是为了使流程图和状态机简洁明了,提高可读性。
下面对这个情况进行详细说明。
当IP和传输层函数发现有ICMP差错的报文的时候,就调用icmp_error函数。
icmp_error函数有5个参数,在这里,我们只说明其中的两个参数。
参数n,指向保存原IP数据报缓存链的指针;参数type,ICMP差错类型。
参数n中保存的原IP数据报有四种类型,普通IP数据报(即:
非ICMP数据报)、ICMP请求报文、ICMP回答报文、ICMP差错报文。
对于参数n和参数type的几种组合情况,icmp_error函数的处理方法如下表。
参数type
参数n
参数type不为“重定向”
参数type为“重定向”
原IP数据报为“普通IP数据报(即:
非ICMP数据报)”
发送ICMP差错报文。
发送ICMP重定向报文。
原IP数据报为“ICMP请求报文”
原IP数据报为“ICMP回答报文”
原IP数据报为“ICMP差错报文”
释放保存原IP数据报的mbuf链条。
上表中的蓝色字体是对原IP数据报的一种“过滤”,但是这个“过滤”过程在流程图和状态机中没有画出来。
注释2:
状态机中,“进程或者传输层协议”实际上在ICMP模块的上层,并不在ICMP模块中。
这里之所以把“进程或者传输层协议”列为一个状态,是为了说明ICMP模块和上层的关系。
注释3:
ICMP模块对从IP层分用上来的路由器请求报文的处理比较特殊。
ICMP模块把路由器请求报文传给路由进程,由路由进程来构造相应的回答报文。
注释4:
普通IP数据报(即:
非ICMP数据报)如果“有ICMP差错”,也会跳到“原IP数据报”状态。
实际上,“原IP数据报”大多数是“有ICMP差错”的普通IP数据报(即:
非ICMP数据报)。
5ICMP接口
5.1数据接口
5.1.1ICMP模块和下层的接口
5.1.1.1IP层——>ICMP模块
icmp_input函数的参数和返回值如下。
void
icmp_input(m,hlen)
registerstructmbuf*m;
inthlen;
参数m为指向“存储ICMP数据报的mbuf链条”的指针。
参数hlen为ICMP数据报的IP首部长度。
5.1.1.2ICMP模块——>IP层
ICMP模块通过调用ip_output函数来实现输出。
ip_output函数的参数和返回值如下。
int
ip_output(m0,opt,ro,flags,imo)
structmbuf*m0;
structmbuf*opt;
structroute*ro;
intflags;
structip_moptions*imo;
介绍这五个参数。
m0,要发送的分组;
opt,包含的IP选项;
ro,缓存的到目的地的路由;
flags,如下图;
imo,指向多播选项的指针。
5.1.2ICMP模块和上层的接口
5.1.2.1ICMP模块——>上层
5.1.2.1.1pr_ctlinput函数
如果收到的是除重定向之外的ICMP差错报文,则icmp_input调用相应协议的pr_ctlinput()函数。
if(ctlfunc=inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput)
(*ctlfunc)(code,(structsockaddr*)&icmpsrc,
&icp->icmp_ip);
其中,
参数code是“与协议无关的差错码”;
参数(structsockaddr*)&icmpsrc表示“无效数据报的目的地地址”,
参数&icp->icmp_ip为“指向无效数据报的指针”。
下面是tcp_ctlinput函数的参数和返回值。
其他协议的pr_ctlinput()函数的参数和返回值是类似的。
void
tcp_ctlinput(cmd,sa,ip)
intcmd;
structsockaddr*sa;
registerstructip*ip;
5.1.2.1.2rtredirect函数
如果收到的是ICMP重定向差错报文,则icmp_input调用rtredirect()函数,如下。
rtredirect((structsockaddr*)&icmpsrc,
(structsockaddr*)&icmpdst,
(structsockaddr*)0,RTF_GATEWAY|RTF_HOST,
(structsockaddr*)&icmpgw,(structrtentry**)0);
其中,
参数(structsockaddr*)&icmpsrc表示“无效数据报的目的地地址”,
参数(structsockaddr*)&icmpdst表示“ICMP报文中的推荐下一跳地址”,
参数(structsockaddr*)&icmpgw表示“ICMP数据报的源地址”。
这行程序的作用是:
根据“ICMP数据报的源地址、ICMP报文中的推荐下一跳地址、无效数据报的目的地地址”来更新路由表。
rtredirect()函数的参数和返回值如下。
int
rtredirect(dst,gateway,netmask,flags,src,rtp)
structsockaddr*dst,*gateway,*netmask,*src;
intflags;
structrtentry**rtp;
5.1.2.1.3pfctlinput函数
如果收到的是ICMP重定向差错报文,则icmp_input调用pfctlinput()函数,如下。
pfctlinput(PRC_REDIRECT_HOST,(structsockaddr*)&icmpsrc);
上面一行程序的第一个参数表示“重定向”,第二个参数是“无效数据报的目的地地址”。
这行程序的作用是:
根据“无效数据报的目的地地址”来通告重定向的所有协议域,使协议有机会把缓存的到目的站的路由作废。
pfctlinput()函数如下。
void
pfctlinput(cmd,sa)
intcmd;
structsockaddr*sa;
{
registerstructdomain*dp;
registerstructprotosw*pr;
for(dp=domains;dp;dp=dp->dom_next)
for(pr=dp->dom_protosw;pr
if(pr->pr_ctlinput)
(*pr->pr_ctlinput)(cmd,sa,(caddr_t)0);
}
5.1.2.1.4rip_input函数
该函数的参数和返回值如下。
void
rip_input(m)
structmbuf*m;
如果收到的是“ICMP回答报文、路由器请求报文、未识别的ICMP报文”,则icmp_input调用rip_input()函数,把这些报文传给等待ICMP报文的进程。
5.1.2.2上层——>ICMP模块
5.1.2.2.1icmp_error函数
传输层和IP层(注:
IP层是ICMP的下层)调用icmp_error()函数来构造ICMP差错报文
icmp_error()函数的参数和返回值如下。
void
icmp_error(n,type,code,dest,destifp)
structmbuf*n;
inttype,code;
n_longdest;
structifnet*destifp;
其中,
参数n表示“指向包含无效数据报缓存链的指针”,
type表示ICMP差错类型,
code表示ICMP差错代码,
dest表示ICMP重定向报文中的下一跳路由器地址(只有当要发送ICMP重定向的时候才用到该参数),
destifp表示指向原IP数据报外出接口的指针(只有当要发送“需要进行分片但是设置了不分片比特”的目的不可达报文的时候才用到该参数)。
5.1.2.2.2rip_output函数
上层用该函数输出请求报文和路由器回答报文。
rip_output函数的参数和返回值如下。
int
rip_output(m,so,dst)
registerstructmbuf*m;
structsocket*so;
u_longdst;
其中,
参数m表示“指向外出IP数据报缓存链的指针”,
参数so表示“指向相应插口的指针”,
参数dst表示“IP数据报的目的IP地址”(只有当进程没有提供IP首部的情况下才用到该参数)。
5.2控制接口
5.2.1概况
下面是protosw结构的定义。
下面是ICMP的protosw结构。
5.2.2rip_ctloutput函数
该函数的参数和返回值如下。
int
ip_ctloutput(op,so,level,optname,mp)
intop;
structsocket*so;
intlevel,optname;
structmbuf**mp;
其中
参数op的值为PRCO_SETOPT或PRCO_GETOPT。
表示上层是要设置某些选项,还是要读取某些选项。
参数so为插口描述符。
参数level为操作的协议,它的值必须为IPPROTO_IP。
参数mp为包含设置值的mbuf指针。
参数optmane为选项名,它的取值和相应的描述如下表。
参数optmane的取值
描述
IP_HDRINCL
设置或者读取inp_flags的INP_HDRINCL比特位。
该比特位表示进程是否有提供IP首部,在rip_output函数中有用到。
DVMRP_INIT
这些选项关于多播。
目前我们不关心多播的内容。
DVMRP_DONE
DVMRP_ADD_VIF
DVMRP_DEL_VIF
DVMRP_ADD_LGRP
DVMRP_DEL_LGRP
DVMRP_ADD_MRT
DVMRP_DEL_MRT
其他值
交给ip_ctloutput函数处理
5.2.3rip_usrreq函数
该函数的分析由肖志给出。
5.2.4icmp_sysctl函数
该函数的参数和返回值如下。
int
icmp_sysctl(name,namelen,oldp,oldlenp,newp,newlen)
int*name;
u_intnamelen;
void*oldp;
size_t*oldlenp;
void*newp;
size_tnewlen;
该函数是用来修改全局变量icmpmaskrepl的。
icmpmaskrepl的默认值是0,icmp_sysctl可以修改它。
如果icmpmaskrepl非零,Net/3会响应地址掩码请求。
除非系统被明确地配置成地址掩码的授权代理(icmpmaskrepl非零),否则,RFC1122禁止其发送掩码回答。
这样,就避免系统与所有向它发出请求的系统共享不正确的地址掩码。
5.3OS接口
5.3.1microtime函数
函数的参数和返回值如下。
void
microtime(tvp)
structtimeval*tvp;
该函数的作用如下。
返回从UTC1970年1月1日午夜以来的时间,放在timeval结构中。
在iptime函数中,会调用microtime函数。
iptime函数以网络字节序返回从UTC1970年1月1日午夜以来的毫秒数。
在时间戳选项处理等等地方会用到iptime函数。
5.3.2m_freem函数
函数参数和返回值如下。
void
m_freem(m)
registerstructmbuf*m;
函数的作用如下。
释放m指向的mbuf链表中的所有mbuf。
5.3.3m_gethdr函数
该函数的参数和返回值如下。
structmbuf*m_gethdr(intnowait,inttype)
该函数是宏MGETHDR的函数版本。
5.3.4m_get函数
函数参数和返回值如下。
structmbuf*m_get(intnowait,inttype);
该函数的作用如下。
向OS申请一个type类型的mbuf。
6ICMP指标
6.1ICMP主机需求指标(RFC1122)
指标
位置
描述
4.4BSD-Lite实现
备注
6.1.1概要分析(GENERALISSUES)
如果主机收到一个类型未知的ICMP报文,主机必须安静地丢弃该报文。
3.2.2
MUST
部分支持:
icmp_input把未知的ICMP报文直接交给rip_input。
rip_input把ICMP报文交给任何等待进程,或者在没有进程接收的情况下将其安静的丢弃。
建议ICMP差错报文携带原IP数据报数据部分的至少前8个字节
3.2.2
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- icmp报文格式 各种 icmp 报文 格式