summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/ping/Makefile11
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/ping/ping.c224
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/ping/ping.h6
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/ping/ping_aux.c27
-rw-r--r--usr/src/cmd/cmd-inet/usr.sbin/ping/ping_aux6.c48
-rw-r--r--usr/src/man/man1m/ping.1m53
6 files changed, 309 insertions, 60 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ping/Makefile b/usr/src/cmd/cmd-inet/usr.sbin/ping/Makefile
index 88f36be473..9724fff4e5 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ping/Makefile
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ping/Makefile
@@ -38,17 +38,18 @@ $(ROOTUSRSBIN)/ping := FILEMODE= 04555
# when IPv6 inspired new interfaces are part of standards.
LDLIBS += -lxnet -lsocket -lnsl -lm -linetutil
-# These #defines are required to use UNIX 98 interfaces
-CPPFLAGS += -D_XOPEN_SOURCE=500 -D__EXTENSIONS__
+# These #defines are required to use SUSv3 interfaces
+CPPFLAGS += -D_XOPEN_SOURCE=600 -D__EXTENSIONS__
+
+C99MODE= -xc99=%all
# Setting the above defines to use the UNIX98 ancillary data feature
# causes lint to output warnings about lint library declarations conflicting
# with those in the header files. Since we need these features the best
# course of action is to switch the types of the resulting warnings off
# when running lint.
-LINTFLAGS += -erroff=E_INCONS_VAL_TYPE_DECL2 -erroff=E_INCONS_ARG_DECL2
-
-CERRWARN += -_gcc=-Wno-uninitialized
+LINTFLAGS += -erroff=E_INCONS_VAL_TYPE_DECL2 -erroff=E_INCONS_ARG_DECL2 \
+ -erroff=E_NAME_USED_NOT_DEF2
.KEEP_STATE:
.PARALLEL:
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.c b/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.c
index 2146efd67b..2d79419245 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.c
@@ -37,6 +37,11 @@
* contributors.
*/
+/*
+ * Copyright 2015, Joyent, Inc.
+ */
+
+#include <assert.h>
#include <stdio.h>
#include <strings.h>
#include <errno.h>
@@ -45,6 +50,9 @@
#include <signal.h>
#include <limits.h>
#include <math.h>
+#include <locale.h>
+#include <thread.h>
+#include <synch.h>
#include <sys/time.h>
#include <sys/param.h>
@@ -53,6 +61,7 @@
#include <sys/stropts.h>
#include <sys/file.h>
#include <sys/sysmacros.h>
+#include <sys/debug.h>
#include <arpa/inet.h>
#include <net/if.h>
@@ -153,7 +162,6 @@ static int eff_num_gw; /* effective number of gateways */
static int num_wraps = -1; /* no of times 64K icmp_seq wrapped */
static ushort_t dest_port = 32768 + 666; /* starting port for the UDP probes */
static char *gw_list[MAXMAX_GWS]; /* list of gateways as user enters */
-static int interval = 1; /* interval between transmissions */
static int options; /* socket options */
static int moptions; /* multicast options */
int npackets; /* number of packets to send */
@@ -164,6 +172,22 @@ static int timeout = TIMEOUT; /* timeout value (sec) for probes */
static struct if_entry out_if; /* interface argument */
int ident; /* ID for this ping run */
static hrtime_t t_last_probe_sent; /* the time we sent the last probe */
+static timer_t timer; /* timer for waiting */
+static volatile boolean_t timer_done = _B_FALSE; /* timer finished? */
+static struct itimerspec interval = { { 0, 0 }, { 1, 0 } }; /* Interval for */
+ /* -I. The default interval is 1s. */
+static hrtime_t mintime = NSEC2MSEC(500); /* minimum time between pings */
+
+/*
+ * Globals for our name services warning. See ns_warning_thr() for more on why
+ * this exists.
+ */
+static mutex_t ns_lock = ERRORCHECKMUTEX; /* Protects the following data */
+static boolean_t ns_active = _B_FALSE; /* Lookup is going on */
+static hrtime_t ns_starttime; /* Time the lookup started */
+static int ns_sleeptime = 2; /* Time in seconds between checks */
+static int ns_warntime = 2; /* Time in seconds before warning */
+static int ns_warninter = 60; /* Time in seconds between warnings */
/*
* This buffer stores the received packets. Currently it needs to be 32 bit
@@ -203,6 +227,8 @@ static ushort_t in_cksum(ushort_t *, int);
static int int_arg(char *s, char *what);
boolean_t is_a_target(struct addrinfo *, union any_in_addr *);
static void mirror_gws(union any_in_addr *, int);
+static void *ns_warning_thr(void *);
+static void parse_interval(char *s);
static void pinger(int, struct sockaddr *, struct msghdr *, int);
char *pr_name(char *, int);
char *pr_protocol(int);
@@ -249,6 +275,8 @@ main(int argc, char *argv[])
progname = argv[0];
+ (void) setlocale(LC_ALL, "");
+
/*
* This program needs the net_icmpaccess privilege for creating
* raw ICMP sockets. It needs sys_ip_config for using the
@@ -322,7 +350,7 @@ main(int argc, char *argv[])
case 'I':
stats = _B_TRUE;
- interval = int_arg(optarg, "interval");
+ parse_interval(optarg);
break;
case 'i':
@@ -689,6 +717,23 @@ main(int argc, char *argv[])
}
}
+ /* Create our timer for future use */
+ if (timer_create(CLOCK_REALTIME, NULL, &timer) != 0) {
+ Fprintf(stderr, "%s: failed to create timer: %s\n",
+ progname, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Finally start up the name services warning thread.
+ */
+ if (thr_create(NULL, 0, ns_warning_thr, NULL,
+ THR_DETACHED | THR_DAEMON, NULL) != 0) {
+ Fprintf(stderr, "%s: failed to create name services "
+ "thread: %s\n", progname, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
/* Let's get things going */
send_scheduled_probe();
@@ -1142,8 +1187,8 @@ select_src_addr(union any_in_addr *dst_addr, int family,
union any_in_addr *src_addr)
{
struct sockaddr *sock;
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
+ struct sockaddr_in *sin = NULL;
+ struct sockaddr_in6 *sin6 = NULL;
int tmp_fd;
size_t sock_len;
@@ -1202,8 +1247,10 @@ select_src_addr(union any_in_addr *dst_addr, int family,
}
if (family == AF_INET) {
+ assert(sin != NULL);
src_addr->addr = sin->sin_addr;
} else {
+ assert(sin6 != NULL);
src_addr->addr6 = sin6->sin6_addr;
}
@@ -1606,6 +1653,14 @@ setup_socket(int family, int *send_sockp, int *recv_sockp, int *if_index,
}
}
+ /* Ensure that timestamping is requested on the receive socket */
+ if (setsockopt(recv_sock, SOL_SOCKET, SO_TIMESTAMP,
+ &on, sizeof (on)) == -1) {
+ Fprintf(stderr, "%s: warning: timing accuracy diminished -- "
+ "setsockopt SO_TIMESTAMP failed %s", progname,
+ strerror(errno));
+ }
+
*send_sockp = send_sock;
*recv_sockp = recv_sock;
@@ -1683,14 +1738,21 @@ void
sigalrm_handler(void)
{
/*
- * Guard againist denial-of-service attacks. Make sure ping doesn't
- * send probes for every SIGALRM it receives. Evil hacker can generate
- * SIGALRMs as fast as it can, but ping will ignore those which are
- * received too soon (earlier than 0.5 sec) after it sent the last
- * probe. We use gethrtime() instead of gettimeofday() because
- * the latter is not linear and is prone to resetting or drifting
+ * If we've been told that we're done, the timer should be cancelled
+ * and not rescheduled, just return.
+ */
+ if (timer_done == _B_TRUE)
+ return;
+
+ /*
+ * Guard against denial-of-service attacks. Make sure ping doesn't send
+ * probes for every SIGALRM it receives in the case of errant SIGALRMs.
+ * ping will ignore those which are received too soon (the smaller of
+ * 0.5 sec and the ping interval, if in effect) after it sent the last
+ * probe. We use gethrtime() instead of gettimeofday() because the
+ * latter is not linear and is prone to resetting or drifting.
*/
- if ((gethrtime() - t_last_probe_sent) < 500000000) {
+ if ((gethrtime() - t_last_probe_sent) < mintime) {
return;
}
send_scheduled_probe();
@@ -1704,10 +1766,12 @@ void
schedule_sigalrm(void)
{
int waittime;
+ struct itimerspec it;
+ bzero(&it, sizeof (struct itimerspec));
if (npackets == 0 ||
current_targetaddr->num_sent < current_targetaddr->num_probes) {
- (void) alarm(interval);
+ it = interval;
} else {
if (current_targetaddr->got_reply) {
waittime = 2 * tmax / MICROSEC;
@@ -1716,7 +1780,13 @@ schedule_sigalrm(void)
} else {
waittime = MAX_WAIT;
}
- (void) alarm(waittime);
+ it.it_value.tv_sec = waittime;
+ }
+
+ if (timer_settime(timer, TIMER_RELTIME, &it, NULL) != 0) {
+ Fprintf(stderr, "%s: unexpected error updating time: %s\n",
+ progname, strerror(errno));
+ exit(EXIT_FAILURE);
}
}
@@ -1772,7 +1842,7 @@ send_scheduled_probe()
* Did we reach the end of road?
*/
if (current_targetaddr == NULL) {
- (void) alarm(0); /* cancel alarm */
+ timer_done = _B_TRUE;
if (stats)
finish();
if (is_alive)
@@ -1933,7 +2003,7 @@ ushort_t udp_src_port6, ushort_t udp_src_port)
*/
if ((npackets > 0) && (current_targetaddr->next == NULL) &&
(nreceived_last_target == npackets)) {
- (void) alarm(0); /* cancel alarm */
+ timer_done = _B_TRUE;
finish();
}
} /* infinite loop */
@@ -2144,6 +2214,10 @@ pr_name(char *addr, int family)
/* compare with the buffered (previous) lookup */
if (memcmp(addr, &prev_addr, alen) != 0) {
int flags = (nflag) ? NI_NUMERICHOST : NI_NAMEREQD;
+ mutex_enter(&ns_lock);
+ ns_active = _B_TRUE;
+ ns_starttime = gethrtime();
+ mutex_exit(&ns_lock);
if (getnameinfo(sa, slen, buf, sizeof (buf),
NULL, 0, flags) != 0) {
/* getnameinfo() failed; return just the address */
@@ -2158,6 +2232,9 @@ pr_name(char *addr, int family)
inet_ntop(family, (const void *)addr, abuf,
sizeof (abuf)));
}
+ mutex_enter(&ns_lock);
+ ns_active = _B_FALSE;
+ mutex_exit(&ns_lock);
/* LINTED E_BAD_PTR_CAST_ALIGN */
prev_addr = *(struct in6_addr *)addr;
@@ -2419,10 +2496,123 @@ int_arg(char *s, char *what)
}
if (errno || *ep != '\0' || num < 0) {
- (void) Fprintf(stderr, "%s: bad %s: %s\n",
- progname, what, s);
+ Fprintf(stderr, "%s: bad %s: %s\n", progname, what, s);
exit(EXIT_FAILURE);
}
return (num);
}
+
+/*
+ * Parse the interval into a itimerspec. The interval used to originally be
+ * parsed as an integer argument. That means that one used to be able to specify
+ * an interval in hex. The strtod() family honors that at times, with strtod
+ * sometimes doing so depending on the compilation environment and strtof() and
+ * srtold() always doing that. To facilitiate that and not worry about a
+ * careless Makefile change breaking us, we instead just use strtold here, even
+ * though we really don't need the precision.
+ */
+static void
+parse_interval(char *s)
+{
+ long double val;
+ char *end;
+
+ errno = 0;
+ val = strtold(s, &end);
+ if (errno != 0 || *end != '\0') {
+ Fprintf(stderr, "%s: bad interval: %s\n", progname, s);
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * Check values that we know are going to be bad. Anything greater than
+ * INT_MAX, anything less than 0, look for specific NaNs. Also, clamp
+ * the value at 0.01 seconds.
+ */
+ if (val == NAN || val <= 0.0 || val >= INT_MAX) {
+ Fprintf(stderr, "%s: bad interval: %s\n", progname, s);
+ exit(EXIT_FAILURE);
+ }
+
+ if (val < 0.01) {
+ Fprintf(stderr, "%s: interval too small: %Lf\n", progname, val);
+ exit(EXIT_FAILURE);
+ }
+
+ interval.it_value.tv_sec = (long)val;
+ interval.it_value.tv_nsec = (long)((val - interval.it_value.tv_sec) *
+ NANOSEC);
+
+ if (interval.it_value.tv_sec == 0 &&
+ interval.it_value.tv_nsec < mintime) {
+ mintime = interval.it_value.tv_nsec;
+ }
+}
+
+/*
+ * We should have an SO_TIMESTAMP message for this socket to indicate
+ * the actual time that the message took. If we don't we'll fall back to
+ * gettimeofday(); however, that can cause any delays due to DNS
+ * resolution and the like to end up wreaking havoc on us.
+ */
+void
+ping_gettime(struct msghdr *msg, struct timeval *tv)
+{
+ struct cmsghdr *cmsg;
+
+ for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(msg, cmsg)) {
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SO_TIMESTAMP &&
+ cmsg->cmsg_len == CMSG_LEN(sizeof (*tv))) {
+ bcopy(CMSG_DATA(cmsg), tv, sizeof (*tv));
+ return;
+ }
+ }
+
+ (void) gettimeofday(tv, (struct timezone *)NULL);
+}
+
+/*
+ * The purpose of this thread is to try and inform a user that we're blocked
+ * doing name lookups. For various reasons, ping has to try and look up the IP
+ * addresses it receives via name services unless the -n flag is specified. The
+ * irony of this is that when trying to use ping to actually diagnose a broken
+ * network, name services are unlikely to be available and that will result in a
+ * lot of confusion as to why pings seem like they're not working. As such, we
+ * basically wake up every 2 seconds and check whether or not we've hit such a
+ * condition where we should inform the user via stderr.
+ *
+ * Once they've been informed, we do not inform them again until approximately a
+ * minute of time has passed, in case that things are working intermittently.
+ */
+/*ARGSUSED*/
+static void *
+ns_warning_thr(void *unused)
+{
+ hrtime_t last_warn = 0;
+ for (;;) {
+ hrtime_t now;
+
+ (void) sleep(ns_sleeptime);
+ now = gethrtime();
+ mutex_enter(&ns_lock);
+ if (ns_active == _B_TRUE &&
+ now - ns_starttime >= ns_warntime * NANOSEC) {
+ if (now - last_warn >=
+ ns_warninter * NANOSEC) {
+ last_warn = now;
+ Fprintf(stderr, "%s: warning: ICMP responses "
+ "received, but name service lookups are "
+ "taking a while. Use ping -n to disable "
+ "name service lookups.\n",
+ progname);
+ }
+ }
+ mutex_exit(&ns_lock);
+ }
+
+ /* LINTED: E_STMT_NOT_REACHED */
+ return (NULL);
+}
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.h b/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.h
index 65be7a1116..9dd579841e 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.h
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ping/ping.h
@@ -27,7 +27,9 @@
#ifndef _PING_H
#define _PING_H
-#pragma ident "%Z%%M% %I% %E% SMI"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
#ifdef __cplusplus
extern "C" {
@@ -131,6 +133,8 @@ extern boolean_t use_udp;
extern boolean_t verbose;
extern boolean_t send_reply;
+extern void ping_gettime(struct msghdr *, struct timeval *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ping/ping_aux.c b/usr/src/cmd/cmd-inet/usr.sbin/ping/ping_aux.c
index d76fae0aaf..9db03cc7a0 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ping/ping_aux.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ping/ping_aux.c
@@ -28,12 +28,14 @@
/* All Rights Reserved */
/*
+ * Copyright 2015, Joyent, Inc.
+ */
+
+/*
* Portions of this source code were derived from Berkeley 4.3 BSD
* under license from the Regents of the University of California.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <string.h>
#include <strings.h>
@@ -233,9 +235,10 @@ check_reply(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
int hlen, hlen1;
int64_t triptime;
boolean_t valid_reply = _B_FALSE;
- boolean_t reply_matched_current_target; /* Is the source address of */
- /* this reply same as where */
- /* we're sending currently? */
+ boolean_t reply_matched_current_target = _B_FALSE; /* Is the source */
+ /* address of this reply same */
+ /* as where we're sending */
+ /* currently? */
boolean_t last_reply_from_targetaddr = _B_FALSE; /* Is this stats, */
/* probe all with npackets>0 */
/* and we received reply for */
@@ -282,7 +285,7 @@ check_reply(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
/* LINTED */
intp = (int32_t *)buf;
- (void) gettimeofday(&tv, (struct timezone *)NULL);
+ ping_gettime(msg, &tv);
/* LINTED */
ip = (struct ip *)buf;
@@ -352,8 +355,8 @@ check_reply(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
nreceived++;
reply_matched_current_target =
seq_match(current_targetaddr->starting_seq_num,
- current_targetaddr->num_sent,
- ntohs(up->uh_dport));
+ current_targetaddr->num_sent,
+ ntohs(up->uh_dport));
if (reply_matched_current_target) {
current_targetaddr->got_reply = _B_TRUE;
nreceived_last_target++;
@@ -552,8 +555,8 @@ check_reply(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
nreceived++;
reply_matched_current_target =
seq_match(current_targetaddr->starting_seq_num,
- current_targetaddr->num_sent,
- ntohs(icp->icmp_seq));
+ current_targetaddr->num_sent,
+ ntohs(icp->icmp_seq));
if (reply_matched_current_target) {
current_targetaddr->got_reply = _B_TRUE;
nreceived_last_target++;
@@ -863,8 +866,8 @@ check_reply(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
nreceived++;
reply_matched_current_target =
seq_match(current_targetaddr->starting_seq_num,
- current_targetaddr->num_sent,
- ntohs(icp->icmp_seq));
+ current_targetaddr->num_sent,
+ ntohs(icp->icmp_seq));
if (reply_matched_current_target) {
current_targetaddr->got_reply = _B_TRUE;
nreceived_last_target++;
diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ping/ping_aux6.c b/usr/src/cmd/cmd-inet/usr.sbin/ping/ping_aux6.c
index 374c88fd1e..02008e62aa 100644
--- a/usr/src/cmd/cmd-inet/usr.sbin/ping/ping_aux6.c
+++ b/usr/src/cmd/cmd-inet/usr.sbin/ping/ping_aux6.c
@@ -28,12 +28,14 @@
/* All Rights Reserved */
/*
+ * Copyright 2015, Joyent, Inc.
+ */
+
+/*
* Portions of this source code were derived from Berkeley 4.3 BSD
* under license from the Regents of the University of California.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <string.h>
#include <strings.h>
@@ -236,7 +238,7 @@ set_ancillary_data(struct msghdr *msgp, int hoplimit,
* therefore let's use bcopy, instead of assignment.
*/
(void) bcopy(&in6addr_any, &pktinfop->ipi6_addr,
- sizeof (struct in6_addr));
+ sizeof (struct in6_addr));
/*
* We can assume pktinfop->ipi6_ifindex is 32 bit aligned.
@@ -271,9 +273,10 @@ check_reply6(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
struct timeval *tp;
int64_t triptime;
boolean_t valid_reply = _B_FALSE;
- boolean_t reply_matched_current_target; /* Is the source address of */
- /* this reply same as where */
- /* we're sending currently? */
+ boolean_t reply_matched_current_target = _B_FALSE; /* Is the source */
+ /* address of this reply same */
+ /* as where we're sending */
+ /* currently? */
boolean_t last_reply_from_targetaddr = _B_FALSE; /* Is this stats, */
/* probe all with npackets>0 */
/* and we received reply for */
@@ -309,8 +312,7 @@ check_reply6(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
/* LINTED */
intp = (int32_t *)buf;
- /* get time now for most accurate time calculation */
- (void) gettimeofday(&tv, (struct timezone *)NULL);
+ ping_gettime(msg, &tv);
/* Ignore packets > 64k or control buffers that don't fit */
if (msg->msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
@@ -341,7 +343,7 @@ check_reply6(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
Printf("packet too short (%d bytes) from %s\n",
cc,
pr_name((char *)&from6->sin6_addr,
- AF_INET6));
+ AF_INET6));
}
return;
}
@@ -362,7 +364,7 @@ check_reply6(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
Printf("packet too short (%d bytes) from %s\n",
cc,
pr_name((char *)&from6->sin6_addr,
- AF_INET6));
+ AF_INET6));
}
return;
}
@@ -389,8 +391,8 @@ check_reply6(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
nreceived++;
reply_matched_current_target =
seq_match(current_targetaddr->starting_seq_num,
- current_targetaddr->num_sent,
- ntohs(up->uh_dport));
+ current_targetaddr->num_sent,
+ ntohs(up->uh_dport));
if (reply_matched_current_target) {
current_targetaddr->got_reply = _B_TRUE;
nreceived_last_target++;
@@ -489,12 +491,12 @@ check_reply6(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
Printf("ICMPv6 %d Unreachable from gateway "
"%s\n", icmp6->icmp6_code,
pr_name((char *)&from6->sin6_addr,
- AF_INET6));
+ AF_INET6));
} else {
Printf("ICMPv6 %s from gateway %s\n",
unreach6[icmp6->icmp6_code],
pr_name((char *)&from6->sin6_addr,
- AF_INET6));
+ AF_INET6));
}
Printf(" for %s from %s", pr_protocol(last_hdr),
pr_name((char *)&ip6h->ip6_src, AF_INET6));
@@ -584,7 +586,7 @@ check_reply6(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
Printf("packet too short (%d bytes) from %s\n",
cc,
pr_name((char *)&from6->sin6_addr,
- AF_INET6));
+ AF_INET6));
}
return;
}
@@ -596,12 +598,12 @@ check_reply6(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
Printf("ICMPv6 %d time exceeded from %s\n",
icmp6->icmp6_code,
pr_name((char *)&from6->sin6_addr,
- AF_INET6));
+ AF_INET6));
} else {
Printf("ICMPv6 %s from %s\n",
timexceed6[icmp6->icmp6_code],
pr_name((char *)&from6->sin6_addr,
- AF_INET6));
+ AF_INET6));
}
Printf(" for %s from %s", pr_protocol(last_hdr),
pr_name((char *)&ip6h->ip6_src, AF_INET6));
@@ -627,7 +629,7 @@ check_reply6(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
Printf("packet too short (%d bytes) from %s\n",
cc,
pr_name((char *)&from6->sin6_addr,
- AF_INET6));
+ AF_INET6));
}
return;
}
@@ -639,12 +641,12 @@ check_reply6(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
Printf("ICMPv6 %d parameter problem from %s\n",
icmp6->icmp6_code,
pr_name((char *)&from6->sin6_addr,
- AF_INET6));
+ AF_INET6));
} else {
Printf("ICMPv6 %s from %s\n",
param_prob6[icmp6->icmp6_code],
pr_name((char *)&from6->sin6_addr,
- AF_INET6));
+ AF_INET6));
}
icmp6->icmp6_pptr = ntohl(icmp6->icmp6_pptr);
Printf(" in byte %d", icmp6->icmp6_pptr);
@@ -692,8 +694,8 @@ check_reply6(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
nreceived++;
reply_matched_current_target =
seq_match(current_targetaddr->starting_seq_num,
- current_targetaddr->num_sent,
- ntohs(icmp6->icmp6_seq));
+ current_targetaddr->num_sent,
+ ntohs(icmp6->icmp6_seq));
if (reply_matched_current_target) {
current_targetaddr->got_reply = _B_TRUE;
nreceived_last_target++;
@@ -859,7 +861,7 @@ check_reply6(struct addrinfo *ai_dst, struct msghdr *msg, int cc,
Printf("packet too short (%d bytes) from %s\n",
cc,
pr_name((char *)&from6->sin6_addr,
- AF_INET6));
+ AF_INET6));
}
return;
}
diff --git a/usr/src/man/man1m/ping.1m b/usr/src/man/man1m/ping.1m
index 4097ca8bb8..a5a29be2d6 100644
--- a/usr/src/man/man1m/ping.1m
+++ b/usr/src/man/man1m/ping.1m
@@ -1,10 +1,11 @@
'\" te
.\" Copyright (C) 2006, Sun Microsystems, Inc. All Rights Reserved
.\" Copyright 1989 AT&T
+.\" Copyright 2015, Joyent, Inc.
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH PING 1M "Feb 20, 2015"
+.TH PING 1M "May 21, 2015"
.SH NAME
ping \- send ICMP (ICMP6) ECHO_REQUEST packets to network hosts
.SH SYNOPSIS
@@ -123,7 +124,8 @@ range from 0 to 1048575. This option is valid only on IPv6.
.RS 24n
Turn on the statistics mode and specify the interval between successive
transmissions. The default is one second. See the discussion of the \fB-s\fR
-option.
+option. The minimum interval is 0.01 seconds. It is an error to specify
+a smaller interval.
.RE
.sp
@@ -422,3 +424,50 @@ machine was not alive.
\fBifconfig\fR(1M), \fBin.routed\fR(1M), \fBndd\fR(1M), \fBnetstat\fR(1M),
\fBrpcinfo\fR(1M), \fBtraceroute\fR(1M), \fBattributes\fR(5), \fBicmp\fR(7P),
\fBicmp6\fR(7P)
+
+.SH DIAGNOSTICS
+.ne 2
+.na
+\fB\fBping: warning: ICMP responses received, but name service lookups
+are taking a while. Use ping -n to disable name service lookups.\fB\fB
+.ad
+.sp .6
+.RS 4n
+When the
+.B -n
+flag is not specified,
+.B ping
+tries to lookup the name corresponding to the IP address that it
+received via name services. If name services are unavailable, it may
+take time before the system properly times out the name service lookups.
+As a result, it may appear that no ICMP replies are being received when
+they in fact are. This diagnostic indicates that this has occurred and
+indicates that there are valid responses and that using the
+.B -n
+flag will stop this from occurring.
+.RE
+
+.sp
+.ne 2
+.na
+\fB\fBping: warning: timing accuracy diminished -- setsockopt
+SO_TIMESTAMP failed\fR\fR
+.ad
+.sp .6
+.RS 4n
+By default, the system attempts to use the
+.B SO_TIMESTAMP
+socket option to allow for more accurate time stamps that reflect when
+the ICMP echo replies were received by the system as opposed to when
+they were received by the
+.B ping
+command. These differences may occur because an operator stopped the
+process or because
+.B ping
+was blocked up behind a name service look up. When this diagnostic is
+emitted, the
+.B ping
+command will continue to function, but it will be doing the time
+stamping itself, which may cause the timing intervals reported to be
+longer than they actually are.
+.RE