Net/3中ARP的實(shí)現(xiàn)是和路由表緊密關(guān)聯(lián)的,下圖顯示了我們描寫(xiě)ARP要用到的1個(gè)例子。
下面,我們扼要概述圖中的有關(guān)要點(diǎn)。
1.llinfo_arp結(jié)構(gòu)的雙向鏈表包括了每個(gè)ARP已知的硬件地址的少許信息。同名全局變量llinfo_arp是該鏈表的頭結(jié)點(diǎn),圖中
沒(méi)有畫(huà)出第1位la_prev指針指向最后1項(xiàng),最后1項(xiàng)的la_next指針指向第1項(xiàng)。該鏈表由ARP時(shí)鐘函數(shù)每一個(gè)5分鐘處理1次。
2.每個(gè)已知硬件地址的IP地址都對(duì)應(yīng)1個(gè)路由表結(jié)點(diǎn)(rtentry結(jié)構(gòu))。llinfo_arp結(jié)構(gòu)的la_rt指針成員用來(lái)指向相應(yīng)的rtentry
結(jié)構(gòu),一樣地,rtentry結(jié)構(gòu)的rt_llinfo指針成員指向llinfo_arp結(jié)構(gòu)。
3.圖中的最左側(cè)第4個(gè)路由表結(jié)點(diǎn)則沒(méi)有l(wèi)linfo_arp結(jié)構(gòu),該結(jié)點(diǎn)對(duì)應(yīng)于本地以太網(wǎng)(140.252.13.32)的路由項(xiàng)。該結(jié)點(diǎn)的
rt_flags中設(shè)置了C比特,表明該結(jié)點(diǎn)是被用來(lái)復(fù)制成其他結(jié)點(diǎn)的。
4.rtentry結(jié)構(gòu)中的rt_gateway指針成員指向1個(gè)sockaddr_dl結(jié)構(gòu)變量。如果保存物理地址長(zhǎng)度的結(jié)構(gòu)sdl_alen成員為6,那末
sockaddr_dl結(jié)構(gòu)就包括相應(yīng)的硬件地址信息。
5.路由結(jié)點(diǎn)變量的rt_ifp成員的相應(yīng)指針指向?qū)?yīng)網(wǎng)絡(luò)裝備接口的ifnet結(jié)構(gòu)。中間的兩個(gè)路由結(jié)點(diǎn)對(duì)應(yīng)的是以太網(wǎng)上的其他主機(jī),
這兩個(gè)結(jié)點(diǎn)都指向le_softc[0]。而右側(cè)的路由結(jié)點(diǎn)指向環(huán)回結(jié)構(gòu)loif。由于rt_ifp.if_output指向輸出函數(shù),所以目的為本地的數(shù)據(jù)
報(bào)被路由至環(huán)回接口。
6.每個(gè)路由結(jié)點(diǎn)還有指向相應(yīng)的in_ifaddr結(jié)構(gòu)的指針變量。
7.la_hold成員是指向mbuf鏈表的指針。當(dāng)要想某個(gè)IP傳送數(shù)據(jù)報(bào)時(shí),就需要廣播1個(gè)ARP要求。當(dāng)內(nèi)核等待ARP回答時(shí),存
放該待發(fā)數(shù)據(jù)報(bào)的mbuf鏈的頭結(jié)點(diǎn)的地址信息就寄存在la_hold里。當(dāng)收到ARP回答后,la_hold指向的mbuf鏈表中的IP數(shù)據(jù)
被發(fā)送出去。
8.路由表結(jié)點(diǎn)中rt_metric結(jié)構(gòu)的變量rmx_expire寄存的是與對(duì)應(yīng)ARP結(jié)點(diǎn)相干的定時(shí)信息,用來(lái)實(shí)現(xiàn)刪除超時(shí)ARP結(jié)點(diǎn)。
下圖顯示了ARP函數(shù)與其他內(nèi)核函數(shù)的關(guān)系。
在以太網(wǎng)中傳送的ARP分組的格式以下圖所示:
結(jié)構(gòu)ether_header定義了以太網(wǎng)幀首部;結(jié)構(gòu)arphdr定義了其后的5個(gè)字段,其信息用于在任何類(lèi)型的介質(zhì)上傳送ARP要求
和回答;ether_arp結(jié)構(gòu)除包括arphdr結(jié)構(gòu)外,還包括源主機(jī)和目的主機(jī)的地址。
結(jié)構(gòu)arphdr的定義以下圖所示:
下圖顯示了ether_arp結(jié)構(gòu)的定義,其中包括了arphdr結(jié)構(gòu)、源主機(jī)和目的主機(jī)的IP地址和硬件地址。
每一個(gè)ARP結(jié)點(diǎn)中,都有1個(gè)llinfo_arp結(jié)構(gòu),所有這些結(jié)構(gòu)組成的鏈表的頭結(jié)點(diǎn)是作為全局變量分配的。我們常常把該鏈表
稱(chēng)為ARP高速緩存。
該雙向鏈表的前兩項(xiàng)是由insque和remque兩個(gè)函數(shù)更新。
arpwhohas函數(shù)通常由arpresolve調(diào)用,用于廣播1個(gè)ARP要求。它還可由每一個(gè)以太網(wǎng)裝備驅(qū)動(dòng)程序調(diào)用,在將IP地址賦予
該裝備接口時(shí)主動(dòng)發(fā)送1個(gè)地址聯(lián)編信息(SIOCSIFADDR),主動(dòng)發(fā)送地址聯(lián)編信息不但可以檢測(cè)在以太網(wǎng)中是不是存在IP
地址沖突,并可使其他機(jī)器更新其相應(yīng)信息(免費(fèi)ARP)。arpwhohas只是簡(jiǎn)單調(diào)用下arprequest函數(shù)。
arprequest函數(shù)由arpwhohas函數(shù)調(diào)用,用于廣播1個(gè)ARP要求。該函數(shù)建立1個(gè)ARP分組,并將它傳送到接口的輸出函數(shù)。
下圖顯示了該函數(shù)建立的兩個(gè)數(shù)據(jù)結(jié)構(gòu)mbuf和sockaddr。另外還有兩個(gè)函數(shù)中用到的指針eh和ea。
函數(shù)的大概處理流程以下:
1.分配和初始化mbuf。分配1個(gè)分組數(shù)據(jù)首部的嗎mbuf,并對(duì)兩個(gè)長(zhǎng)度字段賦值。
2.初始化指針。給ea和eh兩個(gè)指針賦值,并將ether_arp結(jié)構(gòu)的值賦值為0。
3.填充以太網(wǎng)幀首部。目的以太網(wǎng)地址設(shè)為以太網(wǎng)廣播地址,并將以太網(wǎng)幀類(lèi)型設(shè)為ETHERTYPE_ARP。下圖顯示了不同
以太網(wǎng)幀類(lèi)型字段的常量值。
4.填充ARP字段。填充ether_arp的所有字段,除ARP要求所要詢(xún)問(wèn)的目的硬件地址。
5.填充sockaddr,并調(diào)用接口輸出函數(shù)。接口地址結(jié)構(gòu)的sa_family成員的值設(shè)置為AP_UNSPEC,sa_number成員的值
設(shè)為16。調(diào)用接口輸出函數(shù)ether_output。
當(dāng)ether_input函數(shù)接收到幀類(lèi)型字段為ETHERTYPE_ARP的以太網(wǎng)幀時(shí),產(chǎn)生有限級(jí)為NETISR_ARP的軟件中斷,并將
該幀關(guān)在ARP輸入隊(duì)列arpintrq的后面。當(dāng)內(nèi)核處理該軟件中斷時(shí),調(diào)用arpintr函數(shù)。
函數(shù)的大概處理流程是:
只有當(dāng)幀的硬件類(lèi)型指明為以太網(wǎng)地址,并且?guī)拈L(zhǎng)度大于或等于arphdr結(jié)構(gòu)的長(zhǎng)度加上兩個(gè)硬件地址和兩個(gè)協(xié)議地址的
長(zhǎng)度時(shí),該幀才能被處理。如果協(xié)議地址的類(lèi)型是ETHERTYPE_IP或ETHERTYPE_IPTRAILERS時(shí),調(diào)用in_arpinput函數(shù),
否則該幀被拋棄。
該函數(shù)由arpintr調(diào)用,用于處理接收到的ARP要求/回答。ARP本身的概念比較簡(jiǎn)單,但是加上許多規(guī)則后,實(shí)現(xiàn)就比較
復(fù)雜,下面來(lái)看下兩種典型的情況。
1.如果收到了1個(gè)針對(duì)本機(jī)IP地址的要求,則發(fā)送1個(gè)回答。這是1種普遍情況,很明顯,我們將繼續(xù)從那個(gè)主機(jī)收到
數(shù)據(jù)報(bào),隨后也會(huì)向它回送報(bào)文。所以,如果我們還沒(méi)有對(duì)應(yīng)它的ARP結(jié)點(diǎn),就應(yīng)當(dāng)添加1個(gè)ARP結(jié)點(diǎn),由于這時(shí)候我們
已知道對(duì)方的IP地址和硬件地址。
2.如果收到1個(gè)ARP回答,那末此時(shí)ARP結(jié)點(diǎn)是完全的,因此就知道了對(duì)方的硬件地址,該地址寄存sockaddr_dl結(jié)構(gòu)中,
所有發(fā)往該地址的數(shù)據(jù)被將被發(fā)送。
3.如果其他主機(jī)發(fā)送1個(gè)ARP要求或回答,其中發(fā)送方的IP地址與本機(jī)相同,那末肯定有1個(gè)主機(jī)配置有誤,Net/3將檢測(cè)
到該過(guò)失,并向管理員等級(jí)1個(gè)報(bào)文。
4.如果主機(jī)收到來(lái)自其他主機(jī)的要求或回答,對(duì)應(yīng)的ARP結(jié)點(diǎn)早已存在,但硬件地址發(fā)送了變化,那末ARP結(jié)點(diǎn)將被更新。
5.主機(jī)可以被配置成代理ARPhttp://www.jyygyx.com/server/,這類(lèi)情況下,主機(jī)可以代其他主機(jī)響應(yīng)ARP要求,在回答中提供其他主機(jī)的硬件地址。
代理ARP回答中對(duì)應(yīng)目的硬件地址的主機(jī)必須能夠把IP數(shù)據(jù)報(bào)發(fā)至ARP要求中指定的目的地址。
該函數(shù)的大概流程以下:
1.查找匹配的接口和IP地址。搜索本機(jī)的Internet地址鏈表(in_ifaddr結(jié)構(gòu)的鏈表)。要記住1個(gè)接口可以有多個(gè)IP地址。
2.驗(yàn)證發(fā)送方的硬件地址。如果發(fā)送方的硬件地址等于本機(jī)接口的硬件地址。那是由于收到了本機(jī)發(fā)送的要求,疏忽該分組。
如果發(fā)送方的硬件地址等于以太網(wǎng)的廣播地址,說(shuō)明出錯(cuò)了。記錄該過(guò)失,并拋棄該分組。
3.檢查發(fā)送方IP地址。如果發(fā)送方IP地址等于本本機(jī)正在使用的1個(gè)IP地址,在本機(jī)系統(tǒng)配置出了過(guò)失。
4.在路由表中搜索與發(fā)送方IP地址匹配的結(jié)點(diǎn)。arplookup函數(shù)在ARP高速緩存中查找符合發(fā)送方的IP地址。當(dāng)ARP分組中
目的地址就是本機(jī),總是要穿件ARP結(jié)點(diǎn)的。
5.更新已有結(jié)點(diǎn)或填充新的結(jié)點(diǎn)。只有當(dāng)以下3個(gè)條件為真時(shí),語(yǔ)句才履行:
a.找到1個(gè)已有的ARP結(jié)點(diǎn)或成功創(chuàng)建1個(gè)新的ARP結(jié)點(diǎn)。
b.ARP結(jié)點(diǎn)指向1個(gè)路由表結(jié)點(diǎn)。
c.路由表結(jié)點(diǎn)的re_gateway字段指向1個(gè)sockaddr_dl結(jié)構(gòu)。
6.檢查發(fā)送方硬件地址是不是已改變。如果已改變,則記錄發(fā)送方硬件地址,更新最近解析的ARP結(jié)點(diǎn)。
7.如果是該ARP操作不是要求,那末拋棄接收到的分組。
8.產(chǎn)生1個(gè)對(duì)應(yīng)于ARP要求的回答。只有當(dāng)以下兩種情況時(shí)才會(huì)產(chǎn)生ARP回答:
a.本機(jī)就是該要求所要查找的目的主機(jī)。
b.本機(jī)是該要求所要查找的目的主機(jī)的ARP代理http://www.jyygyx.com/server/。
9.用以太網(wǎng)幀首部填充sockaddr。
10.將ARP回答傳送至接口輸出函數(shù),并返回。
ARP結(jié)點(diǎn)1般是動(dòng)態(tài)的,需要時(shí)創(chuàng)建,超時(shí)時(shí)自動(dòng)刪除。也允許管理員創(chuàng)建永久性結(jié)點(diǎn)。
arp_rtrequest函數(shù)使arptimer函數(shù)第1次被調(diào)用,隨后arptimer每隔5分鐘使自己被調(diào)用1次。arptimer查看ARP結(jié)點(diǎn)鏈表
中的每個(gè)結(jié)點(diǎn),如果不是1個(gè)永久結(jié)點(diǎn),而且時(shí)間已超時(shí),那末arptfree就刪除該結(jié)點(diǎn)。
ether_output函數(shù)調(diào)用arpresolve函數(shù)以取得對(duì)應(yīng)某個(gè)IP地址的以太網(wǎng)地址。arpresolve函數(shù)利用llinfo_arp結(jié)構(gòu)的la_hold
成員指針“保持”待發(fā)IP數(shù)據(jù)報(bào),并發(fā)送1個(gè)ARP要求,收到ARP回答后,再將保持的IP數(shù)據(jù)報(bào)發(fā)送出去。
ARPresolve應(yīng)避免ARP洪泛,也就是說(shuō),它不應(yīng)在還沒(méi)有收到ARP回答時(shí)高速重復(fù)發(fā)送ARP要求,出現(xiàn)這類(lèi)情況主要有兩個(gè)
緣由,第1,有多個(gè)IP數(shù)據(jù)報(bào)要發(fā)往同1個(gè)還沒(méi)有解析硬件地址的主機(jī);第2,1個(gè)IP數(shù)據(jù)報(bào)的每一個(gè)分片都會(huì)作為獨(dú)立分組
調(diào)用ether_output。
Net/3采取以下方法來(lái)避免ARP泛洪。
1.Net/3不在同1秒內(nèi)發(fā)送多個(gè)對(duì)應(yīng)同1目的地的ARP要求。
2.如果在連續(xù)5個(gè)ARP要求(也就是5秒鐘)后還沒(méi)有收到回答,路由結(jié)點(diǎn)的RTF_REJECT標(biāo)志置1,實(shí)現(xiàn)設(shè)為往后的20秒。
這會(huì)使ether_output在20秒內(nèi)謝絕發(fā)往該目的地址的IP數(shù)據(jù)報(bào)。
3.20秒后,arpresolve會(huì)繼續(xù)發(fā)送該目的主機(jī)的ARP要求。
arplookup函數(shù)調(diào)用選路函數(shù)rtalloc1在Internet路由表中查找ARP結(jié)點(diǎn),我們已看到過(guò)3次調(diào)用arplookup的情況:
1.在in_arpinput中,在接收到ARP分組后,對(duì)應(yīng)源IP地址查找或創(chuàng)建1個(gè)ARP結(jié)點(diǎn)。
2.在in_arpinput中,接收到ARP要求后,查看是不是存在目的硬件地址的代理ARP結(jié)點(diǎn)。
4.在arpresolve中,查找或創(chuàng)建1個(gè)對(duì)應(yīng)待發(fā)送數(shù)據(jù)報(bào)IP地址的ARP結(jié)點(diǎn)。
如果arplookup履行成功,則返回1個(gè)指向?qū)?yīng)llinfo_arp結(jié)構(gòu)的指針,否則返回1個(gè)空指針。