- 論壇徽章:
- 1
|
TCP/IP詳解(二)
4.5 ARP舉例
在本小節(jié)中,我們用tcpdump命令來看一看運(yùn)行像Telnet這樣的普通TCP工具軟件時ARP會做些什么。附錄A包含tcpdump命令的其它細(xì)節(jié)。
普通例子
為了看清楚ARP的運(yùn)作過程,我們執(zhí)行telnet命令與無效的服務(wù)器連接。
(見原書p.57的①)
當(dāng)我們在另一個系統(tǒng)上(sun)運(yùn)行帶有-e參數(shù)的tcpdump命令時,顯示的是硬件地址(在我們的例子中是48 bit的以太網(wǎng)地址。)
圖4.4 TCP連接請求產(chǎn)生的ARP請求和回答
圖4.4中的tcpdump的原始輸出如圖附錄A中的A.3所示。由于這是本書第一個tcpdump輸出例子,你應(yīng)該去查看附錄中的原始輸出,看看我們作了哪些修改。
我們刪除了tcpdump命令輸出的最后四行,因?yàn)樗鼈兪墙Y(jié)束連接的信息(我們將在第18章進(jìn)行討論),與這里討論的內(nèi)容不相關(guān)。
在第1行中,源端主機(jī)(bsdi)的硬件地址是0:0:c0:6f:2d:40。目的端主機(jī)的硬件地址是ff:ff:ff:ff:ff:ff,這是一個以太網(wǎng)廣播地址。電纜上的每個以太網(wǎng)接口都要接收這個數(shù)據(jù)幀并對它進(jìn)行處理,如圖4.2所示。
第1行中緊接著的一個輸出字段是arp,表明幀類型字段的值是0x0806,說明此數(shù)據(jù)幀是一個ARP請求或回答。
在每行中,單詞arp或ip后面的值60指的是以太網(wǎng)數(shù)據(jù)幀的長度。由于ARP請求或回答的數(shù)據(jù)幀長都是42字節(jié)(28字節(jié)的ARP數(shù)據(jù),14字節(jié)的以太網(wǎng)幀頭),因此每一幀都必須加入填充字符以達(dá)到以太網(wǎng)的最小長度要求:60字節(jié)。
請參見圖1.7,這個最小長度60字節(jié)包含14字節(jié)的以太網(wǎng)幀頭,但是不包括4個字節(jié)的以太網(wǎng)幀尾。有一些書把最小長度定為64字節(jié),它包括以太網(wǎng)的幀尾。我們在圖1.7中把最小長度定為46字節(jié),是有意不包括14字節(jié)的幀首部,因?yàn)閷?yīng)的最大長度(1500字節(jié))指的是MTU――最大傳輸單元(圖2.5)。我們使用MTU經(jīng)常是因?yàn)樗鼘P數(shù)據(jù)報的長度進(jìn)行限制,但一般與最小長度無關(guān)。大多數(shù)的設(shè)備驅(qū)動程序或接口卡自動地用填充字符把以太網(wǎng)數(shù)據(jù)幀充滿到最小長度。第3,4和5行中的IP數(shù)據(jù)報(包含TCP段)的長度都比最小長度小,因此都必須進(jìn)行填充到60字節(jié)。
第1行中的下一個輸出字段arp who-has表示作為ARP請求的這個數(shù)據(jù)幀中,目的IP地址是svr4的地址,發(fā)送端的IP地址是bsdi的地址。tcpdump打印出主機(jī)名對應(yīng)的默認(rèn)IP地址。(在4.7節(jié)中,我們將用-n參數(shù)來查看ARP請求中真正的IP地址。)
從第2行中我們可看到,盡管ARP請求是廣播的,但是ARP回答的目的地址卻是bsdi(0:0:c0:6f:2d:40)。ARP回答是直接送到請求端主機(jī)的,而是廣播的。
tcpdump打印出arp reply的字樣,同時打印出響應(yīng)者的主機(jī)名和硬件地址。
第3行是第一個請求建立連接的TCP段。它的目的硬件地址是目的主機(jī)(svr4)。我們將在第18章討論這個段的細(xì)節(jié)內(nèi)容。
在每一行中,行號后面的數(shù)字表示tcpdump收到分組的時間(以秒為單位)。除第1行外,其它每行在括號中還包含了與上一行的時間差異(以秒為單位)。我們從這個圖可以看出,發(fā)送ARP請求與收到ARP回答之間的時延是2.2 ms。而在0.7 ms之后發(fā)出第一段TCP報文。在本例中,用ARP進(jìn)行動態(tài)地址解析的時間小于3 ms。
最后需要指出的一點(diǎn),在tcpdump命令輸出中,我們沒有看到svr4在發(fā)出第一段TCP報文(第4行)之前發(fā)出的ARP請求。這是因?yàn)榭赡茉趕vr4的ARP高速緩存中已經(jīng)有bsdi的表項(xiàng)。一般情況下,當(dāng)系統(tǒng)收到ARP請求或發(fā)送ARP回答時,都要把請求端的硬件地址和IP地址存入ARP高速緩存。在邏輯上可以假設(shè),如果請求端要發(fā)送IP數(shù)據(jù)報,那么數(shù)據(jù)報的接收端將很可能會發(fā)送一個回答。
對不存在主機(jī)的ARP請求
如果查詢的主機(jī)已關(guān)機(jī)或不存在會發(fā)生什么情況呢?為此我們指定一個并不存在的Internet地址――根據(jù)網(wǎng)絡(luò)號和子網(wǎng)號所對應(yīng)的網(wǎng)絡(luò)確實(shí)存在,但是并不存在所指定的主機(jī)號。從圖3.10我們可以看出,主機(jī)號從36到62的主機(jī)并不存在(主機(jī)號為63是廣播地址)。這里,我們用主機(jī)號36來舉例子。
(見原書p.59的①)
tcpdump命令的輸出如圖4.5所示。
圖4.5 對不存在主機(jī)的ARP請求
這一次,我們沒有用-e選項(xiàng),因?yàn)槲覀円呀?jīng)知道ARP請求是在網(wǎng)上廣播的。
令人感興趣的是看到多次進(jìn)行ARP請求:第一次請求發(fā)生后5.5秒進(jìn)行第二次請求,在24秒之后又進(jìn)行第三次請求。(在第21章我們將看到TCP的超時和重發(fā)算法的細(xì)節(jié)。)tcpdump命令輸出的超時限制為29.5秒。但是,在telnet命令使用前后分別用date命令檢查時間,可以發(fā)現(xiàn)Telnet客戶端的連接請求似乎在大約75秒后才放棄。事實(shí)上,我們在后面將看到,大多數(shù)的BSD實(shí)現(xiàn)把完成TCP連接請求的時間限制設(shè)置為75秒。
在第18章中,當(dāng)我們看到建立連接的TCP報文段序列時,會發(fā)現(xiàn)ARP請求對應(yīng)于TCP試圖發(fā)送的初始TCP SYN(同步)段。
注意,在線路上我們始終看不到TCP的報文段。我們能看到的是ARP請求。直到ARP回答返回時,TCP報文段才可以被發(fā)送,因?yàn)橛布刂返竭@時才可能知道。如果我們用過濾模式運(yùn)行tcpdump命令,只查看TCP數(shù)據(jù),那么將沒有任何輸出。
ARP 高速緩存超時設(shè)置
在ARP高速緩存中的表項(xiàng)一般都要設(shè)置超時值。(在4.8小節(jié)中,我們將看到管理員可以用arp命令把地址放入高速緩存中而不設(shè)置超時值。)從伯克利系統(tǒng)演變而來的系統(tǒng)一般對完整的表項(xiàng)設(shè)置超時值為20分鐘,而對不完整的表項(xiàng)設(shè)置超時值為3分鐘。(在前面的例子中我們已見過一個不完整的表項(xiàng),即在以太網(wǎng)上對一個不存在的主機(jī)發(fā)出ARP請求。)當(dāng)這些表項(xiàng)再次使用時,這些實(shí)現(xiàn)一般都把超時值重新設(shè)為20分鐘。
(下面是原書p.60①的譯文)
在RFC中說,在表項(xiàng)正在使用時,超時值就應(yīng)該啟動,但是大多數(shù)的從伯克利系統(tǒng)演變而來的系統(tǒng)沒有這樣做――它們每次都是在訪問表項(xiàng)進(jìn)重設(shè)超時值。
4.6 ARP代理
如果ARP請求是從一個網(wǎng)絡(luò)的主機(jī)發(fā)往另一個網(wǎng)絡(luò)上的主機(jī),那么連接這兩個網(wǎng)絡(luò)的路由器就可以回答該請求,這個過程稱作委托ARP或ARP代理(Proxy ARP)。這樣可以欺騙發(fā)起ARP請求的發(fā)送端,使它誤以為路由器就是目的主機(jī),而事實(shí)上目的主機(jī)是在路由器的“另一邊”。路由器的功能相當(dāng)于目的主機(jī)的代理,把分組從其它主機(jī)轉(zhuǎn)發(fā)給它。
舉例是說明ARP代理的最好方法。如圖3.10所示,系統(tǒng)sun與兩個以太網(wǎng)相連。但是,我們也指出過,事實(shí)上并不是這樣,請把它與封二中的圖進(jìn)行比較。在sun和子網(wǎng)140.252.1之間實(shí)際存在一個路由器,就是這個具有ARP代理功能的路由器使得sun就好像在子網(wǎng)140.252.1上一樣。具體安置如圖4.6所示,路由器Telebit NetBlazer,取名為netb,在子網(wǎng)和主機(jī)sun之間。
圖4.6 ARP代理的例子
當(dāng)子網(wǎng)140.252.1(稱作gemini)上的其它主機(jī)有一份IP數(shù)據(jù)報要傳給地址為140.252.1.29的sun,gemini比較網(wǎng)絡(luò)號(140.252)和子網(wǎng)號(1),因?yàn)樗鼈兌际窍嗤,因而在圖4.6上面的以太網(wǎng)中發(fā)送IP地址140.252.1.29的ARP請求。路由器netb識別出該IP地址屬于它的一個拔號主機(jī),于是把它的以太網(wǎng)接口地址140.252.1作為硬件地址來回答。主機(jī)gemini通過以太網(wǎng)發(fā)送IP數(shù)據(jù)報到netb,netb通過拔號SLIP鏈路把數(shù)據(jù)報轉(zhuǎn)發(fā)到sun。這個過程對于所有140.252.1子網(wǎng)上的主機(jī)來說都是透明的,主機(jī)sun實(shí)際上是在路由器netb后面進(jìn)行配置的。
如果我們在主機(jī)gemini上執(zhí)行arp命令,經(jīng)過與主機(jī)sun通信以后,我們發(fā)現(xiàn)在同一個子網(wǎng)140.252.1上的netb和sun的IP地址映射的硬件地址是相同的。這通常是使用委托ARP的線索。
gemini % arp -a
這里是子網(wǎng)140.252.1上其他主機(jī)的輸出行
netb (140.252.1.183) at 0:80:ad:3:6a:80
sun (140.252.1.29) at 0:80:ad:3:6a:80
圖4.6中的另一個需要解釋的細(xì)節(jié)是在路由器netb的下方(SLIP鏈路)顯然缺少一個IP地址。為什么在拔號SLIP鏈路的兩端只擁有一個IP地址,而在bsdi和slip之間的兩端卻分別有一個IP地址?在3.8小節(jié)我們已經(jīng)指出,用ifconfig命令可以顯示拔號SLIP鏈路的目的地址,它是140.252.1.183。NetBlazer不需要知道拔號SLIP鏈路每一端的IP地址。(這樣做會用更多的IP地址。)相反,它通過分組到達(dá)的串行線路接口來確定發(fā)送分組的拔號主機(jī),因此對于連接到路由器的每個拔號主機(jī)不需要用唯一的IP地址。所有的拔號主機(jī)使用同一個IP地址140.252.1.183作為SLIP鏈路的目的地址。
ARP代理可以把數(shù)據(jù)報傳送到路由器sun上,但是子網(wǎng)140.252.13上的其它主機(jī)是如何處理的呢?路由選擇必須使數(shù)據(jù)報能到達(dá)其它主機(jī)。這里需要特殊處理,路由選擇表中的表項(xiàng)必須在網(wǎng)絡(luò)140.252的某個地方制定,使所有數(shù)據(jù)報的目的端要么是子網(wǎng)140.252.13,要么是子網(wǎng)上的某個主機(jī),這樣都指向路由器netb。而路由器netb知道如何把數(shù)據(jù)報傳到最終的目的端,即通過路由器sun。
ARP代理也稱作混合ARP(promiscuous ARP)或ARP 出租(ARP hack)。這些名字來自于ARP代理的其它用途:通過兩個物理網(wǎng)絡(luò)之間的路由器可以互相隱藏物理網(wǎng)絡(luò)。在這種情況下,兩個物理網(wǎng)絡(luò)可以使用相同的網(wǎng)絡(luò)號,只要把中間的路由器設(shè)置成一個ARP代理,以響應(yīng)一個網(wǎng)絡(luò)到另一個網(wǎng)絡(luò)主機(jī)的ARP請求。這種技術(shù)在過去用來隱藏一組在不同物理電纜上運(yùn)行舊版TCP/IP的主機(jī)。分開這些舊主機(jī)有兩個共同的理由,其一是它們不能處理子網(wǎng)劃分,其二是它們使用舊的廣播地址(所有比特值為0的主機(jī)號,而不是目前使用的所有比特值為1的主機(jī)號)。
4.7 免費(fèi)ARP
我們可以看到的另一個ARP特性稱作免費(fèi)ARP (gratuitous ARP)。它是指主機(jī)發(fā)送ARP查找自己的IP地址。通常,它發(fā)生在系統(tǒng)引導(dǎo)期間進(jìn)行接口配置的時候。
在我們的互聯(lián)網(wǎng)中,如果我們引導(dǎo)主機(jī)bsdi并在主機(jī)sun上運(yùn)行tcpdump命令,我們可以看到如圖4.7所示的分組。
圖4.7 免費(fèi)ARP的例子
(我們用-n選項(xiàng)運(yùn)行tcpdump命令,打印出點(diǎn)分十進(jìn)制的地址,而不是主機(jī)名。)對于ARP請求中的各字段來說,發(fā)送端的協(xié)議地址和目的端的協(xié)議地址是一致的:即主機(jī)bsdi的地址140.252.13.35。另外,以太網(wǎng)報頭中的源地址0:0:c0:6f:2d:40,正如tcpdump命令顯示的那樣,等于發(fā)送端的硬件地址(見圖4.4)。
免費(fèi)ARP可以有兩個方面的作用。
1. 一個主機(jī)可以通過它來確定另一個主機(jī)是否設(shè)置了相同的IP地址。主機(jī)bsdi并不希望對此請求有一個回答。但是,如果收到一個回答,那么就會在終端日志上產(chǎn)生一個錯誤消息“以太網(wǎng)地址:a:b:c:d:e:f發(fā)送來重復(fù)的IP地址”。這樣就可以警告系統(tǒng)管理員,某個系統(tǒng)有不正確的設(shè)置。
2. 如果發(fā)送免費(fèi)ARP的主機(jī)正好改變了硬件地址(很可能是主機(jī)關(guān)機(jī)了,并換了一塊接口卡,然后重新啟動),那么這個分組就可以使其它主機(jī)高速緩存中舊的硬件地址進(jìn)行相應(yīng)的更新。一個比較著名的ARP協(xié)議事實(shí)[Plummer 1982]是,如果主機(jī)收到某個IP地址的ARP請求,而且它已經(jīng)在接收者的高速緩存中,那么就要用ARP請求中的發(fā)送端硬件地址(如以太網(wǎng)地址)對高速緩存中相應(yīng)的內(nèi)容進(jìn)行更新。主機(jī)接收到任何ARP請求都要完成這個操作。(ARP請求是在網(wǎng)上廣播的,因此每次發(fā)送ARP請求時網(wǎng)絡(luò)上的所有主機(jī)都要這樣做。)
文獻(xiàn)[Bhide, Elnozahy, and Morgan 1991]中有一個應(yīng)用例子,通過發(fā)送含有備份硬件地址和故障服務(wù)器的IP地址的免費(fèi)ARP請求,使得備份文件服務(wù)器可以順利地接替故障服務(wù)器進(jìn)行工作。這使得所有目的地為故障服務(wù)器的報文都被送到備份服務(wù)器那里,客戶程序不用關(guān)心原來的服務(wù)器是否出了故障。
(以下是原書p.63①的譯文)
不幸的是,作者卻反對這個做法,因?yàn)檫@取決于所有不同類型的客戶端都要有正確的ARP協(xié)議實(shí)現(xiàn)。它們顯然碰到過客戶端的ARP協(xié)議實(shí)現(xiàn)與規(guī)范不一致的情況。
通過檢查作者所在子網(wǎng)上的所有系統(tǒng)可以發(fā)現(xiàn),SunOS 4.1.3和4.4BSD在引導(dǎo)時都發(fā)送免費(fèi)ARP,但是SVR4卻沒有這樣做。
4.8 arp命令
我們已經(jīng)用這個命令及參數(shù)-a來顯示ARP高速緩存中的所有內(nèi)容。這里介紹其它參數(shù)的功能。
超級用戶可以用參數(shù)-d來刪除ARP高速緩存中的某一項(xiàng)內(nèi)容。(這個命令格式可以在運(yùn)行一些例子之前使用,以讓我們看清楚ARP的交換過程。)
另外,可以通過參數(shù)-s來增加高速緩存中的內(nèi)容。這個參數(shù)需要主機(jī)名和以太網(wǎng)地址:對應(yīng)于主機(jī)名的IP地址和以太網(wǎng)地址被增加到高速緩存中。新增加的內(nèi)容是永久性的(比如,它沒有超時值),除非在命令行的末尾附上關(guān)鍵字temp。
位于命令行末尾的關(guān)鍵字pub和-s參數(shù)一起,可以使系統(tǒng)起著主機(jī)ARP代理的作用。系統(tǒng)將回答與主機(jī)名對應(yīng)的IP地址的ARP請求,并以指定的以太網(wǎng)地址作為回答。如果廣播的地址是系統(tǒng)本身,那么系統(tǒng)就為指定的主機(jī)名起著委托ARP代理的作用。
4.9 小結(jié)
在大多數(shù)的TCP/IP實(shí)現(xiàn)中,ARP是一個基礎(chǔ)協(xié)議,但是它的運(yùn)行對于應(yīng)用程序或系統(tǒng)管理員來說一般是透明的。ARP高速緩存在它的運(yùn)行過程中非常關(guān)鍵,我們可以用arp命令對高速緩存進(jìn)行檢查和操作。高速緩存中的每一項(xiàng)內(nèi)容都有一個定時器,根據(jù)它來刪除不完整和完整的表項(xiàng)。arp命令可以顯示和修改ARP高速緩存中的內(nèi)容。
我們介紹了ARP的一般操作,同時也介紹了一些特殊的功能:委托ARP(當(dāng)路由器對來自于另一個路由器接口的ARP請求進(jìn)行回答時)和免費(fèi)ARP(發(fā)送自己IP地址的ARP請求,一般發(fā)生在引導(dǎo)過程中)。
習(xí)題
4.1 當(dāng)我們輸入命令以生成類似圖4.4那樣的輸出時,發(fā)現(xiàn)本地ARP快速緩存為空以后,輸入命令
bsdi % rsh svr4 arp -a
如果發(fā)現(xiàn)目的主機(jī)上的ARP快速緩存也是空的,那將發(fā)生什么情況?(該命令將在svr4主機(jī)上運(yùn)行arp -a命令。)
4.2 請描述如何判斷一個給定主機(jī)是否能正確處理接收到的非必要的ARP請求的方法。
4.3 由于發(fā)送一個數(shù)據(jù)包后ARP將等待響應(yīng),因此4.2節(jié)所描述的步驟7可能會持續(xù)一段時間。你認(rèn)為ARP將如何處理在這期間收到相同目的IP地址發(fā)來的多個數(shù)據(jù)包?
4.4 在4.5節(jié)的最后,我們指出Host Requirements RFC和伯克利派生系統(tǒng)在處理活動ARP表目的超時時存在差異。那么如果我們在一個由伯克利派生系統(tǒng)的客戶端上,試圖與一個正在更換以太網(wǎng)卡而處于關(guān)機(jī)狀態(tài)的服務(wù)器主機(jī)聯(lián)系,這時會發(fā)生什么情況?如果服務(wù)器在引導(dǎo)過程中廣播一份免費(fèi)(gratuitous)ARP,這種情況是否會發(fā)生變化?
4-1
5 RARP:逆地址解析協(xié)議
5.1 引言
具有本地磁盤的系統(tǒng)引導(dǎo)時,一般是從磁盤上的配置文件中讀取IP地址。但是無盤機(jī),如X終端或無盤工作站,則需要采用其他方法來獲得IP地址。
網(wǎng)絡(luò)上的每個系統(tǒng)都具有唯一的硬件地址,它是由網(wǎng)絡(luò)接口生產(chǎn)廠家配置的。無盤系統(tǒng)的RARP實(shí)現(xiàn)過程是從接口卡上讀取唯一的硬件地址,然后發(fā)送一份RARP請求(一幀在網(wǎng)絡(luò)上廣播的數(shù)據(jù)),請求某個主機(jī)響應(yīng)該無盤系統(tǒng)的IP地址(在RARP回答中)。
在概念上這個過程是很簡單的,但是實(shí)現(xiàn)起來常常比ARP要困難,其原因在本章后面介紹。RARP的正式規(guī)范是RFC 903 [Finlayson et al. 1984]。
5.2 RARP的分組格式
RARP分組的格式與ARP分組基本一致(圖4.3)。它們之間主要的差別是RARP請求或回答的幀類型代碼為0x8035,而且RARP請求的操作代碼為3,回答操作代碼為4。
對應(yīng)于ARP,RARP請求以廣播方式傳送,而RARP回答一般是單播(unicast)傳送的。
5.3 RARP舉例
在我們的互連網(wǎng)中,我們可以強(qiáng)制sun主機(jī)從網(wǎng)絡(luò)上引導(dǎo),而不是從本地磁盤引導(dǎo)。如果我們在主機(jī)bsdi上運(yùn)行RARP服務(wù)程序和tcpdump命令,那么可以得到如圖5.1那樣的輸出。我們用-e參數(shù)使得tcpdump命令打印出硬件地址:
圖5.1 RARP請求和回答
RARP請求是廣播方式(第1行),而第2行的RARP回答是單播方式。第2行的輸出中at sun表示RARP回答包含主機(jī)sun的IP地址(140.252.13.33)。
在第3行中,我們可以看到,一旦sun收到RARP回答,它就發(fā)送一個TFTP讀請求(RRQ)給文件8CFC0D21.SUN4C。(TFTP表示簡單文件傳輸協(xié)議。我們將在第15章詳細(xì)介紹它。)文件名中的8個十六進(jìn)制數(shù)字表求主機(jī)sun的IP地址140.252.13.33。這個IP地址在RARP回答中返回。文件名的后綴SUN4C表示被引導(dǎo)系統(tǒng)的類型。
tcpdump在第3行中指出IP數(shù)據(jù)報的長度是65個字節(jié),而不是一個UDP數(shù)據(jù)報(實(shí)際上是一個UDP數(shù)據(jù)報),因?yàn)槲覀冞\(yùn)行tcpdump命令時帶有-e參數(shù),以查看硬件層的地址。在圖5.1中需要指出的另一點(diǎn)是,第2行中的以太網(wǎng)數(shù)據(jù)幀長度比最小長度還要。ㄔ4.5節(jié)中我們說過應(yīng)該是60字節(jié)。)其原因是我們在發(fā)送該以太網(wǎng)數(shù)據(jù)幀的系統(tǒng)(bisdi)上運(yùn)行tcpdump命令的。應(yīng)用程序rarpd寫42字節(jié)到BSD分組過濾設(shè)備上(其中14字節(jié)為以太網(wǎng)數(shù)據(jù)幀的報頭,剩下的28字節(jié)是RARP回答),這就是tcpdump收到的副本。但是以太網(wǎng)設(shè)備驅(qū)動程序要把這一短幀填充空白字符以達(dá)到最小傳輸長度(60)。如果我們在另一個系統(tǒng)上運(yùn)行tcpdump命令,其長度將會是60。
我們從這個例子可以看出,當(dāng)無盤系統(tǒng)從RARP回答中收到它的IP地址后,它將發(fā)送TFTP請求來讀取引導(dǎo)映象。在這一點(diǎn)上我們將不再進(jìn)一步詳細(xì)討論無盤系統(tǒng)是如何引導(dǎo)的。(第16章將描述無盤X終端利用RARP,BOOTP以及TFTP進(jìn)行引導(dǎo)的過程。)
當(dāng)網(wǎng)絡(luò)上沒有RARP服務(wù)器時,其結(jié)果如圖5.2所示。每個分組的目的地址都是以太網(wǎng)廣播地址。在who-后面的以太網(wǎng)地址是目的硬件地址,跟在tell后面的以太網(wǎng)地址是發(fā)送端的硬件地址。
請注意重發(fā)的頻度。第一次重發(fā)是在6.55秒以后,然后增加到42.80秒,然后又減到5.34秒和6.55秒,然后又回到42.79秒。這種不確定的情況一直繼續(xù)下去。如果計算一下兩次重發(fā)之間的時間間隔,我們發(fā)現(xiàn)存在一種雙倍的關(guān)系:從5.34到6.55是1.21秒,從 6.55到8.97是2.42秒,從8.97到13.80是4.83秒,一直這樣繼續(xù)下去。當(dāng)時間間隔達(dá)到某個閾值時(大于42.80秒),它又重新置為5.34秒。
圖5.2 網(wǎng)絡(luò)中沒有RARP服務(wù)器的RARP請求
超時間隔采用這樣的遞增方法比每次都采用相同值的方法要好。在圖6.8中,我們將看到一種錯誤的超時重發(fā)方法,以及在第21章中將看到TCP的超時重發(fā)機(jī)制。
5.4 RARP服務(wù)器的設(shè)計
雖然RARP在概念上很簡單,但是設(shè)計一個RARP服務(wù)器與系統(tǒng)相關(guān)而且比較復(fù)雜。相反,提供一個ARP服務(wù)器很簡單,通常是TCP/IP在內(nèi)核中實(shí)現(xiàn)的一部分。由于內(nèi)核知道IP地址和硬件地址,因此當(dāng)它收到一個詢問IP地址的ARP請求時,只需用相應(yīng)的硬件地址來提供回答就可以了。
作為用戶進(jìn)程的RARP服務(wù)器
RARP服務(wù)器的復(fù)雜性在于,服務(wù)器一般要為多個主機(jī)(網(wǎng)絡(luò)上所有的無盤系統(tǒng))提供硬件地址到IP地址的映射。該映射包含在一個磁盤文件中(在Unix系統(tǒng)中一般位于/etc/ethers目錄中)。由于內(nèi)核一般不讀取和分析磁盤文件,因此RARP服務(wù)器的功能就由用戶進(jìn)程來提供,而不是作為內(nèi)核的TCP/IP實(shí)現(xiàn)的一部分。
更為復(fù)雜的是,RARP請求是作為一個特殊類型的以太網(wǎng)數(shù)據(jù)幀來傳送的(幀類型字段值為0x8035,如圖2.1所示)。這說明RARP服務(wù)器必須能夠發(fā)送和接收這種類型的以太網(wǎng)數(shù)據(jù)幀。在附錄A中,我們描述了BSD分組過濾器,Sun的網(wǎng)絡(luò)接口栓,以及SVR4數(shù)據(jù)鏈路提供者接口都可用來接收這些數(shù)據(jù)幀。由于發(fā)送和接收這些數(shù)據(jù)幀與系統(tǒng)有關(guān),因此RARP服務(wù)器的實(shí)現(xiàn)與系統(tǒng)是捆綁在一起的。
每個網(wǎng)絡(luò)有多個RARP服務(wù)器
RARP服務(wù)器實(shí)現(xiàn)的一個復(fù)雜因素是RARP請求是在硬件層上進(jìn)行廣播的,如圖5.2所示。這意味著它們不經(jīng)過路由器進(jìn)行轉(zhuǎn)發(fā)。為了讓無盤系統(tǒng)在RARP服務(wù)器關(guān)機(jī)的狀態(tài)下也能引導(dǎo),通常在一個網(wǎng)絡(luò)上(例如一根電纜)要提供多個RARP服務(wù)器。
當(dāng)服務(wù)器的數(shù)目增加時(以提供冗余備份),網(wǎng)絡(luò)流量也隨之增加,因?yàn)槊總服務(wù)器對每個RARP請求都要發(fā)送RARP回答。發(fā)送RARP請求的無盤系統(tǒng)一般采用最先收到的RARP回答。(對于ARP我們從來沒有遇到這種情況,因?yàn)橹挥幸慌_主機(jī)發(fā)送ARP回答。)另外,還有一種可能發(fā)生的情況是每個RARP服務(wù)器同時回答,這樣會增加以太網(wǎng)發(fā)生沖突的概率。
5.5 小結(jié)
RARP協(xié)議是許多無盤系統(tǒng)在引導(dǎo)時用來獲取IP地址。RARP分組格式基本上與ARP分組一致。一個RARP請求在網(wǎng)絡(luò)上進(jìn)行廣播,它在分組中標(biāo)明發(fā)送端的硬件地址,以請求相應(yīng)IP地址的響應(yīng)。回答通常是單播傳送的。
RARP帶來的問題包括使用鏈路層廣播,這樣就阻止大多數(shù)路由器轉(zhuǎn)發(fā)RARP請求,只返回很少信息:只是系統(tǒng)的IP地址。在第16章中,我們將看到BOOTP在無盤系統(tǒng)引導(dǎo)時會返回更多的信息:IP地址,引導(dǎo)主機(jī)的名字等等。
雖然RARP在概念上很簡單,但是RARP服務(wù)器的實(shí)現(xiàn)卻與系統(tǒng)相關(guān)。因此,并不是所有的TCP/IP實(shí)現(xiàn)都提供RARP服務(wù)器。
習(xí)題
5.1 RARP需要不同的幀類型字段嗎?ARP和RARP都使用相同的值0x0806嗎?
5.2 在一個有多個RARP服務(wù)器的網(wǎng)絡(luò)上,如何防止它們的響應(yīng)發(fā)生沖突?
5-3
6 ICMP:Internet控制報文協(xié)議
6.1 引言
ICMP經(jīng)常被認(rèn)為是IP層的一個組成部分。它傳遞差錯信息以及其它需要注意的信息。ICMP報文通常被IP層或更高層協(xié)議(TCP或UDP)使用。一些ICMP報文把差錯信息返回給用戶進(jìn)程。
ICMP信息是在IP數(shù)據(jù)報內(nèi)部被傳輸?shù),?.1所示。
圖6.1 ICMP封裝在IP數(shù)據(jù)報內(nèi)部
ICMP 的正式規(guī)范參見RFC 792 [Posterl 1981b]。
ICMP報文的格式如圖6.2所示。所有報文的前4個字節(jié)都是一樣的,但是剩下的其它字節(jié)則互不相同。下面我們將逐個介紹各種報文格式。
類型字段可以有15個不同的值,以描述特定類型的ICMP報文。某些ICMP報文還使用代碼字段的值來進(jìn)一步描述不同的條件。
檢驗(yàn)和字段覆蓋整個ICMP報文。使用的算法與我們在3.2節(jié)中介紹的IP首部檢驗(yàn)和算法相同。ICMP的檢驗(yàn)和是必需的。
圖6.2 ICMP報文
在本章中,我們將粗淺地討論ICMP報文,并對其中一部分作詳細(xì)介紹:地址掩碼請求和回答,時間戳請求和回答,以及不可答端口。我們將詳細(xì)介紹第27章Ping程序所使用的回應(yīng)請求和回答報文和第9章處理IP路由的ICMP報文。
6.2 ICMP報文的類型
各種類型的ICMP報文如圖6.3所示,不同類型由報文中的類型字段和代碼字段來共同決定。
圖中的最后兩列表明ICMP報文是一份查詢報文還是一份差錯報文。因?yàn)閷CMP差錯報文有時需要作特殊處理,因此我們需要對它們進(jìn)行區(qū)分。例如,在對ICMP差錯報文進(jìn)行響應(yīng)時,永遠(yuǎn)不會生成另一份ICMP差錯報文。(如果沒有這個限制規(guī)則,我們可能會遇到一個差錯產(chǎn)生另一個差錯的情況,而差錯再產(chǎn)生差錯,這樣無休止地循環(huán)下去。)
當(dāng)發(fā)送一份ICMP差錯報文時,報文始終包含IP的首部和產(chǎn)生ICMP差錯報文的IP數(shù)據(jù)報的前8個字節(jié)。這樣,接收ICMP差錯報文的模塊就會把它與某個特定的協(xié)議(根據(jù)IP數(shù)據(jù)報首部中的協(xié)議字段來判斷)和用戶進(jìn)程(根據(jù)包含在IP數(shù)據(jù)報前8個字節(jié)中的TCP或UDP報文首部中的TCP或UDP端口號來判斷)聯(lián)系起來。在6.5節(jié)我們將舉例來說明一點(diǎn)。
下面各種情況都不會導(dǎo)致產(chǎn)生ICMP差錯報文:
1.ICMP差錯報文。(但是,ICMP查詢報文可能會產(chǎn)生ICMP差錯報文。)
2.目的地址是廣播地址(圖3.9)或多播地址(D類地址,圖1.5)的IP數(shù)據(jù)報。
3.作為鏈路層廣播的數(shù)據(jù)報。
4.不是IP分片的第一片。(我們將在11.5節(jié)介紹分片。)
5.源地址不是單個主機(jī)的數(shù)據(jù)報。這就是說,源地址不能為零地址、環(huán)回地址、廣播地址或多播地址。
(下面是圖6.3的譯文)
類型
代碼
描述
查詢
差錯
0
0
回答回顯(Ping回答,第7章)
•
3
目的不可到達(dá):
0
網(wǎng)絡(luò)不可到達(dá)(9.3節(jié))
•
1
主機(jī)不可到達(dá)(9.3節(jié))
•
2
協(xié)議不可到達(dá)
•
3
端口不可到達(dá)(6.5節(jié))
•
4
需要進(jìn)行分片但設(shè)置了不分片比特(11.6節(jié))
•
5
源站路由選擇失敗(8.5節(jié))
•
6
目的網(wǎng)絡(luò)不認(rèn)識
•
7
目的主機(jī)不認(rèn)識
•
8
源主機(jī)被隔離(作廢不用)
•
9
目的網(wǎng)絡(luò)被強(qiáng)制禁止
•
10
目的主機(jī)被強(qiáng)制禁止
•
11
由于服務(wù)類型TOS網(wǎng)絡(luò)不可到達(dá)(9.3節(jié))
•
12
由于服務(wù)類型TOS主機(jī)不可到達(dá)(9.3節(jié))
•
13
由于過濾通信被強(qiáng)制禁止
•
14
主機(jī)越權(quán)
•
15
優(yōu)先權(quán)中止生效
•
4
0
源端被關(guān)閉(基本流控制,11.11節(jié))
•
5
改變路由(9.5節(jié)):
•
0
對網(wǎng)絡(luò)改變路由
•
1
對主機(jī)改變路由
•
2
對服務(wù)類型和網(wǎng)絡(luò)改變路由
•
3
對服務(wù)類型和主機(jī)改變路由
•
8
0
請求回顯(Ping請求,第7章)
•
9
0
路由器通告(9.6節(jié))
•
10
0
路由器請求(9.6節(jié))
•
11
超時:
0
傳輸期間生存時間為0(Traceroute, 第8章)
•
1
在數(shù)據(jù)報組裝期間生存時間為0(11.5節(jié))
•
12
參數(shù)問題:
0
壞的IP首部(包括各種差錯)
•
1
缺少必需的選項(xiàng)
•
13
0
時間戳請求(6.4節(jié))
•
14
0
時間戳回答(6.4節(jié))
•
15
0
信息回答(作廢不用)
•
16
0
信息回答(作廢不用)
•
17
0
地址掩碼請求(6.3節(jié))
•
18
0
地址掩碼回答(6.3節(jié))
•
圖6.3 ICMP報文類型
這些規(guī)則是為了防止過去允許ICMP差錯報文對廣播分組響應(yīng)所帶來的廣播風(fēng)暴。
6.3 ICMP地址掩碼請求與回答
ICMP地址掩碼請求用于無盤系統(tǒng)在引導(dǎo)過程中獲取自己的子網(wǎng)掩碼(3.5節(jié))。系統(tǒng)廣播它的ICMP請求報文。(這一過程與無盤系統(tǒng)在引導(dǎo)過程中用RARP獲取IP地址是類似的。)無盤系統(tǒng)獲取子網(wǎng)掩碼的另一個方法是BOOTP協(xié)議,我們將在第16章中介紹。ICMP地址掩碼請求和回答報文的格式如圖6.4所示。
圖6.4 ICMP地址掩碼請求和回答報文
ICMP報文中的標(biāo)識符和序列號字段由發(fā)送端任意選擇設(shè)定,這些值在回答中將被返回。這樣,發(fā)送端就可以把回答與請求進(jìn)行匹配。
我們可以寫一個簡單的程序(取名為icmpaddrmask),它發(fā)送一份ICMP地址掩碼請求報文,然后打印出所有的回答。由于一般是把請求報文發(fā)往廣播地址,因此這里我們也這樣做。目的地址(140.252.13.63)是子網(wǎng)140.252.13.32的廣播地址(圖3.12)。
sun % icmpaddrmask 140.252.13.33
received mask = ffffffe0, from 140.252.13.33 來自本機(jī)
received mask = ffffffe0, from 140.252.13.35 來自bsdi
received mask = ffff0000, from 140.252.13.34 來自svr4
在輸出中我們首先注意到的是,從svr4返回的子網(wǎng)掩碼是差錯的。顯然,盡管svr4接口已經(jīng)設(shè)置了正確的子網(wǎng)掩碼,但是SVR4還是返回了一個普通的B類地址掩碼,就好像子網(wǎng)并不存在一樣。
svr4 % ifconfig emd0
emd0: flags=23
inet 140.252.13.34 netmask ffffffe0 broadcast 140.252.13.63
SVR4處理ICMP地址掩碼請求過程存在差錯。
我們用tcpdump命令來查看主機(jī)bsdi上的情況,輸出如圖6.5所示。我們用-e參數(shù)來查看硬件地址。
圖6.5 發(fā)到廣播地址的ICMP地址掩碼請求
注意,盡管在線路上什么也看不見,但是發(fā)送主機(jī)sun也能接收到ICMP回答(帶有from ourself的輸出行)。這是廣播的一般特性:發(fā)送主機(jī)也能通過某種內(nèi)部環(huán)回機(jī)制收到一份廣播報文拷貝。由于術(shù)語“廣播”的定義是指局域網(wǎng)上的所有主機(jī),因此它必須包括發(fā)送主機(jī)在內(nèi)。(參見圖2.4,當(dāng)以太網(wǎng)驅(qū)動程序識別出目的地址是廣播地址后,它就把分組送到網(wǎng)絡(luò)上,同時傳一份拷貝到環(huán)回接口。)
接下來,bsdi廣播回答,而svr4卻只把回答傳給請求主機(jī)。通常,回答地址必須是單播地址,除非請求端的源IP地址是0.0.0.0,本例不屬于這種情況。因此,把回答發(fā)送到廣播地址是BSD/386的一個內(nèi)部差錯。
(下面是原書p.73①的譯文)
RFC規(guī)定,除非系統(tǒng)是地址掩碼的授權(quán)代理,否則它不能發(fā)送地址掩碼回答。(為了成為授權(quán)代理,它必須進(jìn)行特殊配置,以發(fā)送這些回答。參見附錄E。)但是,正如我們從本例中看到的那樣,大多數(shù)主機(jī)在收到請求時都發(fā)送一個回答,甚至有一些主機(jī)還發(fā)送差錯的回答。
最后一點(diǎn)可以通過下面的例子來說明。我們向本機(jī)IP地址和環(huán)回地址分別發(fā)送地址掩碼請求:
sun % icmpaddrmask sun
received mask= ff000000, from 140.252.13.33
sun % icmpaddrmask localhost
received mask= ff000000, from 127.0.0.1
上述兩種情況下返回的地址掩碼對應(yīng)的都是環(huán)回地址,即A類地址127.0.0.1。還有,我們從圖2.4可以看到,發(fā)送給本機(jī)IP地址的數(shù)據(jù)報(140.252.12.33)實(shí)際上是送到環(huán)回接口。ICMP地址掩碼回答必須是收到請求接口的子網(wǎng)掩碼(這是因?yàn)槎嘟涌谥鳈C(jī)每個接口有不同的子網(wǎng)掩碼),因此兩種情況下地址掩碼接求都來自于環(huán)回接口。
6.4 ICMP時間戳請求與回答
ICMP時間戳請求允許系統(tǒng)向另一個系統(tǒng)查詢當(dāng)前的時間。返回的建議值是自午夜開始計算的毫秒數(shù),協(xié)調(diào)的統(tǒng)一時間(Coordinated Universal Time, UTC)。(早期的參考手冊認(rèn)為UTC是格林尼治時間。)這種ICMP報文的好處是它提供了毫秒級的分辨率,而利用其它方法從別的主機(jī)獲取的時間(如某些Unix系統(tǒng)提供的rdate命令)只能提供秒級的分辨率。由于返回的時間是從午夜開始計算的,因此調(diào)用者必須通過其它方法獲知當(dāng)時的日期,這是它的一個缺陷。
ICMP時間戳請求和回答報文格式如圖6.6所示。
圖6.6 ICMP時間戳請求和回答報文
請求端填寫發(fā)起時間戳,然后發(fā)送報文。回答系統(tǒng)收到請求報文時填寫接收時間戳,在發(fā)送回答時填寫發(fā)送時間戳。但是,實(shí)際上,大多數(shù)的實(shí)現(xiàn)把后面兩個字段都設(shè)成相同的值。(提供三個字段的原因是可以讓發(fā)送方分別計算發(fā)送請求的時間和發(fā)送回答的時間。)
例子
我們可以寫一個簡單程序(取名為icmptime),給某個主機(jī)發(fā)送ICMP時間戳請求,并打印出返回的回答。它在我們的小互連網(wǎng)上運(yùn)行結(jié)果如下:
(見原書p.74的①)
程序打印出ICMP報文中的三個時間戳:發(fā)起時間戳(orig),接收時間戳(recv),以及發(fā)送時間戳(xmit)。正如我們在這個例子以及下面的例子中所看到的那樣,所有的主機(jī)把接收時間戳和發(fā)送時間戳都設(shè)成相同的值。
我們還能計算出往返時間(rtt),它的值是收到回答時的時間值減去發(fā)送請求時的時間值。difference的值是接收時間戳值減去發(fā)起時間戳值。這些值之間的關(guān)系如圖6 7所示。
如果我們相信RTT的值,并且相信RTT的一半用于請求報文的傳輸,另一半用于回答報文的傳輸,那么為了使本機(jī)時鐘與查詢主機(jī)的時鐘一致,本機(jī)時鐘需要進(jìn)行調(diào)整,調(diào)整值是difference減去RTT的一半。在前面的例子中,bsdi的時鐘比sun的時鐘要慢7 ms和8 ms。
由于時間戳的值是自午夜開始計算的毫秒數(shù),即UTC,因此它們的值始終小于86,400,000 (24×60×60×1000)。這些例子都是在下午4:00以前運(yùn)行的,并且在一個比UTC慢7個小時的時區(qū),因此它們的值比82,800,000(2300小時)要大是有道理的。
如果我們對主機(jī)bsdi重復(fù)運(yùn)行該程序數(shù)次,我們發(fā)現(xiàn)接收時間戳和發(fā)送時間戳的最后一位數(shù)總是0。這是因?yàn)樵摪姹镜能浖?.9.4版)只能提供10毫秒的時間分辨率。(說明參見附錄B。)
如果我們對主機(jī)svr4運(yùn)行該程序兩次,我們發(fā)現(xiàn)SVR4時間戳的最后三位數(shù)始終為0:
(見原書p.75的①)
由于某種原因,SVR4在ICMP時間戳中不提供毫秒級的分辨率。這樣,對秒以下的時間差調(diào)整將不起任何作用。
如果我們對子網(wǎng)140.252.1上的其它主機(jī)運(yùn)行該程序,結(jié)果表明其中一臺主機(jī)的時鐘與sun相差3.7秒,而另一個主機(jī)時鐘相差近75秒:
(見原書p.75的②)
另一個令人感興趣的例子是路由器gateway(一個Cisco路由器)。這表明,當(dāng)系統(tǒng)返回一個非標(biāo)準(zhǔn)時間戳值時(不是自午夜開始計算的毫秒數(shù),UTC),它就用32 bit時間戳中的高位來表示。我們的程序證明了一點(diǎn),在尖括號中打印出了接收和發(fā)送的時間戳值(在關(guān)閉高位之后)。另外,我們不能計算發(fā)起時間戳和接收時間戳之間的時間差,因?yàn)樗鼈兊膯挝徊灰恢隆?
(見原書p.76的①)
如果我們在這臺主機(jī)上運(yùn)行該程序數(shù)次,會發(fā)現(xiàn)時間戳值顯然具有毫秒級的分辨率,而且是從某個起始點(diǎn)開始計算的毫秒數(shù),但是起始點(diǎn)并不是午夜UTC。(例如,可能是從路由器引導(dǎo)時開始計數(shù)的毫秒數(shù)。)
作為最后一個例子,我們來比較sun主機(jī)和另一個已知是準(zhǔn)確的系統(tǒng)時鐘----一個NTP stratum 1服務(wù)器。(下面我們會更多地討論NTP,網(wǎng)絡(luò)時間協(xié)議。)
(見原書p.76的②)
如果我們把difference的值減去RTT的一半,結(jié)果表明sun主機(jī)上的時鐘要快38.5到51.5 ms。
另一種方法
還可以用另一種方法來獲得時間和日期。
1. 我們在1.12節(jié)中描述了日期時間服務(wù)程序和時間服務(wù)程序。前者是以人們可讀的格式返回當(dāng)前的時間和日期,是一行ASCII字符。我們可以用telnet命令來驗(yàn)證這個服務(wù):
(見原書p.76的③)
另一方面,時間服務(wù)程序返回的是一個32 bit的二制進(jìn)數(shù)值,表示自UTC,1900年1月1日午夜起算的秒數(shù)。這個程序是以秒為單位提供的日期和時間。(前面我們提過的rdate命令使用的是TCP時間服務(wù)程序。)
2. 嚴(yán)格的計時器使用網(wǎng)絡(luò)時間協(xié)議(NTP),該協(xié)議在RFC 1305中給出了描述[Mills 1992]。這個協(xié)議采用先進(jìn)的技術(shù)來保證LAN或WAN上的一組系統(tǒng)的時鐘誤差在毫秒級以內(nèi)。對計算機(jī)精確時間感興趣的讀者應(yīng)該閱讀這份RFC文檔。
3. 開放軟件基金會(OSF)的分布式計算環(huán)境(DCE)定義了分布式時間服務(wù)(DTS),它也提供計算機(jī)之間的時鐘同步。文獻(xiàn)[Rosenberg, Kenney and Fisher 1992]提供了該服務(wù)的其它細(xì)節(jié)描述。
4. 伯克利大學(xué)的Unix系統(tǒng)提供守護(hù)程序timed( ,來同步局域網(wǎng)上的系統(tǒng)時鐘。不像NTP和DTS,timed不在廣域網(wǎng)范圍內(nèi)工作。
6.5 ICMP端口不可達(dá)差錯
最后兩小節(jié)我們來討論ICMP查詢報文----地址掩碼和時間戳查詢及回答。我們現(xiàn)在來分析一種ICMP差錯報文,即端口不可到達(dá)報文,它是ICMP目的不可到達(dá)報文中的一種,以此來看一看ICMP差錯報文中所附加的信息。我們使用UDP(見第11章)來查看它。
UDP的規(guī)則之一是,如果收到一份UDP數(shù)據(jù)報而目的端口與某個正在使用的進(jìn)程不相符,那么UDP返回一個ICMP不可到達(dá)報文。我們可以用TFTP來強(qiáng)制生成一個端口不可到達(dá)報文。(TFTP將在第15章描述。)
對于TFTP服務(wù)器來說,UDP的公共端口號是69。但是大多數(shù)的TFTP客戶程序允許我們用connect命令來指定一個不同的端口號。這里,我們就用為它指定為8888:
(見原書p.77的①)
connect命令首先指定要連接的主機(jī)名及其端口號,接著用get命令來取文件。敲入get命令后,一份UDP數(shù)據(jù)報就發(fā)送到主機(jī)svr4上的8888端口。tcpdump命令引起的報文交換結(jié)果如圖6.8所示。
在UDP數(shù)據(jù)報送到svr4之前,要先發(fā)送一份ARP請求來確定它的硬件地址(第1行)。接著返回ARP回答(第2行),然后才發(fā)送UDP數(shù)據(jù)報(第3行)。(我們在tcpdump的輸出中保留ARP請求和回答是為了提醒我們,這些報文交換可能在第一個IP數(shù)據(jù)報從一個主機(jī)發(fā)送到的另一個主機(jī)之前是必需的。在本書以后的章節(jié)中,如果這些報文與討論的題目不相關(guān),那么我們將省略它們。)
圖6.8 由TFTP產(chǎn)生的ICMP端口不可到達(dá)差錯
一個ICMP端口不可到達(dá)差錯是立刻返回的(第4行)。但是,TFTP客戶程序看上去似乎忽略了這個ICMP報文,而在5秒鐘之后又發(fā)送了另一份UDP數(shù)據(jù)報(第5行)。在客戶程序放棄之前重發(fā)了三次。
注意,ICMP報文是在主機(jī)之間交換的,而不用目的端口號,而每個20字節(jié)的UDP數(shù)據(jù)報則是從一個特定端口(2924)發(fā)送到另一個特定端口(8888)。
跟在每個UDP后面的數(shù)字20指的是UDP數(shù)據(jù)報中的數(shù)據(jù)長度。在這個例子中,20字節(jié)包括TFTP的2個字節(jié)的操作代碼,9個字節(jié)以空字符結(jié)束的文件名temp.foo,以及9個字節(jié)以空字符結(jié)束的字符串netascii。(TFTP報文的詳細(xì)格式參見圖15.1。)
如果用-e參數(shù)運(yùn)行同樣的例子,我們可以看到每個返回的ICMP端口不可到達(dá)報文的完整長度。這里的長度為70字節(jié),各字段分配如圖6.9所示。
圖6.9 “UDP端口不可到達(dá)”例子中返回的ICMP報文
ICMP的一個規(guī)則是,ICMP差錯報文(參見圖6.3的最后一列)必須包括生成該差錯報文的數(shù)據(jù)報IP首部(包含任何選項(xiàng)),還必須至少包括跟在該IP首部后面的前8個字節(jié)。在我們的例子中,跟在IP首部后面的前8個字節(jié)包含UDP的首部(圖11.2)。
一個重要的事實(shí)是包含在UDP首部中內(nèi)容是源端口號和目的端口號。就是由于目的端口號(8888)才導(dǎo)致產(chǎn)生了ICMP端口不可到達(dá)的差錯報文。接收ICMP的系統(tǒng)可以根據(jù)源端口號(2924)來把差錯報文與某個特定的用戶進(jìn)程相關(guān)聯(lián)(在本例中是TFTP客戶程序)。
導(dǎo)致差錯的數(shù)據(jù)報中的IP首部要被送回的原因是因?yàn)镮P首部中包含了協(xié)議字段,使得ICMP可以知道如何解釋后面的8個字節(jié)(在本例中是UDP首部)。如果我們來查看TCP首部(圖17.2),可以發(fā)現(xiàn)源端口和目的端口被包含在TCP首部的前8個字節(jié)中。
ICMP不可到達(dá)報文的一般格式如圖6.10所示。
圖6.10 ICMP不可到達(dá)報文
在圖6.3中,我們注意到有16種不同類型的ICMP不可到達(dá)報文,代碼分別從0到15。ICMP端口不可到達(dá)差錯代碼是3。另外,盡管圖6.10指出了在ICMP報文中的第二個32 bit字必須為0,但是當(dāng)代碼為4時(“需要分片但設(shè)置了不分片比特”),路徑MTU發(fā)現(xiàn)機(jī)制(2.9節(jié))卻允許路由器把外出接口的MTU填在這個32 bit字的低16 bit中。我們在11.6節(jié)中給出了一個這種差錯的例子。
(下面是原書p.79①的譯文)
盡管ICMP規(guī)則允許系統(tǒng)返回多于8個字節(jié)的產(chǎn)生差錯的IP數(shù)據(jù)報中的數(shù)據(jù),但是大多數(shù)從伯克利派生出來的系統(tǒng)只返回8個字節(jié)。Solaris 2.2的ip_icmp_return_data_bytes選項(xiàng)默認(rèn)條件下返回前64個字節(jié)(E.4節(jié))。
tcpdump時間系列
在本書的后面章節(jié)中,我們還要以時間系列的格式給出tcpdump命令的輸出,如圖6.11所示。
圖6.11 發(fā)送到無效端口的TFTP請求的時間系列
時間隨著向下而遞增,在圖左邊的時間標(biāo)記與tcpdump命令的輸出是相同的(圖6.8).位于圖頂部的標(biāo)記是通信雙方的主機(jī)名和端口號。需要指出的是,隨著頁面向下的y坐標(biāo)軸與真正的時間值不是成比例的。當(dāng)出現(xiàn)一個有意義的時間段時,在本例中是每5秒之間的重發(fā),我們就在時間系列的兩側(cè)作上標(biāo)記。當(dāng)UDP或TCP數(shù)據(jù)正在被傳送時,我們用粗線的行來表示。
當(dāng)ICMP報文返回時,為什么TFTP客戶程序還要繼續(xù)重發(fā)請求呢?這是由于網(wǎng)絡(luò)編程中的一個因素,即BSD系統(tǒng)不把從插口(socket)接收到的ICMP報文中的UDP數(shù)據(jù)通知用戶進(jìn)程,除非該進(jìn)程已經(jīng)發(fā)送了一個connect命令給該插口。標(biāo)準(zhǔn)的BSD TFTP客戶程序并不發(fā)送connect命令,因此它永遠(yuǎn)也不會收到ICMP差錯報文的通知。
這里需要注意的另一點(diǎn)是TFTP客戶程序所采用的不太好的超時重發(fā)算法。它只是假定5秒是足夠的,因此每隔5少就重傳一次,總共需要25秒鐘的時間。在后面我們將看到TCP有一個較好的超時重發(fā)算法。
(下面是原書p.81的①的譯文)
TFTP客戶程序所采用的超時重傳算法已被RFC所禁用。不過,在作者所在子網(wǎng)上的三個系統(tǒng)以及Solaris 2.2仍然在使用它。AIX 3.2.2采用一種指數(shù)退避方法來設(shè)置超時值,分別在0,5,15和35秒時重發(fā)報文,這正是所推薦的方法。我們將在第21章更詳細(xì)地討論超時問題。
最后需要指出的是,ICMP報文是在發(fā)送UDP數(shù)據(jù)報3.5 ms后返回的,這與第7章我們所看到的Ping回答的往返時間差不多。
|
|