From: Vincent Bernat Date: Thu, 6 Mar 2014 16:55:22 +0000 (+0100) Subject: interfaces: document and test pattern matching X-Git-Tag: 0.7.8~34 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d5e69431014a0e1afcaf866f3b44650e57d7fb54;p=thirdparty%2Flldpd.git interfaces: document and test pattern matching --- diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am index 231b1d3a..48d5c787 100644 --- a/src/daemon/Makefile.am +++ b/src/daemon/Makefile.am @@ -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"' diff --git a/src/daemon/interfaces.c b/src/daemon/interfaces.c index 86430e43..0f122939 100644 --- a/src/daemon/interfaces.c +++ b/src/daemon/interfaces.c @@ -22,7 +22,6 @@ #include #include #include -#include #include /* 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) diff --git a/src/daemon/lldpd.h b/src/daemon/lldpd.h index 38bb0fbf..fa66636a 100644 --- a/src/daemon/lldpd.h +++ b/src/daemon/lldpd.h @@ -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 index 00000000..10aa770e --- /dev/null +++ b/src/daemon/pattern.c @@ -0,0 +1,65 @@ +/* -*- mode: c; c-file-style: "openbsd" -*- */ +/* + * Copyright (c) 2008 Vincent Bernat + * + * 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 +#include + +/** + * 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; +} diff --git a/tests/Makefile.am b/tests/Makefile.am index 2abb67b8..c5e2fccb 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 index 00000000..58e63a33 --- /dev/null +++ b/tests/check_pattern.c @@ -0,0 +1,118 @@ +/* -*- mode: c; c-file-style: "openbsd" -*- */ +/* + * Copyright (c) 2014 Vincent Bernat + * + * 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 + +#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; +}