From: Vincent Bernat Date: Thu, 6 Mar 2014 17:28:21 +0000 (+0100) Subject: interfaces: circumvent any physical check on exact match X-Git-Tag: 0.7.8~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=627e31c489e61026ec0d39117b17389f5460c56e;p=thirdparty%2Flldpd.git interfaces: circumvent any physical check on exact match When enabling an interface with `-I eth0`, any physical check will be circumvented. This allows lldpd to send and receive on VLAN interfaces. --- diff --git a/NEWS b/NEWS index e77168aa..8ca649f6 100644 --- a/NEWS +++ b/NEWS @@ -10,7 +10,8 @@ lldpd (0.7.8) memory consumption, lower security, don't do it). + Interfaces can now be whitelisted. For example, *,!eth*,!!eth1 is a valid pattern for all interfaces except eth ones, except - eth1. + eth1. Moreover, on exact match, an matching interface + circumvents most sanity checks (like VLAN handling). lldpd (0.7.7) * Features: diff --git a/src/daemon/interfaces.c b/src/daemon/interfaces.c index 0f122939..33638dd5 100644 --- a/src/daemon/interfaces.c +++ b/src/daemon/interfaces.c @@ -166,11 +166,16 @@ interfaces_helper_whitelist(struct lldpd *cfg, return; TAILQ_FOREACH(iface, interfaces, next) { - if (iface->flags == 0) continue; /* Already handled by someone else */ - if (!pattern_match(iface->name, cfg->g_config.c_iface_pattern, 0)) { - /* This interface was not found. We flag it. */ + int m = pattern_match(iface->name, cfg->g_config.c_iface_pattern, 0); + switch (m) { + case 0: log_debug("interfaces", "blacklist %s", iface->name); iface->flags = 0; + continue; + case 2: + log_debug("interfaces", "whitelist %s", iface->name); + iface->whitelisted = 1; + continue; } } } @@ -487,7 +492,7 @@ interfaces_helper_physical(struct lldpd *cfg, struct lldpd_hardware *hardware; TAILQ_FOREACH(iface, interfaces, next) { - if (!(iface->type & IFACE_PHYSICAL_T)) continue; + if (!(iface->type & IFACE_PHYSICAL_T) && !iface->whitelisted) continue; if (!iface->flags) continue; log_debug("interfaces", "%s is an acceptable ethernet device", diff --git a/src/daemon/lldpd.8 b/src/daemon/lldpd.8 index da10a6eb..c62b1e7b 100644 --- a/src/daemon/lldpd.8 +++ b/src/daemon/lldpd.8 @@ -213,6 +213,9 @@ will listen to all interfaces, except interfaces starting by .Em eth with the exception of .Em eth1 . +When an exact match is found, it will circumvent some tests. For example, if +.Em eth0.12 +is specified, it will be accepted even if this is a VLAN interface. .It Fl C Ar interfaces Specify which interfaces to use for computing chassis ID. Without this option, all interfaces are considered. diff --git a/src/daemon/lldpd.h b/src/daemon/lldpd.h index fa66636a..adffaebb 100644 --- a/src/daemon/lldpd.h +++ b/src/daemon/lldpd.h @@ -335,6 +335,7 @@ struct interfaces_device { int mtu; /* MTU */ int type; /* Type (see IFACE_*_T) */ int vlanid; /* If a VLAN, what is the VLAN ID? */ + int whitelisted; /* If the interface has been whitelisted */ struct interfaces_device *lower; /* Lower interface (for a VLAN for example) */ struct interfaces_device *upper; /* Upper interface (for a bridge or a bond) */ diff --git a/src/daemon/pattern.c b/src/daemon/pattern.c index 059effdd..11e69a8c 100644 --- a/src/daemon/pattern.c +++ b/src/daemon/pattern.c @@ -29,21 +29,24 @@ * blacklisted. A pattern may begin with `!!`. In this * case, it is whitelisted. Each pattern will then be * matched against `fnmatch()` function. - * @param found Value to return if the pattern isn't found. + * @param found Value to return if the pattern isn't found. Should be either 0 + * or 1. * * If a pattern is found matching and blacklisted at the same time, it * will be blacklisted. If it is both whitelisted and blacklisted, it * will be whitelisted. * * @return 0 if the string matches a blacklisted pattern which is not - * whitelisted or if the pattern wasn't found and `found` was - * set to 0. Otherwise, return 1. + * whitelisted or if the pattern wasn't found and `found` was set to + * 0. Otherwise, return 1 unless the interface match is exact, in this + * case return 2. */ int pattern_match(char *string, char *patterns, int found) { char *pattern; int blacklisted = 0; + found = !!found; if ((patterns = strdup(patterns)) == NULL) { log_warnx("interfaces", "unable to allocate memory"); @@ -56,15 +59,20 @@ pattern_match(char *string, char *patterns, int found) if ((pattern[0] == '!') && (pattern[1] == '!') && (fnmatch(pattern + 2, string, 0) == 0)) { /* Whitelisted. No need to search further. */ - found = 1; + found = (strcmp(pattern + 2, string))?1:2; break; } if ((pattern[0] == '!') && (fnmatch(pattern + 1, string, 0) == 0)) { blacklisted = 1; found = 0; - } else if (!blacklisted && fnmatch(pattern, string, 0) == 0) - found = 1; + } else if (!blacklisted && fnmatch(pattern, string, 0) == 0) { + if (!strcmp(pattern, string)) { + found = 2; + } else if (found < 2) { + found = 1; + } + } } free(patterns); diff --git a/tests/check_pattern.c b/tests/check_pattern.c index 939b1f99..197c228c 100644 --- a/tests/check_pattern.c +++ b/tests/check_pattern.c @@ -26,8 +26,8 @@ START_TEST(test_empty) { 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", "eth0", 0), 2); + ck_assert_int_eq(pattern_match("eth0", "eth0", 1), 2); ck_assert_int_eq(pattern_match("eth0", "eth1", 0), 0); ck_assert_int_eq(pattern_match("eth0", "eth1", 1), 1); } @@ -42,16 +42,17 @@ START_TEST(test_wildcard) { 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("eth0", "eth0,eth1,eth2", 0), 2); + ck_assert_int_eq(pattern_match("eth1", "eth0,eth1,eth2", 0), 2); 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("eth0", "eth0,eth*,eth2", 0), 2); ck_assert_int_eq(pattern_match("eth1", "eth0,eth*,eth2", 0), 1); + ck_assert_int_eq(pattern_match("eth2", "eth0,eth*,eth2", 0), 2); 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); @@ -87,20 +88,21 @@ START_TEST(test_blacklist_wildcard) { END_TEST START_TEST(test_whitelist) { - 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", "!eth*,!!eth0", 0), 1); - ck_assert_int_eq(pattern_match("eth0", "!eth*,!!eth0", 1), 1); + ck_assert_int_eq(pattern_match("eth0", "!!eth0", 0), 2); + ck_assert_int_eq(pattern_match("eth0", "!!eth0", 1), 2); + ck_assert_int_eq(pattern_match("eth1", "!!eth0", 1), 1); + ck_assert_int_eq(pattern_match("eth0", "!eth*,!!eth0", 0), 2); + ck_assert_int_eq(pattern_match("eth0", "!eth*,!!eth0", 1), 2); ck_assert_int_eq(pattern_match("eth1", "!eth*,!!eth0", 0), 0); ck_assert_int_eq(pattern_match("eth1", "!eth*,!!eth0", 1), 0); ck_assert_int_eq(pattern_match("vlan0", "*,!eth*,!!eth0", 0), 1); ck_assert_int_eq(pattern_match("vlan0", "*,!eth*,!!eth0", 1), 1); - ck_assert_int_eq(pattern_match("eth0", "*,!eth*,!!eth0", 0), 1); - ck_assert_int_eq(pattern_match("eth0", "*,!eth*,!!eth0", 1), 1); + ck_assert_int_eq(pattern_match("eth0", "*,!eth*,!!eth0", 0), 2); + ck_assert_int_eq(pattern_match("eth0", "*,!eth*,!!eth0", 1), 2); ck_assert_int_eq(pattern_match("eth1", "*,!eth*,!!eth0", 0), 0); ck_assert_int_eq(pattern_match("eth1", "*,!!eth0,!eth*", 1), 0); - ck_assert_int_eq(pattern_match("eth0", "*,!!eth0,!eth*", 0), 1); - ck_assert_int_eq(pattern_match("eth0", "*,!!eth0,!eth*", 1), 1); + ck_assert_int_eq(pattern_match("eth0", "*,!!eth0,!eth*", 0), 2); + ck_assert_int_eq(pattern_match("eth0", "*,!!eth0,!eth*", 1), 2); } END_TEST