git: c775b6ebabb3 - stable/13 - ping: fix parsing of options including '4' and '6'
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 13 Dec 2021 01:27:33 UTC
The branch stable/13 has been updated by emaste: URL: https://cgit.FreeBSD.org/src/commit/?id=c775b6ebabb3431cce9233bc6cbb66127cbb5ea0 commit c775b6ebabb3431cce9233bc6cbb66127cbb5ea0 Author: Alan Somers <asomers@FreeBSD.org> AuthorDate: 2021-10-06 22:54:59 +0000 Commit: Ed Maste <emaste@FreeBSD.org> CommitDate: 2021-12-13 01:27:12 +0000 ping: fix parsing of options including '4' and '6' ping uses a two-pass option parser. The first pass determines whether ipv4 or ipv6 is desired, and the second parses the rest of the options. But the first pass wrongly detects a '4' or '6' in an option's value as a request to use ipv6 or ipv6 respectively, for example in an invocation like "ping -c6 1.2.3.4". Fix this confusion by including all options in the first round of parsing, but ignoring those unrelated to ipv4/ipv6 selection. PR: 258048 Reported by: ghuckriede@blackberry.com Submitted by: ghuckriede@blackberry.com MFC after: 2 weeks Reviewed by: emaste Differential Revision: https://reviews.freebsd.org/D32344 (cherry picked from commit 9ce201f2ee3ca340032d9cc71d91a36b3b45a4c3) --- sbin/ping/main.c | 14 +++++------ sbin/ping/main.h | 20 +++++++++++++++ sbin/ping/ping.c | 10 +------- sbin/ping/ping6.c | 20 ++++++--------- sbin/ping/tests/ping_test.sh | 58 +++++++++++++++++++++++++++++++++++++------- 5 files changed, 84 insertions(+), 38 deletions(-) diff --git a/sbin/ping/main.c b/sbin/ping/main.c index 01442679efff..c021e2c26b14 100644 --- a/sbin/ping/main.c +++ b/sbin/ping/main.c @@ -52,13 +52,11 @@ __FBSDID("$FreeBSD$"); #endif #if defined(INET) && defined(INET6) -#define OPTSTR ":46" +#define OPTSTR PING6OPTS PING4OPTS #elif defined(INET) -#define OPTSTR ":4" +#define OPTSTR PING4OPTS #elif defined(INET6) -#define OPTSTR ":6" -#else -#define OPTSTR "" +#define OPTSTR PING6OPTS #endif int @@ -82,7 +80,7 @@ main(int argc, char *argv[]) ipv6 = true; #endif - while ((ch = getopt(argc, argv, OPTSTR)) != -1) { + while ((ch = getopt(argc, argv, ":" OPTSTR)) != -1) { switch(ch) { #ifdef INET case '4': @@ -170,7 +168,7 @@ usage(void) "[-G sweepmaxsize]\n" " [-g sweepminsize] [-h sweepincrsize] [-i wait] " "[-l preload]\n" - " [-M mask | time] [-m ttl]" + " [-M mask | time] [-m ttl] " #ifdef IPSEC "[-P policy] " #endif @@ -188,7 +186,7 @@ usage(void) " [-z tos] IPv4-mcast-group\n" #endif /* INET */ #ifdef INET6 - "\tping [-6aADd" + "\tping [-6AaDd" #if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC) "E" #endif diff --git a/sbin/ping/main.h b/sbin/ping/main.h index f9707ccfb5ff..0f987e9a20ae 100644 --- a/sbin/ping/main.h +++ b/sbin/ping/main.h @@ -31,6 +31,26 @@ #ifndef MAIN_H #define MAIN_H 1 +#ifdef IPSEC +#include <netipsec/ipsec.h> +#endif /*IPSEC*/ + +#if defined(INET) && defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) + #define PING4ADDOPTS "P:" +#else + #define PING4ADDOPTS +#endif +#define PING4OPTS "4AaC:c:DdfG:g:Hh:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:" PING4ADDOPTS + +#if defined(INET6) && defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) + #define PING6ADDOPTS "P:" +#elif defined(INET6) && defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC) + #define PING6ADDOPTS "ZE" +#else + #define PING6ADDOPTS +#endif +#define PING6OPTS "6Aab:C:c:Dde:fHI:i:k:l:m:nNoOp:qS:s:t:uvyYW:z:" PING6ADDOPTS + void usage(void) __dead2; #endif diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c index fe197928085e..be535f72146a 100644 --- a/sbin/ping/ping.c +++ b/sbin/ping/ping.c @@ -301,15 +301,7 @@ ping(int argc, char *const *argv) alarmtimeout = df = preload = tos = pcp = 0; outpack = outpackhdr + sizeof(struct ip); - while ((ch = getopt(argc, argv, - "4AaC:c:DdfG:g:Hh:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:" -#ifdef IPSEC -#ifdef IPSEC_POLICY_IPSEC - "P:" -#endif /*IPSEC_POLICY_IPSEC*/ -#endif /*IPSEC*/ - )) != -1) - { + while ((ch = getopt(argc, argv, PING4OPTS)) != -1) { switch(ch) { case '4': /* This option is processed in main(). */ diff --git a/sbin/ping/ping6.c b/sbin/ping/ping6.c index 4cbeae770372..76a96f0631ff 100644 --- a/sbin/ping/ping6.c +++ b/sbin/ping/ping6.c @@ -293,7 +293,11 @@ static void pr_rthdr(void *, size_t); static int pr_bitrange(u_int32_t, int, int); static void pr_retip(struct ip6_hdr *, u_char *); static void summary(void); +#ifdef IPSEC +#ifdef IPSEC_POLICY_IPSEC static int setpolicy(int, char *); +#endif +#endif static char *nigroup(char *, int); int @@ -345,18 +349,8 @@ ping6(int argc, char *argv[]) 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, - "6k:b:C:c:DdfHe:m:I:i:l:unNop:qaAS:s:OvyYW:t:z:" ADDOPTS)) != -1) { -#undef ADDOPTS + + while ((ch = getopt(argc, argv, PING6OPTS)) != -1) { switch (ch) { case '6': /* This option is processed in main(). */ @@ -2667,7 +2661,9 @@ pr_retip(struct ip6_hdr *ip6, u_char *end) nh = ip6->ip6_nxt; cp += hlen; while (end - cp >= 8) { +#ifdef IPSEC struct ah ah; +#endif switch (nh) { case IPPROTO_HOPOPTS: diff --git a/sbin/ping/tests/ping_test.sh b/sbin/ping/tests/ping_test.sh index ed95594abbd2..54af89f4a22b 100644 --- a/sbin/ping/tests/ping_test.sh +++ b/sbin/ping/tests/ping_test.sh @@ -27,14 +27,23 @@ # # $FreeBSD$ +require_ipv4() { + if ! getaddrinfo -f inet localhost 1>/dev/null 2>&1; then + atf_skip "IPv4 is not configured" + fi +} +require_ipv6() { + if ! getaddrinfo -f inet6 localhost 1>/dev/null 2>&1; then + atf_skip "IPv6 is not configured" + fi +} + atf_test_case ping_c1_s56_t1 ping_c1_s56_t1_head() { atf_set "descr" "Stop after receiving 1 ECHO_RESPONSE packet" } ping_c1_s56_t1_body() { - if ! getaddrinfo -f inet localhost 1>/dev/null 2>&1; then - atf_skip "IPv4 is not configured" - fi + require_ipv4 atf_check -s exit:0 -o save:std.out -e empty \ ping -4 -c 1 -s 56 -t 1 localhost check_ping_statistics std.out $(atf_get_srcdir)/ping_c1_s56_t1.out @@ -45,9 +54,7 @@ ping_6_c1_s8_t1_head() { atf_set "descr" "Stop after receiving 1 ECHO_RESPONSE packet" } ping_6_c1_s8_t1_body() { - if ! getaddrinfo -f inet6 localhost 1>/dev/null 2>&1; then - atf_skip "IPv6 is not configured" - fi + require_ipv6 atf_check -s exit:0 -o save:std.out -e empty \ ping -6 -c 1 -s 8 -t 1 localhost check_ping_statistics std.out $(atf_get_srcdir)/ping_6_c1_s8_t1.out @@ -58,18 +65,51 @@ ping6_c1_s8_t1_head() { atf_set "descr" "Use IPv6 when invoked as ping6" } ping6_c1_s8_t1_body() { - if ! getaddrinfo -f inet6 localhost 1>/dev/null 2>&1; then - atf_skip "IPv6 is not configured" - fi + require_ipv6 atf_check -s exit:0 -o save:std.out -e empty \ ping6 -c 1 -s 8 -t 1 localhost check_ping_statistics std.out $(atf_get_srcdir)/ping_6_c1_s8_t1.out } +ping_c1t6_head() { + atf_set "descr" "-t6 is not interpreted as -t -6 by ping" +} +ping_c1t6_body() { + require_ipv4 + atf_check -s exit:0 -o ignore -e empty ping -c1 -t6 127.0.0.1 +} + +ping6_c1t4_head() { + atf_set "descr" "-t4 is not interpreted as -t -4 by ping6" +} +ping6_c1t4_body() { + require_ipv6 + atf_check -s exit:0 -o ignore -e empty ping6 -c1 -t4 ::1 +} + +ping_46_head() { + atf_set "descr" "-4 and -6 may not be used together" +} +ping_46_body() { + atf_check -s exit:1 -e ignore ping -4 -6 +} + +ping6_46_head() { + atf_set "descr" "-4 and -6 may not be used together" +} +ping6_46_body() { + atf_check -s exit:1 -e ignore ping6 -4 -6 +} + + atf_init_test_cases() { atf_add_test_case ping_c1_s56_t1 atf_add_test_case ping_6_c1_s8_t1 atf_add_test_case ping6_c1_s8_t1 + atf_add_test_case ping_c1t6 + atf_add_test_case ping6_c1t4 + atf_add_test_case ping_46 + atf_add_test_case ping6_46 } check_ping_statistics() {