发送ICMP报文时,必须由程序自己计算校验和,将它填入ICMP头部对应的域中。校验和的计算方法是:
将数据以字(16位)为单位累加到一个双字中,如果数据长度为奇数,最后一个字节将被扩展到字,累加的结果是一个双字,
最后将这个双字的高16位和低16位相加后取反,便得到了校验和!
下面是程序实现源代码:
USHORT checksum(USHORT *buffer,int size)
{
unsigned long cksum=0;
//将数据以字为单位累加到CKSUM中
while(size>1)
{
cksum+=*buffer++;
size-=sizeof(USHORT);
}
//如果为奇数,将最后一个字节扩展到双字,再累加到cksum中
if(size)
{
cksum+=*(UCHAR *)buffer;
}
//将cksum的高16位和低16位相加,取反后得到校验和
cksum=(cksum>>16)+(cksum&0xffff);
cksum+=(cksum>>16);
return (USHORT)(~cksum);
}
icmp头的数据结构
typedef struct icmp_hdr
{
unsigned char icmp_type;//消息类型
unsigned char icmp_code;//代码
unsigned short icmp_checksum;//校验和
unsigned short icmp_id;//用来唯一标识此请求的id号,通常设置为进程id
unsigned short icmp_sequence;//序列号
unsigned long icmp_timestamp;//时间戳
}ICMP_HDR,*PICMP_HDR;
IP头结构
typedef struct IPHeader //20个字节
{
UCHAR iphVerLen;//版本号和头长度
UCHAR ipTOS;//服务类型
USHORT ipLength;//封包总长度,即整个IP报的长度
USHORT ipID;//封包标识,惟一标识发送的每一个数据报
USHORT ipFlags;//标志
UCHAR ipTTL;//生存时间TTL
UCHAR ipProtocol;//协议,可能是TCP,UDP,ICMP等
USHORT ipChecksum;//校验和
ULONG ipSource;//源IP地址
ULONG ipDestination;//目标地址
}IPHeader,*PIPHeader;
UDP头结构
typedef struct UDPHeader
{
USHORT sourcePort;//源端口号
USHORT destinationPort;//目的端口号
USHORT len;//封包长度
USHORT checksum;//校验和
}UDPHeader,*PUDPHeader;
TCP头结构
typedef struct TCPHeader //20个字节
{
USHORT sourcePort;//16位源端口号
USHORT destinationPort;//16位目的端口号
ULONG sequenceNumber;//32位序列号
ULONG acknowledgeNumber;//32位确认号
UCHAR dataoffset; //4位首部长度/6位保留字
UCHAR flags;//6位标志位
USHORT windows;//16位窗口大小
USHORT checksum;//16位校验和
USHORT urgenPointer;//16位紧急数据偏移量
}TCPHeader,*PTCPHeader;
以太网arp包格式
#define ARPHRD_EHER 1
//ARP协议opcodes
#define ARPOP_REQUEST 1 //ARP请求
#define ARPOP_REPLY 2 //arp响应
typedef struct _ARPHeader //28字节的ARP头
{
USHORT hrd; //硬件地址 空间,以太网中为ARPHRD_ETHER
USHORT eth_type; //以太网类型,ETHERTYPE_IP
UCHAR maclen;//MAC地址长度,为6
UCHAR iplen;//IP地址的长度,为4
USHORT opcode; //操作代码,ARPOP_REQUEST为请求,ARPOP_REPLY为响应
UCHAR smac[6];//源MAC地址
UCHAR saddr[4];//源IP地址
UCHAR dmac[6];//目的MAC地址
UCHAR daddr[4];//目的IP地址
}ARPHeader,*PARPHeader;
-------------------------------------------------------------------------------------------------------------
dest | source | type | data |
address | address | | |
-------------------------------------------------------------------------------------------------------------
以太网数据帧头
#define ETHERTYPE_IP 0x0800
#define ETHERTYPE_ARP 0x0806
typedef struct _ETHeader //14 bytes
{
UCHAR dhost[6]; //目的MAC地址
UCHAR shost[6];//源MAC地址
USHORT type; //下层协议类型,如IP(ethertype_ip),arp(ethertype_arp)
}ETHeader,*PETHeader;