mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 04:43:53 +00:00
ping: Simplify protocol selection.
* Interrupt the option loop as soon as we have an indication of which protocol is intended. * If we end up having to perform a DNS lookup, loop over the entire result looking for either IPv4 or IPv6 addresses. Sponsored by: NetApp, Inc. Sponsored by: Klara, Inc. Reviewed by: rscheff, kevans, allanjude Differential Revision: https://reviews.freebsd.org/D42137
This commit is contained in:
parent
26103ccba8
commit
7fd2c91a29
129
sbin/ping/main.c
129
sbin/ping/main.c
|
@ -62,112 +62,99 @@
|
|||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
#if defined(INET) && defined(INET6)
|
||||
#if defined(INET)
|
||||
struct in_addr a;
|
||||
#endif
|
||||
#if defined(INET6)
|
||||
struct in6_addr a6;
|
||||
#endif
|
||||
#if defined(INET) || defined(INET6)
|
||||
struct addrinfo hints;
|
||||
#endif
|
||||
int ch;
|
||||
#ifdef INET
|
||||
bool ipv4 = false;
|
||||
#if defined(INET) && defined(INET6)
|
||||
struct addrinfo hints, *res, *ai;
|
||||
int error;
|
||||
#endif
|
||||
int opt;
|
||||
|
||||
#ifdef INET6
|
||||
bool ipv6 = false;
|
||||
|
||||
if (strcmp(getprogname(), "ping6") == 0)
|
||||
ipv6 = true;
|
||||
return ping6(argc, argv);
|
||||
#endif
|
||||
|
||||
while ((ch = getopt(argc, argv, ":" OPTSTR)) != -1) {
|
||||
switch(ch) {
|
||||
while ((opt = getopt(argc, argv, ":" OPTSTR)) != -1) {
|
||||
switch (opt) {
|
||||
#ifdef INET
|
||||
case '4':
|
||||
ipv4 = true;
|
||||
break;
|
||||
goto ping4;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case '6':
|
||||
ipv6 = true;
|
||||
break;
|
||||
goto ping6;
|
||||
#endif
|
||||
#if defined(INET) && defined(INET6)
|
||||
case 'S':
|
||||
/*
|
||||
* If -S is given with a numeric parameter,
|
||||
* force use of the corresponding version.
|
||||
*/
|
||||
#ifdef INET
|
||||
if (inet_pton(AF_INET, optarg, &a) == 1)
|
||||
ipv4 = true;
|
||||
else if (inet_pton(AF_INET6, optarg, &a6) == 1)
|
||||
ipv6 = true;
|
||||
break;
|
||||
goto ping4;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (inet_pton(AF_INET6, optarg, &a6) == 1)
|
||||
goto ping6;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For IPv4, only one positional argument, the target, is allowed.
|
||||
* For IPv6, multiple positional argument are allowed; the last
|
||||
* one is the target, and preceding ones are intermediate hops.
|
||||
* This nuance is lost here, but the only case where it matters is
|
||||
* an error.
|
||||
*/
|
||||
if (optind >= argc)
|
||||
usage();
|
||||
|
||||
optreset = 1;
|
||||
optind = 1;
|
||||
#if defined(INET) && defined(INET6)
|
||||
if (ipv4 && ipv6)
|
||||
errx(1, "-4 and -6 cannot be used simultaneously");
|
||||
#endif
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
if (inet_pton(AF_INET, argv[argc - 1], &a) == 1) {
|
||||
if (ipv6)
|
||||
errx(1, "IPv6 requested but IPv4 target address "
|
||||
"provided");
|
||||
hints.ai_family = AF_INET;
|
||||
}
|
||||
else if (inet_pton(AF_INET6, argv[argc - 1], &a6) == 1) {
|
||||
if (ipv4)
|
||||
errx(1, "IPv4 requested but IPv6 target address "
|
||||
"provided");
|
||||
hints.ai_family = AF_INET6;
|
||||
} else if (ipv6)
|
||||
hints.ai_family = AF_INET6;
|
||||
else if (ipv4)
|
||||
hints.ai_family = AF_INET;
|
||||
else {
|
||||
if (!feature_present("inet6"))
|
||||
hints.ai_family = AF_INET;
|
||||
else if (!feature_present("inet"))
|
||||
hints.ai_family = AF_INET6;
|
||||
else {
|
||||
struct addrinfo *res;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_socktype = SOCK_RAW;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
getaddrinfo(argv[argc - 1], NULL, &hints, &res);
|
||||
if (res != NULL) {
|
||||
hints.ai_family = res[0].ai_family;
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(INET)
|
||||
if (feature_present("inet") && !feature_present("inet6"))
|
||||
hints.ai_family = AF_INET;
|
||||
#elif defined(INET6)
|
||||
if (feature_present("inet6") && !feature_present("inet"))
|
||||
hints.ai_family = AF_INET6;
|
||||
#endif
|
||||
|
||||
#ifdef INET
|
||||
if (hints.ai_family == AF_INET)
|
||||
return ping(argc, argv);
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
if (hints.ai_family == AF_INET6)
|
||||
return ping6(argc, argv);
|
||||
#endif /* INET6 */
|
||||
else
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
error = getaddrinfo(argv[argc - 1], NULL, &hints, &res);
|
||||
if (res == NULL)
|
||||
errx(1, "%s", gai_strerror(error));
|
||||
for (ai = res; ai != NULL; ai = ai->ai_next) {
|
||||
if (ai->ai_family == AF_INET) {
|
||||
freeaddrinfo(res);
|
||||
goto ping4;
|
||||
}
|
||||
if (ai->ai_family == AF_INET6) {
|
||||
freeaddrinfo(res);
|
||||
goto ping6;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
errx(1, "Unknown host");
|
||||
#endif
|
||||
#ifdef INET
|
||||
ping4:
|
||||
optreset = 1;
|
||||
optind = 1;
|
||||
return ping(argc, argv);
|
||||
#endif
|
||||
#ifdef INET6
|
||||
ping6:
|
||||
optreset = 1;
|
||||
optind = 1;
|
||||
return ping6(argc, argv);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -135,21 +135,34 @@ ping_46_body()
|
|||
require_ipv4
|
||||
require_ipv6
|
||||
atf_check -s exit:1 \
|
||||
-e match:"-4 and -6 cannot be used simultaneously" \
|
||||
-e match:"illegal option -- 6" \
|
||||
ping -4 -6 localhost
|
||||
}
|
||||
|
||||
ping6_46_head()
|
||||
ping_64_head()
|
||||
{
|
||||
atf_set "descr" "-4 and -6 cannot be used simultaneously"
|
||||
}
|
||||
ping6_46_body()
|
||||
ping_64_body()
|
||||
{
|
||||
require_ipv4
|
||||
require_ipv6
|
||||
atf_check -s exit:1 \
|
||||
-e match:"-4 and -6 cannot be used simultaneously" \
|
||||
ping6 -4 -6 localhost
|
||||
-e match:"illegal option -- 4" \
|
||||
ping -6 -4 localhost
|
||||
}
|
||||
|
||||
ping6_4_head()
|
||||
{
|
||||
atf_set "descr" "ping6 does not accept -4"
|
||||
}
|
||||
ping6_4_body()
|
||||
{
|
||||
require_ipv4
|
||||
require_ipv6
|
||||
atf_check -s exit:1 \
|
||||
-e match:"illegal option -- 4" \
|
||||
ping6 -4 localhost
|
||||
}
|
||||
|
||||
atf_test_case "inject_opts" "cleanup"
|
||||
|
@ -212,7 +225,8 @@ atf_init_test_cases()
|
|||
atf_add_test_case ping_c1t6
|
||||
atf_add_test_case ping6_c1t4
|
||||
atf_add_test_case ping_46
|
||||
atf_add_test_case ping6_46
|
||||
atf_add_test_case ping_64
|
||||
atf_add_test_case ping6_4
|
||||
atf_add_test_case inject_opts
|
||||
atf_add_test_case inject_pip
|
||||
atf_add_test_case inject_reply
|
||||
|
|
Loading…
Reference in a new issue