summaryrefslogtreecommitdiff
path: root/lib/command_match.c
diff options
context:
space:
mode:
authorQuentin Young <qlyoung@cumulusnetworks.com>2016-07-19 21:14:27 +0000
committerQuentin Young <qlyoung@cumulusnetworks.com>2016-07-19 21:14:27 +0000
commit9d0662e009c0cf4532b88c9a1fb0f7c0dc174584 (patch)
treeab301ab5ec4b58a249df43e09fbc21154e879499 /lib/command_match.c
parent340a2b4ac0bcc737e24aa6c0e383f1188aaaaf61 (diff)
lib: Break up functions, begin matcher
Moved test hook out of command.c into vtysh.c, renamed graph modules, added matching code Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'lib/command_match.c')
-rw-r--r--lib/command_match.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/lib/command_match.c b/lib/command_match.c
new file mode 100644
index 0000000000..bcc28bdc5b
--- /dev/null
+++ b/lib/command_match.c
@@ -0,0 +1,174 @@
+#include <zebra.h>
+#include "memory.h"
+#include "command_match.h"
+
+enum match_type
+match_command (struct graph_node *start, enum filter_type filter, const char *input)
+{
+ // match input on DFA
+ return exact_match;
+}
+
+
+#define IPV4_ADDR_STR "0123456789."
+#define IPV4_PREFIX_STR "0123456789./"
+
+enum match_type
+cmd_ipv4_match (const char *str)
+{
+ struct sockaddr_in sin_dummy;
+
+ if (str == NULL)
+ return partly_match;
+
+ if (strspn (str, IPV4_ADDR_STR) != strlen (str))
+ return no_match;
+
+ if (inet_pton(AF_INET, str, &sin_dummy.sin_addr) != 1)
+ return no_match;
+
+ return exact_match;
+}
+
+enum match_type
+cmd_ipv4_prefix_match (const char *str)
+{
+ struct sockaddr_in sin_dummy;
+ const char *delim = "/\0";
+ char *dupe, *prefix, *mask, *context, *endptr;
+ int nmask = -1;
+
+ if (str == NULL)
+ return partly_match;
+
+ if (strspn (str, IPV4_PREFIX_STR) != strlen (str))
+ return no_match;
+
+ /* tokenize to address + mask */
+ dupe = XMALLOC(MTYPE_TMP, strlen(str)+1);
+ strncpy(dupe, str, strlen(str)+1);
+ prefix = strtok_r(dupe, delim, &context);
+ mask = strtok_r(NULL, delim, &context);
+
+ if (!mask)
+ return partly_match;
+
+ /* validate prefix */
+ if (inet_pton(AF_INET, prefix, &sin_dummy.sin_addr) != 1)
+ return no_match;
+
+ /* validate mask */
+ nmask = strtol (mask, &endptr, 10);
+ if (*endptr != '\0' || nmask < 0 || nmask > 32)
+ return no_match;
+
+ XFREE(MTYPE_TMP, dupe);
+
+ return exact_match;
+}
+
+#define IPV6_ADDR_STR "0123456789abcdefABCDEF:."
+#define IPV6_PREFIX_STR "0123456789abcdefABCDEF:./"
+
+#ifdef HAVE_IPV6
+enum match_type
+cmd_ipv6_match (const char *str)
+{
+ struct sockaddr_in6 sin6_dummy;
+ int ret;
+
+ if (str == NULL)
+ return partly_match;
+
+ 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;
+}
+
+enum match_type
+cmd_ipv6_prefix_match (const char *str)
+{
+ struct sockaddr_in6 sin6_dummy;
+ const char *delim = "/\0";
+ char *dupe, *prefix, *mask, *context, *endptr;
+ int nmask = -1;
+
+ if (str == NULL)
+ return partly_match;
+
+ if (strspn (str, IPV6_PREFIX_STR) != strlen (str))
+ return no_match;
+
+ /* tokenize to address + mask */
+ dupe = XMALLOC(MTYPE_TMP, strlen(str)+1);
+ strncpy(dupe, str, strlen(str)+1);
+ prefix = strtok_r(dupe, delim, &context);
+ mask = strtok_r(NULL, delim, &context);
+
+ if (!mask)
+ return partly_match;
+
+ /* validate prefix */
+ if (inet_pton(AF_INET6, prefix, &sin6_dummy.sin6_addr) != 1)
+ return no_match;
+
+ /* validate mask */
+ nmask = strtol (mask, &endptr, 10);
+ if (*endptr != '\0' || nmask < 0 || nmask > 128)
+ return no_match;
+
+ XFREE(MTYPE_TMP, dupe);
+
+ return exact_match;
+}
+#endif
+
+enum match_type
+cmd_range_match (struct graph_node *rangenode, const char *str)
+{
+ char *endptr = NULL;
+ signed long long val;
+
+ if (str == NULL)
+ return 1;
+
+ val = strtoll (str, &endptr, 10);
+ if (*endptr != '\0')
+ return 0;
+ val = llabs(val);
+
+ if (val < rangenode->min || val > rangenode->max)
+ return no_match;
+ else
+ return exact_match;
+}
+
+enum match_type
+cmd_word_match(struct graph_node *wordnode,
+ enum filter_type filter,
+ const char *word)
+{
+ if (filter == FILTER_RELAXED)
+ if (!word || !strlen(word))
+ return partly_match;
+
+ if (!word)
+ return no_match;
+
+ if (filter == FILTER_RELAXED && !strncmp(wordnode->text, word, strlen(word)))
+ {
+ if (!strcmp(wordnode->text, word))
+ return exact_match;
+ return partly_match;
+ }
+ if (filter == FILTER_STRICT && !strcmp(wordnode->text, word))
+ return exact_match;
+
+ return no_match;
+}