TCP/IP 校验和算法简介
1.?前言
校驗和計算是NAT功能和內容修改功能的基本功,這些操作進行后都需要修改數據頭中的校驗和。
2.?16位校驗和計算
2.1?基本原理
IP/ICMP/IGMP/TCP/UDP等協議的校驗和算法都是相同的,采用的都是將數據流視為16位整數流進行重復疊加計算。為了計算檢驗和,首先把檢驗和字段置為0。然后,對有效數據范圍內中每個16位進行二進制反碼求和,結果存在檢驗和字段中,如果數據長度為奇數則補一字節0。當收到數據后,同樣對有效數據范圍中每個16位數進行二進制反碼的求和。由于接收方在計算過程中包含了發送方存在首部中的檢驗和,因此,如果首部在傳輸過程中沒有發生任何差錯,那么接收方計算的結果應該為全0或全1(具體看實現了,本質一樣)?。如果結果不是全0或全1,那么表示數據錯誤。
2.2?程序算法
2.2.1?C實現
這是RFC1071中提供的C語言程序:
unsigned?short?csum(unsigned?char?*addr,?int?count)
{
???????????/*?Compute?Internet?Checksum?for?"count"?bytes
????????????*?????????beginning?at?location?"addr".
????????????*/
???????register?long?sum?=?0;
?
???????while(?count?>?1?)??{
???????????/*??This?is?the?inner?loop?*/
???????????????sum?+=?*?(unsigned?short)?addr++;
???????????????count?-=?2;
???????}
?
???????????/*??Add?left-over?byte,?if?any?*/
???????if(?count?>?0?)
???????????????sum?+=?*?(unsigned?char?*)?addr;
?
???????????/*??Fold?32-bit?sum?to?16?bits?*/
???????while?(sum>>16)
???????????sum?=?(sum?&?0xffff)?+?(sum?>>?16);
?
???????return?~sum;
}
當然,如果用匯編語言實現計算速度會快得多,對于不同的CPU體系,需要各自對應編寫不同的匯編,在Linux內核源代碼中有各種CPU體系的IP校驗和計算源代碼。
2.2.2?增量式修改
如果只修改了一個字節,如只修改IP頭中的TTL,重新計算校驗和時是沒必要將所有數據范圍內數據重新計算一遍的,RFC1141中提出了增量式算法:
?????????~C'?=?~(C?+?(-m)?+?m')?=?~C?+?(m?-?m')?=?~C?+?m?+?~m'
C'為修改后的校驗和,C為修改前的校驗和,m為修改前的數值,m'為修改后的數值,~為補碼值。
C代碼實現為:
??????UpdateTTL(iph,n)
??????struct?ip_hdr?*ipptr;
??????unsigned?char?n;
??????{
??????????unsigned?long?sum;
??????????unsigned?short?old;
?
??????????old?=?ntohs(*(unsigned?short?*)&ipptr->ttl);
??????????ipptr->ttl?-=?n;
??????????sum?=?old?+?(~ntohs(*(unsigned?short?*)&ipptr->ttl)?&?0xffff);
??????????sum?+=?ntohs(ipptr->Checksum);
??????????sum?=?(sum?&?0xffff)?+?(sum>>16);
??????????ipptr->Checksum?=?htons(sum?+?(sum>>16));
??????}
?
2.3?網絡應用
2.3.1?IPv4
IPv4層中的校驗和只包括IPv4頭部分,不包括上層協議頭和應用層數據,校驗和是必須計算的。
2.3.2?IPv6
IPv6頭本身已經不包括校驗和字段,只靠上層協議的校驗和。
2.3.3?ICMP/IGMP
ICMP/IGMP校驗和計算范圍為從ICMP/IGMP開始到數據結束,不包括IP頭部分,校驗和是必須計算的。
2.3.4?TCP/UDP
TCP/UDP的校驗和計算有點特殊,所計算的數據范圍除了包括TCP/UDP頭開始到數據結束外,還要包括一個IP偽頭部分,所謂偽頭,只有12字節數據,包括源地址(4字節)、目的地址(4字節)、協議(2字節,第一字節補0)和TCP/UDP包長(2字節)。TCP的校驗和是必須的,而UDP的校驗和是可選的,如果UDP中校驗和字段為0,表示不進行校驗和計算,因此對于UDP協議數據的修改后想偷懶的話直接將校驗和設為0?就可以了。
?
3.?32位校驗和
3.1?以太幀
以太幀校驗和使用的是CRC校驗,校驗和為4字節32位,算法比較適合硬件實現,其計算和校驗都是底層完成的,在IP棧以上時就不用考慮,即使上層直接是構造以太幀發送,也只需構造以太頭部即可,發送時由底層自動添加后面的校驗和。
3.2?SCTP
在SCTP(協議號:132)協議中,校驗和計算比較特殊,采用了和以太包校驗和相似的CRC32算法(RFC3309),計算結果是32位而不再是16位。計算范圍為從SCTP頭到數據結束,不包括IP偽頭。
————————————————
版權聲明:本文為CSDN博主「namelcx」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/namelcx/article/details/6866720
總結
以上是生活随笔為你收集整理的TCP/IP 校验和算法简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IP头中的校验和计算方法介绍
- 下一篇: make -j 的并行任务个数选择