display correct Min RTT
[reactos.git] / reactos / apps / utils / net / ping / ping.c
index 486d2e2..4fee881 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: ping.c,v 1.4 2001/05/01 23:08:17 chorns Exp $
- *
+/*
  * COPYRIGHT:   See COPYING in the top level directory
  * PROJECT:     ReactOS ping utility
  * FILE:        apps/net/ping/ping.c
@@ -8,14 +7,19 @@
  * REVISIONS:
  *   CSH  01/09/2000 Created
  */
+
 #include <winsock2.h>
 #include <tchar.h>
 #include <stdarg.h>
 #include <string.h>
 #include <stdio.h>
+
 #ifndef _MSC_VER
 
 /* FIXME: Where should this be? */
+#ifdef CopyMemory
+#undef CopyMemory
+#endif
 #define CopyMemory(Destination, Source, Length) memcpy(Destination, Source, Length);
 
 /* Should be in the header files somewhere (exported by ntdll.dll) */
@@ -27,8 +31,11 @@ typedef long long __int64;
 
 char * _i64toa(__int64 value, char *string, int radix);
 
-#endif
+#endif /* _MSC_VER */
 
+#ifdef DBG
+#undef DBG
+#endif
 
 /* General ICMP constants */
 #define ICMP_MINSIZE           8               /* Minimum ICMP packet size */
@@ -98,9 +105,29 @@ LARGE_INTEGER       TicksPerMs; /* Ticks per millisecond */
 LARGE_INTEGER       TicksPerUs; /* Ticks per microsecond */
 BOOL                UsePerformanceCounter;
 
+#ifdef DBG
+/* Display the contents of a buffer */
+static VOID DisplayBuffer(
+    PVOID Buffer,
+    DWORD Size)
+{
+    UINT i;
+    PCHAR p;
+
+    printf("Buffer (0x%p)  Size (0x%lX).\n", Buffer, Size);
+
+    p = (PCHAR)Buffer;
+    for (i = 0; i < Size; i++) {
+      if (i % 16 == 0) {
+        printf("\n");
+      }
+      printf("%02X ", (p[i]) & 0xFF);
+    }
+}
+#endif /* DBG */
 
 /* Display usage information on screen */
-VOID Usage(VOID)
+static VOID Usage(VOID)
 {
        printf("\nUsage: ping [-t] [-n count] [-l size] [-w timeout] destination-host\n\n");
        printf("Options:\n");
@@ -112,7 +139,7 @@ VOID Usage(VOID)
 }
 
 /* Reset configuration to default values */
-VOID Reset(VOID)
+static VOID Reset(VOID)
 {
     LARGE_INTEGER PerformanceCounterFrequency;
 
@@ -148,13 +175,13 @@ VOID Reset(VOID)
 }
 
 /* Return ULONG in a string */
-ULONG GetULONG(LPSTR String)
+static ULONG GetULONG(LPSTR String)
 {
     UINT i, Length;
     ULONG Value;
 
     i = 0;
-    Length = strlen(String);
+    Length = (UINT)_tcslen(String);
     while ((i < Length) && ((String[i] < '0') || (String[i] > '9'))) i++;
     if ((i >= Length) || ((String[i] < '0') || (String[i] > '9'))) {
         InvalidOption = TRUE;
@@ -166,7 +193,7 @@ ULONG GetULONG(LPSTR String)
 }
 
 /* Return ULONG in a string. Try next paramter if not successful */
-ULONG GetULONG2(LPSTR String1, LPSTR String2, PINT i)
+static ULONG GetULONG2(LPSTR String1, LPSTR String2, PINT i)
 {
     ULONG Value;
 
@@ -184,16 +211,16 @@ ULONG GetULONG2(LPSTR String1, LPSTR String2, PINT i)
 }
 
 /* Parse command line parameters */
-BOOL ParseCmdline(int argc, char* argv[])
+static BOOL ParseCmdline(int argc, char* argv[])
 {
     INT i;
     BOOL ShowUsage;
     BOOL FoundTarget;
-#if 0
-    lstrcpy(TargetName, "127.0.0.1");
-    PingCount = 1;
-    return TRUE;
-#endif
+//#if 1
+//    lstrcpy(TargetName, "127.0.0.1");
+//    PingCount = 1;
+//    return TRUE;
+//#endif
     if (argc < 2) {
         ShowUsage = TRUE;
     } else {
@@ -253,7 +280,7 @@ BOOL ParseCmdline(int argc, char* argv[])
 }
 
 /* Calculate checksum of data */
-WORD Checksum(PUSHORT data, UINT size)
+static WORD Checksum(PUSHORT data, UINT size)
 {
     ULONG sum = 0;
 
@@ -272,7 +299,7 @@ WORD Checksum(PUSHORT data, UINT size)
 }
 
 /* Prepare to ping target */
-BOOL Setup(VOID)
+static BOOL Setup(VOID)
 {
     WORD     wVersionRequested;
     WSADATA  WsaData;
@@ -281,10 +308,10 @@ BOOL Setup(VOID)
     PHOSTENT phe;
 
     wVersionRequested = MAKEWORD(2, 2);
+
     Status = WSAStartup(wVersionRequested, &WsaData);
     if (Status != 0) {
-        printf("Could not initialize winsock dll.\n"); 
+        printf("Could not initialize winsock dll.\n");
         return FALSE;
     }
 
@@ -302,11 +329,11 @@ BOOL Setup(VOID)
         if (phe == NULL) {
             printf("Unknown host %s.\n", TargetName);
             return FALSE;
-        } 
+        }
     }
-       
+
     if (phe != NULL) {
-        CopyMemory(&Target.sin_addr, phe->h_addr_list, phe->h_length);
+        CopyMemory(&Target.sin_addr, phe->h_addr, phe->h_length);
     } else {
         Target.sin_addr.s_addr = Addr;
     }
@@ -316,7 +343,7 @@ BOOL Setup(VOID)
     } else {
         Target.sin_family = AF_INET;
     }
-       
+
     TargetIP           = inet_ntoa(Target.sin_addr);
     CurrentSeqNum      = 0;
     SentCount          = 0;
@@ -329,7 +356,7 @@ BOOL Setup(VOID)
 }
 
 /* Close socket */
-VOID Cleanup(VOID)
+static VOID Cleanup(VOID)
 {
     if (IcmpSock != INVALID_SOCKET)
         closesocket(IcmpSock);
@@ -337,7 +364,7 @@ VOID Cleanup(VOID)
     WSACleanup();
 }
 
-VOID QueryTime(PLARGE_INTEGER Time)
+static VOID QueryTime(PLARGE_INTEGER Time)
 {
     if (UsePerformanceCounter) {
         if (QueryPerformanceCounter(Time) == 0) {
@@ -359,80 +386,90 @@ VOID QueryTime(PLARGE_INTEGER Time)
     }
 }
 
-VOID TimeToMsString(LPSTR String, LARGE_INTEGER Time)
+static VOID TimeToMsString(LPSTR String, LARGE_INTEGER Time)
 {
-    UINT          i, Length;
     CHAR          Convstr[40];
     LARGE_INTEGER LargeTime;
 
     LargeTime.QuadPart = Time.QuadPart / TicksPerMs.QuadPart;
-    _i64toa(LargeTime.QuadPart, Convstr, 10);
-       strcpy(String, Convstr);
-    strcat(String, ",");
 
-    LargeTime.QuadPart = (Time.QuadPart % TicksPerMs.QuadPart) / TicksPerUs.QuadPart;
     _i64toa(LargeTime.QuadPart, Convstr, 10);
-    Length = strlen(Convstr);
-    if (Length < 4) {
-        for (i = 0; i < 4 - Length; i++)
-            strcat(String, "0");
-    }
-
-    strcat(String, Convstr);
+       strcpy(String, Convstr);
     strcat(String, "ms");
 }
 
 /* Locate the ICMP data and print it. Returns TRUE if the packet was good,
    FALSE if not */
-BOOL DecodeResponse(PCHAR buffer, UINT size, PSOCKADDR_IN from)
+static BOOL DecodeResponse(PCHAR buffer, UINT size, PSOCKADDR_IN from)
 {
     PIPv4_HEADER      IpHeader;
     PICMP_ECHO_PACKET Icmp;
-       UINT              IphLength;
+       UINT              IphLength;
     CHAR              Time[100];
     LARGE_INTEGER     RelativeTime;
     LARGE_INTEGER     LargeTime;
+    CHAR              Sign[1];
 
     IpHeader = (PIPv4_HEADER)buffer;
 
     IphLength = IpHeader->IHL * 4;
 
-    if (size  < IphLength + ICMP_MINSIZE)
+    if (size  < IphLength + ICMP_MINSIZE) {
+#ifdef DBG
+        printf("Bad size (0x%X < 0x%X)\n", size, IphLength + ICMP_MINSIZE);
+#endif /* DBG */
         return FALSE;
+    }
 
     Icmp = (PICMP_ECHO_PACKET)(buffer + IphLength);
 
-    if (Icmp->Icmp.Type != ICMPMSG_ECHOREPLY)
+    if (Icmp->Icmp.Type != ICMPMSG_ECHOREPLY) {
+#ifdef DBG
+        printf("Bad ICMP type (0x%X should be 0x%X)\n", Icmp->Icmp.Type, ICMPMSG_ECHOREPLY);
+#endif /* DBG */
         return FALSE;
+    }
 
-    if (Icmp->Icmp.Id != (USHORT)GetCurrentProcessId())
+    if (Icmp->Icmp.Id != (USHORT)GetCurrentProcessId()) {
+#ifdef DBG
+        printf("Bad ICMP id (0x%X should be 0x%X)\n", Icmp->Icmp.Id, (USHORT)GetCurrentProcessId());
+#endif /* DBG */
         return FALSE;
+    }
 
     QueryTime(&LargeTime);
 
     RelativeTime.QuadPart = (LargeTime.QuadPart - Icmp->Timestamp.QuadPart);
 
-    TimeToMsString(Time, RelativeTime);
+    if ((RelativeTime.QuadPart / TicksPerMs.QuadPart) < 1) {
+        strcpy(Sign, "<");
+        strcpy(Time, "1ms");
+    } else {
+        strcpy(Sign, "=");
+        TimeToMsString(Time, RelativeTime);
+    }
+
 
-    printf("Reply from %s: bytes=%d time=%s TTL=%d\n", inet_ntoa(from->sin_addr), 
-               size - IphLength - sizeof(ICMP_ECHO_PACKET) , Time, IpHeader->TTL);
-    if (RelativeTime.QuadPart < MinRTT.QuadPart) {
-               MinRTT.QuadPart = RelativeTime.QuadPart;
+    printf("Reply from %s: bytes=%d time%s%s TTL=%d\n", inet_ntoa(from->sin_addr),
+      size - IphLength - sizeof(ICMP_ECHO_PACKET), Sign, Time, IpHeader->TTL);
+    if (RelativeTime.QuadPart < MinRTT.QuadPart || !MinRTTSet) {
+           MinRTT.QuadPart = RelativeTime.QuadPart;
         MinRTTSet = TRUE;
     }
        if (RelativeTime.QuadPart > MaxRTT.QuadPart)
-               MaxRTT.QuadPart = RelativeTime.QuadPart;
-       SumRTT.QuadPart += RelativeTime.QuadPart;
+           MaxRTT.QuadPart = RelativeTime.QuadPart;
+
+    SumRTT.QuadPart += RelativeTime.QuadPart;
 
        return TRUE;
 }
 
 /* Send and receive one ping */
-BOOL Ping(VOID)
+static BOOL Ping(VOID)
 {
     INT                 Status;
     SOCKADDR            From;
-    UINT                Length;
+    INT                 Length;
     PVOID               Buffer;
     UINT                Size;
     PICMP_ECHO_PACKET   Packet;
@@ -472,10 +509,17 @@ BOOL Ping(VOID)
     Timeval.tv_usec = Timeout % 1000;
     Status = select(0, NULL, &Fds, NULL, &Timeval);
     if ((Status != SOCKET_ERROR) && (Status != 0)) {
+
+#ifdef DBG
+        printf("Sending packet\n");
+        DisplayBuffer(Buffer, sizeof(ICMP_ECHO_PACKET) + DataSize);
+        printf("\n");
+#endif /* DBG */
+
         Status = sendto(IcmpSock, Buffer, sizeof(ICMP_ECHO_PACKET) + DataSize,
             0, (SOCKADDR*)&Target, sizeof(Target));
+        SentCount++;
     }
-    SentCount++;
     if (Status == SOCKET_ERROR) {
         if (WSAGetLastError() == WSAEHOSTUNREACH) {
             printf("Destination host unreachable.\n");
@@ -496,6 +540,12 @@ BOOL Ping(VOID)
     if ((Status != SOCKET_ERROR) && (Status != 0)) {
         Length = sizeof(From);
         Status = recvfrom(IcmpSock, Buffer, Size, 0, &From, &Length);
+
+#ifdef DBG
+        printf("Received packet\n");
+        DisplayBuffer(Buffer, Status);
+        printf("\n");
+#endif /* DBG */
     }
     if (Status == SOCKET_ERROR) {
         if (WSAGetLastError() != WSAETIMEDOUT) {
@@ -515,7 +565,7 @@ BOOL Ping(VOID)
 
     if (!DecodeResponse(Buffer, Status, (PSOCKADDR_IN)&From)) {
         /* FIXME: Wait again as it could be another ICMP message type */
-        printf("Request timed out.\n");
+        printf("Request timed out (incomplete datagram received).\n");
         LostCount++;
     }
 
@@ -538,7 +588,7 @@ int main(int argc, char* argv[])
 
         printf("\nPinging %s [%s] with %d bytes of data:\n\n",
             TargetName, TargetIP, DataSize);
-               
+
                Count = 0;
                while ((NeverStop) || (Count < PingCount)) {
                        Ping();
@@ -563,7 +613,7 @@ int main(int argc, char* argv[])
         }
 
         if (!MinRTTSet)
-            MinRTT.QuadPart = 0;
+            MinRTT = MaxRTT;
 
         TimeToMsString(MinTime, MinRTT);
         TimeToMsString(MaxTime, MaxRTT);