2013-08-27 15:37:42
6.5 ICMP端口不可达差错
端口不可达报文是ICMP差错报文的一种,它是ICMP不可达报文中的一种,以此来看一看ICMP差错报文中所附加的信息。使用UDP来查看它(第11章)。
UDP的规则之一是,如果收到一份UDP数据报而目的端口与某个正在使用的进程不相符,那么UDP返回一个ICMP不可达报文。可以用TFTP来强制生成一个端口不可达报文(第15章)。
下面通过一个实例来讲解整个过程,例子为用TFTP协议向另一台主机的错误端口发送UDP请求(UDP正确的端口号为69),以接收一个文件:
通过tcpdump命令查看报文交换结果:
我们向错误的端口8888发送了UDP请求,在此之前我们不许通过ARP协议全网广播获得svr4主机的物理地址。我们看到在第一收到ICMP端口不可达差错的报文之后,主机又发送了4次相同的请求才放弃,而每次的请求间隔时间基本相同(这种算法比较烂,已被RFC禁用)。注意:ICMP报文实在主机之间交换的,而不用目的端口号,而每个20字节的UDP数据报则是从一个特定端口(2924)发送到另一个特定端口(8888)。
上图为ICMP端口不可达报文的格式,长度为70字节。ICMP的一个规则是,ICMP差错报文必须包括生成该差错报文的数据报IP首部(包含任何选项),还必须包括跟在该IP首部后面的前8个字节。例如,上图中最后八个字节(跟在差错数据报IP首部后边),就包含了UDP的首部。而UDP首部中的内容是源端口号和目的端口号。接收ICMP的系统可以根据源端口号(2924)来找到那个对应的用户进程(例子中的是TFTP客户程序)。而导致差错的数据报中的IP首部要被送过来的原因是,IP首部中包含了协议字段,使得ICMP可以知道如何解释后面的8个字节(本例可以判断出是UDP请求)。
注意:尽管上图中指出了在ICMP报文中的第二个32bit字必须为0,但是当代码为4时(“需要分片但设置了不分片比特”),路径MTU发现机制却允许路由器把外出接口的MTU填在这个32bit字的低16bit中(11.6节)。
6.6 ICMP报文的4.4BSD处理
下图为4.4BSD系统对每个可能的ICMP报文的处理方法:
如果最后一行标明是“内核”,那么ICMP就由内核来处理。如果最后一列指明是“用户进程”,那么报文就被传送到所有在内核中登记的用户进程,以读取收到的ICMP报文。如果不存在任何这样的用户进程,那么报文就悄悄的被丢弃(这些用户进程还会收到所有其他类型的ICMP报文的拷贝,虽然它们应该由内核来处理,当然用户进程只有在内核处理以后才能收到这些报文)。有一些报文会完全被忽略。最后,如果最后一列标明的是引号内的一串字符,那么它就是对应的Unix差错。其中一些差错,如TCP对发送端关闭的处理等,我们将在以后的章节中对它们进行讨论。
6.7 小结
本章对每个系统都必须包括的Internet控制报文协议进行了讨论。图6-3列出了所有ICMP报文类型,其中大部分会在今后的章节中讨论。
我们详细讨论了ICMP地址掩码请求和应答以及时间戳请求和应答。这些是典型的请求—应答报文。二者在ICMP中都有标识符和序列号。发送端应用程序在标识字段内存入一个唯一的数值,以区别其他进程的应答。序列号字段使得客户程序可以在应答和请求之间进行匹配。
我们还讨论了ICMP端口不可达差错,一种常见的ICMP差错。对返回的ICMP差错信息进行了分析:导致差错的IP数据报的首部及后续8个字节。这个信息对于ICMP差错的接收放来说是必要的,可以更多的了解导致差错的原因。这是因为TCP和UDP都在它们的首部前8个字节中存入源端口号和目的端口号。