lib: cli: fix IPv6 address partial matching

A partially-entered IPv6 address would never return a "partly_match",
meaning some possible completions weren't listed by the matcher.

This specifically breaks autocompleting BGP IPv6 neighbor addresses.
Before:
aegaeon# show ip bg ne 2001:<?>
  WORD      Neighbor on BGP configured interface

After:
aegaeon# show ip bg ne 2001:<?>
  WORD      Neighbor on BGP configured interface
  X:X::X:X  Neighbor to display information about
      2001:db8::2

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
David Lamparter 2017-05-11 11:26:40 +02:00 committed by Quentin Young
parent 4e3e06d638
commit 9a7fc1bd7a
2 changed files with 18 additions and 29 deletions

View File

@ -78,10 +78,7 @@ static enum match_type
match_ipv4_prefix (const char *);
static enum match_type
match_ipv6 (const char *);
static enum match_type
match_ipv6_prefix (const char *);
match_ipv6_prefix (const char *, bool);
static enum match_type
match_range (struct cmd_token *, const char *);
@ -677,9 +674,9 @@ match_token (struct cmd_token *token, char *input_token)
case IPV4_PREFIX_TKN:
return match_ipv4_prefix (input_token);
case IPV6_TKN:
return match_ipv6 (input_token);
return match_ipv6_prefix (input_token, false);
case IPV6_PREFIX_TKN:
return match_ipv6_prefix (input_token);
return match_ipv6_prefix (input_token, true);
case RANGE_TKN:
return match_range (token, input_token);
case VARIABLE_TKN:
@ -835,35 +832,18 @@ match_ipv4_prefix (const char *str)
#define STATE_MASK 7
static enum match_type
match_ipv6 (const char *str)
{
struct sockaddr_in6 sin6_dummy;
int ret;
if (strspn (str, IPV6_ADDR_STR) != strlen (str))
return no_match;
ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr);
if (ret == 1)
return exact_match;
return no_match;
}
static enum match_type
match_ipv6_prefix (const char *str)
match_ipv6_prefix (const char *str, bool prefix)
{
int state = STATE_START;
int colons = 0, nums = 0, double_colon = 0;
int mask;
const char *sp = NULL;
const char *sp = NULL, *start = str;
char *endptr = NULL;
if (str == NULL)
return partly_match;
if (strspn (str, IPV6_PREFIX_STR) != strlen (str))
if (strspn (str, prefix ? IPV6_PREFIX_STR : IPV6_ADDR_STR) != strlen (str))
return no_match;
while (*str != '\0' && state != STATE_MASK)
@ -966,6 +946,13 @@ match_ipv6_prefix (const char *str)
str++;
}
if (!prefix)
{
struct sockaddr_in6 sin6_dummy;
int ret = inet_pton(AF_INET6, start, &sin6_dummy.sin6_addr);
return ret == 1 ? exact_match : partly_match;
}
if (state < STATE_MASK)
return partly_match;

View File

@ -61,7 +61,7 @@ cmd2 with 3 args.
[01]: ipv6
[02]: de4d:b33f::cafe
test# arg ipv6 de4d:b3
% There is no matched command.
X:X::X:X 02
test# arg ipv6 de4d:b33f::caf
X:X::X:X 02
test# arg ipv6 de4d:b33f::cafe
@ -264,7 +264,8 @@ cmd10 with 3 args.
test#
test# alt a
test# alt a a
WORD 02
WORD 02
X:X::X:X 02
test# alt a ab
cmd11 with 3 args.
[00]: alt
@ -281,7 +282,8 @@ cmd12 with 3 args.
[02]: 1.2.3.4
test# alt a 1
test# alt a 1:2
WORD 02
WORD 02
X:X::X:X 02
test# alt a 1:2
test# alt a 1:2::
WORD 02