www.pudn.com > PortScan_sjtu.rar > ICMP_ECHO.cpp


// ICMP_ECHO.cpp : 定义控制台应用程序的入口点。 
// 
#include "stdafx.h" 
#include  
#include  
#include "ICMP_ECHO.h" 
 
#pragma comment(lib,"ws2_32.lib")  
 
void ICMP_ECHO::Init_Header(char* buf) 
{ 
	ICMP_HDR *icmp = NULL; 
	char* datapart = NULL; 
 
	icmp = (ICMP_HDR*)buf;                  //初始化ICP头 
	icmp->icmp_type = 8; 
	icmp->icmp_code = 0; 
	icmp->icmp_id = GetCurrentProcessId(); 
	icmp->icmp_checksum = 0; 
	icmp->icmp_sequence = 0; 
	icmp->icmp_timestamp=GetTickCount(); 
 
	datapart = buf + sizeof(ICMP_HDR); 
    memset(datapart, 'E', 32); 
 
	icmp->icmp_checksum = checksum((USHORT *)buf,sizeof(ICMP_HDR)+32); 
} 
 
USHORT ICMP_ECHO::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); 
} 
 
int ICMP_ECHO::Ping(char* IP_dest,u_int time_out, char* msg) 
{ 
	WSADATA wsd; 
	ICMP_HDR *icmp_send = NULL; 
	ICMP_HDR *icmp_rev = NULL; 
	SOCKADDR_STORAGE dest; 
	struct sockaddr_in src_addr; 
	SOCKET s; 
 
	char send_buf[sizeof(ICMP_HDR)+32]; 
	char recv_buf[sizeof(IPV4_HDR)+sizeof(ICMP_HDR)+32]; 
 
	char tempMsg[50]; 
	tempMsg[0] = '\0'; 
 
	if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) 
	{ 
		sprintf(tempMsg,"Ping %s: WSAStartup() failed: %d\r\n", IP_dest,WSAGetLastError()); 
		strcat(msg,tempMsg); 
		return -1; 
	} 
 
	s = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);          //ICMP协议socket 
	if (s==INVALID_SOCKET) { 
		sprintf(tempMsg,"Ping %s:无法建立套结字 \r\n", IP_dest); 
		strcat(msg,tempMsg); 
		WSACleanup(); 
		return (-1); 
	} 
 
	//设置套接字的超时时间 
	int ret_code = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&time_out, sizeof(time_out)); 
	if (ret_code==SOCKET_ERROR) { 
		sprintf(tempMsg,"Ping %s:ICMP设置接收超时时间失败 \r\n", IP_dest); 
		strcat(msg,tempMsg); 
		closesocket(s); 
		WSACleanup(); 
		return (-1); 
	} 
	ret_code = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&time_out, sizeof(time_out)); 
	if (ret_code==SOCKET_ERROR) { 
		sprintf(tempMsg,"Ping %s:ICMP设置发送超时时间失败 \r\n", IP_dest); 
		strcat(msg,tempMsg); 
		closesocket(s); 
		WSACleanup(); 
		return (-1); 
	} 
 
 
	((SOCKADDR_IN *)&dest)->sin_family = AF_INET;                     //初始化目标地址 
	((SOCKADDR_IN *)&dest)->sin_port = htons(0); 
	((SOCKADDR_IN *)&dest)->sin_addr.s_addr = inet_addr(IP_dest); 
 
    Init_Header(send_buf);                                            //初始化ICMP报文 
 
	ret_code = sendto(s,send_buf,sizeof(ICMP_HDR)+32,0,(SOCKADDR *)&dest,sizeof(dest));       //发送ICMP报文 
	if (ret_code==SOCKET_ERROR) { 
		sprintf(tempMsg,"Ping %s:ICMP发送失败 \r\n", IP_dest); 
		strcat(msg,tempMsg); 
		closesocket(s); 
		WSACleanup(); 
		return(-1); 
	} 
	int src_len = sizeof(src_addr); 
 
	ret_code = recvfrom(s, (char *)&recv_buf, sizeof(recv_buf), 0, (SOCKADDR *)&src_addr, &src_len);  //接受回复 
	 
	if (ret_code==SOCKET_ERROR) { 
		sprintf(tempMsg,"Ping %s: 主机关机 \r\n", IP_dest);           
		strcat(msg,tempMsg); 
		closesocket(s); 
		WSACleanup(); 
		return(-1); 
	} 
 
	int recv_len = ret_code;                    //分析回复报文 
 
	if (recv_len < sizeof(IPV4_HDR)){ 
		sprintf(tempMsg,"Ping %s: ICMP Reply ERROR! \r\n", IP_dest); 
		strcat(msg,tempMsg); 
		closesocket(s); 
		WSACleanup(); 
		return(-1); 
	} 
	IPV4_HDR *ip_hdr_recv = (IPV4_HDR *)recv_buf;              //IP头分析 
 
	int ip_hdr_recv_len = ip_hdr_recv->ip_verlen & 0x0F; 
	ip_hdr_recv_len = (ip_hdr_recv_len) << 2; 
 
	if (checksum((u_short *)ip_hdr_recv, ip_hdr_recv_len)) { 
		sprintf(tempMsg,"Ping %s: ICMP Reply IP header checksum is wrong! \r\n", IP_dest); 
		strcat(msg,tempMsg); 
		closesocket(s); 
		WSACleanup(); 
		return(-1); 
	} 
 
	if (recv_len < (ip_hdr_recv_len + sizeof(ICMP_HDR))) { 
		sprintf(tempMsg,"Ping %s: ICMP Reply len 不正确! \r\n", IP_dest); 
		strcat(msg,tempMsg); 
		closesocket(s); 
		WSACleanup(); 
		return(-1); 
	} 
	ICMP_HDR *icmp_hdr_recv = (ICMP_HDR *) (recv_buf + ip_hdr_recv_len);        //ICMP头分析 
 
	if (icmp_hdr_recv->icmp_type !=0 ){                                        //是否对ping回复 
		sprintf(tempMsg,"Ping %s: ICMP Reply type 不正确! \r\n", IP_dest); 
		strcat(msg,tempMsg); 
		closesocket(s); 
		WSACleanup(); 
		return(-1); 
	} 
	if (icmp_hdr_recv->icmp_id != (u_short)GetCurrentProcessId() ){            //是否对本进程回复 
		sprintf(tempMsg,"Ping %s: ICMP Reply 不是返回本进程的! \r\n", IP_dest); 
		strcat(msg,tempMsg); 
		closesocket(s); 
		WSACleanup(); 
		return(-1); 
	} 
 
	sprintf(tempMsg,"Ping %s: 主机开机! \r\n", IP_dest); 
	strcat(msg,tempMsg); 
	closesocket(s); 
	WSACleanup(); 
	return 0; 
	 
}