]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
interfaces: document and test pattern matching
authorVincent Bernat <vbe@deezer.com>
Thu, 6 Mar 2014 16:55:22 +0000 (17:55 +0100)
committerVincent Bernat <vbe@deezer.com>
Thu, 6 Mar 2014 16:55:22 +0000 (17:55 +0100)
src/daemon/Makefile.am
src/daemon/interfaces.c
src/daemon/lldpd.h
src/daemon/pattern.c [new file with mode: 0644]
tests/Makefile.am
tests/check_pattern.c [new file with mode: 0644]

index 231b1d3a3fc517fad2079c4f61d7e8f4ae556733..48d5c78758751b345dbba0d371d97b4a0bfb83e2 100644 (file)
@@ -19,6 +19,7 @@ liblldpd_la_SOURCES  = \
        priv.c privsep_io.c \
        interfaces.c \
        event.c lldpd.c \
+       pattern.c \
        probes.d trace.h
 liblldpd_la_CFLAGS   = $(AM_CFLAGS) @LIBEVENT_CFLAGS@
 liblldpd_la_CPPFLAGS = -DSYSCONFDIR='"$(sysconfdir)"' -DLLDPCLI_PATH='"$(sbindir)/lldpcli"'
index 86430e43f2a4d4df18469bd1d9eaabf3884a8e33..0f1229390551ca616b590d0b811d699ec4080fe4 100644 (file)
@@ -22,7 +22,6 @@
 #include <unistd.h>
 #include <errno.h>
 #include <assert.h>
-#include <fnmatch.h>
 #include <arpa/inet.h>
 
 /* Generic ethernet interface initialization */
@@ -157,34 +156,6 @@ interfaces_indextointerface(struct interfaces_device_list *interfaces,
        return NULL;
 }
 
-static int
-pattern_match(char *iface, char *list, int found)
-{
-       char *interfaces = NULL;
-       char *pattern;
-
-       if ((interfaces = strdup(list)) == NULL) {
-               log_warnx("interfaces", "unable to allocate memory");
-               return 0;
-       }
-
-       for (pattern = strtok(interfaces, ",");
-            pattern != NULL;
-            pattern = strtok(NULL, ",")) {
-               if ((pattern[0] == '!') &&
-                   ((fnmatch(pattern + 1, iface, 0) == 0))) {
-                       /* Blacklisted. No need to search further. */
-                       found = 0;
-                       break;
-               }
-               if (fnmatch(pattern, iface, 0) == 0)
-                       found = 1;
-       }
-
-       free(interfaces);
-       return found;
-}
-
 void
 interfaces_helper_whitelist(struct lldpd *cfg,
     struct interfaces_device_list *interfaces)
index 38bb0fbf417c4e043416b91a436581cb7c5cb77f..fa66636abcd68da6a7d72c835e7cf3c0dfa203fb 100644 (file)
@@ -402,4 +402,7 @@ int netlink_subscribe_changes(void);
 int ifbpf_phys_init(struct lldpd *, struct lldpd_hardware *);
 #endif
 
+/* pattern.c */
+int pattern_match(char *, char *, int);
+
 #endif /* _LLDPD_H */
diff --git a/src/daemon/pattern.c b/src/daemon/pattern.c
new file mode 100644 (file)
index 0000000..10aa770
--- /dev/null
@@ -0,0 +1,65 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "lldpd.h"
+
+#include <string.h>
+#include <fnmatch.h>
+
+/**
+ * Match a list of patterns.
+ *
+ * @param string   String to match against the list of patterns
+ * @param patterns List of comma separated patterns. A pattern may
+ *                 begin by `!` to negate it. In this case, it is
+ *                 blacklisted. Each pattern will then be matched
+ *                 against `fnmatch()` function.
+ * @param found    Value to return if the pattern isn't found.
+ *
+ * If a pattern is found matching and blacklisted at the same time, it
+ * will be blacklisted.
+ *
+ * @return 0 if the string matches a blacklisted pattern or if the
+ *         pattern wasn't found and `found` was set to 0. Otherwise,
+ *         return 1.
+ */
+int
+pattern_match(char *string, char *patterns, int found)
+{
+       char *pattern;
+
+       if ((patterns = strdup(patterns)) == NULL) {
+               log_warnx("interfaces", "unable to allocate memory");
+               return 0;
+       }
+
+       for (pattern = strtok(patterns, ",");
+            pattern != NULL;
+            pattern = strtok(NULL, ",")) {
+               if ((pattern[0] == '!') &&
+                   ((fnmatch(pattern + 1, string, 0) == 0))) {
+                       /* Blacklisted. No need to search further. */
+                       found = 0;
+                       break;
+               }
+               if (fnmatch(pattern, string, 0) == 0)
+                       found = 1;
+       }
+
+       free(patterns);
+       return found;
+}
index 2abb67b8c573c2ad5a8eb36dad34a25b7a810e97..c5e2fccbcd8a702fa3324308cdbbc92397119c87 100644 (file)
@@ -2,13 +2,16 @@ AM_CFLAGS = -I $(top_srcdir)/include
 
 if HAVE_CHECK
 
-TESTS = check_marshal check_lldp check_cdp check_sonmp check_edp check_fixedpoint
+TESTS = check_marshal check_pattern check_lldp check_cdp check_sonmp check_edp check_fixedpoint
 AM_CFLAGS += @CHECK_CFLAGS@
 LDADD = $(top_builddir)/src/daemon/liblldpd.la @CHECK_LIBS@ @LIBEVENT_LDFLAGS@
 
 check_marshal_SOURCES = check_marshal.c \
        $(top_srcdir)/src/marshal.h
 
+check_pattern_SOURCES = check_pattern.c \
+       $(top_srcdir)/src/daemon/lldpd.h
+
 check_lldp_SOURCES = check_lldp.c \
        $(top_srcdir)/src/daemon/lldpd.h \
        common.h common.c
diff --git a/tests/check_pattern.c b/tests/check_pattern.c
new file mode 100644 (file)
index 0000000..58e63a3
--- /dev/null
@@ -0,0 +1,118 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2014 Vincent Bernat <bernat@luffy.cx>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <check.h>
+
+#include "../src/daemon/lldpd.h"
+
+START_TEST(test_empty) {
+       ck_assert_int_eq(pattern_match("eth0", "", 0), 0);
+       ck_assert_int_eq(pattern_match("eth0", "", 1), 1);
+}
+END_TEST
+
+START_TEST(test_simple_match) {
+       ck_assert_int_eq(pattern_match("eth0", "eth0", 0), 1);
+       ck_assert_int_eq(pattern_match("eth0", "eth0", 1), 1);
+       ck_assert_int_eq(pattern_match("eth0", "eth1", 0), 0);
+       ck_assert_int_eq(pattern_match("eth0", "eth1", 1), 1);
+}
+END_TEST
+
+START_TEST(test_wildcard) {
+       ck_assert_int_eq(pattern_match("eth0", "eth*", 0), 1);
+       ck_assert_int_eq(pattern_match("eth0", "eth*", 1), 1);
+       ck_assert_int_eq(pattern_match("vlan0", "eth*", 0), 0);
+       ck_assert_int_eq(pattern_match("vlan0", "eth*", 1), 1);
+}
+END_TEST
+
+START_TEST(test_match_list) {
+       ck_assert_int_eq(pattern_match("eth0", "eth0,eth1,eth2", 0), 1);
+       ck_assert_int_eq(pattern_match("eth1", "eth0,eth1,eth2", 0), 1);
+       ck_assert_int_eq(pattern_match("eth3", "eth0,eth1,eth2", 0), 0);
+       ck_assert_int_eq(pattern_match("eth3", "eth0,eth1,eth2", 1), 1);
+}
+END_TEST
+
+START_TEST(test_match_list_with_wildcards) {
+       ck_assert_int_eq(pattern_match("eth0", "eth0,eth*,eth2", 0), 1);
+       ck_assert_int_eq(pattern_match("eth1", "eth0,eth*,eth2", 0), 1);
+       ck_assert_int_eq(pattern_match("eth3", "eth0,eth*,eth2", 0), 1);
+       ck_assert_int_eq(pattern_match("vlan3", "eth0,eth*,eth2", 0), 0);
+       ck_assert_int_eq(pattern_match("vlan3", "eth0,eth*,eth2", 1), 1);
+}
+END_TEST
+
+START_TEST(test_simple_blacklist) {
+       ck_assert_int_eq(pattern_match("eth0", "!eth0", 0), 0);
+       ck_assert_int_eq(pattern_match("eth0", "!eth0", 1), 0);
+       ck_assert_int_eq(pattern_match("eth1", "!eth0", 0), 0);
+       ck_assert_int_eq(pattern_match("eth1", "!eth0", 1), 1);
+}
+END_TEST
+
+START_TEST(test_match_and_blacklist) {
+       ck_assert_int_eq(pattern_match("eth0", "eth0,!eth0", 0), 0);
+       ck_assert_int_eq(pattern_match("eth0", "eth0,!eth0", 1), 0);
+       ck_assert_int_eq(pattern_match("eth1", "eth0,!eth0", 0), 0);
+       ck_assert_int_eq(pattern_match("eth1", "eth0,!eth0", 1), 1);
+}
+END_TEST
+
+START_TEST(test_blacklist_wildcard) {
+       ck_assert_int_eq(pattern_match("eth0", "!eth*", 0), 0);
+       ck_assert_int_eq(pattern_match("eth0", "!eth*", 1), 0);
+       ck_assert_int_eq(pattern_match("eth1", "!eth*", 0), 0);
+       ck_assert_int_eq(pattern_match("eth1", "!eth*", 1), 0);
+       ck_assert_int_eq(pattern_match("eth1", "eth*,!eth1", 0), 0);
+       ck_assert_int_eq(pattern_match("eth1", "eth*,!eth1", 1), 0);
+       ck_assert_int_eq(pattern_match("eth0", "eth*,!eth1", 0), 1);
+       ck_assert_int_eq(pattern_match("eth0", "eth*,!eth1", 1), 1);
+}
+END_TEST
+
+Suite *
+pattern_suite(void)
+{
+       Suite *s = suite_create("Pattern matching");
+
+       TCase *tc_pattern = tcase_create("Pattern matching");
+       tcase_add_test(tc_pattern, test_empty);
+       tcase_add_test(tc_pattern, test_simple_match);
+       tcase_add_test(tc_pattern, test_wildcard);
+       tcase_add_test(tc_pattern, test_match_list);
+       tcase_add_test(tc_pattern, test_match_list_with_wildcards);
+       tcase_add_test(tc_pattern, test_simple_blacklist);
+       tcase_add_test(tc_pattern, test_match_and_blacklist);
+       tcase_add_test(tc_pattern, test_blacklist_wildcard);
+       suite_add_tcase(s, tc_pattern);
+
+       return s;
+}
+
+int
+main()
+{
+       int number_failed;
+       Suite *s = pattern_suite();
+       SRunner *sr = srunner_create(s);
+       srunner_run_all(sr, CK_ENV);
+       number_failed = srunner_ntests_failed(sr);
+       srunner_free(sr);
+       return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}