Author: hrs
Date: Thu Jul 23 19:52:03 2015
New Revision: 285820
URL: https://svnweb.freebsd.org/changeset/base/285820

Log:
  MFC r271910, r273211:
  
  * Add -x waittime and -X timeout options for feature parity.  These are
    equivalent to -W and -t options of ping(8).  Different letters are used
    because both have already been used for another purposes in ping6(8).
  
  * Fix a problem that reply packets are not received when -i T option is set
    and (T < RTT).
  
   - Use select(2) for timeout instead of interval timer. Remove poll(2) 
support.
   - Use sigaction(2) instead of signal(3).
   - Exit in SIGINT handler when two signals are received and doing reverse DNS
     lookup as ping(8) does.
   - Remove redundant variables used for getaddrinfo(3).
  
  Approved by:  re (gjb)

Modified:
  stable/10/sbin/ping6/Makefile
  stable/10/sbin/ping6/ping6.8
  stable/10/sbin/ping6/ping6.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sbin/ping6/Makefile
==============================================================================
--- stable/10/sbin/ping6/Makefile       Thu Jul 23 19:13:41 2015        
(r285819)
+++ stable/10/sbin/ping6/Makefile       Thu Jul 23 19:52:03 2015        
(r285820)
@@ -4,7 +4,7 @@ PROG=   ping6
 MAN=   ping6.8
 
 CFLAGS+=-DIPSEC -DKAME_SCOPEID -DUSE_RFC2292BIS \
-       -DHAVE_POLL_H -DHAVE_ARC4RANDOM
+       -DHAVE_ARC4RANDOM
 WARNS?=        2
 
 BINOWN=        root

Modified: stable/10/sbin/ping6/ping6.8
==============================================================================
--- stable/10/sbin/ping6/ping6.8        Thu Jul 23 19:13:41 2015        
(r285819)
+++ stable/10/sbin/ping6/ping6.8        Thu Jul 23 19:52:03 2015        
(r285820)
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 5, 2013
+.Dd September 22, 2014
 .Dt PING6 8
 .Os
 .Sh NAME
@@ -65,6 +65,12 @@ packets to network hosts
 .Op Fl i Ar wait
 .Ek
 .Bk -words
+.Op Fl x Ar waittime
+.Ek
+.Bk -words
+.Op Fl X Ar timeout
+.Ek
+.Bk -words
 .Op Fl l Ar preload
 .Ek
 .Bk -words
@@ -191,6 +197,15 @@ The default is to wait for one second be
 This option is incompatible with the
 .Fl f
 option.
+.It Fl x Ar waittime
+Time in milliseconds to wait for a reply for each packet sent.
+If a reply arrives later,
+the packet is not printed as replied,
+but considered as replied when calculating statistics.
+.It Fl X Ar timeout
+Specify a timeout,
+in seconds,
+before ping exits regardless of how many packets have been received.
 .It Fl l Ar preload
 If
 .Ar preload

Modified: stable/10/sbin/ping6/ping6.c
==============================================================================
--- stable/10/sbin/ping6/ping6.c        Thu Jul 23 19:13:41 2015        
(r285819)
+++ stable/10/sbin/ping6/ping6.c        Thu Jul 23 19:52:03 2015        
(r285820)
@@ -125,10 +125,8 @@ __FBSDID("$FreeBSD$");
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sysexits.h>
 #include <unistd.h>
-#ifdef HAVE_POLL_H
-#include <poll.h>
-#endif
 
 #ifdef IPSEC
 #include <netipsec/ah.h>
@@ -154,6 +152,8 @@ struct tv32 {
 #define        DEFDATALEN      ICMP6ECHOTMLEN
 #define MAXDATALEN     MAXPACKETLEN - IP6LEN - ICMP6ECHOLEN
 #define        NROUTES         9               /* number of record route slots 
*/
+#define        MAXWAIT         10000           /* max ms to wait for response 
*/
+#define        MAXALARM        (60 * 60)       /* max seconds for alarm 
timeout */
 
 #define        A(bit)          rcvd_tbl[(bit)>>3]      /* identify byte in 
array */
 #define        B(bit)          (1 << ((bit) & 0x07))   /* identify bit in byte 
*/
@@ -190,6 +190,7 @@ struct tv32 {
 #define F_MISSED       0x800000
 #define F_DONTFRAG     0x1000000
 #define F_NOUSERDATA   (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES)
+#define        F_WAITTIME      0x2000000
 u_int options;
 
 #define IN6LEN         sizeof(struct in6_addr)
@@ -207,7 +208,6 @@ u_int options;
 int mx_dup_ck = MAX_DUP_CHK;
 char rcvd_tbl[MAX_DUP_CHK / 8];
 
-struct addrinfo *res = NULL;
 struct sockaddr_in6 dst;       /* who to ping6 */
 struct sockaddr_in6 src;       /* src addr of this packet */
 socklen_t srclen;
@@ -223,12 +223,6 @@ u_int8_t nonce[8];         /* nonce field for n
 int hoplimit = -1;             /* hoplimit */
 int pathmtu = 0;               /* path MTU for the destination.  0 = unspec. */
 u_char *packet = NULL;
-#ifdef HAVE_POLL_H
-struct pollfd fdmaskp[1];
-#else
-fd_set *fdmaskp = NULL;
-int fdmasks;
-#endif
 
 /* counters */
 long nmissedmax;               /* max value of ntransmitted - nreceived - 1 */
@@ -236,7 +230,9 @@ long npackets;                      /* max packets to trans
 long nreceived;                        /* # of packets we got back */
 long nrepeats;                 /* number of duplicates */
 long ntransmitted;             /* sequence # for outbound packets = #sent */
-struct timeval interval = {1, 0}; /* interval between packets */
+int interval = 1000;           /* interval between packets in ms */
+int waittime = MAXWAIT;                /* timeout for each packet */
+long nrcvtimeout = 0;          /* # of packets we got back after waittime */
 
 /* timing */
 int timing;                    /* flag to do timing */
@@ -253,7 +249,6 @@ struct msghdr smsghdr;
 struct iovec smsgiov;
 char *scmsg = 0;
 
-volatile sig_atomic_t seenalrm;
 volatile sig_atomic_t seenint;
 #ifdef SIGINFO
 volatile sig_atomic_t seeninfo;
@@ -265,7 +260,6 @@ int  get_hoplim(struct msghdr *);
 int     get_pathmtu(struct msghdr *);
 struct in6_pktinfo *get_rcvpktinfo(struct msghdr *);
 void    onsignal(int);
-void    retransmit(void);
 void    onint(int);
 size_t  pingerlen(void);
 int     pinger(void);
@@ -293,19 +287,15 @@ void       usage(void);
 int
 main(int argc, char *argv[])
 {
-       struct itimerval itimer;
-       struct sockaddr_in6 from;
+       struct timeval last, intvl;
+       struct sockaddr_in6 from, *sin6;
 #ifndef HAVE_ARC4RANDOM
        struct timeval seed;
 #endif
-#ifdef HAVE_POLL_H
-       int timeout;
-#else
-       struct timeval timeout, *tv;
-#endif
-       struct addrinfo hints;
+       struct addrinfo hints, *res;
+       struct sigaction si_sa;
        int cc, i;
-       int ch, hold, packlen, preload, optval, ret_ga;
+       int almost_done, ch, hold, packlen, preload, optval, error;
        int nig_oldmcprefix = -1;
        u_char *datap;
        char *e, *target, *ifname = NULL, *gateway = NULL;
@@ -326,7 +316,8 @@ main(int argc, char *argv[])
        char *policy_in = NULL;
        char *policy_out = NULL;
 #endif
-       double intval;
+       double t;
+       u_long alarmtimeout;
        size_t rthlen;
 #ifdef IPV6_USE_MIN_MTU
        int mflag = 0;
@@ -336,7 +327,7 @@ main(int argc, char *argv[])
        memset(&smsghdr, 0, sizeof(smsghdr));
        memset(&smsgiov, 0, sizeof(smsgiov));
 
-       preload = 0;
+       alarmtimeout = preload = 0;
        datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN];
 #ifndef IPSEC
 #define ADDOPTS
@@ -348,7 +339,7 @@ main(int argc, char *argv[])
 #endif /*IPSEC_POLICY_IPSEC*/
 #endif
        while ((ch = getopt(argc, argv,
-           "a:b:c:DdfHg:h:I:i:l:mnNop:qrRS:s:tvwW" ADDOPTS)) != -1) {
+           "a:b:c:DdfHg:h:I:i:l:mnNop:qrRS:s:tvwWx:X:" ADDOPTS)) != -1) {
 #undef ADDOPTS
                switch (ch) {
                case 'a':
@@ -450,22 +441,22 @@ main(int argc, char *argv[])
 #endif
                        break;
                case 'i':               /* wait between sending packets */
-                       intval = strtod(optarg, &e);
+                       t = strtod(optarg, &e);
                        if (*optarg == '\0' || *e != '\0')
                                errx(1, "illegal timing interval %s", optarg);
-                       if (intval < 1 && getuid()) {
+                       if (t < 1 && getuid()) {
                                errx(1, "%s: only root may use interval < 1s",
                                    strerror(EPERM));
                        }
-                       interval.tv_sec = (long)intval;
-                       interval.tv_usec =
-                           (long)((intval - interval.tv_sec) * 1000000);
-                       if (interval.tv_sec < 0)
+                       intvl.tv_sec = (long)t;
+                       intvl.tv_usec =
+                           (long)((t - intvl.tv_sec) * 1000000);
+                       if (intvl.tv_sec < 0)
                                errx(1, "illegal timing interval %s", optarg);
                        /* less than 1/hz does not make sense */
-                       if (interval.tv_sec == 0 && interval.tv_usec < 1) {
+                       if (intvl.tv_sec == 0 && intvl.tv_usec < 1) {
                                warnx("too small interval, raised to .000001");
-                               interval.tv_usec = 1;
+                               intvl.tv_usec = 1;
                        }
                        options |= F_INTERVAL;
                        break;
@@ -516,10 +507,10 @@ main(int argc, char *argv[])
                        hints.ai_socktype = SOCK_RAW;
                        hints.ai_protocol = IPPROTO_ICMPV6;
 
-                       ret_ga = getaddrinfo(optarg, NULL, &hints, &res);
-                       if (ret_ga) {
+                       error = getaddrinfo(optarg, NULL, &hints, &res);
+                       if (error) {
                                errx(1, "invalid source address: %s",
-                                    gai_strerror(ret_ga));
+                                    gai_strerror(error));
                        }
                        /*
                         * res->ai_family must be AF_INET6 and res->ai_addrlen
@@ -556,6 +547,24 @@ main(int argc, char *argv[])
                        options &= ~F_NOUSERDATA;
                        options |= F_FQDNOLD;
                        break;
+               case 'x':
+                       t = strtod(optarg, &e);
+                       if (*e || e == optarg || t > (double)INT_MAX)
+                               err(EX_USAGE, "invalid timing interval: `%s'",
+                                   optarg);
+                       options |= F_WAITTIME;
+                       waittime = (int)t;
+                       break;
+               case 'X':
+                       alarmtimeout = strtoul(optarg, &e, 0);
+                       if ((alarmtimeout < 1) || (alarmtimeout == ULONG_MAX))
+                               errx(EX_USAGE, "invalid timeout: `%s'",
+                                   optarg);
+                       if (alarmtimeout > MAXALARM)
+                               errx(EX_USAGE, "invalid timeout: `%s' > %d",
+                                   optarg, MAXALARM);
+                       alarm((int)alarmtimeout);
+                       break;
 #ifdef IPSEC
 #ifdef IPSEC_POLICY_IPSEC
                case 'P':
@@ -622,9 +631,9 @@ main(int argc, char *argv[])
        hints.ai_socktype = SOCK_RAW;
        hints.ai_protocol = IPPROTO_ICMPV6;
 
-       ret_ga = getaddrinfo(target, NULL, &hints, &res);
-       if (ret_ga)
-               errx(1, "%s", gai_strerror(ret_ga));
+       error = getaddrinfo(target, NULL, &hints, &res);
+       if (error)
+               errx(1, "%s", gai_strerror(error));
        if (res->ai_canonname)
                hostname = res->ai_canonname;
        else
@@ -647,28 +656,25 @@ main(int argc, char *argv[])
 
        /* set the gateway (next hop) if specified */
        if (gateway) {
-               struct addrinfo ghints, *gres;
-               int error;
-
-               memset(&ghints, 0, sizeof(ghints));
-               ghints.ai_family = AF_INET6;
-               ghints.ai_socktype = SOCK_RAW;
-               ghints.ai_protocol = IPPROTO_ICMPV6;
+               memset(&hints, 0, sizeof(hints));
+               hints.ai_family = AF_INET6;
+               hints.ai_socktype = SOCK_RAW;
+               hints.ai_protocol = IPPROTO_ICMPV6;
 
-               error = getaddrinfo(gateway, NULL, &hints, &gres);
+               error = getaddrinfo(gateway, NULL, &hints, &res);
                if (error) {
                        errx(1, "getaddrinfo for the gateway %s: %s",
                             gateway, gai_strerror(error));
                }
-               if (gres->ai_next && (options & F_VERBOSE))
+               if (res->ai_next && (options & F_VERBOSE))
                        warnx("gateway resolves to multiple addresses");
 
                if (setsockopt(s, IPPROTO_IPV6, IPV6_NEXTHOP,
-                              gres->ai_addr, gres->ai_addrlen)) {
+                   res->ai_addr, res->ai_addrlen)) {
                        err(1, "setsockopt(IPV6_NEXTHOP)");
                }
 
-               freeaddrinfo(gres);
+               freeaddrinfo(res);
        }
 
        /*
@@ -898,7 +904,7 @@ main(int argc, char *argv[])
        }
 
        if (argc > 1) { /* some intermediate addrs are specified */
-               int hops, error;
+               int hops;
 #ifdef USE_RFC2292BIS
                int rthdrlen;
 #endif
@@ -920,26 +926,25 @@ main(int argc, char *argv[])
 #endif /* USE_RFC2292BIS */
 
                for (hops = 0; hops < argc - 1; hops++) {
-                       struct addrinfo *iaip;
+                       memset(&hints, 0, sizeof(hints));
+                       hints.ai_family = AF_INET6;
 
                        if ((error = getaddrinfo(argv[hops], NULL, &hints,
-                           &iaip)))
+                           &res)))
                                errx(1, "%s", gai_strerror(error));
-                       if (SIN6(iaip->ai_addr)->sin6_family != AF_INET6)
+                       if (res->ai_addr->sa_family != AF_INET6)
                                errx(1,
                                    "bad addr family of an intermediate addr");
-
+                       sin6 = (struct sockaddr_in6 *)(void *)res->ai_addr;
 #ifdef USE_RFC2292BIS
-                       if (inet6_rth_add(rthdr,
-                           &(SIN6(iaip->ai_addr))->sin6_addr))
+                       if (inet6_rth_add(rthdr, &sin6->sin6_addr))
                                errx(1, "can't add an intermediate node");
 #else  /* old advanced API */
-                       if (inet6_rthdr_add(scmsgp,
-                           &(SIN6(iaip->ai_addr))->sin6_addr,
+                       if (inet6_rthdr_add(scmsg, &sin6->sin6_addr,
                            IPV6_RTHDR_LOOSE))
                                errx(1, "can't add an intermediate node");
 #endif /* USE_RFC2292BIS */
-                       freeaddrinfo(iaip);
+                       freeaddrinfo(res);
                }
 
 #ifndef USE_RFC2292BIS
@@ -1055,52 +1060,50 @@ main(int argc, char *argv[])
        printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src)));
        printf("%s\n", pr_addr((struct sockaddr *)&dst, sizeof(dst)));
 
-       while (preload--)               /* Fire off them quickies. */
-               (void)pinger();
-
-       (void)signal(SIGINT, onsignal);
-#ifdef SIGINFO
-       (void)signal(SIGINFO, onsignal);
-#endif
-
-       if ((options & F_FLOOD) == 0) {
-               (void)signal(SIGALRM, onsignal);
-               itimer.it_interval = interval;
-               itimer.it_value = interval;
-               (void)setitimer(ITIMER_REAL, &itimer, NULL);
-               if (ntransmitted == 0)
-                       retransmit();
-       }
-
-#ifndef HAVE_POLL_H
-       fdmasks = howmany(s + 1, NFDBITS) * sizeof(fd_mask);
-       if ((fdmaskp = malloc(fdmasks)) == NULL)
-               err(1, "malloc");
-#endif
-
-       seenalrm = seenint = 0;
+       if (preload == 0)
+               pinger();
+       else {
+               if (npackets != 0 && preload > npackets)
+                       preload = npackets;
+               while (preload--)
+                       pinger();
+       }
+       gettimeofday(&last, NULL);
+
+       sigemptyset(&si_sa.sa_mask);
+       si_sa.sa_flags = 0;
+       si_sa.sa_handler = onsignal;
+       if (sigaction(SIGINT, &si_sa, 0) == -1)
+               err(EX_OSERR, "sigaction SIGINT");
+       seenint = 0;
 #ifdef SIGINFO
+       if (sigaction(SIGINFO, &si_sa, 0) == -1)
+               err(EX_OSERR, "sigaction SIGINFO");
        seeninfo = 0;
 #endif
+       if (alarmtimeout > 0) {
+               if (sigaction(SIGALRM, &si_sa, 0) == -1)
+                       err(EX_OSERR, "sigaction SIGALRM");
+       }
+       if (options & F_FLOOD) {
+               intvl.tv_sec = 0;
+               intvl.tv_usec = 10000;
+       } else if ((options & F_INTERVAL) == 0) {
+               intvl.tv_sec = interval / 1000;
+               intvl.tv_usec = interval % 1000 * 1000;
+       }
 
-       for (;;) {
+       almost_done = 0;
+       while (seenint == 0) {
+               struct timeval now, timeout;
                struct msghdr m;
                struct iovec iov[2];
+               fd_set rfds;
+               int n;
 
                /* signal handling */
-               if (seenalrm) {
-                       /* last packet sent, timeout reached? */
-                       if (npackets && ntransmitted >= npackets)
-                               break;
-                       retransmit();
-                       seenalrm = 0;
-                       continue;
-               }
-               if (seenint) {
+               if (seenint)
                        onint(SIGINT);
-                       seenint = 0;
-                       continue;
-               }
 #ifdef SIGINFO
                if (seeninfo) {
                        summary();
@@ -1108,93 +1111,106 @@ main(int argc, char *argv[])
                        continue;
                }
 #endif
+               FD_ZERO(&rfds);
+               FD_SET(s, &rfds);
+               gettimeofday(&now, NULL);
+               timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
+               timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
+               while (timeout.tv_usec < 0) {
+                       timeout.tv_usec += 1000000;
+                       timeout.tv_sec--;
+               }
+               while (timeout.tv_usec > 1000000) {
+                       timeout.tv_usec -= 1000000;
+                       timeout.tv_sec++;
+               }
+               if (timeout.tv_sec < 0)
+                       timeout.tv_sec = timeout.tv_usec = 0;
+
+               n = select(s + 1, &rfds, NULL, NULL, &timeout);
+               if (n < 0)
+                       continue;       /* EINTR */
+               if (n == 1) {
+                       m.msg_name = (caddr_t)&from;
+                       m.msg_namelen = sizeof(from);
+                       memset(&iov, 0, sizeof(iov));
+                       iov[0].iov_base = (caddr_t)packet;
+                       iov[0].iov_len = packlen;
+                       m.msg_iov = iov;
+                       m.msg_iovlen = 1;
+                       memset(cm, 0, CONTROLLEN);
+                       m.msg_control = (void *)cm;
+                       m.msg_controllen = CONTROLLEN;
+
+                       cc = recvmsg(s, &m, 0);
+                       if (cc < 0) {
+                               if (errno != EINTR) {
+                                       warn("recvmsg");
+                                       sleep(1);
+                               }
+                               continue;
+                       } else if (cc == 0) {
+                               int mtu;
 
-               if (options & F_FLOOD) {
-                       (void)pinger();
-#ifdef HAVE_POLL_H
-                       timeout = 10;
-#else
-                       timeout.tv_sec = 0;
-                       timeout.tv_usec = 10000;
-                       tv = &timeout;
-#endif
-               } else {
-#ifdef HAVE_POLL_H
-                       timeout = INFTIM;
-#else
-                       tv = NULL;
-#endif
-               }
-#ifdef HAVE_POLL_H
-               fdmaskp[0].fd = s;
-               fdmaskp[0].events = POLLIN;
-               cc = poll(fdmaskp, 1, timeout);
-#else
-               memset(fdmaskp, 0, fdmasks);
-               FD_SET(s, fdmaskp);
-               cc = select(s + 1, fdmaskp, NULL, NULL, tv);
-#endif
-               if (cc < 0) {
-                       if (errno != EINTR) {
-#ifdef HAVE_POLL_H
-                               warn("poll");
-#else
-                               warn("select");
-#endif
-                               sleep(1);
-                       }
-                       continue;
-               } else if (cc == 0)
-                       continue;
-
-               m.msg_name = (caddr_t)&from;
-               m.msg_namelen = sizeof(from);
-               memset(&iov, 0, sizeof(iov));
-               iov[0].iov_base = (caddr_t)packet;
-               iov[0].iov_len = packlen;
-               m.msg_iov = iov;
-               m.msg_iovlen = 1;
-               memset(cm, 0, CONTROLLEN);
-               m.msg_control = (void *)cm;
-               m.msg_controllen = CONTROLLEN;
-
-               cc = recvmsg(s, &m, 0);
-               if (cc < 0) {
-                       if (errno != EINTR) {
-                               warn("recvmsg");
-                               sleep(1);
+                               /*
+                                * receive control messages only. Process the
+                                * exceptions (currently the only possibility is
+                                * a path MTU notification.)
+                                */
+                               if ((mtu = get_pathmtu(&m)) > 0) {
+                                       if ((options & F_VERBOSE) != 0) {
+                                               printf("new path MTU (%d) is "
+                                                   "notified\n", mtu);
+                                       }
+                               }
+                               continue;
+                       } else {
+                               /*
+                                * an ICMPv6 message (probably an echoreply)
+                                * arrived.
+                                */
+                               pr_pack(packet, cc, &m);
                        }
-                       continue;
-               } else if (cc == 0) {
-                       int mtu;
-
+                       if (((options & F_ONCE) != 0 && nreceived > 0) ||
+                           (npackets > 0 && nreceived >= npackets))
+                               break;
+               }
+               if (n == 0 || (options & F_FLOOD)) {
+                       if (npackets == 0 || ntransmitted < npackets)
+                               pinger();
+                       else {
+                               if (almost_done)
+                                       break;
+                               almost_done = 1;
                        /*
-                        * receive control messages only. Process the
-                        * exceptions (currently the only possibility is
-                        * a path MTU notification.)
+                        * If we're not transmitting any more packets,
+                        * change the timer to wait two round-trip times
+                        * if we've received any packets or (waittime)
+                        * milliseconds if we haven't.
                         */
-                       if ((mtu = get_pathmtu(&m)) > 0) {
-                               if ((options & F_VERBOSE) != 0) {
-                                       printf("new path MTU (%d) is "
-                                           "notified\n", mtu);
+                               intvl.tv_usec = 0;
+                               if (nreceived) {
+                                       intvl.tv_sec = 2 * tmax / 1000;
+                                       if (intvl.tv_sec == 0)
+                                               intvl.tv_sec = 1;
+                               } else {
+                                       intvl.tv_sec = waittime / 1000;
+                                       intvl.tv_usec = waittime % 1000 * 1000;
                                }
                        }
-                       continue;
-               } else {
-                       /*
-                        * an ICMPv6 message (probably an echoreply) arrived.
-                        */
-                       pr_pack(packet, cc, &m);
-               }
-               if (((options & F_ONCE) != 0 && nreceived > 0) ||
-                   (npackets > 0 && nreceived >= npackets))
-                       break;
-               if (ntransmitted - nreceived - 1 > nmissedmax) {
-                       nmissedmax = ntransmitted - nreceived - 1;
-                       if (options & F_MISSED)
-                               (void)write(STDOUT_FILENO, &BBELL, 1);
+                       gettimeofday(&last, NULL);
+                       if (ntransmitted - nreceived - 1 > nmissedmax) {
+                               nmissedmax = ntransmitted - nreceived - 1;
+                               if (options & F_MISSED)
+                                       (void)write(STDOUT_FILENO, &BBELL, 1);
+                       }
                }
        }
+       sigemptyset(&si_sa.sa_mask);
+       si_sa.sa_flags = 0;
+       si_sa.sa_handler = SIG_IGN;
+       sigaction(SIGINT, &si_sa, 0);
+       sigaction(SIGALRM, &si_sa, 0);
        summary();
 
        if (res != NULL)
@@ -1203,11 +1219,6 @@ main(int argc, char *argv[])
         if(packet != NULL)
                 free(packet);
 
-#ifndef HAVE_POLL_H
-        if(fdmaskp != NULL)
-                free(fdmaskp);
-#endif
-
        exit(nreceived == 0 ? 2 : 0);
 }
 
@@ -1216,10 +1227,8 @@ onsignal(int sig)
 {
 
        switch (sig) {
-       case SIGALRM:
-               seenalrm++;
-               break;
        case SIGINT:
+       case SIGALRM:
                seenint++;
                break;
 #ifdef SIGINFO
@@ -1231,38 +1240,6 @@ onsignal(int sig)
 }
 
 /*
- * retransmit --
- *     This routine transmits another ping6.
- */
-void
-retransmit(void)
-{
-       struct itimerval itimer;
-
-       if (pinger() == 0)
-               return;
-
-       /*
-        * If we're not transmitting any more packets, change the timer
-        * to wait two round-trip times if we've received any packets or
-        * ten seconds if we haven't.
-        */
-#define        MAXWAIT         10
-       if (nreceived) {
-               itimer.it_value.tv_sec =  2 * tmax / 1000;
-               if (itimer.it_value.tv_sec == 0)
-                       itimer.it_value.tv_sec = 1;
-       } else
-               itimer.it_value.tv_sec = MAXWAIT;
-       itimer.it_interval.tv_sec = 0;
-       itimer.it_interval.tv_usec = 0;
-       itimer.it_value.tv_usec = 0;
-
-       (void)signal(SIGALRM, onsignal);
-       (void)setitimer(ITIMER_REAL, &itimer, NULL);
-}
-
-/*
  * pinger --
  *     Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
  * will be added on by the kernel.  The ID field is our UNIX process ID,
@@ -1575,6 +1552,11 @@ pr_pack(u_char *buf, int cc, struct msgh
                if (options & F_QUIET)
                        return;
 
+               if (options & F_WAITTIME && triptime > waittime) {
+                       ++nrcvtimeout;
+                       return;
+               }
+
                if (options & F_FLOOD)
                        (void)write(STDOUT_FILENO, &BSPACE, 1);
                else {
@@ -2241,24 +2223,12 @@ tvsub(struct timeval *out, struct timeva
 void
 onint(int notused __unused)
 {
-       summary();
-
-       if (res != NULL)
-               freeaddrinfo(res);
-
-        if(packet != NULL)
-                free(packet);
-
-#ifndef HAVE_POLL_H
-        if(fdmaskp != NULL)
-                free(fdmaskp);
-#endif
-
-       (void)signal(SIGINT, SIG_DFL);
-       (void)kill(getpid(), SIGINT);
-
-       /* NOTREACHED */
-       exit(1);
+       /*
+        * When doing reverse DNS lookups, the seenint flag might not
+        * be noticed for a while.  Just exit if we get a second SIGINT.
+        */
+       if ((options & F_HOSTNAME) && seenint != 0)
+               _exit(nreceived ? 0 : 2);
 }
 
 /*
@@ -2282,6 +2252,8 @@ summary(void)
                            ((((double)ntransmitted - nreceived) * 100.0) /
                            ntransmitted));
        }
+       if (nrcvtimeout)
+               printf(", %ld packets out of wait time", nrcvtimeout);
        (void)putchar('\n');
        if (nreceived && timing) {
                /* Only display average to microseconds */
@@ -2807,6 +2779,7 @@ usage(void)
 #endif
            "\n"
            "             [-p pattern] [-S sourceaddr] [-s packetsize] "
-           "[hops ...] host\n");
+           "[-x waittime]\n"
+           "             [-X timeout] [hops ...] host\n");
        exit(1);
 }
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to