diff options
Diffstat (limited to 'lib/command_match.c')
| -rw-r--r-- | lib/command_match.c | 233 |
1 files changed, 206 insertions, 27 deletions
diff --git a/lib/command_match.c b/lib/command_match.c index d4996f634d..14501c8626 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -27,7 +27,14 @@ #include "command_match.h" #include "memory.h" -DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens") +#ifdef TRACE_MATCHER +#define TM 1 +#else +#define TM 0 +#endif + +#define trace_matcher(...) \ + do { if (TM) fprintf (stderr, __VA_ARGS__); } while (0); /* matcher helper prototypes */ static int @@ -115,12 +122,28 @@ command_match (struct graph *cmdgraph, assert (*el); } +<<<<<<< HEAD + if (!*el) { + trace_matcher ("No match\n"); + } + else { + trace_matcher ("Matched command\n->string %s\n->desc %s\n", (*el)->string, (*el)->doc); + } +||||||| merged common ancestors + if (!*el) { + trace_matcher ("No match"); + } + else { + trace_matcher ("Matched command\n->string %s\n->desc %s\n", (*el)->string, (*el)->doc); + } +======= #ifdef TRACE_MATCHER if (!*el) fprintf (stdout, "No match\n"); else fprintf (stdout, "Matched command\n->string %s\n->desc %s\n", (*el)->string, (*el)->doc); #endif +>>>>>>> osr/master // free the leader token we alloc'd XFREE (MTYPE_TMP, vector_slot (vvline, 0)); @@ -336,6 +359,13 @@ command_complete (struct graph *graph, input_token = vector_slot (vline, idx); + int exact_match_exists = 0; + for (ALL_LIST_ELEMENTS_RO (current,node,gn)) + if (!exact_match_exists) + exact_match_exists = (match_token (gn->data, input_token) == exact_match); + else + break; + for (ALL_LIST_ELEMENTS_RO (current,node,gn)) { struct cmd_token *token = gn->data; @@ -344,17 +374,57 @@ command_complete (struct graph *graph, continue; enum match_type minmatch = min_match_level (token->type); +<<<<<<< HEAD + trace_matcher ("\"%s\" matches \"%s\" (%d) ? ", + input_token, token->text, token->type); +||||||| merged common ancestors + trace_matcher ("\"%s\" matches \"%s\" (%d) ? ", input_token, token->text, token->type); +======= #ifdef TRACE_MATCHER fprintf (stdout, "\"%s\" matches \"%s\" (%d) ? ", input_token, token->text, token->type); #endif +>>>>>>> osr/master - switch (match_token (token, input_token)) + unsigned int last_token = (vector_active (vline) - 1 == idx); + enum match_type matchtype = match_token (token, input_token); + switch (matchtype) { + // occurs when last token is whitespace case trivial_match: +<<<<<<< HEAD + trace_matcher ("trivial_match\n"); + assert(last_token); + listnode_add (next, gn); + break; +||||||| merged common ancestors + trace_matcher ("trivial_match\n"); + assert(idx == vector_active (vline) - 1); + listnode_add (next, gn); + break; +======= #ifdef TRACE_MATCHER fprintf (stdout, "trivial_match\n"); #endif +>>>>>>> osr/master case partly_match: +<<<<<<< HEAD + trace_matcher ("trivial_match\n"); + if (exact_match_exists && !last_token) + break; +||||||| merged common ancestors + trace_matcher ("partly_match\n"); + // last token on line is partial and + // not a space + if (idx == vector_active (vline) - 1) + { + listnode_add (next, gn); + break; + } + if (minmatch <= partly_match) + add_nexthops (next, gn); + + break; +======= #ifdef TRACE_MATCHER fprintf (stdout, "partly_match\n"); #endif @@ -365,11 +435,24 @@ command_complete (struct graph *graph, } if (minmatch > partly_match) break; +>>>>>>> osr/master case exact_match: +<<<<<<< HEAD + trace_matcher ("exact_match\n"); + if (last_token) + listnode_add (next, gn); + else if (matchtype >= minmatch) + add_nexthops (next, gn); +||||||| merged common ancestors + trace_matcher ("exact_match\n"); + add_nexthops (next, gn); + listnode_add (next, gn); +======= #ifdef TRACE_MATCHER fprintf (stdout, "exact_match\n"); #endif add_nexthops (next, gn); +>>>>>>> osr/master break; default: #ifdef TRACE_MATCHER @@ -772,44 +855,140 @@ match_ipv6 (const char *str) return no_match; } +#define IPV6_ADDR_STR "0123456789abcdefABCDEF:.%" +#define IPV6_PREFIX_STR "0123456789abcdefABCDEF:.%/" +#define STATE_START 1 +#define STATE_COLON 2 +#define STATE_DOUBLE 3 +#define STATE_ADDR 4 +#define STATE_DOT 5 +#define STATE_SLASH 6 +#define STATE_MASK 7 static enum match_type match_ipv6_prefix (const char *str) { - struct sockaddr_in6 sin6_dummy; - const char *delim = "/\0"; - char *tofree, *dupe, *prefix, *mask, *endptr; - int nmask = -1; + int state = STATE_START; + int colons = 0, nums = 0, double_colon = 0; + int mask; + const char *sp = NULL; + char *endptr = NULL; + + if (str == NULL) + return partly_match; if (strspn (str, IPV6_PREFIX_STR) != strlen (str)) return no_match; - /* tokenize to prefix + mask */ - tofree = dupe = XSTRDUP (MTYPE_TMP, str); - prefix = strsep (&dupe, delim); - mask = dupe; + while (*str != '\0' && state != STATE_MASK) + { + switch (state) + { + case STATE_START: + if (*str == ':') + { + if (*(str + 1) != ':' && *(str + 1) != '\0') + return no_match; + colons--; + state = STATE_COLON; + } + else + { + sp = str; + state = STATE_ADDR; + } + + continue; + case STATE_COLON: + colons++; + if (*(str + 1) == '/') + return no_match; + else if (*(str + 1) == ':') + state = STATE_DOUBLE; + else + { + sp = str + 1; + state = STATE_ADDR; + } + break; + case STATE_DOUBLE: + if (double_colon) + return no_match; + + if (*(str + 1) == ':') + return no_match; + else + { + if (*(str + 1) != '\0' && *(str + 1) != '/') + colons++; + sp = str + 1; + + if (*(str + 1) == '/') + state = STATE_SLASH; + else + state = STATE_ADDR; + } + + double_colon++; + nums += 1; + break; + case STATE_ADDR: + if (*(str + 1) == ':' || *(str + 1) == '.' + || *(str + 1) == '\0' || *(str + 1) == '/') + { + if (str - sp > 3) + return no_match; + + for (; sp <= str; sp++) + if (*sp == '/') + return no_match; + + nums++; + + if (*(str + 1) == ':') + state = STATE_COLON; + else if (*(str + 1) == '.') + { + if (colons || double_colon) + state = STATE_DOT; + else + return no_match; + } + else if (*(str + 1) == '/') + state = STATE_SLASH; + } + break; + case STATE_DOT: + state = STATE_ADDR; + break; + case STATE_SLASH: + if (*(str + 1) == '\0') + return partly_match; + + state = STATE_MASK; + break; + default: + break; + } + + if (nums > 11) + return no_match; + + if (colons > 7) + return no_match; - /* validate prefix */ - if (inet_pton (AF_INET6, prefix, &sin6_dummy.sin6_addr) != 1) - { - XFREE (MTYPE_TMP, tofree); - return no_match; - } + str++; + } - /* validate mask */ - if (!mask) - { - XFREE (MTYPE_TMP, tofree); + if (state < STATE_MASK) return partly_match; - } - nmask = strtoimax (mask, &endptr, 10); - if (*endptr != '\0' || nmask < 0 || nmask > 128) - { - XFREE (MTYPE_TMP, tofree); + mask = strtol (str, &endptr, 10); + if (*endptr != '\0') + return no_match; + + if (mask < 0 || mask > 128) return no_match; - } - XFREE (MTYPE_TMP, tofree); return exact_match; } #endif |
