#pragma pack(4) #include #include #include #define ICMP_ECHO 8 #define ICMP_ECHOREPLY 0 #define ICMP_MIN 8 //#pragma comment(lib,"ws2_32.lib") //IP数据报头 typedef struct iphdr { unsigned int h_len:4; // length of the header 头部长 unsigned int version:4; // Version of IP IP版本 一般都为IPV4 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; //生存时间TTL unsigned char proto; // protocol (TCP, UDP etc) // 上层协议 unsigned short checksum; // IP checksum IP校验总和 unsigned int sourceIP; //源IP地址 unsigned int destIP; //目的IP地址 }IpHeader; // ICMP header 定义ICMP 头部 typedef struct icmphdr { BYTE i_type; BYTE i_code; USHORT i_cksum; USHORT i_id; USHORT i_seq; ULONG timestamp; }IcmpHeader; #define STATUS_FAILED 0xFFFF #define DEF_PACKET_SIZE 32 #define DEF_PACKET_NUMBER 4 #define MAX_PACKET 1024 #define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s)) #define xfree(p) HeapFree (GetProcessHeap(),0,(p)) USHORT checksum(USHORT *buffer, int size); int decode_resp(char *buf, int bytes,struct sockaddr_in *from); void fill_icmp_data(char * icmp_data, int datasize); void Usage(char *progname) { fprintf(stderr,"Usage:\n"); fprintf(stderr,"%s [number of packets] [data_size]\n",progname); fprintf(stderr,"datasize can be up to 1Kb\n"); ExitProcess(STATUS_FAILED); } int main(int argc, char *argv[]) { WSADATA wsaData; SOCKET sockRaw; struct sockaddr_in dest,from; struct hostent *hp; int result,datasize,times; int fromlen = sizeof(from); int timeout = 1000; int statistic = 0; char *dest_ip; char *icmp_data; char *recvbuf; unsigned int addr=0; USHORT seq_no = 0; if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0) { fprintf(stderr,"WSAStartup failed: %d\n",GetLastError()); ExitProcess(STATUS_FAILED); } if (argc <2 ) { Usage(argv[0]); } sockRaw = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL, 0,WSA_FLAG_OVERLAPPED); if (sockRaw == INVALID_SOCKET) { fprintf(stderr,"WSASocket() failed: %d\n",WSAGetLastError()); ExitProcess(STATUS_FAILED); } result = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout)); if(result == SOCKET_ERROR) { fprintf(stderr,"failed to set recv timeout: %d\n",WSAGetLastError()); ExitProcess(STATUS_FAILED); } timeout = 1000; result = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout)); if(result == SOCKET_ERROR) { fprintf(stderr,"failed to set send timeout: %d\n",WSAGetLastError()); ExitProcess(STATUS_FAILED); } memset(&dest,0,sizeof(sockaddr_in)); /***********/ hp = gethostbyname(argv[1]); if (!hp) { addr = inet_addr(argv[1]); } if ((!hp) && (addr == INADDR_NONE) ) { fprintf(stderr,"Unable to resolve %s\n",argv[1]); ExitProcess(STATUS_FAILED); } 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); if(argc>2) { times=atoi(argv[2]); if(times == 0) times=DEF_PACKET_NUMBER; } else times=DEF_PACKET_NUMBER; if (argc >3) { datasize = atoi(argv[3]); if (datasize == 0) datasize = DEF_PACKET_SIZE; if (datasize >1024) { fprintf(stderr,"WARNING : data_size is too large !\n"); datasize = DEF_PACKET_SIZE; } } else 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()); ExitProcess(STATUS_FAILED); } memset(icmp_data,0,MAX_PACKET); fill_icmp_data(icmp_data,datasize); fprintf(stdout,"\nPinging %s with %d of data\n\n",dest_ip,datasize); for(int i=0; ii_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) { printf("Request timed out.\n"); continue; } fprintf(stderr,"sendto failed: %d\n",WSAGetLastError()); ExitProcess(STATUS_FAILED); } if (bwrote < datasize ) { fprintf(stdout,"Wrote %d bytes\n",bwrote); } result = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen); if (result == SOCKET_ERROR) { if (WSAGetLastError() == WSAETIMEDOUT) { printf("Request timed out.\n"); continue; } fprintf(stderr,"recvfrom failed: %d\n",WSAGetLastError()); ExitProcess(STATUS_FAILED); } if(!decode_resp(recvbuf,result,&from)) statistic++; Sleep(1000); } 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); WSACleanup(); return 0; } 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 ; 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)); }