ICMP在IP系统间传递差错和管理报文,是任何IP实现必须和要求的组成部分。可以把ICMP分成两类:差错和查询。查询报文
是用一对请求和回答定义的。差错报文通常包含了引起错误的IP包的第一个分片的IP首部(和选项),加上该分片数据部分
的前8个字节。
下图显示了所有目前定义的ICMP报文。双线上面的是请求和回答报文,双线下面的是差错报文。
PRC_栏显示了Net/3处理的与协议无关的差错码和ICMP报文之间的映射。对请求和回答,这一列是空的。因为在这种情况
下不会产生差错。如果对一个ICMP差错,这一行为空,说明Net/3不识别该码,并自动丢弃该差错报文。
1.icmp结构
Net/3通过下图中的icmp结构访问某个ICMP报文。
icmp_type标识特定报文,icmp_code进一步制定报文。icmp_cksum的算法与IP首部检验和相同。
联合icmp_hun(首部联合)和icmp_dun(数据联合)按照icmp_type和icmp_code访问多种icmp报文。每个icmp报文都使用
icmphun;只有一部分报文使用icmp_dun。没有使用的字段必须设置为0.
icmp报文时封装在IP数据报中的。
2.ICMP的protosw结构
inetsw[4]的protosw结构描述了icmp,并支持内核和进程对协议的访问。下图显示了该结构。
ipintr对数据报进行分用是根据IP首部中的传输协议编号ip_p。对于ICMP报文,ip_p是1,通过ip_protox选择inetsw[4]。
3.输入处理:icmp_input函数
当一个icmp报文到达时,IP层通过inetsw[4]的pr_input函数,间接调用icmp_input。
在icmp_input中,每一个ICMP报文被处理3次:被icmp_input处理一次;被与ICMP差错报文中的IP分组相关联的传输层协
议处理一次;被记录收到ICMP报文的进程处理一次。
ICMP输入处理过程的总的构成情况如下:
下面分五部分讨论icmp_input:
1.验证收到的报文
2.icmp差错报文
3.icmp请求报文
4.icmp重定向报文
5.icmp回答报文
函数大致流程如下:
判断icmp的报文长度,如果太短,就直接丢弃
↓
icmp包结构中包含校验和字段,使用该字段检查icmp的校验和
↓
判断icmp的报文类型,如果能够识别,根据报文类型执行相应操作;如果无法识别,则直接执行raw操作rip_input
↓
执行raw操作rip_input,rip_input根据报文里含有的协议及源站和目的地址信息,把报文发布给正在监听的进程。
3.1.差错报文处理
当主机发出的数据报无法成功提交给目的主机时,目的主机或中间的路由器生成这些报文,并将它们返回到原来的系统。
下图显示了多种ICMP差错报文的格式:
icmp_input将icmp_type和icmp_code映射到一个协议无关的差错集码上,该差错码是由PRC_常量表示的,且PRC_常量是有
顺序的。如下图所示:
然后icmp_input调用传输层协议的pr_ctlinput函数,该函数根据原始数据报的ip_p,把分组分用到正确的协议,从而构造
出原始的IP数据报。
3.2.请求处理
Net/3响应具有正确格式的ICMP请求报文,把无效的ICMP请求报文传给rip_input。除路由器通告报文外,大多数Net/3所接收
的ICMP请求报文都生成回答报文。为避免回答报文分配新的mbuf,icmp_input把请求报文的缓存转成成回答缓存,并返回给
发送方。
3.2.1.回显询问:ICMP_ECHO和ICMP_ECHOREPLY
ping程序就是使用了回显询问请求。下图是ICMP回显请求和回答报文的结构。
icmp_code总是0,icmp_id和icmp_seq设置成请求的发送方,回答中也不做修改。源系统可以用这些字段匹配请求和回答。
icmpdata中到达的所有数据也被反射。
3.2.2.时间戳询问:ICMP_TSTAMP和ICMP_TSTAMPREPLY
ICMP时间报文如下图所示:
请求的发送方设置icmp_otime(发出请求的时间),icmp_rtime(收到请求的时间)和icmp_ttime(发出回答的时间)由回答
的发送方设置。所有时间都是从UTC午夜开始的毫秒数。如果时间值没有以标准单位记录,就把高位置位,与IP时间戳选项
一样。
3.2.3.地址掩码询问:ICMP_MASKREQ和ICMP_MASKREPLY
该请求可以发现某个网络上使用的子网掩码。
除非系统被明确地配置成地址掩码的授权代理,否则,RFC1122禁止向其发送掩码回答。这样就避免系统与所有向它发送请求
的系统共享不正确的地址掩码。如果没有管理员授权回答,系统也要忽略地址掩码请求。
ICMP地址掩码请求和回答如下图所示:
3.2.4.信息查询:ICMP_IREQ和ICMP_IREQREPLY
ICMP信息报文已经过时。它们企图广播一个源和目的站地址字段的网络部分为全0的请求,使系统发现连接的IP网络的数量。
响应该请求的主机将返回一个填好网络号的报文,主机还需要其他办法找到地址的主机部分。
3.2.5.路由器发现:ICMP_ROUTERADVERT和ICMP_ROUTESOLICIT
RFC1256定义了ICMP路由器发现报文,Net/3内核不直接处理这些报文,而由rip_input把它们传给一个用户级守护程序,由它
发送和响应这种报文。
3.3.重定向处理
下图显示了ICMP重定向报文的格式。
重定向信息被传给rtredirect,由这个函数更新路由表。重定向的目的地址被传给pfctlinput,由它通告重定向的所有协议域,使
协议有机会把缓存的到目的站的路由作废。
3.4.回答处理
内核从不处理任何ICMP回答报文,ICMP请求由进程产生,内核从不产生请求。所以内核把它接收的所有回答传给等待ICMP
报文的进程。内核直接将报文传给rip_input交给传输层进行处理。
3.5.输出处理
有几种方法产生外出的报文。IP调用icmp_error来产生和发送ICMP差错报文。icmp_reflect发送回答报文。同时,进程也可能
通过原始ICMP协议生成ICMP报文。下图显示了这些函数与ICMP外出处理之间的关系。
3.6.icmp_sysctl函数
IP的icmp_sysctl函数只支持下图中列出的选项。系统管理员可以用sysctl程序修改该选项。
《TCP/IP详解卷2:实现》笔记--ICMP:Internet控制报文协议,布布扣,bubuko.com