diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/command_graph.c | 2 | ||||
| -rw-r--r-- | lib/command_graph.h | 10 | ||||
| -rw-r--r-- | lib/command_lex.l | 4 | ||||
| -rw-r--r-- | lib/command_match.c | 55 | ||||
| -rw-r--r-- | lib/command_parse.y | 12 | ||||
| -rw-r--r-- | lib/command_py.c | 2 | ||||
| -rw-r--r-- | lib/grammar_sandbox.c | 2 | ||||
| -rw-r--r-- | lib/routemap.c | 18 |
8 files changed, 93 insertions, 12 deletions
diff --git a/lib/command_graph.c b/lib/command_graph.c index dc7233c1fe..fce11a70cc 100644 --- a/lib/command_graph.c +++ b/lib/command_graph.c @@ -379,6 +379,8 @@ static void cmd_node_names(struct graph_node *gn, struct graph_node *join, case IPV4_PREFIX_TKN: case IPV6_TKN: case IPV6_PREFIX_TKN: + case MAC_TKN: + case MAC_PREFIX_TKN: if (!tok->varname && prevname) cmd_token_varname_set(tok, prevname); prevname = NULL; diff --git a/lib/command_graph.h b/lib/command_graph.h index 879148844c..ec68e284ed 100644 --- a/lib/command_graph.h +++ b/lib/command_graph.h @@ -42,14 +42,17 @@ struct vty; * The type determines what kind of data the token can match (in the * matching use case) or hold (in the argv use case). */ +/* clang-format off */ enum cmd_token_type { - WORD_TKN, // words + WORD_TKN, // words VARIABLE_TKN, // almost anything RANGE_TKN, // integer range - IPV4_TKN, // IPV4 addresses + IPV4_TKN, // IPV4 addresses IPV4_PREFIX_TKN, // IPV4 network prefixes - IPV6_TKN, // IPV6 prefixes + IPV6_TKN, // IPV6 prefixes IPV6_PREFIX_TKN, // IPV6 network prefixes + MAC_TKN, // Ethernet address + MAC_PREFIX_TKN, // Ethernet address w/ CIDR mask /* plumbing types */ FORK_TKN, // marks subgraph beginning @@ -59,6 +62,7 @@ enum cmd_token_type { SPECIAL_TKN = FORK_TKN, }; +/* clang-format on */ #define IS_VARYING_TOKEN(x) ((x) >= VARIABLE_TKN && (x) < FORK_TKN) diff --git a/lib/command_lex.l b/lib/command_lex.l index fddbf7b287..59d0d840a8 100644 --- a/lib/command_lex.l +++ b/lib/command_lex.l @@ -40,6 +40,8 @@ IPV4 A\.B\.C\.D IPV4_PREFIX A\.B\.C\.D\/M IPV6 X:X::X:X IPV6_PREFIX X:X::X:X\/M +MAC M:A:C +MAC_PREFIX M:A:C\/M VARIABLE [A-Z][-_a-zA-Z:0-9]+ NUMBER (\-|\+)?[0-9]{1,20} RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\) @@ -67,6 +69,8 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\) {IPV4_PREFIX} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return IPV4_PREFIX;} {IPV6} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return IPV6;} {IPV6_PREFIX} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return IPV6_PREFIX;} +{MAC} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return MAC;} +{MAC_PREFIX} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return MAC_PREFIX;} {VARIABLE} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return VARIABLE;} {RANGE} {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return RANGE;} . {return yytext[0];} diff --git a/lib/command_match.c b/lib/command_match.c index bc54f1bb09..f07448d716 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -78,6 +78,8 @@ static enum match_type match_word(struct cmd_token *, const char *); static enum match_type match_variable(struct cmd_token *, const char *); +static enum match_type match_mac(const char *, bool); + /* matching functions */ static enum matcher_rv matcher_rv; @@ -537,6 +539,8 @@ static int score_precedence(enum cmd_token_type type) case IPV4_PREFIX_TKN: case IPV6_TKN: case IPV6_PREFIX_TKN: + case MAC_TKN: + case MAC_PREFIX_TKN: case RANGE_TKN: return 2; case WORD_TKN: @@ -658,6 +662,10 @@ static enum match_type match_token(struct cmd_token *token, char *input_token) return match_range(token, input_token); case VARIABLE_TKN: return match_variable(token, input_token); + case MAC_TKN: + return match_mac(input_token, false); + case MAC_PREFIX_TKN: + return match_mac(input_token, true); case END_TKN: default: return no_match; @@ -964,3 +972,50 @@ static enum match_type match_variable(struct cmd_token *token, const char *word) assert(token->type == VARIABLE_TKN); return exact_match; } + +#define MAC_CHARS "ABCDEFabcdef0123456789:" + +static enum match_type match_mac(const char *word, bool prefix) +{ + /* 6 2-digit hex numbers separated by 5 colons */ + size_t mac_explen = 6 * 2 + 5; + /* '/' + 2-digit integer */ + size_t mask_len = 1 + 2; + unsigned int i; + char *eptr; + unsigned int maskval; + + /* length check */ + if (strlen(word) > mac_explen + (prefix ? mask_len : 0)) + return no_match; + + /* address check */ + for (i = 0; i < mac_explen; i++) { + if (word[i] == '\0' || !strchr(MAC_CHARS, word[i])) + break; + if (((i + 1) % 3 == 0) != (word[i] == ':')) + return no_match; + } + + /* incomplete address */ + if (i < mac_explen && word[i] == '\0') + return partly_match; + else if (i < mac_explen) + return no_match; + + /* mask check */ + if (prefix && word[i] == '/') { + if (word[++i] == '\0') + return partly_match; + + maskval = strtoul(&word[i], &eptr, 10); + if (*eptr != '\0' || maskval > 48) + return no_match; + } else if (prefix && word[i] == '\0') { + return partly_match; + } else if (prefix) { + return no_match; + } + + return exact_match; +} diff --git a/lib/command_parse.y b/lib/command_parse.y index 1bc8ea1a44..0f3e42219e 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -101,6 +101,8 @@ %token <string> IPV6_PREFIX %token <string> VARIABLE %token <string> RANGE +%token <string> MAC +%token <string> MAC_PREFIX /* union types for parsed rules */ %type <node> start @@ -273,6 +275,16 @@ placeholder_token_real: XFREE (MTYPE_LEX, $1); } +| MAC +{ + $$ = new_token_node (ctx, MAC_TKN, $1, doc_next(ctx)); + XFREE (MTYPE_LEX, $1); +} +| MAC_PREFIX +{ + $$ = new_token_node (ctx, MAC_PREFIX_TKN, $1, doc_next(ctx)); + XFREE (MTYPE_LEX, $1); +} placeholder_token: placeholder_token_real varname_token diff --git a/lib/command_py.c b/lib/command_py.c index 785d2ffa70..755cfb55ce 100644 --- a/lib/command_py.c +++ b/lib/command_py.c @@ -199,6 +199,8 @@ static PyObject *graph_to_pyobj(struct wrap_graph *wgraph, item(IPV4_PREFIX_TKN) // IPV4 network prefixes item(IPV6_TKN) // IPV6 prefixes item(IPV6_PREFIX_TKN) // IPV6 network prefixes + item(MAC_TKN) // MAC address + item(MAC_PREFIX_TKN) // MAC address with mask /* plumbing types */ item(FORK_TKN) item(JOIN_TKN) item(START_TKN) diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index 8dd8d2e2bb..96ecfa44d3 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -498,6 +498,8 @@ struct message tokennames[] = {item(WORD_TKN), // words item(IPV4_PREFIX_TKN), // IPV4 network prefixes item(IPV6_TKN), // IPV6 prefixes item(IPV6_PREFIX_TKN), // IPV6 network prefixes + item(MAC_TKN), // MAC address + item(MAC_PREFIX_TKN), // MAC address w/ mask /* plumbing types */ item(FORK_TKN), diff --git a/lib/routemap.c b/lib/routemap.c index 3d1add25dc..a70248633c 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -2194,24 +2194,24 @@ DEFUN (set_ip_nexthop, DEFUN (no_set_ip_nexthop, no_set_ip_nexthop_cmd, - "no set ip next-hop [<peer-address|A.B.C.D>]", + "no set ip next-hop [A.B.C.D]", NO_STR SET_STR IP_STR "Next hop address\n" - "Use peer address (for BGP only)\n" "IP address of next hop\n") { - int idx_peer = 4; + int idx; VTY_DECLVAR_CONTEXT(route_map_index, index); + const char *arg = NULL; - if (rmap_match_set_hook.no_set_ip_nexthop) { - if (argc <= idx_peer) - return rmap_match_set_hook.no_set_ip_nexthop( - vty, index, "ip next-hop", NULL); + if (argv_find(argv, argc, "A.B.C.D", &idx)) + arg = argv[idx]->arg; + + if (rmap_match_set_hook.no_set_ip_nexthop) return rmap_match_set_hook.no_set_ip_nexthop( - vty, index, "ip next-hop", argv[idx_peer]->arg); - } + vty, index, "ip next-hop", arg); + return CMD_SUCCESS; } |
