summaryrefslogtreecommitdiff
path: root/lib/command_match.c
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2017-05-11 11:26:40 +0200
committerQuentin Young <qlyoung@users.noreply.github.com>2017-05-15 10:27:43 -0400
commit9a7fc1bd7a4961793bfb4340a4c4819e217fcb70 (patch)
tree628c33445a53f73c4a7882f0fb553dc6e090197c /lib/command_match.c
parent4e3e06d6384c1e0a7106d740945344d095f02b9c (diff)
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>
Diffstat (limited to 'lib/command_match.c')
-rw-r--r--lib/command_match.c39
1 files changed, 13 insertions, 26 deletions
diff --git a/lib/command_match.c b/lib/command_match.c
index df1a8bb72b..d1f9ef1cb1 100644
--- a/lib/command_match.c
+++ b/lib/command_match.c
@@ -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;