1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (C) 2019 Jan Sucan <jansucan@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/types.h> 33 #include <sys/socket.h> 34 35 #include <arpa/inet.h> 36 #include <netdb.h> 37 #include <netinet/in.h> 38 39 #include <err.h> 40 #include <stdbool.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <unistd.h> 45 46 #include "main.h" 47 #include "ping.h" 48 #ifdef INET6 49 #include "ping6.h" 50 #endif 51 52 #ifdef INET6 53 #define OPTSTR ":46" 54 #else 55 #define OPTSTR ":4" 56 #endif 57 58 int 59 main(int argc, char *argv[]) 60 { 61 struct in_addr a; 62 struct addrinfo hints; 63 int ch; 64 bool ipv4; 65 #ifdef INET6 66 struct in6_addr a6; 67 bool ipv6; 68 69 if (strcmp(getprogname(), "ping6") == 0) 70 ipv6 = true; 71 else 72 ipv6 = false; 73 #endif 74 ipv4 = false; 75 76 while ((ch = getopt(argc, argv, OPTSTR)) != -1) { 77 switch(ch) { 78 case '4': 79 ipv4 = true; 80 break; 81 #ifdef INET6 82 case '6': 83 ipv6 = true; 84 break; 85 #endif 86 default: 87 break; 88 } 89 } 90 91 if (optind >= argc) 92 usage(); 93 94 optreset = 1; 95 optind = 1; 96 #ifdef INET6 97 if (ipv4 && ipv6) 98 errx(1, "-4 and -6 cannot be used simultaneously"); 99 #endif 100 101 if (inet_pton(AF_INET, argv[argc - 1], &a) == 1) { 102 #ifdef INET6 103 if (ipv6) 104 errx(1, "IPv6 requested but IPv4 target address " 105 "provided"); 106 #endif 107 hints.ai_family = AF_INET; 108 } 109 #ifdef INET6 110 else if (inet_pton(AF_INET6, argv[argc - 1], &a6) == 1) { 111 if (ipv4) 112 errx(1, "IPv4 requested but IPv6 target address " 113 "provided"); 114 hints.ai_family = AF_INET6; 115 } else if (ipv6) 116 hints.ai_family = AF_INET6; 117 #endif 118 else if (ipv4) 119 hints.ai_family = AF_INET; 120 else { 121 struct addrinfo *res; 122 123 memset(&hints, 0, sizeof(hints)); 124 hints.ai_socktype = SOCK_RAW; 125 hints.ai_family = AF_UNSPEC; 126 getaddrinfo(argv[argc - 1], NULL, &hints, &res); 127 if (res != NULL) { 128 hints.ai_family = res[0].ai_family; 129 freeaddrinfo(res); 130 } 131 } 132 133 if (hints.ai_family == AF_INET) 134 return ping(argc, argv); 135 #ifdef INET6 136 else if (hints.ai_family == AF_INET6) 137 return ping6(argc, argv); 138 #endif 139 else 140 errx(1, "Unknown host"); 141 } 142 143 void 144 usage(void) 145 { 146 (void)fprintf(stderr, 147 "usage: ping [-4AaDdfHnoQqRrv] [-C pcp] [-c count] " 148 "[-G sweepmaxsize]\n" 149 " [-g sweepminsize] [-h sweepincrsize] [-i wait] " 150 "[-l preload]\n" 151 " [-M mask | time] [-m ttl]" 152 #ifdef IPSEC 153 "[-P policy] " 154 #endif 155 "[-p pattern] [-S src_addr] \n" 156 " [-s packetsize] [-t timeout] [-W waittime] [-z tos] " 157 "IPv4-host\n" 158 " ping [-4AaDdfHLnoQqRrv] [-C pcp] [-c count] [-I iface] " 159 "[-i wait]\n" 160 " [-l preload] [-M mask | time] [-m ttl] " 161 #ifdef IPSEC 162 "[-P policy] " 163 #endif 164 "[-p pattern]\n" 165 " [-S src_addr] [-s packetsize] [-T ttl] [-t timeout] [-W waittime]\n" 166 " [-z tos] IPv4-mcast-group\n" 167 #ifdef INET6 168 " ping [-6aADd" 169 #if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC) 170 "E" 171 #endif 172 "fHnNoOq" 173 #ifdef IPV6_USE_MIN_MTU 174 "u" 175 #endif 176 "vyY" 177 #if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC) 178 "Z" 179 #endif 180 "] " 181 "[-b bufsiz] [-c count] [-e gateway]\n" 182 " [-I interface] [-i wait] [-k addrtype] [-l preload] " 183 "[-m hoplimit]\n" 184 " [-p pattern]" 185 #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 186 " [-P policy]" 187 #endif 188 " [-S sourceaddr] [-s packetsize] [-t timeout]\n" 189 " [-W waittime] [-z tclass] [IPv6-hops ...] IPv6-host\n" 190 #endif /* INET6 */ 191 ); 192 193 exit(1); 194 } 195