]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
interfaces: circumvent any physical check on exact match
authorVincent Bernat <vbe@deezer.com>
Thu, 6 Mar 2014 17:28:21 +0000 (18:28 +0100)
committerVincent Bernat <vbe@deezer.com>
Thu, 6 Mar 2014 17:28:21 +0000 (18:28 +0100)
When enabling an interface with `-I eth0`, any physical check will be
circumvented. This allows lldpd to send and receive on VLAN interfaces.

NEWS
src/daemon/interfaces.c
src/daemon/lldpd.8
src/daemon/lldpd.h
src/daemon/pattern.c
tests/check_pattern.c

diff --git a/NEWS b/NEWS
index e77168aa6a7ba363a725a74074e87e0af9f0df28..8ca649f6cbbeb2393b3b7db13324387010c8f98a 100644 (file)
--- 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:
index 0f1229390551ca616b590d0b811d699ec4080fe4..33638dd5798dd9a42b8badc32b21d9c1a9ff85a2 100644 (file)
@@ -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",
index da10a6eb7c560d3737d09b28e982b9c98b84d20c..c62b1e7b0e8789f4084af36666bc0cf052ba7d60 100644 (file)
@@ -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.
index fa66636abcd68da6a7d72c835e7cf3c0dfa203fb..adffaebb1f4b10a492a747cf8a4cacd60e7669ba 100644 (file)
@@ -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) */
 
index 059effdd5c0407f10dc45584e33395b6fec4aace..11e69a8ce5f4f5d73f274a24e773a6f43c6f0e0b 100644 (file)
  *                 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);
index 939b1f99989b9fc39e680a855bb7ae9b9033e554..197c228c0e0c7dfa40d1114058931c48b1ff8d9b 100644 (file)
@@ -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