《TCP/IP詳解卷2:實現》筆記--選路請求和選路消息

內核的各種協議並不直接使用前面提供的函數來訪問選路樹,而是調用幾個函數: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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章