1. 程式人生 > >《TCP/IP詳解卷2:實現》筆記--選路請求和選路訊息

《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。