《TCP/IP详解卷2:实现》笔记--选路请求和选路消息

来源:互联网 发布:cmd 映射网络磁盘 编辑:程序博客网 时间:2024/06/05 05:30

内核的各种协议并不直接使用前面提供的函数来访问选路树,而是调用几个函数:rtalloc和rtallocl是完成路由表查询的两个

函数;rtrequest函数用于添加和删除路由表项;另外大多数接口在接口连接或断开时都会调用函数rtinit。

选路消息在两个方向上传递信息。进程(route命令)或守护进程(routed或gated)把选路消息写入选路插口,以使内核添加

路由、删除路由或者修改现有的路由。当有时间发生时,如接口断开、收到重定向等,内核也会发送选路消息。进程通过选路

插口来读取它们感兴趣的内容。

内核还提供了另一种访问路由表的接口,即系统的sysctl调用。


1.rtalloc和rtalloc1函数

通常,路由表的查找通过调查rtalloc和rtalloc1函数来实现的。rtalloc调用rtalloc1,rtalloc1调用rnh_matchaddr函数,对于

Internet地址来说,该函数就是rn_match函数。

rtalloc1的大概处理流程如下:

调用rn_match,如果符合下列三个条件,则查找成功。

1)存在该协议族的路由表。

2)rn_match返回一个非空指针;并且

3)匹配的radix_node结构没有设置RNF_ROOT标志。

如果查找成功,则指向匹配的radix_node结构的指针保存在rt中。如果调用的第二个参数非0,而且匹配的路由表设有

RTF_CLONING标志,则调用rtrequest函数发送RTM_RESOLVE命令来创建一个新的rtentry结构,该结构是查询结果的

克隆。


2.宏RTFREE和rtfree函数

宏RTFREE,仅在引用计数小于等于1时才调用rtfree函数;否则,它仅完成引用计数的递减。


3.rtrequest函数

rtrequest函数是添加和删除路由表项的关键点。下图给出了调用它的一些其他函数。


rtrequest是一个switch语句,每个case对应一个命令:RTM_ADD、RTM_DELETE和RTM_RESOLVE。

对于RTM_DELETE命令:

1.从选路树中删除路由

2.删除对网络路由表项的引用。

3.调用接口请求函数。如果该表项定义了ifa_rtrequest函数,就调用该函数。ARP会使用该函数。

4.返回指针或删除引用。如果调用者需要选路树中被删除的rtentry结构指针,则返回该指针,但此时不能释放该表项,调用

这必须使用完该表项后调用rtfree来删除它。


对于RTM_RESOLVE命令:

只有rtalloc1能够携带此命令参数调用本函数。也只有在从一个设有RTF_CLONING标志的表项中克隆一个新的表项时,

rtalloc1才这么用。

这个命令将跳转到makeroute标记处继续执行。


对于RTM_ADD命令:

定位相应的接口。查找适当的本地接口,并返回指向该接口的ifaddr结构的指针。

进入makeroute标记处执行。


makeroute的大概处理流程如下:

1.为路由表项分配存储器。分配rtentry结构。

2.分配并复制网关地址。

3.复制目的地址。

4.往选路树中添加表项(rtentry结构)。

5.保存接口指针。递增ifaddr结构的引用计数,并保存ifaddr和ifnet结构的指针。

6.为新克隆的路由复制度量。如果是RTM_RESOLVE,则把被克隆的表项中的整个度量结构复制到新的表项里。如果是

RTM_ADD,则调用者可在函数返回后设置该度量值。

7.调用接口请求函数。如果为该表项定义了ifa_rtrequest函数,则调用该函数。

8.返回指正并递增引用计数。如果调用者需要改新结构的指针,在返回该指针,并将该引用计数值从0递增到1。


4.rtinit函数

Internet协议添加或删除相关接口的路由时,对rtinit的调用有四个。

1.在设置点到点接口的目的地址时,in_control调用rtinit两次。第一次调用指定RTM_DELETE命令,以删除所有现存的到

该目的地址的路由,第二次调用指定RTM_ADD命令,以添加新路由。

2.in_ifinit调用rtinit为广播网络添加一条网络路由或为点到点链路添加一条主机路由。如果是给以太网接口添加的路由。

3.in_ifscrub调用rtinit,以删除一个接口现存的路由。

函数的大概处理流程如下:

1.为路由获取目的地址。如果是一个到达某主机的路由,则目的地址是点到点链路的另一端。否则,我们处理的就是一个

网络路由,其目的地址是接口的单播地址。

2.如果要删除路由,则必须在路由表中查找该目的地址,并得到它的路由表。

3.调用rt_request执行RTM_ADD或者RTM_DELETE命令。

4.如果删除成功,则产生一个选路消息。

5.如果添加成功但是新路由表项接口的ifaddr指针不等于调用参数,则表明有差错产生。做如下步骤:向控制台输出一条

出错消息;如果rt_request获得到的rtentry中ifa_rtrequest函数(rt->ifa->ifa_rtrequest),就以RTM_DELETE为参数调用

它。如果函数的参数中ifa定义了ifa_rtrequest函数,就以RTM_ADD为参数调用它。最后产生选路消息。


5.rtredirct函数

当收到一个ICMP重定向后,icmp_input调用rtredirect及pfctlinput。后一个函数又调用udp_cltinput和tcp_ctlinput,这两个

函数遍历所有的UDP和TCP协议控制块(PCB)。如果PCB连接到一个外部地址,而到该外部地址的方向已经被改变,并且

该PCB持有到那个外部地址的路由,则调用rtfree释放该路由。下一次使用这些控制块发送外部地址的IP数据报时,就会调用

rtalloc,并在路由表中查找该目的地址,很可能会找到一条新的路由。

rtredirect函数的作用是验证重定向中的信息,并立即更新路由表,产生选路插口消息。该函数的大概处理流程如下:

1.新路由必须直接相连,否则该重定向失效。

2.查找目的地址的路由表项并验证重定向。调用rtalloc1在路由表中查找到目的地址的路由。验证重定向时,下列条件必须为

真:

  必须未设置RTF_DONE标志。

  rtalloc必须已经找到一个到dst的路由表项。

  发送重定向的路由器的地址必须等于当前为目的地址设置的rt_gateway.

  新网关的接口必须等于当前为目的地址设置的接口,也就是说,新网关必须和当前网关在同一网络上。

  新网关不能把到这个主机的路由改变到自己,也就是说,不能存在与gateway相等的有单播地址或广播地址的连接着的接口。

3.创建新的主机路由。如果到达目的地址的当前路由是一个网络路由,并且重定向是主机重定向而不是网络重定向,那么就为

该目的地址建立一个主机路由(调用rtrequest,RTM_ADD),而不必去管现存的网络路由。

4.改变现存的主机路由。当到达目的地址的当前路由已经是一个主机路由时,不需要创建新的表项,而是修改现存的表项。

5.由rt_missmsg产生一个选路插口消息。


6.选路消息的结构

选路消息有一个定长的首部和至多8个插口地址结构组成。该定长首部是下列三种结构中的一个:

rt_msghdr

if_msghdr

ifa_msghdr

选路消息三种首部结构的前三个成员的数据类型及其含义是相同的,分别为:消息的长度,版本和类型。每中结构都都有

一个成员来编码首部之后8个可能的插口地址:rtm_addr、ifm_addrs和ifam_addrs成员,它们都是一个比特掩码。

下图给出了最常用的结构,rt_msghdr。


RTM_IFINFO消息使用了下图的if_msghdr结构。


RTM_NEWADDR和RTM_DELADDR消息使用了下图的ifa_msghdr结构。


三个变量rtm_addrs、ifm_addrs和ifam_addrs都是比特掩码,它们定义了首部之后的插口地址结构,下图给出了比特掩码

用到的一些常量。


内核用上图的数组下标来引用rt_addrinfo结构,如下图所示。


如果rti_addrs成员中设置了RTA_GATEWAY比特,则rti_info[RTA_GATEWAY]成员就是含网关地址的插口地址结构的指针。


7.rt_missmsg函数

rt_missmsg函数使用了rt_addrinfo结构,并调用rt_msg1在mbuf链中为进程创建了相应的变长消息,之后调用raw_input将

该mbuf链传递给所有相关的选路插口。函数的处理流程如下:

1.在mbuf中创建消息。rt_msg1在mbuf链中创建相应的消息,并返回该链的指针,下图为rt_msg1创建的一个mbuf链。


2.完成消息的创建。设置rt_msghdr的其他成员。

3.设置消息的协议,调用raw_input。


8.rt_ifmsg函数

在if_up和if_down中都调用了rt_ifmsg。在接口连接或断开时,该函数被用来产生一个选路插口消息。函数的大概处理流程

如下:

1.调用rt_msg1函数在mbuf链中创建消息。

2.完成消息的创建。设置if_msghdr接口中其他成员。

3.设置消息的协议,调用raw_input。


9.rt_newaddrmsg函数

在接口上添加或者删除一个地址时,rtinit要以RTM_ADD或者RTM_DELETE为参数调用rt_newaddrmsg。函数的大概处理

流程如下:

1.调用rt_msg1函数在mbuf链中创建消息。

2.完成消息的创建。设置ifa_msghdr接口中其他成员。

3.设置消息的协议,调用raw_input。

0 0
原创粉丝点击