#include <afxsock.h>
#define DEF_PACKET_SIZE 32
#define MAX_PACKET 1024 // Max ICMP packet size
#define MAX_IP_HDR_SIZE 60 // Max IP header size w/options
#define IP_RECORD_ROUTE 0x7
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0
#define ICMP_MIN 8 // Minimum 8-byte ICMP packet (header)
typedef struct _iphdr
{
unsigned int h_len:4; // Length of the header
unsigned int version:4; // Version of IP
unsigned char tos; // Type of service
unsigned short total_len; // Total length of the packet
unsigned short ident; // Unique identifier
unsigned short frag_and_flags; // Flags
unsigned char ttl; // Time to live
unsigned char proto; // Protocol (TCP, UDP etc)
unsigned short checksum; // IP checksum
unsigned int sourceIP;
unsigned int destIP;
} IpHeader;
typedef struct _icmphdr
{
BYTE i_type;
BYTE i_code; // Type sub code
USHORT i_cksum;
USHORT i_id;
USHORT i_seq;
ULONG timestamp;
} IcmpHeader;
typedef struct _ipoptionhdr
{
unsigned char code; // Option type
unsigned char len; // Length of option hdr
unsigned char ptr; // Offset into options
unsigned long addr[9]; // List of IP addrs
} IpOptionHeader;
BOOL CSearchSite::CheckHostStatus(CString &strIPAddr)
{
char destip[20];
sprintf(destip,"%s",strIPAddr.GetBuffer(strIPAddr.GetLength()));
SOCKET m_hSockets;
SOCKADDR_IN m_addrDest;
SOCKADDR_IN m_addrFrom;
char *icmp_data;
char *recvbuf;
USHORT seq_no;
char *lpdest;
int datasize;
BOOL m_bRecordRout;
int timeout;
int recvicmpnum;
int ret =0;
icmp_data=NULL;
seq_no=0;
recvbuf=NULL;
m_bRecordRout=FALSE;
lpdest=NULL;
datasize=DEF_PACKET_SIZE;
m_hSockets=INVALID_SOCKET;
recvicmpnum=0;
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
return 0;
}
m_bRecordRout=FALSE;
lpdest=destip;
m_hSockets=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
if(m_hSockets==INVALID_SOCKET)
{
return FALSE;
}
timeout=100;
//设置接收延时时间
ret=setsockopt(m_hSockets,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));
if(ret==SOCKET_ERROR)
{
if(m_hSockets!=INVALID_SOCKET)
{
closesocket(m_hSockets);
}
return FALSE;
}
//设置发送延时时间
ret=setsockopt(m_hSockets,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));
if(ret==SOCKET_ERROR)
{
if(m_hSockets!=INVALID_SOCKET)
{
closesocket(m_hSockets);
}
return FALSE;
}
memset(&m_addrDest,0,sizeof(m_addrDest));
m_addrDest.sin_family=AF_INET;
//将字符串类型的IP地址转化为SocKADDR_in
if((m_addrDest.sin_addr.s_addr=inet_addr(lpdest))==INADDR_NONE)
{
if(m_hSockets!=INVALID_SOCKET)
{
closesocket(m_hSockets);
}
return FALSE;
}
//创建ICMP数据报
datasize+=sizeof(IcmpHeader);
icmp_data=(char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET);
if(!icmp_data)
{
if(m_hSockets!=INVALID_SOCKET)
{
closesocket(m_hSockets);
}
return FALSE;
}
recvbuf=(char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET);
if(!recvbuf)
{
if(m_hSockets!=INVALID_SOCKET)
{
closesocket(m_hSockets);
}
return FALSE;
}
memset(icmp_data,0,MAX_PACKET);
//填充ICMP包头
FillCMPData(icmp_data,datasize);
((IcmpHeader*)icmp_data)->i_cksum=0;
((IcmpHeader*)icmp_data)->timestamp=GetTickCount();
((IcmpHeader*)icmp_data)->i_seq=seq_no++;
((IcmpHeader*)icmp_data)->i_cksum=CheckSum((USHORT*)icmp_data,datasize);
DWORD time=GetTickCount();
//发送ping命令
ret=sendto(m_hSockets,icmp_data,datasize,0,(struct sockaddr *)&m_addrDest,sizeof(m_addrDest));
if(ret==SOCKET_ERROR)
{
if(m_hSockets!=INVALID_SOCKET)
{
closesocket(m_hSockets);
}
HeapFree(GetProcessHeap(),0,recvbuf);
HeapFree(GetProcessHeap(),0,icmp_data);
WSACleanup();
return FALSE;
}
int fromlen=sizeof(m_addrFrom);
time=GetTickCount();
//接收主机回复
ret=recvfrom(m_hSockets,recvbuf,MAX_PACKET,0,(struct sockaddr *)&m_addrFrom,&fromlen);
if(ret==SOCKET_ERROR)
{
if(m_hSockets!=INVALID_SOCKET)
{
closesocket(m_hSockets);
}
HeapFree(GetProcessHeap(),0,recvbuf);
HeapFree(GetProcessHeap(),0,icmp_data);
WSACleanup();
return FALSE;
}
if(m_hSockets!=INVALID_SOCKET)
{
closesocket(m_hSockets);
}
HeapFree(GetProcessHeap(),0,recvbuf);
HeapFree(GetProcessHeap(),0,icmp_data);
WSACleanup();
return true;
}
void CSearchSite::FillCMPData(char *icmp_data, int datasize)
{
IcmpHeader *icmp_hdr=NULL;
char *datapart=NULL;
icmp_hdr=(IcmpHeader*)icmp_data;
icmp_hdr->i_type=ICMP_ECHO;
icmp_hdr->i_code=0;
icmp_hdr->i_id=(USHORT)GetCurrentProcessId();
icmp_hdr->i_cksum=0;
icmp_hdr->i_seq=0;
}
USHORT CSearchSite::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);
}