当I P数据报应该被发送到另一个路由器时,收到数据报的路由器就要发送ICMP重定向差错报文给I P数据报的发送端。这在概念上是很简单的,正如图9 - 3所示的那样。只有当主机可以选择路由器发送分组的情况下,我们才可能看到ICMP重定向报文(回忆我们在图7 - 6中看过的例子)
1) 我们假定主机发送一份I P数据报给R 1。这种选路决策经常发生,因为R 1是该主机的默认路由。
2) R1收到数据报并且检查它的路由表,发现R 2是发送该数据报的下一站。当它把数据报发送给R 2时,R 1检测到它正在发送的接口与数据报到达接口是相同的(即主机和两个路由器所在的L A N)。这样就给路由器发送重定向报文给原始发送端提供了线索。
3) R1 发送一份ICMP重定向报文给主机,告诉它以后把数据报发送给R 2而不是R 1。
重定向一般用来让具有很少选路信息的主机逐渐建立更完善的路由表。主机启动时路由表中可以只有一个默认表项(在图9 - 3所示的例子中,为R 1或R 2)。一旦默认路由发生差错,默认路由器将通知它进行重定向,并允许主机对路由表作相应的改动。ICMP重定向允许TCP/IP主机在进行选路时不需要具备智能特性,而把所有的智能特性放在路由器端。显然,在我们的例子中,R 1和R2 必须知道有关相连网络的更多拓扑结构的信息,但是连在LAN上的所有主机在启动时只需一个默认路由,通过接收重定向报文来逐步学习。
9.5.1 一个例子
可以在我们的网络上观察到ICMP重定向的操作过程(见封二的图)。尽管在拓扑图中只画出了三台主机(aix,solaris和gemini和两台路由器(gateway和netb),但是整个网络有超过150台主机和10台另外的路由器。大多数的主机都把gateway指定为默认路由器,因为它提供了Internet的入口。
子网140.252.1上的主机是如何访问作者所在子网(图中底下的四台主机)的呢?首先,如果在SLIP链路的一端只有一台主机,那么就要使用代理ARP(4.6节)。这意味着位于拓扑图顶部的子网(140.252.1)中的主机不需要其他特殊条件就可以访问主机sun(140.252.1.29)。位于netb上的代理A R P软件处理这些事情。
但是,当网络位于SLIP链路的另一端时,就要涉及到选路了。一个办法是让所有的主机和路由器都知道路由器netb是网络140.252.13的网关。这可以在每个主机的路由表中设置静态路由,或者在每个主机上运行守护程序来实现。另一个更简单的办法(也是实际采用的方法)是利用ICMP重定向报文来实现。
在位于网络顶部的主机solaris上运行ping程序到主机bsdi(140.252.13.35)。由于子网号不相同,代理ARP不能使用。假定没有安装静态路由,发送的第一个分组将采用到路由器gateway的默认路由。下面是我们运行ping程序之前的路由表:
(224.0.0.0所在的表项是IP广播地址。我们将在第12章讨论)。如果为ping程序指定-v选项,可以看到主机接收到的任何ICMP报文。我们需要指定该选项以观察发送的重定向报文。
在收到ping程序的第一个响应之前,主机先收到一份来自默认路由器gateway发来的ICMP重定向报文。如果这时查看路由表,就会发现已经插入了一个到主机bsdi的新路由(该表项如以下黑体字所示)。
这是我们第一次看到D标志,表示该路由是被ICMP重定向报文创建的。G标志说明这是一份到达gateway(netb)的间接路由,H标志则说明这是一个主机路由(正如我们期望的那样),而不是一个网络路由。
由于这是一个被主机重定向报文增加的主机路由,因此它只处理到达主机bsdi的报文。如果我们接着访问主机svr4,那么就要产生另一个ICMP重定向报文,创建另一个主机路由。类似地,访问主机slip也创建另一个主机路由。位于子网上的三台主机(bsdi,svr4和slip)还可以由一个指向路由器sun的网络路由来进行处理。但是ICMP重定向报文创建的是主机路由,而不是网络路由,这是因为在本例中,产生ICMP重定向报文的路由器并不知道位于140.252.13网络上的子网信息。
9.5.2 更多的细节
ICMP重定向报文的格式如图9 - 4所示。
有四种不同类型的重定向报文,有不同的代码值,如图9 - 5所示。
ICMP重定向报文的接收者必须查看三个I P地址:( 1 )导致重定向的I P地址(即ICMP重定向报文的数据位于I P数据报的首部); ( 2 )发送重定向报文的路由器的I P地址(包含重定向信息的I P数据报中的源地址;( 3 )应该采用的路由器I P地址(在ICMP报文中的4 ~ 7字节)。
关于ICMP重定向报文有很多规则。首先,重定向报文只能由路由器生成,而不能由主机生成。另外,重定向报文是为主机而不是为路由器使用的。假定路由器和其他一些路由器共同参与某一种选路协议,则该协议就能消除重定向的需要(这意味着在图9 - 1中的路由表应该消除或者能被选路守护程序修改,或者能被重定向报文修改,但不能同时被二者修改)。
在4 . 4 BSD系统中,当主机作为路由器使用时,要进行下列检查。在生成ICMP重定向报文之前这些条件都要满足。
1) 出接口必须等于入接口。
2) 用于向外传送数据报的路由不能被ICMP重定向报文创建或修改过,而且不能是路由器的默认路由。
3) 数据报不能用源站选路来转发。
4) 内核必须配置成可以发送重定向报文。
内核变量取名为ip_sendredirects或其他类似的名字(参见附录E)。大多数当前的系统(例如BSD、SunOS 4.1.x、Solaris 2.x 及AIX 3.2.2)在默认条件下都设置该变量,使系统可以发送重定向报文。其他系统如SVR4则关闭了该项功能。
另外,一台4 . 4 BSD主机收到ICMP重定向报文后,在修改路由表之前要作一些检查。这是为了防止路由器或主机的误操作,以及恶意用户的破坏,导致错误地修改系统路由表。
1) 新的路由器必须直接与网络相连接。
2) 重定向报文必须来自当前到目的地所选择的路由器。
3) 重定向报文不能让主机本身作为路由器。
4) 被修改的路由必须是一个间接路由。
关于重定向最后要指出的是,路由器应该发送的只是对主机的重定向(代码1或3,如图9 - 5所示),而不是对网络的重定向。子网的存在使得难于准确指明何时应发送对网络的重定向而不是对主机的重定向。只当路由器发送了错误的类型时,一些主机才把收到的对网络的重定向当作对主机的重定向来处理。