diff options
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ping6/Makefile | 6 | ||||
-rw-r--r-- | sbin/ping6/ping6.8 | 132 | ||||
-rw-r--r-- | sbin/ping6/ping6.c | 381 |
3 files changed, 263 insertions, 256 deletions
diff --git a/sbin/ping6/Makefile b/sbin/ping6/Makefile index 98378fc..4073a56 100644 --- a/sbin/ping6/Makefile +++ b/sbin/ping6/Makefile @@ -3,7 +3,8 @@ PROG= ping6 MAN= ping6.8 -CFLAGS+=-DINET6 -DIPSEC +CFLAGS+=-DINET6 -DIPSEC -DKAME_SCOPEID -DUSE_RFC2292BIS \ + -DHAVE_POLL_H -DHAVE_ARC4RANDOM WARNS= 0 BINOWN= root @@ -12,7 +13,4 @@ BINMODE=4555 LDADD= -lipsec -lm -lmd DPADD= ${LIBIPSEC} ${LIBM} ${LIBMD} -# kame scopeid hack -CFLAGS+=-DKAME_SCOPEID - .include <bsd.prog.mk> diff --git a/sbin/ping6/ping6.8 b/sbin/ping6/ping6.8 index 554bf2b..84a51ed 100644 --- a/sbin/ping6/ping6.8 +++ b/sbin/ping6/ping6.8 @@ -1,4 +1,4 @@ -.\" $KAME: ping6.8,v 1.43 2001/06/28 06:54:29 suz Exp $ +.\" $KAME: ping6.8,v 1.58 2003/06/20 12:00:22 itojun Exp $ .\" .\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. .\" All rights reserved. @@ -40,9 +40,9 @@ packets to network hosts .Sh SYNOPSIS .Nm .\" without ipsec, or new ipsec -.Op Fl dfHnNqRtvwW +.Op Fl dfHmnNqtvwW .\" old ipsec -.\" .Op Fl AdEfnNqRtvwW +.\" .Op Fl AdEfmnNqRtvwW .Bk -words .Op Fl a Ar addrtype .Ek @@ -53,6 +53,9 @@ packets to network hosts .Op Fl c Ar count .Ek .Bk -words +.Op Fl g Ar gateway +.Ek +.Bk -words .Op Fl h Ar hoplimit .Ek .Bk -words @@ -78,7 +81,7 @@ packets to network hosts .Op Fl s Ar packetsize .Ek .Bk -words -.Op Ar hops...\& +.Op Ar hops ... .Ek .Bk -words .Ar host @@ -86,7 +89,7 @@ packets to network hosts .Sh DESCRIPTION The .Nm -utility uses the +command uses the .Tn ICMPv6 protocol's mandatory .Tn ICMP6_ECHO_REQUEST @@ -103,14 +106,14 @@ The options are as follows: .\" old ipsec .\" .It Fl A .\" Enables transport-mode IPsec authentication header -.\" (experimental). +.\" .Pq experimental . .It Fl a Ar addrtype Generate ICMPv6 Node Information Node Addresses query, rather than echo-request. .Ar addrtype must be a string constructed of the following characters. .Bl -tag -width Ds -compact .It Ic a -requests all the responder's unicast addresses. +requests unicast addresses from all of the responder's interfaces. If the character is omitted, only those addresses which belong to the interface which has the responder's address are requests. @@ -134,7 +137,7 @@ This is an experimental option. Set socket buffer size. .It Fl c Ar count Stop after sending -(and receiving) +.Pq and receiving .Ar count .Tn ECHO_RESPONSE packets. @@ -144,7 +147,7 @@ Set the option on the socket being used. .\" .It Fl E .\" Enables transport-mode IPsec encapsulated security payload -.\" (experimental). +.\" .Pq experimental . .It Fl f Flood ping. Outputs packets as fast as they come back or one hundred times per second, @@ -152,7 +155,7 @@ whichever is more. For every .Tn ECHO_REQUEST sent a period -.Dq .\& +.Dq \&. is printed, while for every .Tn ECHO_REPLY received a backspace is printed. @@ -161,11 +164,16 @@ 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 g Ar gateway +Specifies to use +.Ar gateway +as the next hop to the destination. +The gateway must be a neighbor of the sending node. .It Fl H Specifies to try reverse-lookup of IPv6 addresses. The .Nm -utility does not try reverse-lookup unless the option is specified. +command does not try reverse-lookup unless the option is specified. .It Fl h Ar hoplimit Set the IPv6 hoplimit. .It Fl I Ar interface @@ -189,6 +197,16 @@ is specified, 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 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 lookup symbolic names from addresses in the reply. @@ -197,12 +215,12 @@ Probe node information multicast group .Pq Li ff02::2:xxxx:xxxx . .Ar host must be string hostname of the target -(must not be a numeric IPv6 address). +.Pq must not be a numeric IPv6 address . Node information multicast group will be computed based on given .Ar host , and will be used as the final destination. Since node information multicast group is a link-local multicast group, -destination link needs to be specified by +outgoing interface needs to be specified by .Fl I option. .It Fl p Ar pattern @@ -222,26 +240,10 @@ specifies IPsec policy to be used for the probe. 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 -(or the first -.Ar hop -if you specify -.Ar hops ) -is reachable, by injecting upper-layer reachability confirmation hint. -The option is meaningful only if the target -.Ar host -(or the first hop) -is a neighbor. .It Fl S Ar sourceaddr Specifies the source address of request packets. -The source address must be one of the unicast addresses of the sending node. -If the outgoing interface is specified by the -.Fl I -option as well, -.Ar sourceaddr -needs to be an address assigned to the specified interface. +The source address must be one of the unicast addresses of the sending node, +and must be numeric. .It Fl s Ar packetsize Specifies the number of data bytes to be sent. The default is 56, which translates into 64 @@ -299,26 +301,13 @@ 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 -(and received) +.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, mean, maximum, and standard deviation of +received, and the minimum, maximum, mean, and standard deviation of the round-trip times. .Pp -If -.Nm -receives a -.Dv SIGINFO -(see the -.Cm status -argument for -.Xr stty 1 ) -signal, the current number of packets sent and received, and the -minimum, mean, maximum, and standard deviation of the round-trip times -will be written to the standard output in the same format as the -standard completion message. -.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 @@ -335,14 +324,12 @@ during normal operations or from automated scripts. .\" When a .\" .Ar packetsize .\" is given, this indicated the size of this extra piece of data -.\" (the default is 56). +.\" .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 -.\" (the -.\" .Tn ICMP -.\" header). +.\" .Pq the Tn ICMP header . .\" .Pp .\" If the data space is at least eight bytes large, .\" .Nm @@ -353,12 +340,12 @@ during normal operations or from automated scripts. .Sh DUPLICATE AND DAMAGED PACKETS The .Nm -utility will report duplicate and damaged packets. +command 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 -(if ever) +.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, @@ -369,7 +356,7 @@ Damaged packets are obviously serious cause for alarm and often indicate broken hardware somewhere in the .Nm packet's path -(in the network or in the hosts). +.Pq in the network or in the hosts . .Sh TRYING DIFFERENT DATA PATTERNS The (inter)network @@ -398,11 +385,10 @@ You can then examine this file for repeated patterns that you can test using the .Fl p option of -.Nm . +.Nm Ns . .Sh RETURN VALUES -The .Nm -utility returns 0 on success (the host is alive), +command returns 0 on success (the host is alive), and non-zero if the arguments are incorrect or the host is not responding. .Sh EXAMPLES Normally, @@ -451,11 +437,28 @@ ping6 -a agl dst.foo.com .Rs .%A Matt Crawford .%T "IPv6 Node Information Queries" -.%N draft-ietf-ipngwg-icmp-name-lookups-07.txt -.%D August 2000 +.%N draft-ietf-ipngwg-icmp-name-lookups-09.txt +.%D May 2002 .%O work in progress material .Re +.Sh HISTORY +The +.Xr ping 8 +command appeared in +.Bx 4.3 . +The +.Nm +command with IPv6 support first appeared in the WIDE Hydrangea IPv6 +protocol stack kit. +.Pp +IPv6 and IPsec support based on the KAME Project (http://www.kame.net/) stack +was initially integrated into +.Fx 4.0 .Sh BUGS +.Nm +is intentionally separate from +.Xr ping 8 . +.Pp There have been many discussions on why we separate .Nm and @@ -484,16 +487,3 @@ or .Fl 4 option (or something like those) to specify the particular address family. This essentially means that we have two different commands. -.Sh HISTORY -The -.Xr ping 8 -command appeared in -.Bx 4.3 . -The -.Nm -utility with IPv6 support first appeared in WIDE Hydrangea IPv6 protocol stack -kit. -.Pp -IPv6 and IPsec support based on the KAME Project (http://www.kame.net/) stack -was initially integrated into -.Fx 4.0 diff --git a/sbin/ping6/ping6.c b/sbin/ping6/ping6.c index 70e2221..42c517c 100644 --- a/sbin/ping6/ping6.c +++ b/sbin/ping6/ping6.c @@ -1,4 +1,4 @@ -/* $KAME: ping6.c,v 1.126 2001/05/17 03:39:08 itojun Exp $ */ +/* $KAME: ping6.c,v 1.169 2003/07/25 06:01:47 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -123,30 +123,32 @@ static const char rcsid[] = #include <err.h> #include <errno.h> #include <fcntl.h> -#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) #include <math.h> -#endif #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +#ifdef HAVE_POLL_H +#include <poll.h> +#endif #ifdef IPSEC #include <netinet6/ah.h> #include <netinet6/ipsec.h> #endif -#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) #include <md5.h> -#else -#include "md5.h" -#endif + +struct tv32 { + u_int32_t tv32_sec; + u_int32_t tv32_usec; +}; #define MAXPACKETLEN 131072 #define IP6LEN 40 -#define ICMP6ECHOLEN 8 /* icmp echo header length excluding time */ -#define ICMP6ECHOTMLEN sizeof(struct timeval) +#define ICMP6ECHOLEN 8 /* icmp echo header len excluding time */ +#define ICMP6ECHOTMLEN sizeof(struct tv32) #define ICMP6_NIQLEN (ICMP6ECHOLEN + 8) /* FQDN case, 64 bits of nonce + 32 bits ttl */ #define ICMP6_NIRLEN (ICMP6ECHOLEN + 12) @@ -180,9 +182,6 @@ static const char rcsid[] = #define F_FQDN 0x1000 #define F_INTERFACE 0x2000 #define F_SRCADDR 0x4000 -#ifdef IPV6_REACHCONF -#define F_REACHCONF 0x8000 -#endif #define F_HOSTNAME 0x10000 #define F_FQDNOLD 0x20000 #define F_NIGROUP 0x40000 @@ -209,6 +208,7 @@ char rcvd_tbl[MAX_DUP_CHK / 8]; struct addrinfo *res; struct sockaddr_in6 dst; /* who to ping6 */ struct sockaddr_in6 src; /* src addr of this packet */ +socklen_t srclen; int datalen = DEFDATALEN; int s; /* socket file descriptor */ u_char outpack[MAXPACKETLEN]; @@ -217,7 +217,6 @@ char DOT = '.'; char *hostname; int ident; /* process id to identify our packets */ u_int8_t nonce[8]; /* nonce field for node information */ -struct in6_addr srcaddr; int hoplimit = -1; /* hoplimit */ int pathmtu = 0; /* path MTU for the destination. 0 = unspec. */ @@ -233,9 +232,7 @@ int timing; /* flag to do timing */ 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 */ -#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) double tsumsq = 0.0; /* sum of all times squared, for std. dev. */ -#endif /* for node addresses */ u_short naflags; @@ -245,17 +242,16 @@ struct msghdr smsghdr; struct iovec smsgiov; char *scmsg = 0; -volatile int signo; volatile sig_atomic_t seenalrm; volatile sig_atomic_t seenint; #ifdef SIGINFO volatile sig_atomic_t seeninfo; #endif +int main(int, char *[]); void fill(char *, char *); int get_hoplim(struct msghdr *); int get_pathmtu(struct msghdr *); -void set_pathmtu(int); struct in6_pktinfo *get_rcvpktinfo(struct msghdr *); void onsignal(int); void retransmit(void); @@ -270,7 +266,7 @@ void pr_nodeaddr(struct icmp6_nodeinfo *, int); int myechoreply(const struct icmp6_hdr *); int mynireply(const struct icmp6_nodeinfo *); char *dnsdecode(const u_char **, const u_char *, const u_char *, - u_char *, size_t); + char *, size_t); void pr_pack(u_char *, int, struct msghdr *); void pr_exthdrs(struct msghdr *); void pr_ip6opt(void *); @@ -290,17 +286,31 @@ main(argc, argv) { struct itimerval itimer; struct sockaddr_in6 from; +#ifndef HAVE_ARC4RANDOM + struct timeval seed; +#endif +#ifdef HAVE_POLL_H + int timeout; +#else struct timeval timeout, *tv; +#endif struct addrinfo hints; +#ifdef HAVE_POLL_H + struct pollfd fdmaskp[1]; +#else fd_set *fdmaskp; int fdmasks; +#endif int cc, i; - int ch, fromlen, hold, packlen, preload, optval, ret_ga; + int ch, hold, packlen, preload, optval, ret_ga; u_char *datap, *packet; - char *e, *target, *ifname = NULL; + char *e, *target, *ifname = NULL, *gateway = NULL; int ip6optlen = 0; struct cmsghdr *scmsgp = NULL; +#if defined(SO_SNDBUF) && defined(SO_RCVBUF) + u_long lsockbufsize; int sockbufsize = 0; +#endif int usepktinfo = 0; struct in6_pktinfo *pktinfo = NULL; #ifdef USE_RFC2292BIS @@ -312,6 +322,9 @@ main(argc, argv) #endif double intval; size_t rthlen; +#ifdef IPV6_USE_MIN_MTU + int mflag = 0; +#endif /* just to be sure */ memset(&smsghdr, 0, sizeof(smsghdr)); @@ -329,7 +342,7 @@ main(argc, argv) #endif /*IPSEC_POLICY_IPSEC*/ #endif while ((ch = getopt(argc, argv, - "a:b:c:dfHh:I:i:l:mnNp:qRS:s:tvwW" ADDOPTS)) != -1) { + "a:b:c:dfHg:h:I:i:l:mnNp:qS:s:tvwW" ADDOPTS)) != -1) { #undef ADDOPTS switch (ch) { case 'a': @@ -377,7 +390,13 @@ main(argc, argv) } case 'b': #if defined(SO_SNDBUF) && defined(SO_RCVBUF) - sockbufsize = atoi(optarg); + errno = 0; + e = NULL; + lsockbufsize = strtoul(optarg, &e, 10); + sockbufsize = lsockbufsize; + if (errno || !*optarg || *e || + sockbufsize != lsockbufsize) + errx(1, "invalid socket buffer size"); #else errx(1, "-b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported"); @@ -393,16 +412,23 @@ main(argc, argv) options |= F_SO_DEBUG; break; case 'f': - if (getuid()) - errx(1, "must be superuser to flood ping"); + if (getuid()) { + errno = EPERM; + errx(1, "Must be superuser to flood ping"); + } options |= F_FLOOD; setbuf(stdout, (char *)NULL); break; + case 'g': + gateway = optarg; + break; case 'H': options |= F_HOSTNAME; break; case 'h': /* hoplimit */ hoplimit = strtol(optarg, &e, 10); + if (*optarg == '\0' || *e != '\0') + errx(1, "illegal hoplimit %s", optarg); if (255 < hoplimit || hoplimit < -1) errx(1, "illegal hoplimit -- %s", optarg); @@ -435,15 +461,17 @@ main(argc, argv) options |= F_INTERVAL; break; case 'l': - if (getuid()) - errx(1, "must be superuser to preload"); + if (getuid()) { + errno = EPERM; + errx(1, "Must be superuser to preload"); + } preload = strtol(optarg, &e, 10); if (preload < 0 || *optarg == '\0' || *e != '\0') errx(1, "illegal preload value -- %s", optarg); break; case 'm': #ifdef IPV6_USE_MIN_MTU - options |= F_NOMINMTU; + mflag++; break; #else errx(1, "-%c is not supported on this platform", ch); @@ -462,19 +490,26 @@ main(argc, argv) case 'q': options |= F_QUIET; break; - case 'R': -#ifdef IPV6_REACHCONF - options |= F_REACHCONF; - break; -#else - errx(1, "-R is not supported in this configuration"); -#endif case 'S': - /* XXX: use getaddrinfo? */ - if (inet_pton(AF_INET6, optarg, (void *)&srcaddr) != 1) - errx(1, "invalid IPv6 address: %s", optarg); + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_NUMERICHOST; /* allow hostname? */ + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_RAW; + hints.ai_protocol = IPPROTO_ICMPV6; + + ret_ga = getaddrinfo(optarg, NULL, &hints, &res); + if (ret_ga) { + errx(1, "invalid source address: %s", + gai_strerror(ret_ga)); + } + /* + * res->ai_family must be AF_INET6 and res->ai_addrlen + * must be sizeof(src). + */ + memcpy(&src, res->ai_addr, res->ai_addrlen); + srclen = res->ai_addrlen; + freeaddrinfo(res); options |= F_SRCADDR; - usepktinfo++; break; case 's': /* size of packet to send */ datalen = strtol(optarg, &e, 10); @@ -528,6 +563,7 @@ main(argc, argv) /*NOTREACHED*/ } } + argc -= optind; argv += optind; @@ -560,7 +596,7 @@ main(argc, argv) target = argv[argc - 1]; /* getaddrinfo */ - bzero(&hints, sizeof(struct addrinfo)); + memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_CANONNAME; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_RAW; @@ -583,6 +619,38 @@ main(argc, argv) res->ai_protocol)) < 0) err(1, "socket"); + /* set the source address if specified. */ + if ((options & F_SRCADDR) && + bind(s, (struct sockaddr *)&src, srclen) != 0) { + err(1, "bind"); + } + + /* 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; + + error = getaddrinfo(gateway, NULL, &hints, &gres); + if (error) { + errx(1, "getaddrinfo for the gateway %s: %s", + gateway, gai_strerror(error)); + } + if (gres->ai_next && (options & F_VERBOSE)) + warnx("gateway resolves to multiple addresses"); + + if (setsockopt(s, IPPROTO_IPV6, IPV6_NEXTHOP, + gres->ai_addr, gres->ai_addrlen)) { + err(1, "setsockopt(IPV6_NEXTHOP)"); + } + + freeaddrinfo(gres); + } + /* * let the kerel pass extension headers of incoming packets, * for privileged socket options @@ -619,11 +687,11 @@ main(argc, argv) seteuid(getuid()); setuid(getuid()); - if (options & F_FLOOD && options & F_INTERVAL) + if ((options & F_FLOOD) && (options & F_INTERVAL)) errx(1, "-f and -i incompatible options"); if ((options & F_NOUSERDATA) == 0) { - if (datalen >= sizeof(struct timeval)) { + if (datalen >= sizeof(struct tv32)) { /* we can time transfer */ timing = 1; } else @@ -641,15 +709,15 @@ main(argc, argv) } if (!(packet = (u_char *)malloc((u_int)packlen))) - errx(1, "unable to allocate packet"); + err(1, "Unable to allocate packet"); if (!(options & F_PINGFILLED)) for (i = ICMP6ECHOLEN; i < packlen; ++i) *datap++ = i; ident = getpid() & 0xFFFF; -#ifndef __OpenBSD__ - gettimeofday(&timeout, NULL); - srand((unsigned int)(timeout.tv_sec ^ timeout.tv_usec ^ (long)ident)); +#ifndef HAVE_ARC4RANDOM + gettimeofday(&seed, NULL); + srand((unsigned int)(seed.tv_sec ^ seed.tv_usec ^ (long)ident)); memset(nonce, 0, sizeof(nonce)); for (i = 0; i < sizeof(nonce); i += sizeof(int)) *((int *)&nonce[i]) = rand(); @@ -670,8 +738,9 @@ main(argc, argv) &optval, sizeof(optval)) == -1) err(1, "IPV6_MULTICAST_HOPS"); #ifdef IPV6_USE_MIN_MTU - if ((options & F_NOMINMTU) == 0) { - optval = 1; + if (mflag != 1) { + optval = mflag > 1 ? 0 : 1; + if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &optval, sizeof(optval)) == -1) err(1, "setsockopt(IPV6_USE_MIN_MTU)"); @@ -765,11 +834,6 @@ main(argc, argv) if (hoplimit != -1) ip6optlen += CMSG_SPACE(sizeof(int)); -#ifdef IPV6_REACHCONF - if (options & F_REACHCONF) - ip6optlen += CMSG_SPACE(0); -#endif - /* set IP6 packet options */ if (ip6optlen) { if ((scmsg = (char *)malloc(ip6optlen)) == 0) @@ -798,10 +862,6 @@ main(argc, argv) errx(1, "%s: invalid interface name", ifname); #endif } - /* set the source address */ - if (options & F_SRCADDR)/* pktinfo must be valid */ - pktinfo->ipi6_addr = srcaddr; - if (hoplimit != -1) { scmsgp->cmsg_len = CMSG_LEN(sizeof(int)); scmsgp->cmsg_level = IPPROTO_IPV6; @@ -810,15 +870,6 @@ main(argc, argv) scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); } -#ifdef IPV6_REACHCONF - if (options & F_REACHCONF) { - scmsgp->cmsg_len = CMSG_LEN(0); - scmsgp->cmsg_level = IPPROTO_IPV6; - scmsgp->cmsg_type = IPV6_REACHCONF; - - scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); - } -#endif if (argc > 1) { /* some intermediate addrs are specified */ int hops, error; @@ -873,11 +924,13 @@ main(argc, argv) scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); } - { + if (!(options & F_SRCADDR)) { /* - * source selection + * get the source address. XXX since we revoked the root + * privilege, we cannot use a raw socket for this. */ - int dummy, len = sizeof(src); + int dummy; + socklen_t len = sizeof(src); if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) err(1, "UDP socket"); @@ -894,9 +947,14 @@ main(argc, argv) err(1, "UDP setsockopt(IPV6_PKTINFO)"); if (hoplimit != -1 && - setsockopt(dummy, IPPROTO_IPV6, IPV6_HOPLIMIT, + setsockopt(dummy, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (void *)&hoplimit, sizeof(hoplimit))) - err(1, "UDP setsockopt(IPV6_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 (rthdr && setsockopt(dummy, IPPROTO_IPV6, IPV6_RTHDR, @@ -984,15 +1042,17 @@ main(argc, argv) itimer.it_interval = interval; itimer.it_value = interval; (void)setitimer(ITIMER_REAL, &itimer, NULL); - if (ntransmitted == 0) + if (ntransmitted) retransmit(); } +#ifndef HAVE_POLL_H fdmasks = howmany(s + 1, NFDBITS) * sizeof(fd_mask); if ((fdmaskp = malloc(fdmasks)) == NULL) err(1, "malloc"); +#endif - signo = seenalrm = seenint = 0; + seenalrm = seenint = 0; #ifdef SIGINFO seeninfo = 0; #endif @@ -1024,24 +1084,42 @@ main(argc, argv) if (options & F_FLOOD) { (void)pinger(); +#ifdef HAVE_POLL_H + timeout = 10; +#else timeout.tv_sec = 0; timeout.tv_usec = 10000; tv = &timeout; - } else +#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; - fromlen = sizeof(from); m.msg_name = (caddr_t)&from; m.msg_namelen = sizeof(from); memset(&iov, 0, sizeof(iov)); @@ -1073,7 +1151,6 @@ main(argc, argv) printf("new path MTU (%d) is " "notified\n", mtu); } - set_pathmtu(mtu); } continue; } else { @@ -1093,7 +1170,7 @@ void onsignal(sig) int sig; { - signo = sig; + switch (sig) { case SIGALRM: seenalrm++; @@ -1245,9 +1322,14 @@ pinger() icp->icmp6_code = 0; icp->icmp6_id = htons(ident); icp->icmp6_seq = ntohs(seq); - if (timing) - (void)gettimeofday((struct timeval *) - &outpack[ICMP6ECHOLEN], NULL); + if (timing) { + struct timeval tv; + struct tv32 *tv32; + (void)gettimeofday(&tv, NULL); + tv32 = (struct tv32 *)&outpack[ICMP6ECHOLEN]; + tv32->tv32_sec = htonl(tv.tv_sec); + tv32->tv32_usec = htonl(tv.tv_usec); + } cc = ICMP6ECHOLEN + datalen; } @@ -1305,7 +1387,7 @@ dnsdecode(sp, ep, base, buf, bufsiz) const u_char **sp; const u_char *ep; const u_char *base; /*base for compressed name*/ - u_char *buf; + char *buf; size_t bufsiz; { int i; @@ -1322,7 +1404,7 @@ dnsdecode(sp, ep, base, buf, bufsiz) while (cp < ep) { i = *cp; if (i == 0 || cp != *sp) { - if (strlcat(buf, ".", bufsiz) >= bufsiz) + if (strlcat((char *)buf, ".", bufsiz) >= bufsiz) return NULL; /*result overrun*/ } if (i == 0) @@ -1347,7 +1429,7 @@ dnsdecode(sp, ep, base, buf, bufsiz) while (i-- > 0 && cp < ep) { l = snprintf(cresult, sizeof(cresult), isprint(*cp) ? "%c" : "\\%03o", *cp & 0xff); - if (l < 0 || l >= sizeof(cresult)) + if (l >= sizeof(cresult) || l < 0) return NULL; if (strlcat(buf, cresult, bufsiz) >= bufsiz) return NULL; /*result overrun*/ @@ -1385,7 +1467,8 @@ pr_pack(buf, cc, mhdr) int fromlen; u_char *cp = NULL, *dp, *end = buf + cc; struct in6_pktinfo *pktinfo = NULL; - struct timeval tv, *tp; + struct timeval tv, tp; + struct tv32 *tpp; double triptime = 0; int dupflag; size_t off; @@ -1399,7 +1482,7 @@ pr_pack(buf, cc, mhdr) mhdr->msg_namelen != sizeof(struct sockaddr_in6) || ((struct sockaddr *)mhdr->msg_name)->sa_family != AF_INET6) { if (options & F_VERBOSE) - warnx("invalid peername\n"); + warnx("invalid peername"); return; } from = (struct sockaddr *)mhdr->msg_name; @@ -1427,14 +1510,14 @@ pr_pack(buf, cc, mhdr) seq = ntohs(icp->icmp6_seq); ++nreceived; if (timing) { - tp = (struct timeval *)(icp + 1); - tvsub(&tv, tp); + tpp = (struct tv32 *)(icp + 1); + tp.tv_sec = ntohl(tpp->tv32_sec); + tp.tv_usec = ntohl(tpp->tv32_usec); + tvsub(&tv, &tp); triptime = ((double)tv.tv_sec) * 1000.0 + ((double)tv.tv_usec) / 1000.0; tsum += triptime; -#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) tsumsq += triptime * triptime; -#endif if (triptime < tmin) tmin = triptime; if (triptime > tmax) @@ -1464,9 +1547,7 @@ pr_pack(buf, cc, mhdr) memset(&dstsa, 0, sizeof(dstsa)); dstsa.sin6_family = AF_INET6; -#ifdef SIN6_LEN dstsa.sin6_len = sizeof(dstsa); -#endif dstsa.sin6_scope_id = pktinfo->ipi6_ifindex; dstsa.sin6_addr = pktinfo->ipi6_addr; (void)printf(" dst=%s", @@ -1767,7 +1848,7 @@ pr_rthdr(void *extbuf) else { if (!inet_ntop(AF_INET6, in6, ntopbuf, sizeof(ntopbuf))) - strncpy(ntopbuf, "?", sizeof(ntopbuf)); + strlcpy(ntopbuf, "?", sizeof(ntopbuf)); printf(" [%d]%s\n", i, ntopbuf); } } @@ -1787,9 +1868,9 @@ pr_rthdr(void *extbuf) #endif /* USE_RFC2292BIS */ int -pr_bitrange(v, s, ii) +pr_bitrange(v, soff, ii) u_int32_t v; - int s; + int soff; int ii; { int off; @@ -1800,7 +1881,7 @@ pr_bitrange(v, s, ii) /* shift till we have 0x01 */ if ((v & 0x01) == 0) { if (ii > 1) - printf("-%u", s + off - 1); + printf("-%u", soff + off - 1); ii = 0; switch (v & 0x0f) { case 0x00: @@ -1828,7 +1909,7 @@ pr_bitrange(v, s, ii) break; } if (!ii) - printf(" %u", s + off); + printf(" %u", soff + off); ii += i; v >>= i; off += i; } @@ -1949,7 +2030,7 @@ pr_nodeaddr(ni, nilen) if (inet_ntop(AF_INET6, cp, ntop_buf, sizeof(ntop_buf)) == NULL) - strncpy(ntop_buf, "?", sizeof(ntop_buf)); + strlcpy(ntop_buf, "?", sizeof(ntop_buf)); printf(" %s", ntop_buf); if (withttl) { if (ttl == 0xffffffff) { @@ -2065,60 +2146,6 @@ get_pathmtu(mhdr) return(0); } -void -set_pathmtu(mtu) - int mtu; -{ -#ifdef IPV6_USE_MTU - static int firsttime = 1; - struct cmsghdr *cm; - - if (firsttime) { - int oldlen = smsghdr.msg_controllen; - char *oldbuf = smsghdr.msg_control; - - /* XXX: We need to enlarge control message buffer */ - firsttime = 0; /* prevent further enlargement */ - - smsghdr.msg_controllen = oldlen + CMSG_SPACE(sizeof(int)); - if ((smsghdr.msg_control = - (char *)malloc(smsghdr.msg_controllen)) == NULL) - err(1, "set_pathmtu: malloc"); - cm = (struct cmsghdr *)CMSG_FIRSTHDR(&smsghdr); - cm->cmsg_len = CMSG_LEN(sizeof(int)); - cm->cmsg_level = IPPROTO_IPV6; - cm->cmsg_type = IPV6_USE_MTU; - - cm = (struct cmsghdr *)CMSG_NXTHDR(&smsghdr, cm); - if (oldlen) - memcpy((void *)cm, (void *)oldbuf, oldlen); - - free(oldbuf); - } - - /* - * look for a cmsgptr that points MTU structure. - * XXX: this procedure seems redundant at this moment, but we'd better - * keep the code generic enough for future extensions. - */ - for (cm = CMSG_FIRSTHDR(&smsghdr); cm; - cm = (struct cmsghdr *)CMSG_NXTHDR(&smsghdr, cm)) { - if (cm->cmsg_len == 0) /* XXX: paranoid check */ - errx(1, "set_pathmtu: internal error"); - - if (cm->cmsg_level == IPPROTO_IPV6 && - cm->cmsg_type == IPV6_USE_MTU && - cm->cmsg_len == CMSG_LEN(sizeof(int))) - break; - } - - if (cm == NULL) - errx(1, "set_pathmtu: internal error: no space for path MTU"); - - *(int *)CMSG_DATA(cm) = mtu; -#endif -} - /* * tvsub -- * Subtract 2 timeval structs: out = out - in. Out is assumed to @@ -2144,12 +2171,13 @@ void onint(notused) int notused; { - (void)signal(SIGINT, SIG_IGN); - (void)signal(SIGALRM, SIG_IGN); - summary(); - exit(nreceived == 0); + (void)signal(SIGINT, SIG_DFL); + (void)kill(getpid(), SIGINT); + + /* NOTREACHED */ + exit(1); } /* @@ -2167,10 +2195,10 @@ summary() (void)printf("+%ld duplicates, ", nrepeats); if (ntransmitted) { if (nreceived > ntransmitted) - (void)printf("-- somebody's printing up packets!"); + (void)printf("-- somebody's duplicating packets!"); else - (void)printf("%d%% packet loss", - (int) (((ntransmitted - nreceived) * 100) / + (void)printf("%.1f%% packet loss", + ((((double)ntransmitted - nreceived) * 100.0) / ntransmitted)); } (void)putchar('\n'); @@ -2178,30 +2206,24 @@ summary() /* Only display average to microseconds */ double num = nreceived + nrepeats; double avg = tsum / num; -#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) double dev = sqrt(tsumsq / num - avg * avg); (void)printf( "round-trip min/avg/max/std-dev = %.3f/%.3f/%.3f/%.3f ms\n", tmin, avg, tmax, dev); -#else - (void)printf( - "round-trip min/avg/max = %.3f/%.3f/%.3f ms\n", - tmin, avg, tmax); -#endif (void)fflush(stdout); } (void)fflush(stdout); } /*subject type*/ -static char *niqcode[] = { +static const char *niqcode[] = { "IPv6 address", "DNS label", /*or empty*/ "IPv4 address", }; /*result code*/ -static char *nircode[] = { +static const char *nircode[] = { "Success", "Refused", "Unknown", }; @@ -2323,11 +2345,11 @@ pr_icmph(icp, end) (void)printf("Redirect\n"); if (!inet_ntop(AF_INET6, &red->nd_rd_dst, ntop_buf, sizeof(ntop_buf))) - strncpy(ntop_buf, "?", sizeof(ntop_buf)); + strlcpy(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)); + strlcpy(ntop_buf, "?", sizeof(ntop_buf)); (void)printf(" New Target: %s", ntop_buf); break; case ICMP6_NI_QUERY: @@ -2459,10 +2481,10 @@ pr_iph(ip6) (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)); + strlcpy(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)); + strlcpy(ntop_buf, "?", sizeof(ntop_buf)); printf("%s\n", ntop_buf); } @@ -2594,7 +2616,7 @@ fill(bp, patp) /* xxx */ if (ii > 0) for (kk = 0; - kk <= MAXDATALEN - (8 + sizeof(struct timeval) + ii); + kk <= MAXDATALEN - (8 + sizeof(struct tv32) + ii); kk += ii) for (jj = 0; jj < ii; ++jj) bp[jj + kk] = pat[jj]; @@ -2623,7 +2645,7 @@ setpolicy(so, policy) errx(1, "%s", ipsec_strerror()); if (setsockopt(s, IPPROTO_IPV6, IPV6_IPSEC_POLICY, buf, ipsec_get_policylen(buf)) < 0) - warnx("unable to set IPSec policy"); + warnx("Unable to set IPsec policy"); free(buf); return 0; @@ -2636,7 +2658,7 @@ nigroup(name) char *name; { char *p; - unsigned char *q; + char *q; MD5_CTX ctxt; u_int8_t digest[16]; u_int8_t c; @@ -2654,16 +2676,16 @@ nigroup(name) hbuf[(int)l] = '\0'; for (q = name; *q; q++) { - if (isupper(*q)) - *q = tolower(*q); + if (isupper(*(unsigned char *)q)) + *q = tolower(*(unsigned char *)q); } /* generate 8 bytes of pseudo-random value. */ - bzero(&ctxt, sizeof(ctxt)); + memset(&ctxt, 0, sizeof(ctxt)); MD5Init(&ctxt); c = l & 0xff; MD5Update(&ctxt, &c, sizeof(c)); - MD5Update(&ctxt, name, l); + MD5Update(&ctxt, (unsigned char *)name, l); MD5Final(digest, &ctxt); if (inet_pton(AF_INET6, "ff02::2:0000:0000", &in6) != 1) @@ -2685,9 +2707,6 @@ usage() "m" #endif "nNqtvwW" -#ifdef IPV6_REACHCONF - "R" -#endif #ifdef IPSEC #ifdef IPSEC_POLICY_IPSEC "] [-P policy" @@ -2695,9 +2714,9 @@ usage() "AE" #endif #endif - "] [-a [aAclsg]] [-b sockbufsiz] [-c count]\n" + "] [-a [aAclsg]] [-b sockbufsiz] [-c count] \n" "\t[-I interface] [-i wait] [-l preload] [-p pattern] " "[-S sourceaddr]\n" - "\t[-s packetsize] [-h hoplimit] [hops...] host\n"); + "\t[-s packetsize] [-h hoplimit] [hops...] [-g gateway] host\n"); exit(1); } |