summaryrefslogtreecommitdiffstats
path: root/lib/command_match.c
diff options
context:
space:
mode:
authorQuentin Young <qlyoung@cumulusnetworks.com>2017-08-08 23:10:23 +0200
committerQuentin Young <qlyoung@cumulusnetworks.com>2017-08-11 18:42:01 +0200
commit9779e3f19368fe05199cddc3bc4029288c34be3f (patch)
tree75e82daeba86fefd735f98f29b2f23c9148df572 /lib/command_match.c
parentMerge pull request #953 from jbonor/nhrpd-fixes (diff)
downloadfrr-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.c55
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;
+}