IP頭校驗和


IP數據包的頭信息格式:
    +-------------------------------------------------+
    |  版本 (4位)                                    |
    +-------------------------------------------------+
    |  首部長度(4位)                                |
    +-------------------------------------------------+    
    |  服務類型(TOS)8位                            |
    +-------------------------------------------------+
    |  數據包總長度(16位)                            |
    +-------------------------------------------------+
    |  標識ID號(16位)                                |
    +-------------------------------------------------+    
    |  標志位(3位)                                  |
    +-------------------------------------------------+
    |  片偏移(13位)                                  |
    +-------------------------------------------------+    
    |  生存時間(TTL)(8位)                          |
    +-------------------------------------------------+    
    |  協議類型 (8位)                                |
    +-------------------------------------------------+    
    |  首部校驗和(16位)                              |
    +-------------------------------------------------+    
    |  源IP地址(32位)                                |
    +-------------------------------------------------+    
    |  目的IP地址 (32位)                            |
    +-------------------------------------------------+  
    *  IP選項(若有) (32位)                        *
    +-------------------------------------------------+    
    *  數據                                          *
    +-------------------------------------------------+    
    
    這里要說的是首部校驗和字段。
    在發送數據時,為了計算數IP據報的校驗和。應該按如下步驟:
    (1)把IP數據報的首部都置為0,包括校驗和字段。
    (2)把首部看成以16位為單位的數字組成,依次進行二進制反碼求和。
    (3)把得到的結果存入校驗和字段中。
    在接收數據時,計算數據報的校驗和相對簡單,按如下步驟:
    (1)把首部看成以16位為單位的數字組成,依次進行二進制反碼求和,包括校驗和字段。
    (2)檢查計算出的校驗和的結果是否等於零。
    (3)如果等於零,說明被整除,校驗是和正確。否則,校驗和就是錯誤的,協議棧要拋棄這個數據包

二進制反碼求和:先進行二進制求和,然后對和取反

計算對IP首部檢驗和的算法如下:   
(1)把IP數據包的校驗和字段置為0;   
(2)把首部看成以16位為單位的數字組成,依次進行二進制求和(注意:求和時應將最高位的進位保存,所以加法應采用32位加法);   
(3)將上述加法過程中產生的進位(最高位的進位)加到低16位(采用32位加法時,即為將高16位與低16位相加,之后還要把該次加法最高位產生的進位加到低16位)   
(4)將上述的和取反,即得到校驗和。

程序如下:

unsigned short ipCksum(unsigned short *addr,int len)
{
	unsigned short cksum;
	unsigned int sum=0;

	while(len>1)
	{
		sum+=*addr++;
		len-=2;
	}
	if(len==1)
		sum+=*(unsigned char*)addr;
	sum=(sum>>16)+(sum&0xffff);  //把高位的進位,加到低八位,其實是32位加法
	sum+=(sum>>16);  //add carry
	cksum=~sum;   //取反
	return (cksum);
}

int main()
{
	unsigned short iph[]={0x4500,0x00ad,0x7755,0x4000,0x8006,
		0x0000,0x0a97,0x7819,0x0a97,0x781d};
	unsigned short cksum;

	cksum=ipCksum(iph,20);
	printf("%X\n",cksum);
	iph[5]=cksum;
	cksum=ipCksum(iph,20);
	if(cksum)
		printf("Checksum is incorrect!\n");
	else
		printf("Checksum is correct!\n");
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM