《LwIP協(xié)議棧源碼詳解——TCP/IP協(xié)議的實(shí)現(xiàn)》ARP表查詢

姓名:朱小鵬 ? ?學(xué)號(hào):16010130023

轉(zhuǎn)載:

http://blog.sina.com.cn/s/blog_62a85b950101anvd.html

【嵌牛導(dǎo)讀】:這一節(jié)主要針對(duì)ARP講解ARP表的創(chuàng)建澳泵,更新生蚁,查詢等操作。這里我們先從幾個(gè)簡(jiǎn)單的函數(shù)入手講解ARP各個(gè)子模塊功能藏姐,然后再將各個(gè)模塊與上層協(xié)議結(jié)合起來呀酸,宏觀的講解ARP模塊凉蜂。

【嵌牛鼻子】:ARP表的創(chuàng)建,更新性誉,查詢等操作

【嵌牛提問】:LWIP是怎樣進(jìn)行ARP表的創(chuàng)建窿吩,更新,查詢等操作错览?

【嵌牛正文】:

ARP攻擊纫雁,是針對(duì)以太網(wǎng)地址解析協(xié)議(ARP)的一種攻擊技術(shù)。在局域網(wǎng)中倾哺,ARP病毒收到廣播的ARP請(qǐng)求包轧邪,能夠解析出其它節(jié)點(diǎn)的(IP, MAC)地址,然后病毒偽裝為目的主機(jī),告訴源主機(jī)一個(gè)假M(fèi)AC地址羞海,這樣就使得源主機(jī)發(fā)送給目的主機(jī)的所有數(shù)據(jù)包都被病毒軟件截取忌愚,而源主機(jī)和目的主機(jī)卻渾然不知。ARP攻擊通過偽造IP地址和MAC地址實(shí)現(xiàn)ARP欺騙却邓,能夠在網(wǎng)絡(luò)中產(chǎn)生大量的ARP通信量使網(wǎng)絡(luò)阻塞菜循,攻擊者只要持續(xù)不斷的發(fā)出偽造的ARP響應(yīng)包就能更改目標(biāo)主機(jī)ARP緩存中的IP-MAC條目。ARP協(xié)議在設(shè)計(jì)時(shí)未考慮網(wǎng)絡(luò)安全方面的特性申尤,這就注定了其很容易遭受ARP攻擊癌幕。黑客只要在局域網(wǎng)內(nèi)閱讀送上門來的廣播ARP請(qǐng)求數(shù)據(jù)包,就能偷聽到網(wǎng)內(nèi)所有的(IP, MAC)地址昧穿。而源節(jié)點(diǎn)收到ARP響應(yīng)時(shí)勺远,它也不會(huì)質(zhì)疑,這樣黑客很容易冒充他人时鸵。

這一節(jié)主要針對(duì)ARP講解ARP表的創(chuàng)建胶逢,更新,查詢等操作饰潜。這里我們先從幾個(gè)簡(jiǎn)單的函數(shù)入手講解ARP各個(gè)子模塊功能初坠,然后再將各個(gè)模塊與上層協(xié)議結(jié)合起來,宏觀的講解ARP模塊彭雾。

第一個(gè)需要迫不及待要說的函數(shù)是find_entry碟刺,該函數(shù)最重要的輸入是一個(gè)IP地址,返回值是該IP地址對(duì)應(yīng)的ARP緩存表項(xiàng)索引薯酝。函數(shù)聲明原型如下半沽,

static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags)

這里爽柒,很有必要翻譯一下源代碼中注釋的內(nèi)容:該函數(shù)主要功能是尋找一個(gè)匹配的ARP表項(xiàng)或者創(chuàng)建一個(gè)新的ARP表項(xiàng),并返回該表項(xiàng)的索引號(hào)者填。如果參數(shù)ipaddr為給定的非空的內(nèi)容浩村,則函數(shù)需要返回一個(gè)處于pending或stable的索引表項(xiàng),如果沒有匹配的表項(xiàng)占哟,則該函數(shù)需要返回一個(gè)empty的表項(xiàng)心墅,但該表項(xiàng)的IP字段的值要被設(shè)置為ipaddr的值,這種情況下榨乎,find_entry函數(shù)返回后怎燥,調(diào)用者需要將表項(xiàng)從狀態(tài)empty改為pending。還有一種情況谬哀,如果參數(shù)ipaddr為空值刺覆,同樣返回一個(gè)狀態(tài)為empty的表項(xiàng)严肪。

返回狀態(tài)為empty的表項(xiàng)史煎,首先從狀態(tài)標(biāo)示為empty的空閑ARP表項(xiàng)中選取,如果這樣的表項(xiàng)都用完了驳糯,同時(shí)參數(shù)flags的值被設(shè)置為ETHARP_TRY_HARD篇梭,則find_entry就回收最老的ARP表項(xiàng),將該表項(xiàng)設(shè)置為empty狀態(tài)返回酝枢。

這個(gè)函數(shù)比較大恬偷,有將近200行代碼,這里就不貼了帘睦,直接講講它的工作流程袍患。這部分的討論還是參考了網(wǎng)上某位大俠的博客,名字記不得了竣付,對(duì)不起啊啊啊啊肮钛印!網(wǎng)絡(luò)古胆,有時(shí)確實(shí)是個(gè)好東西肆良,越發(fā)的明白。好了逸绎,看看find_entry的工作流程惹恃。

首先,lwip有一個(gè)比較巧妙的地方棺牧,它并不是沖上去就是就把a(bǔ)rp緩存中所有的表項(xiàng)搜索一遍巫糙,而是做了一個(gè)假設(shè),假設(shè)這次的表項(xiàng)索引還是上一次的(在很多情況下就是這樣的)颊乘。所以曲秉,LWIP中有個(gè)全局的變量etharp_cached_entry采蚀,它始終保存著上次用到的索引號(hào),如果這個(gè)索引恰好就是我們要找的內(nèi)容承二,且索引的表項(xiàng)已經(jīng)處于stable狀態(tài)榆鼠,那就直接返回這個(gè)索引號(hào)就完成了,we're really fast亥鸠!

如果情況不夠理想妆够,就必須去檢索整個(gè)ARP表了,檢索的過程是從ARP表的第一個(gè)表項(xiàng)開始负蚊,依次往后檢索直至最后一個(gè)表項(xiàng)神妹,過程較復(fù)雜。對(duì)于每個(gè)表項(xiàng)首先判斷它是否為empty狀態(tài)家妆,find_entry只關(guān)心第一個(gè)狀態(tài)為empty的表項(xiàng)索引值鸵荠,對(duì)該索引值以后的empty表項(xiàng)不感興趣,忽略伤极。如果一個(gè)表項(xiàng)不是empty狀態(tài)蛹找,則判斷它是不是pending狀態(tài)。對(duì)于pending狀態(tài)的表項(xiàng)哨坪,需要做以下的事情庸疾,先看看它里面存的IP地址和我們的ipaddr是否匹配,如果匹配当编,好返回該索引值届慈,記住還要更新etharp_cached_entry為該索引值,如果不匹配忿偷,則判斷該索引的數(shù)據(jù)包指針是否為空金顿,find_entry試圖記錄生存時(shí)間最長(zhǎng)的pending狀態(tài)有數(shù)據(jù)緩沖或無數(shù)據(jù)緩沖的表項(xiàng)索引。如果一個(gè)表項(xiàng)也不是pending狀態(tài)鲤桥,則判斷它是不是stable狀態(tài)揍拆。對(duì)于stable狀態(tài)的表項(xiàng),與pending狀態(tài)的表項(xiàng)處理過程相似芜壁,find_entry試圖記錄生存時(shí)間最長(zhǎng)的stable表項(xiàng)的索引礁凡。很暈吧,我也很暈慧妄,看了下面這段可能你會(huì)好點(diǎn)顷牌!

如果到這里都還沒有找到匹配的表項(xiàng),那就很杯具了塞淹,我們需要為find_entry調(diào)用者返回一個(gè)empty的表項(xiàng)索引窟蓝。經(jīng)過上面一段后,find_entry已經(jīng)知道了第一個(gè)empty狀態(tài)表項(xiàng)的索引饱普、生存時(shí)間最老的pending狀態(tài)且有數(shù)據(jù)緩沖表項(xiàng)的索引运挫、生存時(shí)間最老的pending狀態(tài)且無數(shù)據(jù)緩沖表項(xiàng)的索引状共、生存時(shí)間最老的stable狀態(tài)表項(xiàng)的索引,我們暫且先將這四個(gè)值假設(shè)為a谁帕、b峡继、c、d匈挖。如果參數(shù)flags的值被設(shè)置為ETHARP_TRY_HARD碾牌,那么find_entry會(huì)按照a-->d-->c-->b的順序選擇一個(gè)合適的索引返回,為什么是這樣的順序儡循?很明顯舶吗,不解釋。find_entry首先判斷a是否在ARP表項(xiàng)范圍內(nèi)择膝,如果是誓琼,則選擇a,如果不是肴捉,則判斷b是否在ARP表項(xiàng)范圍內(nèi)腹侣,依此類推。當(dāng)選中一個(gè)索引后每庆,隨即就會(huì)將該索引對(duì)應(yīng)的表項(xiàng)設(shè)置為empty狀態(tài)筐带,并且將該表項(xiàng)的IP地址設(shè)置為ipaddr的值今穿,ctime值設(shè)置為0缤灵,最后返回索引。至此蓝晒,find_entry大功告成腮出!

接下來,我很感興趣的一個(gè)函數(shù)是etharp_query芝薇,該函數(shù)的功能是向給定的IP地址發(fā)送一個(gè)數(shù)據(jù)包或者發(fā)送一個(gè)ARP請(qǐng)求胚嘲,當(dāng)然情況遠(yuǎn)不如此簡(jiǎn)單。還是很有必要翻譯一下源代碼中函數(shù)功能注釋的內(nèi)容:如果給定的IP地址不在ARP表中洛二,則一個(gè)新的ARP表項(xiàng)會(huì)被創(chuàng)建馋劈,此時(shí)該表項(xiàng)處于pending狀態(tài),同時(shí)一個(gè)關(guān)于該IP地址的ARP請(qǐng)求包會(huì)被廣播出去晾嘶,再同時(shí)要發(fā)送的數(shù)據(jù)包會(huì)被掛接在該表項(xiàng)的數(shù)據(jù)緩沖指針上妓雾;如果IP地址在ARP表中有相應(yīng)的表項(xiàng)存在,但該表項(xiàng)處于pending狀態(tài)垒迂,則操作與前者相同械姻,即發(fā)送一個(gè)ARP請(qǐng)求和掛接數(shù)據(jù)包;如果IP地址在ARP表中有相應(yīng)的表項(xiàng)存在机断,且表項(xiàng)處于stable狀態(tài)楷拳,此時(shí)再來判斷給定的數(shù)據(jù)包是否為空绣夺,不為空則直接將該數(shù)據(jù)包發(fā)送出去,為空則向該IP地址發(fā)送一個(gè)ARP請(qǐng)求欢揖。

etharp_query函數(shù)原型如下所示陶耍,源代碼在150行左右,這里主要講解其流程:

err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)

(1)首先判斷給定的ipaddr是否合法她混,對(duì)于空IP地址物臂、廣播IP地址、多播IP地址不予處理产上。

(2)將ipaddr作為參數(shù)調(diào)用函數(shù)find_entry棵磷,函數(shù)返回一個(gè)ARP表項(xiàng)索引,該表項(xiàng)可能是原來已經(jīng)有的晋涣,此時(shí)該表項(xiàng)應(yīng)該是pending或stable狀態(tài)仪媒;該表項(xiàng)也可能是新申請(qǐng)得到的,此時(shí)該表項(xiàng)應(yīng)該是empty狀態(tài)谢鹊。

(3)根據(jù)返回的表項(xiàng)索引找到該ARP表項(xiàng)算吩,判斷該表項(xiàng)是否為empty狀態(tài),如果是佃扼,說明該表項(xiàng)是新申請(qǐng)的偎巢,則將該表項(xiàng)狀態(tài)設(shè)置為pending狀態(tài)。

(4)判斷要發(fā)送的數(shù)據(jù)包是否為空兼耀,或者判斷ARP表項(xiàng)是否為pending狀態(tài)压昼,這兩個(gè)條件只要有一個(gè)成立,就發(fā)送一個(gè)ARP請(qǐng)求出去瘤运,發(fā)送ARP請(qǐng)求的函數(shù)是etharp_request窍霞。

(5)如果待發(fā)送的數(shù)據(jù)包不為空,此刻就根據(jù)ARP表項(xiàng)的狀態(tài)作不同的處理:若ARP表項(xiàng)處于stable狀態(tài)拯坟,則直接調(diào)用函數(shù)etharp_send_ip發(fā)送數(shù)據(jù)包但金;若ARP表項(xiàng)處于pending狀態(tài),則需要將該數(shù)據(jù)包掛接到表項(xiàng)的待發(fā)送數(shù)據(jù)鏈表上郁季,由于pending狀態(tài)的表項(xiàng)必然在第(4)步中發(fā)出了一個(gè)ARP請(qǐng)求冷溃,當(dāng)內(nèi)核接收到ARP回應(yīng)時(shí),會(huì)將表項(xiàng)設(shè)置為stable狀態(tài)梦裂,并將其鏈表上的數(shù)據(jù)全部發(fā)送出去似枕,當(dāng)然這項(xiàng)工作具體是怎樣完成的那是后話了。

將數(shù)據(jù)包掛接在表項(xiàng)的發(fā)送鏈表上塞琼,這又是一個(gè)較復(fù)雜的過程:最重要的一點(diǎn)是判斷該數(shù)據(jù)包pbuf的類型菠净,對(duì)于PBUF_REF、PBUF_POOL、PBUF_RAM型的數(shù)據(jù)包不能直接掛在發(fā)送鏈表上毅往,因?yàn)檫@些數(shù)據(jù)包在被掛接后并不會(huì)被立刻發(fā)送出去牵咙,這可能導(dǎo)致數(shù)據(jù)包在等待發(fā)送的過程中內(nèi)部數(shù)據(jù)被改動(dòng)。對(duì)于以上這些類型的待發(fā)送數(shù)據(jù)包攀唯,需要將數(shù)據(jù)拷貝至新的pbuf中洁桌,然后將新的pbuf掛接至發(fā)送鏈表。至此侯嘀,etharp_query函數(shù)功德圓滿另凌!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市戒幔,隨后出現(xiàn)的幾起案子吠谢,更是在濱河造成了極大的恐慌,老刑警劉巖诗茎,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件工坊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡敢订,警方通過查閱死者的電腦和手機(jī)王污,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來楚午,“玉大人昭齐,你說我怎么就攤上這事》瘢” “怎么了阱驾?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)把沼。 經(jīng)常有香客問我啊易,道長(zhǎng)吁伺,這世上最難降的妖魔是什么饮睬? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮篮奄,結(jié)果婚禮上捆愁,老公的妹妹穿的比我還像新娘。我一直安慰自己窟却,他們只是感情好昼丑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著夸赫,像睡著了一般菩帝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天呼奢,我揣著相機(jī)與錄音宜雀,去河邊找鬼。 笑死握础,一個(gè)胖子當(dāng)著我的面吹牛辐董,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播禀综,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼简烘,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了定枷?” 一聲冷哼從身側(cè)響起孤澎,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤华畏,失蹤者是張志新(化名)和其女友劉穎沈堡,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體屈溉,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贱迟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年姐扮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衣吠。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茶敏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缚俏,到底是詐尸還是另有隱情惊搏,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布忧换,位于F島的核電站恬惯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏亚茬。R本人自食惡果不足惜酪耳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望刹缝。 院中可真熱鬧碗暗,春花似錦、人聲如沸梢夯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽颂砸。三九已至噪奄,卻和暖如春死姚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背勤篮。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工知允, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人叙谨。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓温鸽,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親手负。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涤垫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容