123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- #pragma pack(4)
- #include "Stdafx.h"
- #include "ping.h"
- #include "winsock2.h"
- #include "stdlib.h"
- #include "stdio.h"
- #pragma comment(lib,"WS2_32")
- WSADATA wsaData;
- SOCKET sockRaw;
- int bread;
- int timeout = 1000;
- int InitPing(void)
- {
- CString str;
- if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0)
- {
- //fprintf(stderr,"WSAStartup failed: %d\n",GetLastError());
- //ExitProcess(STATUS_FAILED);
- str.Format("WSAStartup failed: %d\n",GetLastError());
- return -1;
- }
- sockRaw = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL, 0,WSA_FLAG_OVERLAPPED);
- //
- //注:为了使用发送接收超时设置(即设置SO_RCVTIMEO, SO_SNDTIMEO),
- // 必须将标志位设为WSA_FLAG_OVERLAPPED !
- //
- if (sockRaw == INVALID_SOCKET)
- {
- //fprintf(stderr,"WSASocket() failed: %d\n",WSAGetLastError());
- str.Format("WSASocket() failed: %d\n",WSAGetLastError());
- return -1;
- }
- bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,
- sizeof(timeout));
- if(bread == SOCKET_ERROR)
- {
- //fprintf(stderr,"failed to set recv timeout: %d\n",WSAGetLastError());
- str.Format("failed to set recv timeout: %d\n",WSAGetLastError());
- return -1;
- }
- timeout = 1000;
- bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,
- sizeof(timeout));
- if(bread == SOCKET_ERROR)
- {
- //fprintf(stderr,"failed to set send timeout: %d\n",WSAGetLastError());
- str.Format("failed to set send timeout: %d\n",WSAGetLastError());
- return -1;
- }
- return 0;
- }
- void UnInitPing(void)
- {
- WSACleanup();
- }
- int Ping(UINT nRetries,LPCSTR pstrHost)
- {
- CString str;
- struct sockaddr_in dest,from;
- struct hostent * hp;
- int datasize;
- int fromlen = sizeof(from);
- int statistic = 0; /* 用于统计结果 */
- char *dest_ip;
- char *icmp_data;
- char *recvbuf;
- unsigned int addr=0;
- USHORT seq_no = 0;
-
- memset(&dest,0,sizeof(dest));
- hp = gethostbyname(pstrHost);
- if (!hp)
- {
- addr = inet_addr(pstrHost);
- }
- if ((!hp) && (addr == INADDR_NONE) )
- {
- //fprintf(stderr,"Unable to resolve %s\n",argv[1]);
- LOG4C((LOG_NOTICE, "Unable to resolve %s",pstrHost));
- return -1;
- }
- if (hp != NULL)
- {
- memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
- }
- else
- {
- dest.sin_addr.s_addr = addr;
- }
- if (hp)
- {
- dest.sin_family = hp->h_addrtype;
- }
- else
- {
- dest.sin_family = AF_INET;
- }
- dest_ip = inet_ntoa(dest.sin_addr);
- //
- // atoi函数原型是: int atoi( const char *string );
- // The return value is 0 if the input cannot be converted to an integer !
- //
-
- datasize = DEF_PACKET_SIZE;
- datasize += sizeof(IcmpHeader);
- icmp_data = (char*)xmalloc(MAX_PACKET);
- recvbuf = (char*)xmalloc(MAX_PACKET);
- if (!icmp_data)
- {
- //fprintf(stderr,"HeapAlloc failed %d\n",GetLastError());
- str.Format("HeapAlloc failed %d\n",GetLastError());
- LOG4C((LOG_NOTICE, "%s", str));
- return -1;
- }
- memset(icmp_data,0,MAX_PACKET);
- fill_icmp_data(icmp_data,datasize);
- //
- //显示提示信息
- //
- //fprintf(stdout,"\nPinging %s ....\n\n",dest_ip);
- //LOG4C((LOG_NOTICE, "\nPinging %s ....\n\n",dest_ip));
- for(int i=0;i<4;i++)
- {
- int bwrote;
- ((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);
- bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));
- if (bwrote == SOCKET_ERROR)
- {
- if (WSAGetLastError() == WSAETIMEDOUT)
- {
- str.Format("%s=Request timed out.\n",pstrHost);
- //LOG4C((LOG_NOTICE, "%s", str));
- xfree(icmp_data);
- xfree(recvbuf);
- return 1;
- }
- //LOG4C((LOG_NOTICE, "sendto failed: %d",WSAGetLastError()));
- return -1;
- //fprintf(stderr,"sendto failed: %d\n",WSAGetLastError());
- //ExitProcess(STATUS_FAILED);
- }
- if (bwrote < datasize )
- {
- //LOG4C((LOG_NOTICE, "Wrote %d bytes",bwrote));
- //fprintf(stdout,"Wrote %d bytes\n",bwrote);
- }
- bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen);
- if (bread == SOCKET_ERROR)
- {
- if (WSAGetLastError() == WSAETIMEDOUT)
- {
- //printf("Request timed out.\n");
- //continue;
- str.Format("%s=Request timed out.\n",pstrHost);
- //LOG4C((LOG_NOTICE, "%s", str));
- xfree(icmp_data);
- xfree(recvbuf);
- return 1;
- }
- LOG4C((LOG_NOTICE, "recvfrom failed: %d",WSAGetLastError()));
- //fprintf(stderr,"recvfrom failed: %d\n",WSAGetLastError());
- //ExitProcess(STATUS_FAILED);
- return -1;
- }
- if(!decode_resp(recvbuf,bread,&from))
- {
- //statistic++; /* 成功接收的数目++ */
- break;
- }
- }
-
- /*
- Display the statistic result
- */
- //fprintf(stdout,"\nPing statistics for %s \n",dest_ip);
- //fprintf(stdout," Packets: Sent = %d,Received = %d, Lost = %d (%2.0f%% loss)\n",times,
- // statistic,(times-statistic),(float)(times-statistic)/times*100);
- //LOG4C((LOG_NOTICE, "\nPing statistics for %s",dest_ip));
- xfree(icmp_data);
- xfree(recvbuf);
- return 0;
- }
- /*
- The response is an IP packet. We must decode the IP header to locate
- the ICMP data
- */
- int decode_resp(char *buf, int bytes,struct sockaddr_in *from)
- {
- IpHeader *iphdr;
- IcmpHeader *icmphdr;
- unsigned short iphdrlen;
- iphdr = (IpHeader *)buf;
- iphdrlen = (iphdr->h_len) * 4 ; // number of 32-bit words *4 = bytes
- if (bytes < iphdrlen + ICMP_MIN)
- {
- //printf("Too few bytes from %s\n",inet_ntoa(from->sin_addr));
- }
- icmphdr = (IcmpHeader*)(buf + iphdrlen);
- if (icmphdr->i_type != ICMP_ECHOREPLY)
- {
- //fprintf(stderr,"non-echo type %d recvd\n",icmphdr->i_type);
- return 1;
- }
- if (icmphdr->i_id != (USHORT)GetCurrentProcessId())
- {
- //fprintf(stderr,"someone else's packet!\n");
- return 1;
- }
- //printf("%d bytes from %s:",bytes, inet_ntoa(from->sin_addr));
- //printf(" icmp_seq = %d. ",icmphdr->i_seq);
- //printf(" time: %d ms ",GetTickCount()-icmphdr->timestamp);
- //printf("\n");
- return 0;
- }
- USHORT 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);
- }
- /*
- Helper function to fill in various stuff in our ICMP request.
- */
- void fill_icmp_data(char * icmp_data, int datasize)
- {
- IcmpHeader *icmp_hdr;
- char *datapart;
- 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;
- datapart = icmp_data + sizeof(IcmpHeader);
- //
- // Place some junk in the buffer.
- //
- memset(datapart,'E', datasize - sizeof(IcmpHeader));
- }
|