分析TCP/IP協(xié)議棧代碼之IP & ICMP(STM32平臺(tái))
1. IP介紹
IP是TCP/IP協(xié)議族中最為核心的協(xié)議。大家,如TCP、UDP、ICMP及IGMP數(shù)據(jù),都是在IP數(shù)據(jù)報(bào)格式基礎(chǔ)上再封裝一層再來(lái)傳輸?shù)模ㄒ?jiàn)圖1 - 4)。
不可靠(unreliable)的意思是它不能保證 IP數(shù)據(jù)報(bào)能成功地到達(dá)目的地。 IP僅提供最好的傳輸服務(wù)。如果發(fā)生某種錯(cuò)誤時(shí),如某個(gè)路由器暫時(shí)用完了緩沖區(qū), IP有一個(gè)簡(jiǎn)單的錯(cuò)誤處理算法:丟棄該數(shù)據(jù)報(bào),然后發(fā)送 ICMP消息報(bào)給信源端。任何要求的可靠性必須由上層來(lái)提供(如TCP) 。
無(wú)連接(connectionless)這個(gè)術(shù)語(yǔ)的意思是I P并不維護(hù)任何關(guān)于后續(xù)數(shù)據(jù)報(bào)的狀態(tài)信息。每個(gè)數(shù)據(jù)報(bào)的處理是相互獨(dú)立的。這也說(shuō)明, IP數(shù)據(jù)報(bào)可以不按發(fā)送順序接收。如果一信源向相同的信宿發(fā)送兩個(gè)連續(xù)的數(shù)據(jù)報(bào)(先是 A,然后是B) ,每個(gè)數(shù)據(jù)報(bào)都是獨(dú)立地進(jìn)行路由選擇,可能選擇不同的路線,因此B可能在A到達(dá)之前先到達(dá)。
2. IP首部
I P數(shù)據(jù)報(bào)的格式如圖3 - 1所示。普通的IP首部長(zhǎng)為20個(gè)字節(jié),除非含有選項(xiàng)字段。
分析圖3 - 1中的首部。最高位在左邊,記為0 bit;最低位在右邊,記為31 bit。4個(gè)字節(jié)的32 bit值以下面的次序傳輸:首先是0~7 bit,其次8~15 bit,然后1 6~23 bit,最后是24~31 bit。這種傳輸次序稱作big endian字節(jié)序。由于TCP/IP首部中所有的二進(jìn)制整數(shù)在網(wǎng)絡(luò)中傳輸時(shí)都要求以這種次序,因此它又稱作網(wǎng)絡(luò)字節(jié)序。
目前的協(xié)議版本號(hào)是4,因此IP有時(shí)也稱作IPv4。
服務(wù)類型(TOS)字段包括一個(gè)3 bit的優(yōu)先權(quán)子字段(現(xiàn)在已被忽略) ,4 bit的TO S子字段和1 bit未用位但必須置0。4 bit的TO S分別代表:最小時(shí)延、最大吞吐量、最高可靠性和最小費(fèi)用。
總長(zhǎng)度字段是指整個(gè)I P數(shù)據(jù)報(bào)的長(zhǎng)度,以字節(jié)為單位。
標(biāo)識(shí)字段唯一地標(biāo)識(shí)主機(jī)發(fā)送的每一份數(shù)據(jù)報(bào)。通常每發(fā)送一份報(bào)文它的值就會(huì)加 1。在大多數(shù)從伯克利派生出來(lái)的系統(tǒng)中,每發(fā)送一個(gè)I P數(shù)據(jù)報(bào),I P層都要把一個(gè)內(nèi)核變量的值加1,不管交給IP的數(shù)據(jù)來(lái)自哪一層。內(nèi)核變量的初始值根據(jù)系統(tǒng)引導(dǎo)時(shí)的時(shí)間來(lái)設(shè)置。
TTL(time-to-live)生存時(shí)間字段設(shè)置了數(shù)據(jù)報(bào)可以經(jīng)過(guò)的最多路由器數(shù)。TTL的初始值由源主機(jī)設(shè)置(通常為3 2或6 4) ,一旦經(jīng)過(guò)一個(gè)處理它的路由器,它的值就減去1。當(dāng)該字段的值為0時(shí),數(shù)據(jù)報(bào)就被丟棄,并發(fā)送 ICMP報(bào)文通知源主機(jī)。
協(xié)議字段可以識(shí)別是哪個(gè)協(xié)議向I P傳送數(shù)據(jù)。
首部檢驗(yàn)和字段是根據(jù)IP首部計(jì)算的檢驗(yàn)和碼。它不對(duì)首部后面的數(shù)據(jù)進(jìn)行計(jì)算。 ICMP、IGMP、UDP和TCP在它們各自的首部中均含有同時(shí)覆蓋首部和數(shù)據(jù)檢驗(yàn)和碼。
目前,這些任選項(xiàng)定義如下:
? 安全和處理限制(用于軍事領(lǐng)域,詳細(xì)內(nèi)容參見(jiàn) RFC 1108[Kent 1991])
? 記錄路徑(讓每個(gè)路由器都記下它的IP地址,見(jiàn)7 . 3節(jié))
? 時(shí)間戳(讓每個(gè)路由器都記下它的IP地址和時(shí)間,見(jiàn)7 . 4節(jié))
? 寬松的源站選路(為數(shù)據(jù)報(bào)指定一系列必須經(jīng)過(guò)的 IP地址,見(jiàn)8 . 5節(jié))
? 嚴(yán)格的源站選路(與寬松的源站選路類似,但是要求只能經(jīng)過(guò)指定的這些地址,不能經(jīng)過(guò)其他的地址) 。
------------------------------------------以上內(nèi)容整理于《TCP/IP協(xié)議詳解:卷1》--------------------------------------
------------------------------------------以下內(nèi)容產(chǎn)生于代碼及分析--------------------------------------
3. IP宏定義實(shí)現(xiàn)
C++ Code
4. IP函數(shù)實(shí)現(xiàn)
以太網(wǎng)的header在IP的header之前,很簡(jiǎn)單的,介紹先。
配置以太網(wǎng)的頭,為14字節(jié):6字節(jié)目的mac地址+6字節(jié)源mac地址+2字節(jié)協(xié)議類型
展開(kāi)之后如下所示,其在以太網(wǎng)幀中的位置與之前的宏定義是一一對(duì)應(yīng)的。
IP與ARP一樣,需要判定是不是發(fā)給本機(jī)的(eth_type_is_ip_and_my_ip函數(shù)),還有與填充make_eth 函數(shù)一樣需要填充函數(shù)(make_ip函數(shù)),此外還有填充其他雜七雜八和16位首部校驗(yàn)和函數(shù)(fill_ip_hdr_checksum函數(shù))
C++ Code
5. IP校驗(yàn)和實(shí)現(xiàn)
校驗(yàn)和函數(shù)式如何得出校驗(yàn)和值的呢?看《TCP/IP協(xié)議詳解:卷1》里面咋說(shuō)的吧。
”為了計(jì)算一份數(shù)據(jù)報(bào)的 IP檢驗(yàn)和,首先把檢驗(yàn)和字段置為 0。然后,對(duì)首部中每個(gè) 16 bit進(jìn)行二進(jìn)制反碼求和(整個(gè)首部看成是由一串 16 bit的字組成) ,結(jié)果存在檢驗(yàn)和字段中。當(dāng)收到一份I P數(shù)據(jù)報(bào)后,同樣對(duì)首部中每個(gè)16 bit進(jìn)行二進(jìn)制反碼的求和。由于接收方在計(jì)算過(guò)程中包含了發(fā)送方存在首部中的檢驗(yàn)和,因此,如果首部在傳輸過(guò)程中