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
This commit is contained in:
parent
5c5340108e
commit
9ce201f2ee
@ -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
|
||||
|
@ -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
|
||||
|
@ -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(). */
|
||||
|
@ -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:
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user