PING.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:7k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. * ping.c - Simple ping utility using SOCK_RAW
  3. *       This is a part of the Microsoft Source Code Samples.
  4. *       Copyright 1996-1997 Microsoft Corporation.
  5. *       All rights reserved.
  6. *       This source code is only intended as a supplement to
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the
  9. *       Microsoft samples programs.
  10. ******************************************************************************/
  11. #pragma pack(4)
  12. #define WIN32_LEAN_AND_MEAN
  13. #include <winsock2.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #define ICMP_ECHO 8
  17. #define ICMP_ECHOREPLY 0
  18. #define ICMP_MIN 8 // minimum 8 byte icmp packet (just header)
  19. /* The IP header */
  20. typedef struct iphdr {
  21. unsigned int h_len:4;          // length of the header
  22. unsigned int version:4;        // Version of IP
  23. unsigned char tos;             // Type of service
  24. unsigned short total_len;      // total length of the packet
  25. unsigned short ident;          // unique identifier
  26. unsigned short frag_and_flags; // flags
  27. unsigned char  ttl; 
  28. unsigned char proto;           // protocol (TCP, UDP etc)
  29. unsigned short checksum;       // IP checksum
  30. unsigned int sourceIP;
  31. unsigned int destIP;
  32. }IpHeader;
  33. //
  34. // ICMP header
  35. //
  36. typedef struct _ihdr {
  37.   BYTE i_type;
  38.   BYTE i_code; /* type sub code */
  39.   USHORT i_cksum;
  40.   USHORT i_id;
  41.   USHORT i_seq;
  42.   /* This is not the std header, but we reserve space for time */
  43.   ULONG timestamp;
  44. }IcmpHeader;
  45. #define STATUS_FAILED 0xFFFF
  46. #define DEF_PACKET_SIZE 32
  47. #define MAX_PACKET 1024
  48. #define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))
  49. #define xfree(p)   HeapFree (GetProcessHeap(),0,(p))
  50. void fill_icmp_data(char *, int);
  51. USHORT checksum(USHORT *, int);
  52. void decode_resp(char *,int ,struct sockaddr_in *);
  53. void Usage(char *progname){
  54.   
  55.   fprintf(stderr,"Usage:n");
  56.   fprintf(stderr,"%s <host> [data_size]n",progname);
  57.   fprintf(stderr,"datasize can be up to 1Kbn");
  58.   ExitProcess(STATUS_FAILED);
  59. }
  60. int main(int argc, char **argv){
  61.   WSADATA wsaData;
  62.   SOCKET sockRaw;
  63.   struct sockaddr_in dest,from;
  64.   struct hostent * hp;
  65.   int bread,datasize;
  66.   int fromlen = sizeof(from);
  67.   int timeout = 1000;
  68.   char *dest_ip;
  69.   char *icmp_data;
  70.   char *recvbuf;
  71.   unsigned int addr=0;
  72.   USHORT seq_no = 0;
  73.   if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0){
  74. fprintf(stderr,"WSAStartup failed: %dn",GetLastError());
  75. ExitProcess(STATUS_FAILED);
  76.   }
  77.   if (argc <2 ) {
  78. Usage(argv[0]);
  79.   }
  80.   sockRaw = WSASocket (AF_INET,
  81.    SOCK_RAW,
  82.    IPPROTO_ICMP,
  83.    NULL, 0,0);
  84.   
  85.   if (sockRaw == INVALID_SOCKET) {
  86. fprintf(stderr,"WSASocket() failed: %dn",WSAGetLastError());
  87. ExitProcess(STATUS_FAILED);
  88.   }
  89.   bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,
  90.    sizeof(timeout));
  91.   if(bread == SOCKET_ERROR) {
  92.    fprintf(stderr,"failed to set recv timeout: %dn",WSAGetLastError());
  93. ExitProcess(STATUS_FAILED);
  94.   }
  95.   timeout = 1000;
  96.   bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,
  97.    sizeof(timeout));
  98.   if(bread == SOCKET_ERROR) {
  99.    fprintf(stderr,"failed to set send timeout: %dn",WSAGetLastError());
  100. ExitProcess(STATUS_FAILED);
  101.   }
  102.   memset(&dest,0,sizeof(dest));
  103.   hp = gethostbyname(argv[1]);
  104.   if (!hp){
  105. addr = inet_addr(argv[1]);
  106.   }
  107.   if ((!hp)  && (addr == INADDR_NONE) ) {
  108. fprintf(stderr,"Unable to resolve %sn",argv[1]);
  109. ExitProcess(STATUS_FAILED);
  110.   }
  111.   if (hp != NULL)
  112.   memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
  113.   else
  114.    dest.sin_addr.s_addr = addr;
  115.   if (hp)
  116.   dest.sin_family = hp->h_addrtype;
  117.   else
  118.   dest.sin_family = AF_INET;
  119.   dest_ip = inet_ntoa(dest.sin_addr);
  120.   if (argc >2) {
  121. datasize = atoi(argv[2]);
  122. if (datasize == 0)
  123.   datasize = DEF_PACKET_SIZE;
  124.   }
  125.   else
  126.   datasize = DEF_PACKET_SIZE;
  127.   datasize += sizeof(IcmpHeader);  
  128.   icmp_data = xmalloc(MAX_PACKET);
  129.   recvbuf = xmalloc(MAX_PACKET);
  130.   if (!icmp_data) {
  131. fprintf(stderr,"HeapAlloc failed %dn",GetLastError());
  132. ExitProcess(STATUS_FAILED);
  133.   }
  134.   
  135.   memset(icmp_data,0,MAX_PACKET);
  136.   fill_icmp_data(icmp_data,datasize);
  137.   while(1) {
  138. int bwrote;
  139. ((IcmpHeader*)icmp_data)->i_cksum = 0;
  140. ((IcmpHeader*)icmp_data)->timestamp = GetTickCount();
  141. ((IcmpHeader*)icmp_data)->i_seq = seq_no++;
  142. ((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data, 
  143. datasize);
  144. bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,
  145. sizeof(dest));
  146. if (bwrote == SOCKET_ERROR){
  147.   if (WSAGetLastError() == WSAETIMEDOUT) {
  148.    printf("timed outn");
  149. continue;
  150.   }
  151.   fprintf(stderr,"sendto failed: %dn",WSAGetLastError());
  152.   ExitProcess(STATUS_FAILED);
  153. }
  154. if (bwrote < datasize ) {
  155.   fprintf(stdout,"Wrote %d bytesn",bwrote);
  156. }
  157. bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,
  158.  &fromlen);
  159. if (bread == SOCKET_ERROR){
  160.   if (WSAGetLastError() == WSAETIMEDOUT) {
  161.    printf("timed outn");
  162. continue;
  163.   }
  164.   fprintf(stderr,"recvfrom failed: %dn",WSAGetLastError());
  165.   ExitProcess(STATUS_FAILED);
  166. }
  167. decode_resp(recvbuf,bread,&from);
  168. Sleep(1000);
  169.   }
  170.   return 0;
  171. }
  172. /* 
  173. The response is an IP packet. We must decode the IP header to locate 
  174. the ICMP data 
  175. */
  176. void decode_resp(char *buf, int bytes,struct sockaddr_in *from) {
  177. IpHeader *iphdr;
  178. IcmpHeader *icmphdr;
  179. unsigned short iphdrlen;
  180. iphdr = (IpHeader *)buf;
  181. iphdrlen = iphdr->h_len * 4 ; // number of 32-bit words *4 = bytes
  182. if (bytes  < iphdrlen + ICMP_MIN) {
  183. printf("Too few bytes from %sn",inet_ntoa(from->sin_addr));
  184. }
  185. icmphdr = (IcmpHeader*)(buf + iphdrlen);
  186. if (icmphdr->i_type != ICMP_ECHOREPLY) {
  187. fprintf(stderr,"non-echo type %d recvdn",icmphdr->i_type);
  188. return;
  189. }
  190. if (icmphdr->i_id != (USHORT)GetCurrentProcessId()) {
  191. fprintf(stderr,"someone else's packet!n");
  192. return ;
  193. }
  194. printf("%d bytes from %s:",bytes, inet_ntoa(from->sin_addr));
  195. printf(" icmp_seq = %d. ",icmphdr->i_seq);
  196. printf(" time: %d ms ",GetTickCount()-icmphdr->timestamp);
  197. printf("n");
  198. }
  199. USHORT checksum(USHORT *buffer, int size) {
  200.   unsigned long cksum=0;
  201.   while(size >1) {
  202. cksum+=*buffer++;
  203. size -=sizeof(USHORT);
  204.   }
  205.   
  206.   if(size ) {
  207. cksum += *(UCHAR*)buffer;
  208.   }
  209.   cksum = (cksum >> 16) + (cksum & 0xffff);
  210.   cksum += (cksum >>16);
  211.   return (USHORT)(~cksum);
  212. }
  213. /* 
  214. Helper function to fill in various stuff in our ICMP request.
  215. */
  216. void fill_icmp_data(char * icmp_data, int datasize){
  217.   IcmpHeader *icmp_hdr;
  218.   char *datapart;
  219.   icmp_hdr = (IcmpHeader*)icmp_data;
  220.   icmp_hdr->i_type = ICMP_ECHO;
  221.   icmp_hdr->i_code = 0;
  222.   icmp_hdr->i_id = (USHORT)GetCurrentProcessId();
  223.   icmp_hdr->i_cksum = 0;
  224.   icmp_hdr->i_seq = 0;
  225.   
  226.   datapart = icmp_data + sizeof(IcmpHeader);
  227.   //
  228.   // Place some junk in the buffer.
  229.   //
  230.   memset(datapart,'E', datasize - sizeof(IcmpHeader));
  231. }