diff options
author | Quentin Young <qlyoung@cumulusnetworks.com> | 2017-08-08 23:10:23 +0200 |
---|---|---|
committer | Quentin Young <qlyoung@cumulusnetworks.com> | 2017-08-11 18:42:01 +0200 |
commit | 9779e3f19368fe05199cddc3bc4029288c34be3f (patch) | |
tree | 75e82daeba86fefd735f98f29b2f23c9148df572 /lib/command_match.c | |
parent | Merge pull request #953 from jbonor/nhrpd-fixes (diff) | |
download | frr-9779e3f19368fe05199cddc3bc4029288c34be3f.tar.xz frr-9779e3f19368fe05199cddc3bc4029288c34be3f.zip |
lib: add CLI token for 48-bit mac addresses
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'lib/command_match.c')
-rw-r--r-- | lib/command_match.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/lib/command_match.c b/lib/command_match.c index bc54f1bb0..f07448d71 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; +} |