home *** CD-ROM | disk | FTP | other *** search
/ CD Loisirs 18 / cd.iso / PLANETE / WS_PING / WSPI_SRC.ZIP / WS_PINGR.C < prev   
C/C++ Source or Header  |  1994-10-20  |  7KB  |  227 lines

  1. /*************************************************************************
  2.  Windows Sockets PING Application Support Module
  3.  
  4.  Written by John A. Junod, 267 Hillwood St., Martinez, GA, 30907 93.10.01
  5.  <junodj@css583.gordon.army.mil>     <zj8549@trotter.usma.edu> 
  6.  
  7.  Released into the public domain with no restrictions other than to give
  8.  me some of the credit if you use this code in other applications.  Some
  9.  code concepts based on code published in UNIX Network Programming by
  10.  W. Richard Stevens or on BSD networking source code.
  11.  
  12.  Note that MOST Windows Sockets DLL's do not support RAW_SOCKETS.  This
  13.  does work with Trumpet's Windows Sockets DLL Alpha 18.
  14. *************************************************************************/
  15. #include "ws_glob.h"
  16. #include "ws_ping.h"
  17. #include "ip_icmp.h"
  18.  
  19. int nTransmitted=0;
  20. int nReceived=0;
  21. int nMaxWait=5000;  // milliseconds
  22.  
  23. u_long lTotalTime,lMinTime,lMaxTime;
  24.  
  25. SOCKET DoClose(SOCKET sockfd)
  26. {
  27.   if(WSAIsBlocking()) {
  28.     bAborted=TRUE;
  29.     WSACancelBlockingCall();
  30.   }
  31.  
  32.   if(closesocket(sockfd)==SOCKET_ERROR) {
  33.     DoPrintf("[%u] close error: %s",sockfd,
  34.        ReturnWSError(WSAGetLastError(),NULL));
  35.   } else {
  36.     DoPrintf("[%u] socket closed.",sockfd);
  37.     sockfd=INVALID_SOCKET;
  38.   }
  39.   return(sockfd);
  40. }
  41.  
  42. PrintHeader(struct sockaddr_in FAR *saDestAddr,int nDataSize)
  43. {
  44.   DoAddLine(" ");
  45.   DoPrintf("PING %s (%s): %u data bytes",
  46.       szRemoteHost,inet_ntoa(saDestAddr->sin_addr),nDataSize+SIZE_ICMP_HDR);
  47.   lMaxTime=lTotalTime=0l; lMinTime=99999999l;
  48.   return(0);
  49. }
  50.  
  51. PrintStats() {
  52.   DoAddLine(" ");
  53.   DoPrintf("PING Statistics for %s",szRemoteHost);
  54.   if(nTransmitted && nReceived)
  55.     DoPrintf("%d packets transmitted, %d packets received, %d%% packet loss",
  56.       nTransmitted,nReceived,
  57.       (int)(((nTransmitted-nReceived)*100)/nTransmitted));
  58.   else if(nTransmitted)
  59.     DoPrintf("%d packets transmitted, %d packets received, 100%% packet loss",
  60.       nTransmitted,nReceived);
  61.   if(nReceived)
  62.     DoPrintf("round-trip (ms) min/avg/max = %ld/%ld/%ld",
  63.       lMinTime,lTotalTime/nReceived,lMaxTime);
  64.   return 0;
  65. }
  66.  
  67. int send_ping(SOCKET sockfd, struct sockaddr_in FAR *saDestAddr,
  68.           LPSTR pPacket,int nLength)
  69. {
  70.   int nRC;
  71.   struct icmp *icmp;
  72.   u_long *timeloc;
  73.  
  74.   nLength+=SIZE_ICMP_HDR;
  75.   icmp=(struct icmp *)pPacket;
  76.   // set the send time
  77.   timeloc=&pPacket[SIZE_ICMP_HDR];
  78.   *timeloc=GetTickCount();
  79.   // complete the ICMP packet header
  80.   icmp->icmp_type=ICMP_ECHO;
  81.   icmp->icmp_code=0;
  82.   icmp->icmp_cksum=0;
  83.   icmp->icmp_id=(int)hWndMain;
  84.   icmp->icmp_seq=nTransmitted;
  85.   // compute the checksum
  86.   icmp->icmp_cksum=in_cksum(icmp,nLength);
  87.   // send the packet
  88.   if((nRC=sendto(sockfd,pPacket,nLength,0,
  89.                  (struct sockaddr *) saDestAddr,
  90.                  sizeof(struct sockaddr)))==SOCKET_ERROR) {
  91.     DoPrintf("[sendto] %s",ReturnWSError(WSAGetLastError(),NULL));
  92.     if(WSAGetLastError()!=WSAEWOULDBLOCK &&
  93.        WSAGetLastError()!=WSAEINPROGRESS)
  94.       nTransmitted++;
  95.   } else {
  96.     nTransmitted++;
  97.     if(nRC!=nLength)
  98.       DoPrintf("[sendto] wrote %d bytes, return=%d",nLength,nRC);
  99.   }
  100.  
  101.   return(nRC==nLength);
  102. }
  103.  
  104. recv_ping(SOCKET sockfd,LPSTR szRecvPkt,BOOL bPrintFlag)
  105. {
  106.   int  nBytesRecv;
  107.   int  saFromAddrLen;
  108.   struct sockaddr_in  saFromAddr;
  109.   int  nRC;
  110.  
  111. // NOTE: this is for the blocking version..... this means we won't exit
  112. // until we get the packet(s) we are looking for.  This means we have to
  113. // use a timer function to make us exit.
  114.  
  115.   nRC=FALSE;
  116.   saFromAddrLen=sizeof(saFromAddr);
  117.   SetTimer(hWndMain,10,nMaxWait,NULL);
  118.   nBytesRecv=recvfrom(sockfd,szRecvPkt,MAXPACKET,0,
  119.                  (struct sockaddr *)&saFromAddr,
  120.                  &saFromAddrLen);
  121.   KillTimer(hWndMain,10);
  122.   if(nBytesRecv!=SOCKET_ERROR || WSAGetLastError()!=WSAEINTR) {
  123.     if(nBytesRecv==SOCKET_ERROR) {
  124.       DoPrintf("[recvfrom] %s",ReturnWSError(WSAGetLastError(),NULL));
  125.       return FALSE;
  126.     } else
  127.       nRC=PrintPkt(szRecvPkt,nBytesRecv,&saFromAddr,bPrintFlag);
  128.   }
  129.   return nRC;
  130. }
  131.  
  132. // compute packet checksum
  133. int in_cksum(u_short FAR *pPacket,int nBytes)
  134. {
  135.   long sum;
  136.   u_short oddbyte;
  137.   u_short answer;
  138.  
  139.   sum=0l;
  140.   while(nBytes>1) { sum += *pPacket++; nBytes -= 2; }
  141.   if(nBytes==1) {
  142.     oddbyte=0;
  143.     *((u_char FAR *) &oddbyte) = *(u_char FAR *)pPacket;
  144.     sum += oddbyte;
  145.   }
  146.   sum = (sum >> 16) + (sum & 0xffff);
  147.   sum += (sum >> 16);
  148.   answer= ~sum;
  149.   return (answer);
  150. }
  151.  
  152. int PrintPkt(LPSTR pPacket,int nLength,struct sockaddr_in FAR *saFromAddr,
  153.              BOOL bVerbose)
  154. {
  155.   int iphdrlen;
  156.   static struct ip *ip;
  157.   static struct icmp *icmp;
  158.   static struct in_addr *iptr;
  159.   u_long ulrc;
  160.   static u_long lEndTime,*lpStartTime,lTripTime;
  161.  
  162.   lEndTime=GetTickCount();
  163.   saFromAddr->sin_addr.s_addr=ntohl(saFromAddr->sin_addr.s_addr);
  164.   ip=(struct ip *) pPacket;
  165.   iphdrlen=ip->ip_hl << 2;
  166.   if(nLength < iphdrlen + ICMP_MINLEN) {
  167.     if(bVerbose) {
  168.       ulrc=ntohl(saFromAddr->sin_addr.s_addr);
  169.       iptr = (struct in_addr *) &ulrc;
  170.       DoPrintf("[received] too short (%d bytes) from %s\n",nLength,
  171.          inet_ntoa(*iptr));
  172.     }
  173.     return FALSE;
  174.   }
  175.   nLength -= iphdrlen;
  176.   icmp=(struct icmp *)(pPacket + iphdrlen);
  177.   if(icmp->icmp_type != ICMP_ECHOREPLY) {
  178.     if(bVerbose) {
  179.       ulrc=ntohl(saFromAddr->sin_addr.s_addr);
  180.       iptr = (struct in_addr *) &ulrc;
  181.       DoPrintf("[received] %d bytes from %s: icmp_type=%d (%s) icmp_code=%d",
  182.         nLength,
  183.         inet_ntoa(*iptr),
  184.         icmp->icmp_type,
  185.         ReturnICMPType(icmp->icmp_type),
  186.         icmp->icmp_code);
  187.     }
  188.     return FALSE;
  189.   }
  190.  
  191.   ulrc=ntohl(saFromAddr->sin_addr.s_addr);
  192.   iptr = (struct in_addr *) &ulrc;
  193.  
  194.   if(icmp->icmp_id!=hWndMain) {
  195.     DoPrintf("[received] %d bytes from %s. not for us",
  196.         nLength,inet_ntoa(*iptr));
  197.     return FALSE;
  198.   }
  199.   lpStartTime = &pPacket[SIZE_ICMP_HDR+ iphdrlen];
  200.   lTripTime = lEndTime - *lpStartTime;
  201.   lTotalTime += lTripTime;
  202.   if(lTripTime < lMinTime) lMinTime=lTripTime;
  203.   if(lTripTime > lMaxTime) lMaxTime=lTripTime;
  204.  
  205.   DoPrintf("%d bytes from %s: icmp_seq=%d time=%ld ms",
  206.        nLength,inet_ntoa(*iptr),icmp->icmp_seq,lTripTime);
  207.  
  208.   nReceived++;
  209.  
  210.   return TRUE;
  211. }
  212.  
  213. LPSTR ReturnICMPType(int nType)
  214. {
  215.   static char *ICMPTypeTable[]={
  216.     "Echo Reply", "ICMP 1", "ICMP 2", "DestUnrchbl",
  217.     "SrcQnch", "Redirect", "6", "7","Echo","9","10",
  218.     "Time Exceed", "ParamPrblm", "Timestamp", "Timestamp reply",
  219.     "InfoRqst", "InfoRply"
  220.   };
  221.  
  222.   if(nType<0 || nType>16)
  223.     return("Out-of-range");
  224.   return(ICMPTypeTable[nType]);
  225. }
  226.  
  227.