IP首部校驗合

IP/ICMP/IGMP/TCP/UDP等協議的校驗和算法都是相同的,算法如下:
  在發送數據時,爲了計算IP數據包的校驗和。應該按如下步驟:
  (1)把IP數據包的校驗和字段置爲0;
  (2)把首部看成以16位爲單位的數字組成,依次進行二進制反碼求和;
  (3)把得到的結果存入校驗和字段中。
  在接收數據時,計算數據包的校驗和相對簡單,按如下步驟:
  (1)把首部看成以16位爲單位的數字組成,依次進行二進制反碼求和,包括校驗和字段;
  (2)檢查計算出的校驗和的結果是否等於零(反碼應爲16個1);
  (3)如果等於零,說明被整除,校驗是和正確。否則,校驗和就是錯誤的,協議棧要拋棄這個數據包。
  所謂的二進制反碼求和,即爲先進行二進制求和,然後對和取反。
  IP數據報格式

wKioL1hnTW-iW2EMAABf2E4I1pw146.jpg-wh_50


最後對上述過程舉個例子:

  IP頭:

  45 00    00 31

  89 F5    00 00

  6E 06    00 00(校驗字段)

  DE B7   45 5D       ->    222.183.69.93

  C0 A8   00 DC     ->    192.168.0.220

  計算:  

  4500 + 0031 +89F5 + 0000 + 6e06+ 0000 + DEB7 + 455D + C0A8 + 00DC =3 22C4

  0003 + 22C4 = 22C7

  ~22C7 = DD38      ->即爲應填充的校驗和

  當接受到IP數據包時,要檢查IP頭是否正確,則對IP頭進行檢驗,方法同上:

  計算:

  4500 + 0031 +89F5 + 0000 + 6E06+ DD38 + DEB7 + 455D + C0A8 + 00DC =3 FFFC

  0003 + FFFC = FFFF

  得到的結果是全一,正確。



代碼實現

SHORT checksum(USHORT* buffer, int size)

{

    unsigned long cksum = 0;

    while(size>1)

    {

        cksum += *buffer++;

        size -= sizeof(USHORT);

    }

    if(size)

    {

        cksum += *(UCHAR*)buffer;

    }

    cksum = (cksum>>16) + (cksum&0xffff); 

    cksum += (cksum>>16); 

    return (USHORT)(~cksum);

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章