IP報文及ICMP報文結構原理
IP報頭結構:
typedef struct _iphdr{
unsigned char h_lenver; //4 位IP版本號+4位首部長度
unsigned char tos; //8位服務類型TOS
unsigned short total_len; //16位IP包總長度(字節)
unsigned short ident; //1 6位標識, 用於輔助IP包的拆裝
unsigned short frag_and_flags; //3位標誌位+13位偏移位, 也是用於IP包的拆裝
unsigned char ttl; //8位IP包生存時間 TTL
unsigned char proto; //8位協議 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校驗和,最初置零,等所有包頭都填寫正確後,計算並替換.
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HEADER;
在給張圖片看下ip報頭的結構:
計算校驗和的經典函數:
{
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);
}
ICMP報頭結構:
typedef struct _icmphdr{
unsigned char i_type; //8位類型
unsigned char i_code; //8位代碼
unsigned short i_cksum; //16位校驗和, 從TYPE開始,直到最後一位用戶數據,如果爲字節數爲奇數則補充一位
unsigned short i_id ; //識別號(一般用進程號作爲識別號), 用於匹配ECHO和ECHO REPLY包
unsigned short i_seq ; //報文序列號, 用於標記ECHO報文順序
unsigned int timestamp; //時間戳
}ICMP_HEADER;
再上一張圖看看:
ICMP報文的各種狀態:
目的不可達報文
類型:3 | 代碼:0至15 | 檢驗和 |
未使用(全0) | ||
收到的IP數據報的一部分,包括IP首部以及數據報數據的前8個字節 |
源端抑制報文
類型:4 | 代碼:0 | 檢驗和 |
未使用(全0) | ||
收到的IP數據報的一部分,包括IP首部以及數據報數據的前8個字節 |
超時報文
類型:11 | 代碼:0或1 | 檢驗和 |
未使用(全0) | ||
收到的IP數據報的一部分,包括IP首部以及數據報數據的前8個字節 |
參數問題
類型:12 | 代碼:0或1 | 檢驗和 |
指針 | 未使用(全0) | |
收到的IP數據報的一部分,包括IP首部以及數據報數據的前8個字節 |
改變路由
類型:5 | 代碼:0到3 | 檢驗和 |
目標路由器IP地址 | ||
收到的IP數據報的一部分,包括IP首部以及數據報數據的前8個字節 |
回送請求和回答
類型:8或0 | 代碼:0 | 檢驗和 | |
標識符 | 序號 | ||
由請求報文發送;由回答報文重複 |
時間戳請求和回答
類型:13或14 | 代碼:0 | 檢驗和 | |
標識符 | 序號 | ||
原始時間戳 | |||
接收時間戳 | |||
發送時間戳 |
地址掩碼請求和回答
類型:17或18 | 代碼:0 | 檢驗和 | |
標識符 | 序號 | ||
地址掩碼 |
路由詢問和通告
類型:10 | 代碼:0 | 檢驗和 | |
標識符 | 序號 |
類型:9 | 代碼:0 | 檢驗和 | |
地址數 | 地址項目長度 | 壽命 | |
路由器地址1 | |||
地址參考1 | |||
路由器地址2 | |||
地址參考2 | |||
... |