svn commit: r285820 - stable/10/sbin/ping6

Hiroki Sato hrs at FreeBSD.org
Thu Jul 23 19:52:05 UTC 2015


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);
 }


More information about the svn-src-all mailing list