13cde9171SAlan Somers /*- 23cde9171SAlan Somers * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 33cde9171SAlan Somers * 43cde9171SAlan Somers * Copyright (C) 2019 Jan Sucan <jansucan@FreeBSD.org> 53cde9171SAlan Somers * All rights reserved. 63cde9171SAlan Somers * 73cde9171SAlan Somers * Redistribution and use in source and binary forms, with or without 83cde9171SAlan Somers * modification, are permitted provided that the following conditions 93cde9171SAlan Somers * are met: 103cde9171SAlan Somers * 1. Redistributions of source code must retain the above copyright 113cde9171SAlan Somers * notice, this list of conditions and the following disclaimer. 123cde9171SAlan Somers * 2. Redistributions in binary form must reproduce the above copyright 133cde9171SAlan Somers * notice, this list of conditions and the following disclaimer in the 143cde9171SAlan Somers * documentation and/or other materials provided with the distribution. 153cde9171SAlan Somers * 163cde9171SAlan Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 173cde9171SAlan Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 183cde9171SAlan Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 193cde9171SAlan Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 203cde9171SAlan Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 213cde9171SAlan Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 223cde9171SAlan Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 233cde9171SAlan Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 243cde9171SAlan Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 253cde9171SAlan Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 263cde9171SAlan Somers * SUCH DAMAGE. 273cde9171SAlan Somers */ 283cde9171SAlan Somers 293cde9171SAlan Somers #include <sys/cdefs.h> 303cde9171SAlan Somers __FBSDID("$FreeBSD$"); 313cde9171SAlan Somers 323cde9171SAlan Somers #include <sys/types.h> 333cde9171SAlan Somers #include <sys/socket.h> 343cde9171SAlan Somers 353cde9171SAlan Somers #include <arpa/inet.h> 363cde9171SAlan Somers #include <netdb.h> 373cde9171SAlan Somers #include <netinet/in.h> 383cde9171SAlan Somers 393cde9171SAlan Somers #include <err.h> 403cde9171SAlan Somers #include <stdbool.h> 413cde9171SAlan Somers #include <stdio.h> 423cde9171SAlan Somers #include <stdlib.h> 433cde9171SAlan Somers #include <string.h> 443cde9171SAlan Somers #include <unistd.h> 453cde9171SAlan Somers 463cde9171SAlan Somers #include "main.h" 47fd26389bSAlan Somers #ifdef INET 483cde9171SAlan Somers #include "ping.h" 49fd26389bSAlan Somers #endif 503cde9171SAlan Somers #ifdef INET6 513cde9171SAlan Somers #include "ping6.h" 523cde9171SAlan Somers #endif 533cde9171SAlan Somers 54fd26389bSAlan Somers #if defined(INET) && defined(INET6) 559ce201f2SAlan Somers #define OPTSTR PING6OPTS PING4OPTS 56fd26389bSAlan Somers #elif defined(INET) 579ce201f2SAlan Somers #define OPTSTR PING4OPTS 58fd26389bSAlan Somers #elif defined(INET6) 599ce201f2SAlan Somers #define OPTSTR PING6OPTS 60*a4ef9e58SEd Maste #else 61*a4ef9e58SEd Maste #error At least one of INET and INET6 is required 623cde9171SAlan Somers #endif 633cde9171SAlan Somers 643cde9171SAlan Somers int 653cde9171SAlan Somers main(int argc, char *argv[]) 663cde9171SAlan Somers { 67fd26389bSAlan Somers #if defined(INET) && defined(INET6) 683cde9171SAlan Somers struct in_addr a; 693cde9171SAlan Somers struct in6_addr a6; 70fd26389bSAlan Somers #endif 71fd26389bSAlan Somers #if defined(INET) || defined(INET6) 72fd26389bSAlan Somers struct addrinfo hints; 73fd26389bSAlan Somers #endif 74fd26389bSAlan Somers int ch; 75fd26389bSAlan Somers #ifdef INET 76fd26389bSAlan Somers bool ipv4 = false; 77fd26389bSAlan Somers #endif 78fd26389bSAlan Somers #ifdef INET6 79fd26389bSAlan Somers bool ipv6 = false; 803cde9171SAlan Somers 81d2624517SAlan Somers if (strcmp(getprogname(), "ping6") == 0) 82d2624517SAlan Somers ipv6 = true; 833cde9171SAlan Somers #endif 843cde9171SAlan Somers 859ce201f2SAlan Somers while ((ch = getopt(argc, argv, ":" OPTSTR)) != -1) { 863cde9171SAlan Somers switch(ch) { 87fd26389bSAlan Somers #ifdef INET 883cde9171SAlan Somers case '4': 893cde9171SAlan Somers ipv4 = true; 903cde9171SAlan Somers break; 91fd26389bSAlan Somers #endif 923cde9171SAlan Somers #ifdef INET6 933cde9171SAlan Somers case '6': 943cde9171SAlan Somers ipv6 = true; 953cde9171SAlan Somers break; 963cde9171SAlan Somers #endif 973cde9171SAlan Somers default: 983cde9171SAlan Somers break; 993cde9171SAlan Somers } 1003cde9171SAlan Somers } 1013cde9171SAlan Somers 1023cde9171SAlan Somers if (optind >= argc) 1033cde9171SAlan Somers usage(); 1043cde9171SAlan Somers 1053cde9171SAlan Somers optreset = 1; 1063cde9171SAlan Somers optind = 1; 107fd26389bSAlan Somers #if defined(INET) && defined(INET6) 1083cde9171SAlan Somers if (ipv4 && ipv6) 1093cde9171SAlan Somers errx(1, "-4 and -6 cannot be used simultaneously"); 1103cde9171SAlan Somers #endif 1113cde9171SAlan Somers 112fd26389bSAlan Somers #if defined(INET) && defined(INET6) 1133cde9171SAlan Somers if (inet_pton(AF_INET, argv[argc - 1], &a) == 1) { 1143cde9171SAlan Somers if (ipv6) 1153cde9171SAlan Somers errx(1, "IPv6 requested but IPv4 target address " 1163cde9171SAlan Somers "provided"); 1173cde9171SAlan Somers hints.ai_family = AF_INET; 1183cde9171SAlan Somers } 1193cde9171SAlan Somers else if (inet_pton(AF_INET6, argv[argc - 1], &a6) == 1) { 1203cde9171SAlan Somers if (ipv4) 1213cde9171SAlan Somers errx(1, "IPv4 requested but IPv6 target address " 1223cde9171SAlan Somers "provided"); 1233cde9171SAlan Somers hints.ai_family = AF_INET6; 1243cde9171SAlan Somers } else if (ipv6) 1253cde9171SAlan Somers hints.ai_family = AF_INET6; 1263cde9171SAlan Somers else if (ipv4) 1273cde9171SAlan Somers hints.ai_family = AF_INET; 1283cde9171SAlan Somers else { 129b586c66bSAlan Somers if (!feature_present("inet6")) 130b586c66bSAlan Somers hints.ai_family = AF_INET; 131b586c66bSAlan Somers else if (!feature_present("inet")) 132b586c66bSAlan Somers hints.ai_family = AF_INET6; 133b586c66bSAlan Somers else { 1343cde9171SAlan Somers struct addrinfo *res; 1353cde9171SAlan Somers 1363cde9171SAlan Somers memset(&hints, 0, sizeof(hints)); 1373cde9171SAlan Somers hints.ai_socktype = SOCK_RAW; 1383cde9171SAlan Somers hints.ai_family = AF_UNSPEC; 1393cde9171SAlan Somers getaddrinfo(argv[argc - 1], NULL, &hints, &res); 1403cde9171SAlan Somers if (res != NULL) { 1413cde9171SAlan Somers hints.ai_family = res[0].ai_family; 1423cde9171SAlan Somers freeaddrinfo(res); 1433cde9171SAlan Somers } 1443cde9171SAlan Somers } 145b586c66bSAlan Somers } 146fd26389bSAlan Somers #elif defined(INET) 147fd26389bSAlan Somers hints.ai_family = AF_INET; 148fd26389bSAlan Somers #elif defined(INET6) 149fd26389bSAlan Somers hints.ai_family = AF_INET6; 150fd26389bSAlan Somers #endif 1513cde9171SAlan Somers 152fd26389bSAlan Somers #ifdef INET 1533cde9171SAlan Somers if (hints.ai_family == AF_INET) 1543cde9171SAlan Somers return ping(argc, argv); 155fd26389bSAlan Somers #endif /* INET */ 1563cde9171SAlan Somers #ifdef INET6 157fd26389bSAlan Somers if (hints.ai_family == AF_INET6) 1583cde9171SAlan Somers return ping6(argc, argv); 159fd26389bSAlan Somers #endif /* INET6 */ 1603cde9171SAlan Somers errx(1, "Unknown host"); 1613cde9171SAlan Somers } 1623cde9171SAlan Somers 1633cde9171SAlan Somers void 1643cde9171SAlan Somers usage(void) 1653cde9171SAlan Somers { 1663cde9171SAlan Somers (void)fprintf(stderr, 167fd26389bSAlan Somers "usage:\n" 168fd26389bSAlan Somers #ifdef INET 169fd26389bSAlan Somers "\tping [-4AaDdfHnoQqRrv] [-C pcp] [-c count] " 1703cde9171SAlan Somers "[-G sweepmaxsize]\n" 1713cde9171SAlan Somers " [-g sweepminsize] [-h sweepincrsize] [-i wait] " 1723cde9171SAlan Somers "[-l preload]\n" 1733cde9171SAlan Somers " [-M mask | time] [-m ttl] " 1743cde9171SAlan Somers #ifdef IPSEC 1753cde9171SAlan Somers "[-P policy] " 1763cde9171SAlan Somers #endif 1773cde9171SAlan Somers "[-p pattern] [-S src_addr] \n" 1783cde9171SAlan Somers " [-s packetsize] [-t timeout] [-W waittime] [-z tos] " 1793cde9171SAlan Somers "IPv4-host\n" 180fd26389bSAlan Somers "\tping [-4AaDdfHLnoQqRrv] [-C pcp] [-c count] [-I iface] " 1813cde9171SAlan Somers "[-i wait]\n" 1823cde9171SAlan Somers " [-l preload] [-M mask | time] [-m ttl] " 1833cde9171SAlan Somers #ifdef IPSEC 1843cde9171SAlan Somers "[-P policy] " 1853cde9171SAlan Somers #endif 1863cde9171SAlan Somers "[-p pattern]\n" 1873cde9171SAlan Somers " [-S src_addr] [-s packetsize] [-T ttl] [-t timeout] [-W waittime]\n" 1883cde9171SAlan Somers " [-z tos] IPv4-mcast-group\n" 189fd26389bSAlan Somers #endif /* INET */ 1903cde9171SAlan Somers #ifdef INET6 1919ce201f2SAlan Somers "\tping [-6AaDd" 1923cde9171SAlan Somers #if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC) 1933cde9171SAlan Somers "E" 1943cde9171SAlan Somers #endif 1953cde9171SAlan Somers "fHnNoOq" 1963cde9171SAlan Somers #ifdef IPV6_USE_MIN_MTU 1973cde9171SAlan Somers "u" 1983cde9171SAlan Somers #endif 1993cde9171SAlan Somers "vyY" 2003cde9171SAlan Somers #if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC) 2013cde9171SAlan Somers "Z" 2023cde9171SAlan Somers #endif 2033cde9171SAlan Somers "] " 2043cde9171SAlan Somers "[-b bufsiz] [-c count] [-e gateway]\n" 2053cde9171SAlan Somers " [-I interface] [-i wait] [-k addrtype] [-l preload] " 2063cde9171SAlan Somers "[-m hoplimit]\n" 2073cde9171SAlan Somers " [-p pattern]" 2083cde9171SAlan Somers #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 2093cde9171SAlan Somers " [-P policy]" 2103cde9171SAlan Somers #endif 2113cde9171SAlan Somers " [-S sourceaddr] [-s packetsize] [-t timeout]\n" 2123cde9171SAlan Somers " [-W waittime] [-z tclass] [IPv6-hops ...] IPv6-host\n" 2133cde9171SAlan Somers #endif /* INET6 */ 2143cde9171SAlan Somers ); 2153cde9171SAlan Somers 2163cde9171SAlan Somers exit(1); 2173cde9171SAlan Somers } 218