Index: sbin/ping6/Makefile =================================================================== --- sbin/ping6/Makefile +++ sbin/ping6/Makefile @@ -4,6 +4,7 @@ PACKAGE=runtime PROG= ping6 +SRCS= ping6.c options.c MAN= ping6.8 CFLAGS+=-DIPSEC -DKAME_SCOPEID Index: sbin/ping6/options.h =================================================================== --- /dev/null +++ sbin/ping6/options.h @@ -0,0 +1,163 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (C) 2019 Jan Sucan + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* $KAME: ping6.c,v 1.169 2003/07/25 06:01:47 itojun Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * 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. + */ + +/* BSDI ping.c,v 2.3 1996/01/21 17:56:50 jch Exp */ + +/* + * 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. + */ + +/* $FreeBSD$ */ + +#ifndef OPTIONS_H +#define OPTIONS_H 1 + +#include + +#include +#include + +#include + +#define F_FLOOD 0x0001 +#define F_INTERVAL 0x0002 +#define F_PINGFILLED 0x0008 +#define F_QUIET 0x0010 +#define F_RROUTE 0x0020 +#define F_SO_DEBUG 0x0040 +#define F_VERBOSE 0x0100 +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC +#define F_POLICY 0x0400 +#else +#define F_AUTHHDR 0x0200 +#define F_ENCRYPT 0x0400 +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ +#define F_NODEADDR 0x0800 +#define F_FQDN 0x1000 +#define F_INTERFACE 0x2000 +#define F_SRCADDR 0x4000 +#define F_HOSTNAME 0x10000 +#define F_FQDNOLD 0x20000 +#define F_NIGROUP 0x40000 +#define F_SUPTYPES 0x80000 +#define F_NOMINMTU 0x100000 +#define F_ONCE 0x200000 +#define F_AUDIBLE 0x400000 +#define F_MISSED 0x800000 +#define F_DONTFRAG 0x1000000 +#define F_NOUSERDATA (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES) +#define F_WAITTIME 0x2000000 + +/* Options that are counted or have an argument. */ +struct options_processed { + char *arg_addrtype; + char *arg_interface; + char *arg_gateway; + char *arg_hoplimit; + char *arg_interval; + char *arg_ipsec_policy; + char *arg_packet_count; + char *arg_packet_size; + char *arg_pattern; + char *arg_preload; + char *arg_sock_buff_size; + char *arg_source_address; + char *arg_timeout; + char *arg_wait_time; + unsigned int count_interface; + unsigned int count_nigroup; + unsigned int count_use_min_mtu; +}; + +bool options_parse(int argc, char *argv[], + struct options_processed *const opts, u_int *const flags); + +#endif Index: sbin/ping6/options.c =================================================================== --- /dev/null +++ sbin/ping6/options.c @@ -0,0 +1,265 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (C) 2019 Jan Sucan + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* $KAME: ping6.c,v 1.169 2003/07/25 06:01:47 itojun Exp $ */ + +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * 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. + */ + +/* BSDI ping.c,v 2.3 1996/01/21 17:56:50 jch Exp */ + +/* + * 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. + */ + +#if 0 +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ +#endif + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include "options.h" + +#ifndef IPSEC +#define ADDOPTS +#else +#ifdef IPSEC_POLICY_IPSEC +#define ADDOPTS "P:" +#else +#define ADDOPTS "ZE" +#endif /*IPSEC_POLICY_IPSEC*/ +#endif + +bool +options_parse(int argc, char *argv[], + struct options_processed *const opts, u_int *const flags) +{ + int ch; + + memset(opts, 0, sizeof(*opts)); + + while ((ch = getopt(argc, argv, + "k:b:c:DdfHe:m:I:i:l:unNop:qaAS:s:OvyYW:t:" ADDOPTS)) != -1) { + switch (ch) { + case 'k': + *flags &= ~F_NOUSERDATA; + *flags |= F_NODEADDR; + opts->arg_addrtype = optarg; + break; + case 'b': +#if defined(SO_SNDBUF) && defined(SO_RCVBUF) + opts->arg_sock_buff_size = optarg; + break; +#else + errx(1, "-b option ignored: SO_SNDBUF/SO_RCVBUF socket" + "options not supported"); + /*NOTREACHED*/ +#endif + case 'c': + opts->arg_packet_count = optarg; + break; + case 'D': + *flags |= F_DONTFRAG; + break; + case 'd': + *flags |= F_SO_DEBUG; + break; + case 'f': + *flags |= F_FLOOD; + break; + case 'e': + opts->arg_gateway = optarg; + break; + case 'H': + *flags |= F_HOSTNAME; + break; + case 'm': + opts->arg_hoplimit = optarg; + break; + case 'I': + *flags |= F_INTERFACE; + opts->arg_interface = optarg; + (opts->count_interface)++; + break; + case 'i': + *flags |= F_INTERVAL; + opts->arg_interval = optarg; + break; + case 'l': + opts->arg_preload = optarg; + break; + case 'u': +#ifdef IPV6_USE_MIN_MTU + (opts->count_use_min_mtu)++; + break; +#else + errx(1, "-u is not supported on this platform"); + /*NOTREACHED*/ +#endif + case 'n': + *flags &= ~F_HOSTNAME; + break; + case 'N': + *flags |= F_NIGROUP; + (opts->count_nigroup)++; + break; + case 'o': + *flags |= F_ONCE; + break; + case 'p': + *flags |= F_PINGFILLED; + opts->arg_pattern = optarg; + break; + case 'q': + *flags |= F_QUIET; + break; + case 'a': + *flags |= F_AUDIBLE; + break; + case 'A': + *flags |= F_MISSED; + break; + case 'S': + *flags |= F_SRCADDR; + opts->arg_source_address = optarg; + break; + case 's': + opts->arg_packet_size = optarg; + break; + case 'O': + *flags &= ~F_NOUSERDATA; + *flags |= F_SUPTYPES; + break; + case 'v': + *flags |= F_VERBOSE; + break; + case 'y': + *flags &= ~F_NOUSERDATA; + *flags |= F_FQDN; + break; + case 'Y': + *flags &= ~F_NOUSERDATA; + *flags |= F_FQDNOLD; + break; + case 'W': + *flags |= F_WAITTIME; + opts->arg_wait_time = optarg; + break; + case 't': + opts->arg_timeout = optarg; + break; +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC + case 'P': + *flags |= F_POLICY; + opts->arg_ipsec_policy = optarg; + break; +#else + case 'Z': + *flags |= F_AUTHHDR; + break; + case 'E': + *flags |= F_ENCRYPT; + break; +#endif /*IPSEC_POLICY_IPSEC*/ +#endif /*IPSEC*/ + default: + return (false); + } + } + + return (true); +} Index: sbin/ping6/ping6.c =================================================================== --- sbin/ping6/ping6.c +++ sbin/ping6/ping6.c @@ -142,6 +142,8 @@ #include +#include "options.h" + struct tv32 { u_int32_t tv32_sec; u_int32_t tv32_nsec; @@ -168,36 +170,6 @@ #define CLR(bit) (A(bit) &= (~B(bit))) #define TST(bit) (A(bit) & B(bit)) -#define F_FLOOD 0x0001 -#define F_INTERVAL 0x0002 -#define F_PINGFILLED 0x0008 -#define F_QUIET 0x0010 -#define F_RROUTE 0x0020 -#define F_SO_DEBUG 0x0040 -#define F_VERBOSE 0x0100 -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC -#define F_POLICY 0x0400 -#else -#define F_AUTHHDR 0x0200 -#define F_ENCRYPT 0x0400 -#endif /*IPSEC_POLICY_IPSEC*/ -#endif /*IPSEC*/ -#define F_NODEADDR 0x0800 -#define F_FQDN 0x1000 -#define F_INTERFACE 0x2000 -#define F_SRCADDR 0x4000 -#define F_HOSTNAME 0x10000 -#define F_FQDNOLD 0x20000 -#define F_NIGROUP 0x40000 -#define F_SUPTYPES 0x80000 -#define F_NOMINMTU 0x100000 -#define F_ONCE 0x200000 -#define F_AUDIBLE 0x400000 -#define F_MISSED 0x800000 -#define F_DONTFRAG 0x1000000 -#define F_NOUSERDATA (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES) -#define F_WAITTIME 0x2000000 static u_int options; #define IN6LEN sizeof(struct in6_addr) @@ -299,8 +271,9 @@ struct sockaddr_in6 from, *sin6; struct addrinfo hints, *res; struct sigaction si_sa; + struct options_processed opts; int cc, i; - int almost_done, ch, hold, packlen, preload, optval, error; + int almost_done, hold, packlen, preload, optval, error; int nig_oldmcprefix = -1; u_char *datap; char *e, *target, *ifname = NULL, *gateway = NULL; @@ -341,268 +314,186 @@ alarmtimeout = preload = 0; datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN]; capdns = capdns_setup(); -#ifndef IPSEC -#define ADDOPTS -#else -#ifdef IPSEC_POLICY_IPSEC -#define ADDOPTS "P:" -#else -#define ADDOPTS "ZE" -#endif /*IPSEC_POLICY_IPSEC*/ -#endif - while ((ch = getopt(argc, argv, - "k:b:c:DdfHe:m:I:i:l:unNop:qaAS:s:OvyYW:t:" ADDOPTS)) != -1) { -#undef ADDOPTS - switch (ch) { - case 'k': - { - char *cp; - - options &= ~F_NOUSERDATA; - options |= F_NODEADDR; - for (cp = optarg; *cp != '\0'; cp++) { - switch (*cp) { - case 'a': - naflags |= NI_NODEADDR_FLAG_ALL; - break; - case 'c': - case 'C': - naflags |= NI_NODEADDR_FLAG_COMPAT; - break; - case 'l': - case 'L': - naflags |= NI_NODEADDR_FLAG_LINKLOCAL; - break; - case 's': - case 'S': - naflags |= NI_NODEADDR_FLAG_SITELOCAL; - break; - case 'g': - case 'G': - naflags |= NI_NODEADDR_FLAG_GLOBAL; - break; - case 'A': /* experimental. not in the spec */ + + if (!options_parse(argc, argv, &opts, &options)) + usage(); + /* NOTREACHED */ + + if ((options & F_NODEADDR) != 0) { + char *cp; + + for (cp = opts.arg_addrtype; *cp != '\0'; cp++) { + switch (*cp) { + case 'a': + naflags |= NI_NODEADDR_FLAG_ALL; + break; + case 'c': + case 'C': + naflags |= NI_NODEADDR_FLAG_COMPAT; + break; + case 'l': + case 'L': + naflags |= NI_NODEADDR_FLAG_LINKLOCAL; + break; + case 's': + case 'S': + naflags |= NI_NODEADDR_FLAG_SITELOCAL; + break; + case 'g': + case 'G': + naflags |= NI_NODEADDR_FLAG_GLOBAL; + break; + case 'A': /* experimental. not in the spec */ #ifdef NI_NODEADDR_FLAG_ANYCAST - naflags |= NI_NODEADDR_FLAG_ANYCAST; - break; + naflags |= NI_NODEADDR_FLAG_ANYCAST; + break; #else - errx(1, -"-a A is not supported on the platform"); - /*NOTREACHED*/ + errx(1, + "-a A is not supported on the platform"); + /*NOTREACHED*/ #endif - default: - usage(); - /*NOTREACHED*/ - } + default: + usage(); + /*NOTREACHED*/ } - break; } - case 'b': -#if defined(SO_SNDBUF) && defined(SO_RCVBUF) - errno = 0; - e = NULL; - lsockbufsize = strtoul(optarg, &e, 10); - sockbufsize = (int)lsockbufsize; - if (errno || !*optarg || *e || - lsockbufsize > INT_MAX) - errx(1, "invalid socket buffer size"); -#else + } + if (opts.arg_sock_buff_size != NULL) { + errno = 0; + e = NULL; + lsockbufsize = strtoul(opts.arg_sock_buff_size, &e, 10); + sockbufsize = (int)lsockbufsize; + if (errno || !*opts.arg_sock_buff_size || *e || + lsockbufsize > INT_MAX) + errx(1, "invalid socket buffer size"); + } + if (opts.arg_packet_count != NULL) { + npackets = strtol(opts.arg_packet_count, &e, 10); + if (npackets <= 0 || *opts.arg_packet_count == '\0' || + *e != '\0') errx(1, -"-b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported"); -#endif - break; - case 'c': - npackets = strtol(optarg, &e, 10); - if (npackets <= 0 || *optarg == '\0' || *e != '\0') - errx(1, - "illegal number of packets -- %s", optarg); - break; - case 'D': - options |= F_DONTFRAG; - break; - case 'd': - options |= F_SO_DEBUG; - break; - case 'f': - if (getuid()) { - errno = EPERM; - errx(1, "Must be superuser to flood ping"); - } - options |= F_FLOOD; - setbuf(stdout, (char *)NULL); - break; - case 'e': - gateway = optarg; - break; - case 'H': - options |= F_HOSTNAME; - break; - case 'm': /* 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); - break; - case 'I': - ifname = optarg; - options |= F_INTERFACE; + "illegal number of packets -- %s", + opts.arg_packet_count); + } + if ((options & F_FLOOD) != 0) { + if (getuid()) { + errno = EPERM; + errx(1, "Must be superuser to flood ping"); + } + setbuf(stdout, (char *)NULL); + } + if (opts.arg_gateway != NULL) + gateway = opts.arg_gateway; + if (opts.arg_hoplimit != NULL) { + hoplimit = strtol(opts.arg_hoplimit, &e, 10); + if (*opts.arg_hoplimit == '\0' || *e != '\0') + errx(1, "illegal hoplimit %s", opts.arg_hoplimit); + if (255 < hoplimit || hoplimit < -1) + errx(1, + "illegal hoplimit -- %s", opts.arg_hoplimit); + } + if ((options & F_INTERFACE) != 0) { + ifname = opts.arg_interface; #ifndef USE_SIN6_SCOPE_ID - usepktinfo++; + usepktinfo += opts.count_interface; #endif - break; - case 'i': /* wait between sending packets */ - t = strtod(optarg, &e); - if (*optarg == '\0' || *e != '\0') - errx(1, "illegal timing interval %s", optarg); - if (t < 1 && getuid()) { - errx(1, "%s: only root may use interval < 1s", - strerror(EPERM)); - } - intvl.tv_sec = (time_t)t; - intvl.tv_nsec = - (long)((t - intvl.tv_sec) * 1000000000); - if (intvl.tv_sec < 0) - errx(1, "illegal timing interval %s", optarg); - /* less than 1/hz does not make sense */ - if (intvl.tv_sec == 0 && intvl.tv_nsec < 1000) { - warnx("too small interval, raised to .000001"); - intvl.tv_nsec = 1000; - } - options |= F_INTERVAL; - break; - case 'l': - 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 'u': -#ifdef IPV6_USE_MIN_MTU - mflag++; - break; -#else - errx(1, "-%c is not supported on this platform", ch); - /*NOTREACHED*/ -#endif - case 'n': - options &= ~F_HOSTNAME; - break; - case 'N': - options |= F_NIGROUP; - nig_oldmcprefix++; - break; - case 'o': - options |= F_ONCE; - break; - case 'p': /* fill buffer with user pattern */ - options |= F_PINGFILLED; - fill((char *)datap, optarg); - break; - case 'q': - options |= F_QUIET; - break; - case 'a': - options |= F_AUDIBLE; - break; - case 'A': - options |= F_MISSED; - break; - case 'S': - 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; + } + if ((options & F_INTERVAL) != 0) { + t = strtod(opts.arg_interval, &e); + if (*opts.arg_interval == '\0' || *e != '\0') + errx(1, "illegal timing interval %s", opts.arg_interval); + if (t < 1 && getuid()) { + errx(1, "%s: only root may use interval < 1s", + strerror(EPERM)); + } + intvl.tv_sec = (time_t)t; + intvl.tv_nsec = + (long)((t - intvl.tv_sec) * 1000000000); + if (intvl.tv_sec < 0) + errx(1, "illegal timing interval %s", opts.arg_interval); + /* less than 1/hz does not make sense */ + if (intvl.tv_sec == 0 && intvl.tv_nsec < 1000) { + warnx("too small interval, raised to .000001"); + intvl.tv_nsec = 1000; + } + } + if (opts.arg_preload != NULL) { + if (getuid()) { + errno = EPERM; + errx(1, "Must be superuser to preload"); + } + preload = strtol(opts.arg_preload, &e, 10); + if (preload < 0 || *opts.arg_preload == '\0' || *e != '\0') + errx(1, "illegal preload value -- %s", + opts.arg_preload); + } + mflag += opts.count_use_min_mtu; + nig_oldmcprefix += opts.count_nigroup; + if ((options & F_PINGFILLED) != 0) + fill((char *)datap, opts.arg_pattern); + if ((options & F_SRCADDR) != 0) { + 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; - error = cap_getaddrinfo(capdns, optarg, NULL, &hints, &res); - if (error) { - errx(1, "invalid source address: %s", - gai_strerror(error)); - } - /* - * 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; - break; - case 's': /* size of packet to send */ - datalen = strtol(optarg, &e, 10); - if (datalen <= 0 || *optarg == '\0' || *e != '\0') - errx(1, "illegal datalen value -- %s", optarg); - if (datalen > MAXDATALEN) { - errx(1, - "datalen value too large, maximum is %d", - MAXDATALEN); - } - break; - case 'O': - options &= ~F_NOUSERDATA; - options |= F_SUPTYPES; - break; - case 'v': - options |= F_VERBOSE; - break; - case 'y': - options &= ~F_NOUSERDATA; - options |= F_FQDN; - break; - case 'Y': - options &= ~F_NOUSERDATA; - options |= F_FQDNOLD; - break; - case 'W': - t = strtod(optarg, &e); - if (*e || e == optarg || t > (double)INT_MAX) - err(EX_USAGE, "invalid timing interval: `%s'", - optarg); - options |= F_WAITTIME; - waittime = (int)t; - break; - case 't': - alarmtimeout = strtoul(optarg, &e, 0); - if ((alarmtimeout < 1) || (alarmtimeout == ULONG_MAX)) - errx(EX_USAGE, "invalid timeout: `%s'", - optarg); - if (alarmtimeout > MAXALARM) - errx(EX_USAGE, "invalid timeout: `%s' > %d", - optarg, MAXALARM); - alarm((int)alarmtimeout); - break; + error = cap_getaddrinfo(capdns, opts.arg_source_address, NULL, + &hints, &res); + if (error) { + errx(1, "invalid source address: %s", + gai_strerror(error)); + } + /* + * 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); + } + if (opts.arg_packet_size != NULL) { + datalen = strtol(opts.arg_packet_size, &e, 10); + if (datalen <= 0 || *opts.arg_packet_size == '\0' || *e != '\0') + errx(1, "illegal datalen value -- %s", + opts.arg_packet_size); + if (datalen > MAXDATALEN) { + errx(1, + "datalen value too large, maximum is %d", + MAXDATALEN); + } + } + if ((options & F_WAITTIME) != 0) { + t = strtod(opts.arg_wait_time, &e); + if (*e || e == opts.arg_wait_time || t > (double)INT_MAX) + err(EX_USAGE, "invalid timing interval: `%s'", + opts.arg_wait_time); + waittime = (int)t; + } + if (opts.arg_timeout != NULL) { + alarmtimeout = strtoul(opts.arg_timeout, &e, 0); + if ((alarmtimeout < 1) || (alarmtimeout == ULONG_MAX)) + errx(EX_USAGE, "invalid timeout: `%s'", + opts.arg_timeout); + if (alarmtimeout > MAXALARM) + errx(EX_USAGE, "invalid timeout: `%s' > %d", + opts.arg_timeout, MAXALARM); + alarm((int)alarmtimeout); + } #ifdef IPSEC #ifdef IPSEC_POLICY_IPSEC - case 'P': - options |= F_POLICY; - if (!strncmp("in", optarg, 2)) { - if ((policy_in = strdup(optarg)) == NULL) - errx(1, "strdup"); - } else if (!strncmp("out", optarg, 3)) { - if ((policy_out = strdup(optarg)) == NULL) - errx(1, "strdup"); - } else - errx(1, "invalid security policy"); - break; -#else - case 'Z': - options |= F_AUTHHDR; - break; - case 'E': - options |= F_ENCRYPT; - break; + if ((options & F_POLICY) != 0) { + if (!strncmp("in", opts.arg_ipsec_policy, 2)) { + if ((policy_in = strdup(opts.arg_ipsec_policy)) == NULL) + errx(1, "strdup"); + } else if (!strncmp("out", opts.arg_ipsec_policy, 3)) { + if ((policy_out = strdup(opts.arg_ipsec_policy)) == NULL) + errx(1, "strdup"); + } else + errx(1, "invalid security policy"); + } #endif /*IPSEC_POLICY_IPSEC*/ #endif /*IPSEC*/ - default: - usage(); - /*NOTREACHED*/ - } - } argc -= optind; argv += optind;