【Linux 网络】IP校验和计算相关
校驗和只是為防止報文在信道傳輸出現誤碼導致報文錯誤,并不保證報文被他人惡意篡改。
轉發報文相關的校驗和包括3層校驗和4層校驗,2中的校驗和的計算公式的入參不同:3層校驗僅僅校驗3層頭;4層校驗需要校驗偽頭部+4層頭+4層負載。
所有校驗和的計算方法是統一的,即所有2字節數據相加,結果的進位再次與2字節數據相加,對最終結果取反。還有一種是4字節相加,然后再2字節折疊,進位再與2字節相加,最終取反。
根據以上計算方式有推論:
csum(ip頭)+csum(ip負載)=csum(ip頭+ip負載)
一、IP校驗和
unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl);
iph:ip頭指針
ihl:ip頭長度,4字節長度的數目。
采用4字節進位累加,最終再2字節折疊進位累加。
?
? ? ? ? ?該函數發包計算和收包校驗都可以。發包計算虛將ip->check字段清0;收包校驗不用將check清0,直接對整個ip頭計算結果如果為0則認為校驗成功(因為校驗和字段存的是反碼,如果將校驗和結果也納入校驗和計算公式,相當于正碼+反碼=0)。
二、TCP、UDP校驗和計算
偽頭部=saddr + daddr + len(tcp頭+tcp負載) + protocol(L4)
L4校驗和=csum(偽頭部+tcp頭+tcp負載),計算之前需將頭里校驗和字段清0.
增加偽頭部的校驗進一步增加校驗內容,為保證L3和L4的一致(防君子不防小人)
csum_tcpudp_magic()的sum參數就是tcp頭+tcp負載的校驗和
?
?如:
?三、其他校驗和函數
1、csum_partial()
從buff開始的len長度的內存計算校驗和,并且對sum增量計算。簡單說將len對4補齊計算32bit校驗和,但沒有取反。
2、csum_fold()
將32bit數字折疊成16bit校驗和,并取反。以4字節計算校驗和方式的接口最終都會調用該接口獲取最終結果。
一般校驗和計算都是統一對數據進行++操作后如skb_csum()、csum_partial()函數等等,最終調用csum_fold()函數對結算結果進程折疊并取反,得出最終的校驗和結果。
四、skb中校驗和相關字段
ip_summed表明L3和L4的計算結果,區分接收和發送。
1、接收過程
skb->csum可能包含L4一部分校驗和;
skb->ip_summed字段代表:設備驅動告訴L4, 軟件當前校驗和的狀態,各取值含義如下:
(1) CHECKSUM_NONE:
skb->csum中的校驗和無效,可能是硬件沒有提供校驗和,可能是硬件不支持,也可能是硬件校驗出錯但是并未丟棄數據包,此時將ip_summed設為CHECKSUM_NONE,讓L4軟件重新校驗;
(2) CHECKSUM_COMPLETE:
硬件已經校驗了L4報頭和其payload部分,并且校驗和保存在了skb->csum中,L4軟件只需要再計算偽報頭然后檢查校驗結果即可。硬件計算稍復雜的偽頭部比較好性能,因為偽頭部需要提取ip頭的信息。
(3) CHECKSUM_UNNECESSARY:
硬件已經進行了完整的校驗,無需軟件再進行檢查,L4收到數據包后如果檢查ip_summed是這種情況,就可以跳過校驗過程;
2、發送過程
skb->ip_summed字段包含了L4軟件告訴設備驅動程序當前校驗和的狀態,各取值含義如下:
(1) CHECKSUM_NONE:L4軟件已經進行了校驗,硬件無需做任何事情;
(2) CHECKSUM_PARTIAL:L4軟件計算了偽報頭,并且將值保存在了tcp/udp首部的check字段中,硬件需要計算其余部分的校驗和。硬件適合做簡單的++操作,偽頭部稍復雜交給cpu。
?
總結
以上是生活随笔為你收集整理的【Linux 网络】IP校验和计算相关的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ceph理论概述
- 下一篇: Armijo-Goldstein法则和W