summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorflorian <florian@openbsd.org>2016-09-17 18:42:10 +0000
committerflorian <florian@openbsd.org>2016-09-17 18:42:10 +0000
commitd2d8382b998ab14503e5cbfec3e708fffc444bb4 (patch)
tree6bad87312f17d89f418520cfb7948ba9d804d7c8
parentunhook ping6 from the build (diff)
downloadwireguard-openbsd-d2d8382b998ab14503e5cbfec3e708fffc444bb4.tar.xz
wireguard-openbsd-d2d8382b998ab14503e5cbfec3e708fffc444bb4.zip
... and we have unification.
"Das tritt nach meiner Kenntnis... ist das sofort... unverzueglich..."
-rw-r--r--sbin/ping6/Makefile5
-rw-r--r--sbin/ping6/ping6.8345
-rw-r--r--sbin/ping6/ping6.c1497
3 files changed, 0 insertions, 1847 deletions
diff --git a/sbin/ping6/Makefile b/sbin/ping6/Makefile
deleted file mode 100644
index b3d111012e5..00000000000
--- a/sbin/ping6/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# $OpenBSD: Makefile,v 1.12 2016/09/17 15:03:39 florian Exp $
-
-MAN= ping6.8
-
-.include <bsd.prog.mk>
diff --git a/sbin/ping6/ping6.8 b/sbin/ping6/ping6.8
deleted file mode 100644
index 03d49649331..00000000000
--- a/sbin/ping6/ping6.8
+++ /dev/null
@@ -1,345 +0,0 @@
-.\" $OpenBSD: ping6.8,v 1.64 2016/09/03 16:22:26 akfaew Exp $
-.\" $KAME: ping6.8,v 1.57 2002/05/26 13:18:25 itojun Exp $
-.\"
-.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. Neither the name of the project nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.Dd $Mdocdate: September 3 2016 $
-.Dt PING6 8
-.Os
-.Sh NAME
-.Nm ping6
-.Nd send ICMPv6 ECHO_REQUEST packets to network hosts
-.Sh SYNOPSIS
-.Nm ping6
-.Op Fl dEefHLmnqv
-.Op Fl c Ar count
-.Op Fl h Ar hoplimit
-.Op Fl I Ar sourceaddr
-.Op Fl i Ar wait
-.Op Fl l Ar preload
-.Op Fl p Ar pattern
-.Op Fl s Ar packetsize
-.Op Fl V Ar rtable
-.Op Fl w Ar maxwait
-.Ar host
-.Sh DESCRIPTION
-.Nm
-uses the
-ICMPv6
-protocol's mandatory
-.Dv ICMP6_ECHO_REQUEST
-datagram to elicit an
-.Dv ICMP6_ECHO_REPLY
-from a host or gateway.
-.Dv ICMP6_ECHO_REQUEST
-datagrams
-.Pq Dq pings
-have an IPv6 header,
-followed by an
-ICMPv6
-header formatted as documented in RFC 4443.
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl c Ar count
-Stop after sending
-.Pq and receiving
-.Ar count
-.Dv ECHO_RESPONSE
-packets.
-If
-.Ar count
-is 0, send an unlimited number of packets.
-.It Fl d
-Set the
-.Dv SO_DEBUG
-option on the socket being used.
-.It Fl E
-Emit an audible beep (by sending an ASCII BEL character to the
-standard error output) when no packet is received before the next
-packet is transmitted.
-To cater for round-trip times that are longer than the interval
-between transmissions, further missing packets cause a bell only
-if the maximum number of unreceived packets has increased.
-This option is disabled for flood pings.
-.It Fl e
-Emit an audible beep (by sending an ASCII BEL character to the
-standard error output) after each non-duplicate response is received.
-This option is disabled for flood pings.
-.It Fl f
-Flood ping.
-Outputs packets as fast as they come back or one hundred times per second,
-whichever is more.
-For every
-.Dv ECHO_REQUEST
-sent a period
-.Pq Sq \&.
-is printed, while for every
-.Dv ECHO_REPLY
-received a backspace is printed.
-This provides a rapid display of how many packets are being dropped.
-Only the super-user may use this option.
-.Bf -emphasis
-This can be very hard on a network and should be used with caution.
-.Ef
-.It Fl H
-Try reverse lookups for addresses.
-.It Fl h Ar hoplimit
-Set the IPv6 hoplimit.
-.It Fl I Ar sourceaddr
-Specifies the source address of request packets.
-The source address must be one of the unicast addresses of the sending node,
-and must be numeric.
-.It Fl i Ar wait
-Wait
-.Ar wait
-seconds
-.Em between sending each packet .
-The default is to wait for one second between each packet.
-This option is incompatible with the
-.Fl f
-option.
-.It Fl L
-Disable the loopback, so the transmitting host doesn't see ICMP
-requests.
-For multicast pings.
-.It Fl l Ar preload
-If
-.Ar preload
-is specified,
-.Nm
-sends that many packets as fast as possible before falling into its normal
-mode of behavior.
-Only the super-user may use this option.
-.It Fl m
-By default,
-.Nm
-asks the kernel to fragment packets to fit into the minimum IPv6 MTU.
-.Fl m
-will suppress the behavior in the following two levels:
-when the option is specified once, the behavior will be disabled for
-unicast packets.
-When the option is specified more than once, it will be disabled for both
-unicast and multicast packets.
-.It Fl n
-Numeric output only.
-No attempt will be made to look up symbolic names from addresses in the reply.
-.It Fl p Ar pattern
-Up to 16
-.Dq pad
-bytes may be specified to fill out the packet sent.
-This is useful for diagnosing data-dependent problems in a network.
-For example,
-.Dq -p ff
-will cause the packet sent to be filled with all
-ones.
-.\" new ipsec
-.\".It Fl P Ar policy
-.\".Ar policy
-.\"specifies IPsec policy to be used for the probe.
-.It Fl q
-Quiet output.
-Nothing is displayed except the summary lines at startup time and
-when finished.
-.\".It Fl R
-.\"Make the kernel believe that the target
-.\".Ar host
-.\".Po
-.\"or the first
-.\".Ar hop
-.\"if you specify
-.\".Ar hops
-.\".Pc
-.\"is reachable, by injecting upper-layer reachability confirmation hint.
-.\"The option is meaningful only if the target
-.\".Ar host
-.\".Pq or the first hop
-.\"is a neighbor.
-.It Fl s Ar packetsize
-Specifies the number of data bytes to be sent.
-The default is 24,
-which translates into 32 ICMP data bytes
-when combined with the 8 bytes of ICMP header data.
-The maximum packet size is 65527.
-.It Fl V Ar rtable
-Set the routing table to be used for outgoing packets.
-.It Fl v
-Verbose output.
-All ICMP packets
-that are received are listed.
-.It Fl w Ar maxwait
-Specifies the maximum number of seconds to wait for responses
-after the last request has been sent.
-The default is 10.
-.El
-.Pp
-When using
-.Nm
-for fault isolation, it should first be run on the local host, to verify
-that the local network interface is up and running.
-Then hosts and gateways further and further away can be
-.Dq pinged .
-Round-trip times and packet loss statistics are computed.
-If duplicate packets are received, they are not included in the packet
-loss calculation, although the round trip time of these packets is used
-in calculating the round-trip time statistics.
-When the specified number of packets have been sent
-.Pq and received
-or if the program is terminated with a
-.Dv SIGINT ,
-a brief summary is displayed, showing the number of packets sent and
-received, and the minimum, maximum, mean, and standard deviation of
-the round-trip times.
-.Pp
-This program is intended for use in network testing, measurement, and
-management.
-Because of the load it can impose on the network, it is unwise to use
-.Nm
-during normal operations or from automated scripts.
-.\" .Sh ICMP PACKET DETAILS
-.\" An IP header without options is 20 bytes.
-.\" An
-.\" .Tn ICMP
-.\" .Tn ECHO_REQUEST
-.\" packet contains an additional 8 bytes worth of
-.\" .Tn ICMP
-.\" header followed by an arbitrary amount of data.
-.\" When a
-.\" .Ar packetsize
-.\" is given, this indicated the size of this extra piece of data
-.\" .Pq the default is 56 .
-.\" Thus the amount of data received inside of an IP packet of type
-.\" .Tn ICMP
-.\" .Tn ECHO_REPLY
-.\" will always be 8 bytes more than the requested data space
-.\" .Pq the Tn ICMP header .
-.\" .Pp
-.\" If the data space is at least eight bytes large,
-.\" .Nm
-.\" uses the first eight bytes of this space to include a timestamp which
-.\" it uses in the computation of round trip times.
-.\" If less than eight bytes of pad are specified, no round trip times are
-.\" given.
-.Sh DUPLICATE AND DAMAGED PACKETS
-.Nm
-will report duplicate and damaged packets.
-Duplicate packets should never occur when pinging a unicast address,
-and seem to be caused by
-inappropriate link-level retransmissions.
-Duplicates may occur in many situations and are rarely
-.Pq if ever
-a good sign, although the presence of low levels of duplicates may not
-always be cause for alarm.
-Duplicates are expected when pinging a broadcast or multicast address,
-since they are not really duplicates but replies from different hosts
-to the same request.
-.Pp
-Damaged packets are obviously serious cause for alarm and often
-indicate broken hardware somewhere in the
-.Nm
-packet's path
-.Pq in the network or in the hosts .
-.Sh TRYING DIFFERENT DATA PATTERNS
-The
-(inter)network
-layer should never treat packets differently depending on the data
-contained in the data portion.
-Unfortunately, data-dependent problems have been known to sneak into
-networks and remain undetected for long periods of time.
-In many cases the particular pattern that will have problems is something
-that does not have sufficient
-.Dq transitions ,
-such as all ones or all zeros, or a pattern right at the edge, such as
-almost all zeros.
-It is not
-necessarily enough to specify a data pattern of all zeros (for example)
-on the command line because the pattern that is of interest is
-at the data link level, and the relationship between what is typed and
-what the controllers transmit can be complicated.
-.Pp
-This means that if there is a data-dependent problem,
-a lot of testing will probably have to be done to find it.
-It may be possible to find a file that either cannot
-be sent across the network or that takes much longer to transfer than
-other similar length files.
-This file can then be examined for repeated patterns that can be tested
-using the
-.Fl p
-option.
-.Sh EXIT STATUS
-.Nm
-exits 0 if at least one reply is received,
-and \*(Gt0 if no reply is received or an error occurred.
-.Sh EXAMPLES
-Normally,
-.Nm
-works just like
-.Xr ping 8
-would work; the following will send ICMPv6 echo requests to dst.foo.com:
-.Bd -literal -offset indent
-$ ping6 -n dst.foo.com
-.Ed
-.Pp
-The following will send ICMPv6 echo requests to the link-local all-node
-multicast address.
-The packet reaches all nodes on the network link attached to the wi0
-interface.
-.Bd -literal -offset indent
-$ ping6 ff02::1%wi0
-.Ed
-.Sh SEE ALSO
-.Xr netstat 1 ,
-.Xr icmp6 4 ,
-.Xr inet6 4 ,
-.Xr ip6 4 ,
-.Xr ifconfig 8 ,
-.Xr ping 8 ,
-.Xr route6d 8 ,
-.Xr traceroute6 8
-.Sh STANDARDS
-.Rs
-.%A A. Conta
-.%A S. Deering
-.%A M. Gupta
-.%D March 2006
-.%R RFC 4443
-.%T "Internet Control Message Protocol (ICMPv6) for the Internet Protocol Version 6 (IPv6) Specification"
-.Re
-.Sh HISTORY
-The
-.Xr ping 8
-command first appeared in
-.Bx 4.3 .
-The
-.Nm
-command with IPv6 support first appeared in the WIDE Hydrangea IPv6
-protocol stack kit.
-.Sh BUGS
-.\" except for bsdi
-.Nm
-is intentionally separate from
-.Xr ping 8 .
diff --git a/sbin/ping6/ping6.c b/sbin/ping6/ping6.c
deleted file mode 100644
index fee3ae70781..00000000000
--- a/sbin/ping6/ping6.c
+++ /dev/null
@@ -1,1497 +0,0 @@
-/* $OpenBSD: ping6.c,v 1.222 2016/09/17 09:39:09 florian Exp $ */
-
-/*
- * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Muuss.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
- * measure round-trip-delays and packet loss across network paths.
- *
- * Author -
- * Mike Muuss
- * U. S. Army Ballistic Research Laboratory
- * December, 1983
- *
- * Status -
- * Public Domain. Distribution Unlimited.
- * Bugs -
- * More statistics could always be gathered.
- * This program has to run SUID to ROOT to access the ICMP socket.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/ip_var.h>
-#include <netinet/ip6.h>
-#include <netinet/icmp6.h>
-#include <netinet/ip_ah.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <limits.h>
-#include <math.h>
-#include <poll.h>
-#include <signal.h>
-#include <siphash.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
-struct tv64 {
- u_int64_t tv64_sec;
- u_int64_t tv64_nsec;
-};
-
-struct payload {
- struct tv64 tv64;
- u_int8_t mac[SIPHASH_DIGEST_LENGTH];
-};
-
-#define ECHOLEN 8 /* icmp echo header len excluding time */
-#define ECHOTMLEN sizeof(struct payload)
-#define DEFDATALEN (64 - ECHOLEN) /* default data length */
-#define IP6LEN 40
-#define EXTRA 256 /* for AH and various other headers. weird. */
-#define MAXPAYLOAD6 IPV6_MAXPACKET - IP6LEN - ECHOLEN
-#define MAXWAIT_DEFAULT 10 /* secs to wait for response */
-
-#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */
-#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */
-#define SET(bit) (A(bit) |= B(bit))
-#define CLR(bit) (A(bit) &= (~B(bit)))
-#define TST(bit) (A(bit) & B(bit))
-
-/* various options */
-int options;
-#define F_FLOOD 0x0001
-#define F_INTERVAL 0x0002
-#define F_HOSTNAME 0x0004
-#define F_PINGFILLED 0x0008
-#define F_QUIET 0x0010
-/* 0x0020 */
-#define F_SO_DEBUG 0x0040
-/* 0x0080 */
-#define F_VERBOSE 0x0100
-/* 0x0200 */
-/* 0x0400 */
-/* 0x0800 */
-/* 0x1000 */
-#define F_AUD_RECV 0x2000
-#define F_AUD_MISS 0x4000
-
-/* multicast options */
-int moptions;
-#define MULTICAST_NOLOOP 0x001
-
-#define DUMMY_PORT 10101
-
-/*
- * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
- * number of received sequence numbers we can keep track of. Change 128
- * to 8192 for complete accuracy...
- */
-#define MAX_DUP_CHK (8 * 8192)
-int mx_dup_ck = MAX_DUP_CHK;
-char rcvd_tbl[MAX_DUP_CHK / 8];
-
-int datalen = DEFDATALEN;
-int maxpayload;
-u_char outpackhdr[IP_MAXPACKET+sizeof(struct ip)];
-u_char *outpack = outpackhdr+sizeof(struct ip);
-char BSPACE = '\b'; /* characters written for flood */
-char DOT = '.';
-char *hostname;
-int ident; /* process id to identify our packets */
-
-/* counters */
-int64_t npackets; /* max packets to transmit */
-int64_t nreceived; /* # of packets we got back */
-int64_t nrepeats; /* number of duplicates */
-int64_t ntransmitted; /* sequence # for outbound packets = #sent */
-int64_t nmissedmax = 1; /* max value of ntransmitted - nreceived - 1 */
-struct timeval interval = {1, 0}; /* interval between packets */
-
-/* timing */
-int timing = 0; /* flag to do timing */
-int timinginfo = 0;
-unsigned int maxwait = MAXWAIT_DEFAULT; /* max seconds to wait for response */
-double tmin = 999999999.0; /* minimum round trip time */
-double tmax = 0.0; /* maximum round trip time */
-double tsum = 0.0; /* sum of all times, for doing average */
-double tsumsq = 0.0; /* sum of all times squared, for std. dev. */
-
-struct tv64 tv64_offset;
-SIPHASH_KEY mac_key;
-
-struct msghdr smsghdr;
-struct iovec smsgiov;
-
-volatile sig_atomic_t seenalrm;
-volatile sig_atomic_t seenint;
-volatile sig_atomic_t seeninfo;
-
-void fill(char *, char *);
-void summary(void);
-void onsignal(int);
-void retransmit(int);
-int pinger(int);
-const char *pr_addr(struct sockaddr *, socklen_t);
-void pr_pack(u_char *, int, struct msghdr *);
-__dead void usage(void);
-
-int get_hoplim(struct msghdr *);
-int get_pathmtu(struct msghdr *, struct sockaddr_in6 *);
-void pr_icmph6(struct icmp6_hdr *, u_char *);
-void pr_iph6(struct ip6_hdr *);
-void pr_exthdrs(struct msghdr *);
-void pr_ip6opt(void *);
-void pr_rthdr(void *);
-void pr_retip6(struct ip6_hdr *, u_char *);
-
-int
-main(int argc, char *argv[])
-{
- struct addrinfo hints, *res;
- struct itimerval itimer;
- struct sockaddr *from, *dst;
- struct sockaddr_in6 from6, dst6;
- struct cmsghdr *scmsg = NULL;
- struct in6_pktinfo *pktinfo = NULL;
- struct icmp6_filter filt;
- socklen_t maxsizelen;
- int64_t preload;
- int ch, i, optval = 1, packlen, maxsize, error, s, hoplimit = -1;
- int bufspace = IP_MAXPACKET;
- u_char *datap, *packet, loop = 1;
- char *e, *target, hbuf[NI_MAXHOST], *source = NULL;
- const char *errstr;
- double intval;
- int mflag = 0;
- uid_t uid;
- u_int rtableid = 0;
-
- if ((s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
- err(1, "socket");
-
- /* revoke privs */
- uid = getuid();
- if (setresuid(uid, uid, uid) == -1)
- err(1, "setresuid");
-
- preload = 0;
- maxpayload = MAXPAYLOAD6;
- datap = &outpack[ECHOLEN + ECHOTMLEN];
- while ((ch = getopt(argc, argv,
- "c:dEefHh:I:i:Ll:mNnp:qS:s:V:vw:")) != -1) {
- switch (ch) {
- case 'c':
- npackets = strtonum(optarg, 0, INT64_MAX, &errstr);
- if (errstr)
- errx(1,
- "number of packets to transmit is %s: %s",
- errstr, optarg);
- break;
- case 'd':
- options |= F_SO_DEBUG;
- break;
- case 'E':
- options |= F_AUD_MISS;
- break;
- case 'e':
- options |= F_AUD_RECV;
- break;
- case 'f':
- if (getuid())
- errx(1, "%s", strerror(EPERM));
- options |= F_FLOOD;
- setvbuf(stdout, NULL, _IONBF, 0);
- break;
- case 'H':
- options |= F_HOSTNAME;
- break;
- case 'h': /* hoplimit */
- hoplimit = strtonum(optarg, 0, IPV6_MAXHLIM, &errstr);
- if (errstr)
- errx(1, "hoplimit is %s: %s", errstr, optarg);
- break;
- case 'I':
- case 'S': /* deprecated */
- source = optarg;
- break;
- case 'i': /* wait between sending packets */
- intval = strtod(optarg, &e);
- if (*optarg == '\0' || *e != '\0')
- errx(1, "illegal timing interval %s", optarg);
- if (intval < 1 && getuid()) {
- errx(1, "%s: only root may use interval < 1s",
- strerror(EPERM));
- }
- interval.tv_sec = (time_t)intval;
- interval.tv_usec =
- (long)((intval - interval.tv_sec) * 1000000);
- if (interval.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 < 10000) {
- warnx("too small interval, raised to 0.01");
- interval.tv_usec = 10000;
- }
- options |= F_INTERVAL;
- break;
- case 'L':
- moptions |= MULTICAST_NOLOOP;
- loop = 0;
- break;
- case 'l':
- if (getuid())
- errx(1, "%s", strerror(EPERM));
- preload = strtonum(optarg, 1, INT64_MAX, &errstr);
- if (errstr)
- errx(1, "preload value is %s: %s", errstr,
- optarg);
- break;
- case 'm':
- mflag++;
- break;
- case 'n':
- options &= ~F_HOSTNAME;
- break;
- case 'p': /* fill buffer with user pattern */
- options |= F_PINGFILLED;
- fill((char *)datap, optarg);
- break;
- case 'q':
- options |= F_QUIET;
- break;
- case 's': /* size of packet to send */
- datalen = strtonum(optarg, 0, maxpayload, &errstr);
- if (errstr)
- errx(1, "packet size is %s: %s", errstr,
- optarg);
- break;
- case 'V':
- rtableid = strtonum(optarg, 0, RT_TABLEID_MAX, &errstr);
- if (errstr)
- errx(1, "rtable value is %s: %s", errstr,
- optarg);
- if (setsockopt(s, SOL_SOCKET, SO_RTABLE, &rtableid,
- sizeof(rtableid)) == -1)
- err(1, "setsockopt SO_RTABLE");
- break;
- case 'v':
- options |= F_VERBOSE;
- break;
- case 'w':
- maxwait = strtonum(optarg, 1, INT_MAX, &errstr);
- if (errstr)
- errx(1, "maxwait value is %s: %s",
- errstr, optarg);
- break;
- default:
- usage();
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (argc != 1)
- usage();
-
- memset(&dst6, 0, sizeof(dst6));
-
-#if 0
- if (inet_aton(*argv, &dst4.sin_addr) != 0) {
- hostname = *argv;
- if ((target = strdup(inet_ntoa(dst4.sin_addr))) == NULL)
- err(1, "malloc");
- } else
-#endif
- target = *argv;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_RAW;
- hints.ai_protocol = 0;
- hints.ai_flags = AI_CANONNAME;
- if ((error = getaddrinfo(target, NULL, &hints, &res)))
- errx(1, "%s", gai_strerror(error));
-
- switch (res->ai_family) {
- case AF_INET6:
- if (res->ai_addrlen != sizeof(dst6))
- errx(1, "size of sockaddr mismatch");
- dst = (struct sockaddr *)&dst6;
- from = (struct sockaddr *)&from6;
- break;
- case AF_INET:
- default:
- errx(1, "unsupported AF: %d", res->ai_family);
- break;
- }
-
- memcpy(dst, res->ai_addr, res->ai_addrlen);
-
- if (!hostname) {
- hostname = res->ai_canonname ? strdup(res->ai_canonname) :
- target;
- if (!hostname)
- err(1, "malloc");
- }
-
- if (res->ai_next) {
- if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
- sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
- strlcpy(hbuf, "?", sizeof(hbuf));
- warnx("Warning: %s has multiple "
- "addresses; using %s", hostname, hbuf);
- }
- freeaddrinfo(res);
-
- if (source) {
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET6;
- if ((error = getaddrinfo(source, NULL, &hints, &res)))
- errx(1, "%s: %s", source, gai_strerror(error));
- if (res->ai_family != AF_INET6 || res->ai_addrlen !=
- sizeof(from6))
- errx(1, "invalid source address");
- memcpy(from, res->ai_addr, res->ai_addrlen);
- freeaddrinfo(res);
- if (bind(s, from, from->sa_len) < 0)
- err(1, "bind");
- } else if (options & F_VERBOSE) {
- /*
- * get the source address. XXX since we revoked the root
- * privilege, we cannot use a raw socket for this.
- */
- int dummy;
- socklen_t len = dst->sa_len;
-
- if ((dummy = socket(dst->sa_family, SOCK_DGRAM, 0)) < 0)
- err(1, "UDP socket");
-
- memcpy(from, dst, dst->sa_len);
- from6.sin6_port = ntohs(DUMMY_PORT);
-
- if (pktinfo &&
- setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTINFO,
- (void *)pktinfo, sizeof(*pktinfo)))
- err(1, "UDP setsockopt(IPV6_PKTINFO)");
-
- if (hoplimit != -1 &&
- setsockopt(dummy, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
- (void *)&hoplimit, sizeof(hoplimit)))
- err(1, "UDP setsockopt(IPV6_UNICAST_HOPS)");
-
- if (hoplimit != -1 &&
- setsockopt(dummy, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
- (void *)&hoplimit, sizeof(hoplimit)))
- err(1, "UDP setsockopt(IPV6_MULTICAST_HOPS)");
-
- if (rtableid > 0 &&
- setsockopt(dummy, SOL_SOCKET, SO_RTABLE, &rtableid,
- sizeof(rtableid)) < 0)
- err(1, "setsockopt(SO_RTABLE)");
-
- if (connect(dummy, from, len) < 0)
- err(1, "UDP connect");
-
- if (getsockname(dummy, from, &len) < 0)
- err(1, "getsockname");
-
- close(dummy);
- }
-
- if (options & F_SO_DEBUG)
- (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, &optval,
- sizeof(optval));
-
- if ((options & F_FLOOD) && (options & F_INTERVAL))
- errx(1, "-f and -i options are incompatible");
-
- if ((options & F_FLOOD) && (options & (F_AUD_RECV | F_AUD_MISS)))
- warnx("No audible output for flood pings");
-
- if (datalen >= sizeof(struct payload)) /* can we time transfer */
- timing = 1;
-
- /* in F_VERBOSE case, we may get non-echoreply packets*/
- if (options & F_VERBOSE && datalen < 2048)
- packlen = 2048 + IP6LEN + ECHOLEN + EXTRA; /* XXX 2048? */
- else
- packlen = datalen + IP6LEN + ECHOLEN + EXTRA;
-
- if (!(packet = malloc(packlen)))
- err(1, "malloc");
-
- if (!(options & F_PINGFILLED))
- for (i = ECHOTMLEN; i < datalen; ++i)
- *datap++ = i;
-
- ident = getpid() & 0xFFFF;
-
- /*
- * When trying to send large packets, you must increase the
- * size of both the send and receive buffers...
- */
- maxsizelen = sizeof maxsize;
- if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &maxsize, &maxsizelen) < 0)
- err(1, "getsockopt");
- if (maxsize < packlen &&
- setsockopt(s, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(maxsize)) < 0)
- err(1, "setsockopt");
-
- /*
- * When pinging the broadcast address, you can get a lot of answers.
- * Doing something so evil is useful if you are trying to stress the
- * ethernet, or just want to fill the arp cache to get some stuff for
- * /etc/ethers.
- */
- while (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
- (void*)&bufspace, sizeof(bufspace)) < 0) {
- if ((bufspace -= 1024) <= 0)
- err(1, "Cannot set the receive buffer size");
- }
- if (bufspace < IP_MAXPACKET)
- warnx("Could only allocate a receive buffer of %d bytes "
- "(default %d)", bufspace, IP_MAXPACKET);
-
- /*
- * let the kernel pass extension headers of incoming packets,
- * for privileged socket options
- */
- if ((options & F_VERBOSE) != 0) {
- int opton = 1;
-
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton,
- (socklen_t)sizeof(opton)))
- err(1, "setsockopt(IPV6_RECVHOPOPTS)");
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton,
- (socklen_t)sizeof(opton)))
- err(1, "setsockopt(IPV6_RECVDSTOPTS)");
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_RECVRTHDR)");
- ICMP6_FILTER_SETPASSALL(&filt);
- } else {
- ICMP6_FILTER_SETBLOCKALL(&filt);
- ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
- }
-
- if ((moptions & MULTICAST_NOLOOP) &&
- setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop,
- sizeof(loop)) < 0)
- err(1, "setsockopt IP6_MULTICAST_LOOP");
-
- optval = IPV6_DEFHLIM;
- if (IN6_IS_ADDR_MULTICAST(&dst6.sin6_addr))
- if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
- &optval, (socklen_t)sizeof(optval)) == -1)
- err(1, "IPV6_MULTICAST_HOPS");
- if (mflag != 1) {
- optval = mflag > 1 ? 0 : 1;
-
- if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
- &optval, (socklen_t)sizeof(optval)) == -1)
- err(1, "setsockopt(IPV6_USE_MIN_MTU)");
- } else {
- optval = 1;
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPATHMTU,
- &optval, sizeof(optval)) == -1)
- err(1, "setsockopt(IPV6_RECVPATHMTU)");
- }
-
- if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
- (socklen_t)sizeof(filt)) < 0)
- err(1, "setsockopt(ICMP6_FILTER)");
-
- if (hoplimit != -1) {
- /* set IP6 packet options */
- if ((scmsg = malloc( CMSG_SPACE(sizeof(int)))) == NULL)
- err(1, "malloc");
- smsghdr.msg_control = (caddr_t)scmsg;
- smsghdr.msg_controllen = CMSG_SPACE(sizeof(int));
-
- scmsg->cmsg_len = CMSG_LEN(sizeof(int));
- scmsg->cmsg_level = IPPROTO_IPV6;
- scmsg->cmsg_type = IPV6_HOPLIMIT;
- *(int *)(CMSG_DATA(scmsg)) = hoplimit;
- }
-
- optval = 1;
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval,
- (socklen_t)sizeof(optval)) < 0)
- warn("setsockopt(IPV6_RECVPKTINFO)"); /* XXX err? */
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &optval,
- (socklen_t)sizeof(optval)) < 0)
- warn("setsockopt(IPV6_RECVHOPLIMIT)"); /* XXX err? */
-
- if (options & F_HOSTNAME) {
- if (pledge("stdio inet dns", NULL) == -1)
- err(1, "pledge");
- } else {
- if (pledge("stdio inet", NULL) == -1)
- err(1, "pledge");
- }
-
- arc4random_buf(&tv64_offset, sizeof(tv64_offset));
- arc4random_buf(&mac_key, sizeof(mac_key));
-
- printf("PING6 %s (", hostname);
- if (options & F_VERBOSE)
- printf("%s --> ", pr_addr(from, from->sa_len));
- printf("%s): %d data bytes\n", pr_addr(dst, dst->sa_len), datalen);
-
- smsghdr.msg_name = dst;
- smsghdr.msg_namelen = dst->sa_len;
- smsgiov.iov_base = (caddr_t)outpack;
- smsghdr.msg_iov = &smsgiov;
- smsghdr.msg_iovlen = 1;
-
- while (preload--) /* Fire off them quickies. */
- pinger(s);
-
- (void)signal(SIGINT, onsignal);
- (void)signal(SIGINFO, onsignal);
-
- 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(s);
- }
-
- seenalrm = seenint = 0;
- seeninfo = 0;
-
- for (;;) {
- struct msghdr m;
- union {
- struct cmsghdr hdr;
- u_char buf[CMSG_SPACE(1024)];
- } cmsgbuf;
- struct iovec iov[1];
- struct pollfd pfd;
- struct sockaddr_in6 peer;
- ssize_t cc;
- int timeout;
-
- /* signal handling */
- if (seenint)
- break;
- if (seenalrm) {
- retransmit(s);
- seenalrm = 0;
- if (ntransmitted - nreceived - 1 > nmissedmax) {
- nmissedmax = ntransmitted - nreceived - 1;
- if (!(options & F_FLOOD) &&
- (options & F_AUD_MISS))
- (void)fputc('\a', stderr);
- }
- continue;
- }
- if (seeninfo) {
- summary();
- seeninfo = 0;
- continue;
- }
-
- if (options & F_FLOOD) {
- (void)pinger(s);
- timeout = 10;
- } else
- timeout = INFTIM;
-
- pfd.fd = s;
- pfd.events = POLLIN;
-
- if (poll(&pfd, 1, timeout) <= 0)
- continue;
-
- m.msg_name = &peer;
- m.msg_namelen = sizeof(peer);
- 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;
- m.msg_control = (caddr_t)&cmsgbuf.buf;
- m.msg_controllen = sizeof(cmsgbuf.buf);
-
- cc = recvmsg(s, &m, 0);
- if (cc < 0) {
- if (errno != EINTR) {
- warn("recvmsg");
- sleep(1);
- }
- continue;
- } else if (cc == 0) {
- int mtu;
-
- /*
- * receive control messages only. Process the
- * exceptions (currently the only possibility is
- * a path MTU notification.)
- */
- if ((mtu = get_pathmtu(&m, &dst6)) > 0) {
- if ((options & F_VERBOSE) != 0) {
- printf("new path MTU (%d) is "
- "notified\n", mtu);
- }
- }
- continue;
- } else
- pr_pack(packet, cc, &m);
-
- if (npackets && nreceived >= npackets)
- break;
- }
- summary();
- exit(nreceived == 0);
-}
-
-void
-onsignal(int sig)
-{
- switch (sig) {
- case SIGALRM:
- seenalrm++;
- break;
- case SIGINT:
- seenint++;
- break;
- case SIGINFO:
- seeninfo++;
- break;
- }
-}
-
-void
-fill(char *bp, char *patp)
-{
- int ii, jj, kk;
- int pat[16];
- char *cp;
-
- for (cp = patp; *cp; cp++)
- if (!isxdigit((unsigned char)*cp))
- errx(1, "patterns must be specified as hex digits");
- ii = sscanf(patp,
- "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
- &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
- &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
- &pat[13], &pat[14], &pat[15]);
-
- if (ii > 0)
- for (kk = 0;
- kk <= maxpayload - (ECHOLEN + ECHOTMLEN + ii);
- kk += ii)
- for (jj = 0; jj < ii; ++jj)
- bp[jj + kk] = pat[jj];
- if (!(options & F_QUIET)) {
- (void)printf("PATTERN: 0x");
- for (jj = 0; jj < ii; ++jj)
- (void)printf("%02x", bp[jj] & 0xFF);
- (void)printf("\n");
- }
-}
-
-void
-summary(void)
-{
- printf("\n--- %s ping6 statistics ---\n", hostname);
- printf("%lld packets transmitted, ", ntransmitted);
- printf("%lld packets received, ", nreceived);
-
- if (nrepeats)
- printf("%lld duplicates, ", nrepeats);
- if (ntransmitted) {
- if (nreceived > ntransmitted)
- printf("-- somebody's duplicating packets!");
- else
- printf("%.1f%% packet loss",
- ((((double)ntransmitted - nreceived) * 100) /
- ntransmitted));
- }
- printf("\n");
- if (timinginfo) {
- /* Only display average to microseconds */
- double num = nreceived + nrepeats;
- double avg = tsum / num;
- double dev = sqrt(fmax(0, tsumsq / num - avg * avg));
- printf("round-trip min/avg/max/std-dev = %.3f/%.3f/%.3f/%.3f ms\n",
- tmin, avg, tmax, dev);
- }
-}
-
-/*
- * pr_addr --
- * Return address in numeric form or a host name
- */
-const char *
-pr_addr(struct sockaddr *addr, socklen_t addrlen)
-{
- static char buf[NI_MAXHOST];
- int flag = 0;
-
- if ((options & F_HOSTNAME) == 0)
- flag |= NI_NUMERICHOST;
-
- if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, flag) == 0)
- return (buf);
- else
- return "?";
-}
-
-/*
- * retransmit --
- * This routine transmits another ping6.
- */
-void
-retransmit(int s)
-{
- struct itimerval itimer;
- static int last_time = 0;
-
- if (last_time) {
- seenint = 1; /* break out of ping event loop */
- return;
- }
-
- if (pinger(s) == 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
- * maxwait seconds if we haven't.
- */
- 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)setitimer(ITIMER_REAL, &itimer, NULL);
-
- /* When the alarm goes off we are done. */
- last_time = 1;
-}
-
-/*
- * 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,
- * and the sequence number is an ascending integer. The first 8 bytes
- * of the data portion are used to hold a UNIX "timeval" struct in VAX
- * byte-order, to compute the round-trip time.
- */
-int
-pinger(int s)
-{
- struct icmp6_hdr *icp;
- int cc, i;
- u_int16_t seq;
-
- if (npackets && ntransmitted >= npackets)
- return(-1); /* no more transmission */
-
- seq = htons(ntransmitted++);
-
- icp = (struct icmp6_hdr *)outpack;
- memset(icp, 0, sizeof(*icp));
- icp->icmp6_cksum = 0;
- icp->icmp6_type = ICMP6_ECHO_REQUEST;
- icp->icmp6_code = 0;
- icp->icmp6_id = htons(ident);
- icp->icmp6_seq = seq;
-
- CLR(ntohs(seq) % mx_dup_ck);
-
- if (timing) {
- SIPHASH_CTX ctx;
- struct timespec ts;
- struct payload payload;
- struct tv64 *tv64 = &payload.tv64;
-
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
- err(1, "clock_gettime(CLOCK_MONOTONIC)");
- tv64->tv64_sec = htobe64((u_int64_t)ts.tv_sec +
- tv64_offset.tv64_sec);
- tv64->tv64_nsec = htobe64((u_int64_t)ts.tv_nsec +
- tv64_offset.tv64_nsec);
-
- SipHash24_Init(&ctx, &mac_key);
- SipHash24_Update(&ctx, tv64, sizeof(*tv64));
- SipHash24_Update(&ctx, &ident, sizeof(ident));
- SipHash24_Update(&ctx, &seq, sizeof(seq));
- SipHash24_Final(&payload.mac, &ctx);
-
- memcpy(&outpack[ECHOLEN], &payload, sizeof(payload));
- }
-
- cc = ECHOLEN + datalen;
-
- smsgiov.iov_len = cc;
-
- i = sendmsg(s, &smsghdr, 0);
-
- if (i < 0 || i != cc) {
- if (i < 0)
- warn("sendmsg");
- printf("ping6: wrote %s %d chars, ret=%d\n", hostname, cc, i);
- }
- if (!(options & F_QUIET) && options & F_FLOOD)
- (void)write(STDOUT_FILENO, &DOT, 1);
-
- return (0);
-}
-
-/*
- * pr_pack --
- * Print out the packet, if it came from us. This logic is necessary
- * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
- * which arrive ('tis only fair). This permits multiple copies of this
- * program to be run without having intermingled output (or statistics!).
- */
-void
-pr_pack(u_char *buf, int cc, struct msghdr *mhdr)
-{
- struct icmp6_hdr *icp;
- struct timespec ts, tp;
- struct payload payload;
- struct sockaddr *from;
- socklen_t fromlen;
- double triptime = 0;
- int i, dupflag;
- int hoplim;
- u_int16_t seq;
- u_char *cp = NULL, *dp, *end = buf + cc;
-
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
- err(1, "clock_gettime(CLOCK_MONOTONIC)");
-
- if (!mhdr || !mhdr->msg_name ||
- mhdr->msg_namelen != sizeof(struct sockaddr_in6) ||
- ((struct sockaddr *)mhdr->msg_name)->sa_family != AF_INET6) {
- if (options & F_VERBOSE)
- warnx("invalid peername");
- return;
- }
- from = (struct sockaddr *)mhdr->msg_name;
- fromlen = mhdr->msg_namelen;
- if (cc < sizeof(struct icmp6_hdr)) {
- if (options & F_VERBOSE)
- warnx("packet too short (%d bytes) from %s", cc,
- pr_addr(from, fromlen));
- return;
- }
- icp = (struct icmp6_hdr *)buf;
-
- if ((hoplim = get_hoplim(mhdr)) == -1) {
- warnx("failed to get receiving hop limit");
- return;
- }
-
- if (icp->icmp6_type == ICMP6_ECHO_REPLY) {
- if (ntohs(icp->icmp6_id) != ident)
- return; /* 'Twas not our ECHO */
- seq = icp->icmp6_seq;
- ++nreceived;
- if (cc >= ECHOLEN + ECHOTMLEN) {
- SIPHASH_CTX ctx;
- struct tv64 *tv64;
- u_int8_t mac[SIPHASH_DIGEST_LENGTH];
-
- memcpy(&payload, icp + 1, sizeof(payload));
- tv64 = &payload.tv64;
-
- SipHash24_Init(&ctx, &mac_key);
- SipHash24_Update(&ctx, tv64, sizeof(*tv64));
- SipHash24_Update(&ctx, &ident, sizeof(ident));
- SipHash24_Update(&ctx, &seq, sizeof(seq));
- SipHash24_Final(mac, &ctx);
-
- if (timingsafe_memcmp(mac, &payload.mac,
- sizeof(mac)) != 0) {
- (void)printf("signature mismatch!\n");
- return;
- }
- timinginfo=1;
-
- tp.tv_sec = betoh64(tv64->tv64_sec) -
- tv64_offset.tv64_sec;
- tp.tv_nsec = betoh64(tv64->tv64_nsec) -
- tv64_offset.tv64_nsec;
-
- timespecsub(&ts, &tp, &ts);
- triptime = ((double)ts.tv_sec) * 1000.0 +
- ((double)ts.tv_nsec) / 1000000.0;
- tsum += triptime;
- tsumsq += triptime * triptime;
- if (triptime < tmin)
- tmin = triptime;
- if (triptime > tmax)
- tmax = triptime;
- }
-
- if (TST(ntohs(seq) % mx_dup_ck)) {
- ++nrepeats;
- --nreceived;
- dupflag = 1;
- } else {
- SET(ntohs(seq) % mx_dup_ck);
- dupflag = 0;
- }
-
- if (options & F_QUIET)
- return;
-
- if (options & F_FLOOD)
- (void)write(STDOUT_FILENO, &BSPACE, 1);
- else {
- (void)printf("%d bytes from %s: icmp_seq=%u", cc,
- pr_addr(from, fromlen), ntohs(seq));
- (void)printf(" hlim=%d", hoplim);
- if (cc >= ECHOLEN + ECHOTMLEN)
- (void)printf(" time=%.3f ms", triptime);
- if (dupflag)
- (void)printf(" (DUP!)");
- /* check the data */
- if (cc - ECHOLEN < datalen)
- (void)printf(" (TRUNC!)");
- cp = buf + ECHOLEN + ECHOTMLEN;
- dp = &outpack[ECHOLEN + ECHOTMLEN];
- for (i = ECHOLEN + ECHOTMLEN;
- i < cc && i < datalen;
- ++i, ++cp, ++dp) {
- if (*cp != *dp) {
- (void)printf("\nwrong data byte #%d "
- "should be 0x%x but was 0x%x",
- i - ECHOLEN, *dp, *cp);
- cp = buf + ECHOLEN;
- for (i = ECHOLEN; i < cc && i < datalen;
- ++i, ++cp) {
- if ((i % 32) == 8)
- (void)printf("\n\t");
- (void)printf("%x ", *cp);
- }
- break;
- }
- }
- }
- } else {
- /* We've got something other than an ECHOREPLY */
- if (!(options & F_VERBOSE))
- return;
- (void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));
- pr_icmph6(icp, end);
- }
-
- if (!(options & F_FLOOD)) {
- (void)putchar('\n');
- if (options & F_VERBOSE)
- pr_exthdrs(mhdr);
- (void)fflush(stdout);
- if (options & F_AUD_RECV)
- (void)fputc('\a', stderr);
- }
-}
-
-void
-pr_exthdrs(struct msghdr *mhdr)
-{
- struct cmsghdr *cm;
-
- for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
- cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
- if (cm->cmsg_level != IPPROTO_IPV6)
- continue;
-
- switch (cm->cmsg_type) {
- case IPV6_HOPOPTS:
- printf(" HbH Options: ");
- pr_ip6opt(CMSG_DATA(cm));
- break;
- case IPV6_DSTOPTS:
- case IPV6_RTHDRDSTOPTS:
- printf(" Dst Options: ");
- pr_ip6opt(CMSG_DATA(cm));
- break;
- case IPV6_RTHDR:
- printf(" Routing: ");
- pr_rthdr(CMSG_DATA(cm));
- break;
- }
- }
-}
-
-void
-pr_ip6opt(void *extbuf)
-{
- struct ip6_hbh *ext;
- int currentlen;
- u_int8_t type;
- size_t extlen;
- socklen_t len;
- void *databuf;
- u_int16_t value2;
- u_int32_t value4;
-
- ext = (struct ip6_hbh *)extbuf;
- extlen = (ext->ip6h_len + 1) * 8;
- printf("nxt %u, len %u (%lu bytes)\n", ext->ip6h_nxt,
- (unsigned int)ext->ip6h_len, (unsigned long)extlen);
-
- currentlen = 0;
- while (1) {
- currentlen = inet6_opt_next(extbuf, extlen, currentlen,
- &type, &len, &databuf);
- if (currentlen == -1)
- break;
- switch (type) {
- /*
- * Note that inet6_opt_next automatically skips any padding
- * options.
- */
- case IP6OPT_JUMBO:
- inet6_opt_get_val(databuf, 0, &value4, sizeof(value4));
- printf(" Jumbo Payload Opt: Length %u\n",
- (u_int32_t)ntohl(value4));
- break;
- case IP6OPT_ROUTER_ALERT:
- inet6_opt_get_val(databuf, 0, &value2, sizeof(value2));
- printf(" Router Alert Opt: Type %u\n",
- ntohs(value2));
- break;
- default:
- printf(" Received Opt %u len %lu\n",
- type, (unsigned long)len);
- break;
- }
- }
- return;
-}
-
-void
-pr_rthdr(void *extbuf)
-{
- struct in6_addr *in6;
- char ntopbuf[INET6_ADDRSTRLEN];
- struct ip6_rthdr *rh = (struct ip6_rthdr *)extbuf;
- int i, segments;
-
- /* print fixed part of the header */
- printf("nxt %u, len %u (%d bytes), type %u, ", rh->ip6r_nxt,
- rh->ip6r_len, (rh->ip6r_len + 1) << 3, rh->ip6r_type);
- if ((segments = inet6_rth_segments(extbuf)) >= 0)
- printf("%d segments, ", segments);
- else
- printf("segments unknown, ");
- printf("%d left\n", rh->ip6r_segleft);
-
- for (i = 0; i < segments; i++) {
- in6 = inet6_rth_getaddr(extbuf, i);
- if (in6 == NULL)
- printf(" [%d]<NULL>\n", i);
- else {
- if (!inet_ntop(AF_INET6, in6, ntopbuf,
- sizeof(ntopbuf)))
- strncpy(ntopbuf, "?", sizeof(ntopbuf));
- printf(" [%d]%s\n", i, ntopbuf);
- }
- }
-
- return;
-
-}
-
-int
-get_hoplim(struct msghdr *mhdr)
-{
- struct cmsghdr *cm;
-
- for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
- cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
- if (cm->cmsg_len == 0)
- return(-1);
-
- if (cm->cmsg_level == IPPROTO_IPV6 &&
- cm->cmsg_type == IPV6_HOPLIMIT &&
- cm->cmsg_len == CMSG_LEN(sizeof(int)))
- return(*(int *)CMSG_DATA(cm));
- }
-
- return(-1);
-}
-
-int
-get_pathmtu(struct msghdr *mhdr, struct sockaddr_in6 *dst)
-{
- struct cmsghdr *cm;
- struct ip6_mtuinfo *mtuctl = NULL;
-
- for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
- cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
- if (cm->cmsg_len == 0)
- return(0);
-
- if (cm->cmsg_level == IPPROTO_IPV6 &&
- cm->cmsg_type == IPV6_PATHMTU &&
- cm->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) {
- mtuctl = (struct ip6_mtuinfo *)CMSG_DATA(cm);
-
- /*
- * If the notified destination is different from
- * the one we are pinging, just ignore the info.
- * We check the scope ID only when both notified value
- * and our own value have non-0 values, because we may
- * have used the default scope zone ID for sending,
- * in which case the scope ID value is 0.
- */
- if (!IN6_ARE_ADDR_EQUAL(&mtuctl->ip6m_addr.sin6_addr,
- &dst->sin6_addr) ||
- (mtuctl->ip6m_addr.sin6_scope_id &&
- dst->sin6_scope_id &&
- mtuctl->ip6m_addr.sin6_scope_id !=
- dst->sin6_scope_id)) {
- if ((options & F_VERBOSE) != 0) {
- printf("path MTU for %s is notified. "
- "(ignored)\n",
- pr_addr((struct sockaddr *)&mtuctl->ip6m_addr,
- sizeof(mtuctl->ip6m_addr)));
- }
- return(0);
- }
-
- /*
- * Ignore an invalid MTU. XXX: can we just believe
- * the kernel check?
- */
- if (mtuctl->ip6m_mtu < IPV6_MMTU)
- return(0);
-
- /* notification for our destination. return the MTU. */
- return((int)mtuctl->ip6m_mtu);
- }
- }
- return(0);
-}
-
-/*
- * pr_icmph6 --
- * Print a descriptive string about an ICMP header.
- */
-void
-pr_icmph6(struct icmp6_hdr *icp, u_char *end)
-{
- char ntop_buf[INET6_ADDRSTRLEN];
- struct nd_redirect *red;
-
- switch (icp->icmp6_type) {
- case ICMP6_DST_UNREACH:
- switch (icp->icmp6_code) {
- case ICMP6_DST_UNREACH_NOROUTE:
- (void)printf("No Route to Destination\n");
- break;
- case ICMP6_DST_UNREACH_ADMIN:
- (void)printf("Destination Administratively "
- "Unreachable\n");
- break;
- case ICMP6_DST_UNREACH_BEYONDSCOPE:
- (void)printf("Destination Unreachable Beyond Scope\n");
- break;
- case ICMP6_DST_UNREACH_ADDR:
- (void)printf("Destination Host Unreachable\n");
- break;
- case ICMP6_DST_UNREACH_NOPORT:
- (void)printf("Destination Port Unreachable\n");
- break;
- default:
- (void)printf("Destination Unreachable, Bad Code: %d\n",
- icp->icmp6_code);
- break;
- }
- /* Print returned IP header information */
- pr_retip6((struct ip6_hdr *)(icp + 1), end);
- break;
- case ICMP6_PACKET_TOO_BIG:
- (void)printf("Packet too big mtu = %d\n",
- (int)ntohl(icp->icmp6_mtu));
- pr_retip6((struct ip6_hdr *)(icp + 1), end);
- break;
- case ICMP6_TIME_EXCEEDED:
- switch (icp->icmp6_code) {
- case ICMP6_TIME_EXCEED_TRANSIT:
- (void)printf("Time to live exceeded\n");
- break;
- case ICMP6_TIME_EXCEED_REASSEMBLY:
- (void)printf("Frag reassembly time exceeded\n");
- break;
- default:
- (void)printf("Time exceeded, Bad Code: %d\n",
- icp->icmp6_code);
- break;
- }
- pr_retip6((struct ip6_hdr *)(icp + 1), end);
- break;
- case ICMP6_PARAM_PROB:
- (void)printf("Parameter problem: ");
- switch (icp->icmp6_code) {
- case ICMP6_PARAMPROB_HEADER:
- (void)printf("Erroneous Header ");
- break;
- case ICMP6_PARAMPROB_NEXTHEADER:
- (void)printf("Unknown Nextheader ");
- break;
- case ICMP6_PARAMPROB_OPTION:
- (void)printf("Unrecognized Option ");
- break;
- default:
- (void)printf("Bad code(%d) ", icp->icmp6_code);
- break;
- }
- (void)printf("pointer = 0x%02x\n",
- (u_int32_t)ntohl(icp->icmp6_pptr));
- pr_retip6((struct ip6_hdr *)(icp + 1), end);
- break;
- case ICMP6_ECHO_REQUEST:
- (void)printf("Echo Request");
- /* XXX ID + Seq + Data */
- break;
- case ICMP6_ECHO_REPLY:
- (void)printf("Echo Reply");
- /* XXX ID + Seq + Data */
- break;
- case ICMP6_MEMBERSHIP_QUERY:
- (void)printf("Listener Query");
- break;
- case ICMP6_MEMBERSHIP_REPORT:
- (void)printf("Listener Report");
- break;
- case ICMP6_MEMBERSHIP_REDUCTION:
- (void)printf("Listener Done");
- break;
- case ND_ROUTER_SOLICIT:
- (void)printf("Router Solicitation");
- break;
- case ND_ROUTER_ADVERT:
- (void)printf("Router Advertisement");
- break;
- case ND_NEIGHBOR_SOLICIT:
- (void)printf("Neighbor Solicitation");
- break;
- case ND_NEIGHBOR_ADVERT:
- (void)printf("Neighbor Advertisement");
- break;
- case ND_REDIRECT:
- red = (struct nd_redirect *)icp;
- (void)printf("Redirect\n");
- if (!inet_ntop(AF_INET6, &red->nd_rd_dst, ntop_buf,
- sizeof(ntop_buf)))
- strncpy(ntop_buf, "?", sizeof(ntop_buf));
- (void)printf("Destination: %s", ntop_buf);
- if (!inet_ntop(AF_INET6, &red->nd_rd_target, ntop_buf,
- sizeof(ntop_buf)))
- strncpy(ntop_buf, "?", sizeof(ntop_buf));
- (void)printf(" New Target: %s", ntop_buf);
- break;
- default:
- (void)printf("Bad ICMP type: %d", icp->icmp6_type);
- }
-}
-
-/*
- * pr_iph6 --
- * Print an IP6 header.
- */
-void
-pr_iph6(struct ip6_hdr *ip6)
-{
- u_int32_t flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
- u_int8_t tc;
- char ntop_buf[INET6_ADDRSTRLEN];
-
- tc = *(&ip6->ip6_vfc + 1); /* XXX */
- tc = (tc >> 4) & 0x0f;
- tc |= (ip6->ip6_vfc << 4);
-
- printf("Vr TC Flow Plen Nxt Hlim\n");
- printf(" %1x %02x %05x %04x %02x %02x\n",
- (ip6->ip6_vfc & IPV6_VERSION_MASK) >> 4, tc, (u_int32_t)ntohl(flow),
- ntohs(ip6->ip6_plen), ip6->ip6_nxt, ip6->ip6_hlim);
- if (!inet_ntop(AF_INET6, &ip6->ip6_src, ntop_buf, sizeof(ntop_buf)))
- strncpy(ntop_buf, "?", sizeof(ntop_buf));
- printf("%s->", ntop_buf);
- if (!inet_ntop(AF_INET6, &ip6->ip6_dst, ntop_buf, sizeof(ntop_buf)))
- strncpy(ntop_buf, "?", sizeof(ntop_buf));
- printf("%s\n", ntop_buf);
-}
-
-/*
- * pr_retip6 --
- * Dump some info on a returned (via ICMPv6) IPv6 packet.
- */
-void
-pr_retip6(struct ip6_hdr *ip6, u_char *end)
-{
- u_char *cp = (u_char *)ip6, nh;
- int hlen;
-
- if (end - (u_char *)ip6 < sizeof(*ip6)) {
- printf("IP6");
- goto trunc;
- }
- pr_iph6(ip6);
- hlen = sizeof(*ip6);
-
- nh = ip6->ip6_nxt;
- cp += hlen;
- while (end - cp >= 8) {
- switch (nh) {
- case IPPROTO_HOPOPTS:
- printf("HBH ");
- hlen = (((struct ip6_hbh *)cp)->ip6h_len+1) << 3;
- nh = ((struct ip6_hbh *)cp)->ip6h_nxt;
- break;
- case IPPROTO_DSTOPTS:
- printf("DSTOPT ");
- hlen = (((struct ip6_dest *)cp)->ip6d_len+1) << 3;
- nh = ((struct ip6_dest *)cp)->ip6d_nxt;
- break;
- case IPPROTO_FRAGMENT:
- printf("FRAG ");
- hlen = sizeof(struct ip6_frag);
- nh = ((struct ip6_frag *)cp)->ip6f_nxt;
- break;
- case IPPROTO_ROUTING:
- printf("RTHDR ");
- hlen = (((struct ip6_rthdr *)cp)->ip6r_len+1) << 3;
- nh = ((struct ip6_rthdr *)cp)->ip6r_nxt;
- break;
- case IPPROTO_AH:
- printf("AH ");
- hlen = (((struct ah *)cp)->ah_hl+2) << 2;
- nh = ((struct ah *)cp)->ah_nh;
- break;
- case IPPROTO_ICMPV6:
- printf("ICMP6: type = %d, code = %d\n",
- *cp, *(cp + 1));
- return;
- case IPPROTO_ESP:
- printf("ESP\n");
- return;
- case IPPROTO_TCP:
- printf("TCP: from port %u, to port %u (decimal)\n",
- (*cp * 256 + *(cp + 1)),
- (*(cp + 2) * 256 + *(cp + 3)));
- return;
- case IPPROTO_UDP:
- printf("UDP: from port %u, to port %u (decimal)\n",
- (*cp * 256 + *(cp + 1)),
- (*(cp + 2) * 256 + *(cp + 3)));
- return;
- default:
- printf("Unknown Header(%d)\n", nh);
- return;
- }
-
- if ((cp += hlen) >= end)
- goto trunc;
- }
- if (end - cp < 8)
- goto trunc;
-
- putchar('\n');
- return;
-
- trunc:
- printf("...\n");
- return;
-}
-
-__dead void
-usage(void)
-{
- (void)fprintf(stderr,
- "usage: ping6 [-dEefHLmnqv] [-c count] [-h hoplimit] "
- "[-I sourceaddr]\n\t[-i wait] [-l preload] [-p pattern] "
- "[-s packetsize] [-V rtable]\n\t[-w maxwait] host\n");
- exit(1);
-}