start adding burst, don't print negative losses
[unix-history] / usr / src / sbin / ping / ping.c
index a644778..9d50c33 100644 (file)
@@ -1,6 +1,29 @@
+/*
+ * Copyright (c) 1987, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)ping.c     4.3 (Berkeley) %G%";
-#endif
+char copyright[] =
+"@(#) Copyright (c) 1987, 1988 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)ping.c     4.11 (Berkeley) %G%";
+#endif /* not lint */
 
 /*
  *                     P I N G . C
 
 /*
  *                     P I N G . C
@@ -58,8 +81,10 @@ char usage[] = "Usage:  ping [-drv] host [data size] [npackets]\n";
 
 char *hostname;
 char hnamebuf[MAXHOSTNAMELEN];
 
 char *hostname;
 char hnamebuf[MAXHOSTNAMELEN];
+char *inet_ntoa();
 
 int npackets;
 
 int npackets;
+int burst = 1;
 int ntransmitted = 0;          /* sequence # for outbound packets = #sent */
 int ident;
 
 int ntransmitted = 0;          /* sequence # for outbound packets = #sent */
 int ident;
 
@@ -78,6 +103,7 @@ char *argv[];
 {
        struct sockaddr_in from;
        char **av = argv;
 {
        struct sockaddr_in from;
        char **av = argv;
+       char *toaddr = NULL;
        struct sockaddr_in *to = (struct sockaddr_in *) &whereto;
        int on = 1;
        struct protoent *proto;
        struct sockaddr_in *to = (struct sockaddr_in *) &whereto;
        int on = 1;
        struct protoent *proto;
@@ -110,14 +136,15 @@ char *argv[];
                hostname = hnamebuf;
        } else {
                hp = gethostbyname(av[0]);
                hostname = hnamebuf;
        } else {
                hp = gethostbyname(av[0]);
-               if (hp) {
-                       to->sin_family = hp->h_addrtype;
-                       bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
-                       hostname = hp->h_name;
-               } else {
-                       printf("%s: unknown host %s\n", argv[0], av[0]);
+               if (!hp) {
+                       fprintf(stderr, "ping: %s: ", av[0]);
+                       herror((char *)NULL);
                        exit(1);
                }
                        exit(1);
                }
+               to->sin_family = hp->h_addrtype;
+               bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
+               hostname = hp->h_name;
+               toaddr = inet_ntoa(to->sin_addr.s_addr);
        }
 
        if( argc >= 2 )
        }
 
        if( argc >= 2 )
@@ -148,7 +175,11 @@ char *argv[];
        if (options & SO_DONTROUTE)
                setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &on, sizeof(on));
 
        if (options & SO_DONTROUTE)
                setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &on, sizeof(on));
 
-       printf("PING %s: %d data bytes\n", hostname, datalen );
+       printf("PING %s", hostname);
+       if (toaddr)
+               printf(" (%s)", toaddr);
+       printf(": %d data bytes\n", datalen);
+                               
 
        setlinebuf( stdout );
 
 
        setlinebuf( stdout );
 
@@ -218,7 +249,7 @@ pinger()
 {
        static u_char outpack[MAXPACKET];
        register struct icmp *icp = (struct icmp *) outpack;
 {
        static u_char outpack[MAXPACKET];
        register struct icmp *icp = (struct icmp *) outpack;
-       int i, cc;
+       int i, cc, n;
        register struct timeval *tp = (struct timeval *) &outpack[8];
        register u_char *datap = &outpack[8+sizeof(struct timeval)];
 
        register struct timeval *tp = (struct timeval *) &outpack[8];
        register u_char *datap = &outpack[8+sizeof(struct timeval)];
 
@@ -240,13 +271,15 @@ pinger()
        icp->icmp_cksum = in_cksum( icp, cc );
 
        /* cc = sendto(s, msg, len, flags, to, tolen) */
        icp->icmp_cksum = in_cksum( icp, cc );
 
        /* cc = sendto(s, msg, len, flags, to, tolen) */
-       i = sendto( s, outpack, cc, 0, &whereto, sizeof(struct sockaddr) );
-
-       if( i < 0 || i != cc )  {
-               if( i<0 )  perror("sendto");
-               printf("ping: wrote %s %d chars, ret=%d\n",
-                       hostname, cc, i );
-               fflush(stdout);
+       for (n = 0; n < burst; n++) {
+               i = sendto(s, outpack, cc, 0, &whereto, sizeof(whereto));
+
+               if( i < 0 || i != cc )  {
+                       if( i<0 )  perror("sendto");
+                       printf("ping: wrote %s %d chars, ret=%d\n",
+                               hostname, cc, i );
+                       fflush(stdout);
+               }
        }
 }
 
        }
 }
 
@@ -293,21 +326,32 @@ register int t;
  * which arrive ('tis only fair).  This permits multiple copies of this
  * program to be run without having intermingled output (or statistics!).
  */
  * which arrive ('tis only fair).  This permits multiple copies of this
  * program to be run without having intermingled output (or statistics!).
  */
-pr_pack( icp, cc, from )
-register struct icmp *icp;
+pr_pack( buf, cc, from )
+char *buf;
 int cc;
 struct sockaddr_in *from;
 {
 int cc;
 struct sockaddr_in *from;
 {
+       struct ip *ip;
+       register struct icmp *icp;
        register long *lp = (long *) packet;
        register int i;
        struct timeval tv;
        register long *lp = (long *) packet;
        register int i;
        struct timeval tv;
-       struct timeval *tp = (struct timeval *) &packet[8];
-       int triptime;
-       char *inet_ntoa();
+       struct timeval *tp;
+       int hlen, triptime;
 
        from->sin_addr.s_addr = ntohl( from->sin_addr.s_addr );
        gettimeofday( &tv, &tz );
 
 
        from->sin_addr.s_addr = ntohl( from->sin_addr.s_addr );
        gettimeofday( &tv, &tz );
 
+       ip = (struct ip *) buf;
+       hlen = ip->ip_hl << 2;
+       if (cc < hlen + ICMP_MINLEN) {
+               if (verbose)
+                       printf("packet too short (%d bytes) from %s\n", cc,
+                               inet_ntoa(ntohl(from->sin_addr.s_addr)));
+               return;
+       }
+       cc -= hlen;
+       icp = (struct icmp *)(buf + hlen);
        if( icp->icmp_type != ICMP_ECHOREPLY )  {
                if (verbose) {
                        printf("%d bytes from %s: ", cc,
        if( icp->icmp_type != ICMP_ECHOREPLY )  {
                if (verbose) {
                        printf("%d bytes from %s: ", cc,
@@ -323,6 +367,7 @@ struct sockaddr_in *from;
        if( icp->icmp_id != ident )
                return;                 /* 'Twas not our ECHO */
 
        if( icp->icmp_id != ident )
                return;                 /* 'Twas not our ECHO */
 
+       tp = (struct timeval *)&icp->icmp_data[0];
        printf("%d bytes from %s: ", cc,
                inet_ntoa(ntohl(from->sin_addr.s_addr)));
        printf("icmp_seq=%d. ", icp->icmp_seq );
        printf("%d bytes from %s: ", cc,
                inet_ntoa(ntohl(from->sin_addr.s_addr)));
        printf("icmp_seq=%d. ", icp->icmp_seq );
@@ -355,6 +400,7 @@ int len;
        register u_short *w = addr;
        register u_short answer;
        register int sum = 0;
        register u_short *w = addr;
        register u_short answer;
        register int sum = 0;
+       u_short odd_byte = 0;
 
        /*
         *  Our algorithm is simple, using a 32 bit accumulator (sum),
 
        /*
         *  Our algorithm is simple, using a 32 bit accumulator (sum),
@@ -368,14 +414,17 @@ int len;
        }
 
        /* mop up an odd byte, if necessary */
        }
 
        /* mop up an odd byte, if necessary */
-       if( nleft == 1 )
-               sum += *(u_char *)w;
+       if( nleft == 1 ) {
+               *(u_char *)(&odd_byte) = *(u_char *)w;
+               sum += odd_byte;
+       }
 
        /*
         * add back carry outs from top 16 bits to low 16 bits
         */
 
        /*
         * add back carry outs from top 16 bits to low 16 bits
         */
-       sum += (sum >> 16);     /* add hi 16 to low 16 */
-       answer = ~sum;          /* truncate to 16 bits */
+       sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
+       sum += (sum >> 16);                     /* add carry */
+       answer = ~sum;                          /* truncate to 16 bits */
        return (answer);
 }
 
        return (answer);
 }
 
@@ -410,9 +459,14 @@ finish()
        printf("\n----%s PING Statistics----\n", hostname );
        printf("%d packets transmitted, ", ntransmitted );
        printf("%d packets received, ", nreceived );
        printf("\n----%s PING Statistics----\n", hostname );
        printf("%d packets transmitted, ", ntransmitted );
        printf("%d packets received, ", nreceived );
-       if (ntransmitted)
-           printf("%d%% packet loss",
-               (int) (((ntransmitted-nreceived)*100) / ntransmitted ) );
+       if (ntransmitted) {
+               if (nreceived <= ntransmitted)
+                   printf("%d%% packet loss",
+                       (int) (((ntransmitted-nreceived)*100) / ntransmitted));
+               else
+                   printf("%.2f responses per request",
+                       (float) nreceived / (float) ntransmitted);
+       }
        printf("\n");
        if (nreceived && timing)
            printf("round-trip (ms)  min/avg/max = %d/%d/%d\n",
        printf("\n");
        if (nreceived && timing)
            printf("round-trip (ms)  min/avg/max = %d/%d/%d\n",