IP报头结构:
//定义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报头的结构:
计算校验和的经典函数:
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);
}
ICMP报头结构:
//定义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
|
检验和
|
标识符
|
序号
|
地址掩码
|
路由询问和通告
类型:9
|
代码:0
|
检验和
|
地址数
|
地址项目长度
|
寿命
|
路由器地址1
|
地址参考1
|
路由器地址2
|
地址参考2
|
...
|
阅读(7185) | 评论(0) | 转发(0) |