]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
interfaces: enable matching on interface name for management address feature/management-device
authorVincent Bernat <vincent@bernat.ch>
Sun, 15 Sep 2019 15:45:52 +0000 (17:45 +0200)
committerVincent Bernat <vincent@bernat.ch>
Sun, 15 Sep 2019 15:47:41 +0000 (17:47 +0200)
We allow the user to match a management address using the interface
name by specifying the interface name as a pattern. The same rules as
for specifying IP patterns apply but there is no notion of exact match
for an interface.

Fix #349.

NEWS
src/client/lldpcli.8.in
src/daemon/interfaces-bsd.c
src/daemon/interfaces-linux.c
src/daemon/interfaces-solaris.c
src/daemon/interfaces.c
src/daemon/lldpd.8.in
src/daemon/lldpd.h
tests/integration/test_basic.py

diff --git a/NEWS b/NEWS
index 2fb526265b6149ce76d5a73d2bc0849e3685b624..0a27324a5b6c46d87dcd3473ceb36f54b7d06062 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+lldpd (1.0.5)
+  * Changes:
+    + Interface names are also matched for management addresses.
+
 lldpd (1.0.4)
   * Changes:
     + Add "configure system max-neighbors XX" command to modify maximum
index bf902b0d61fdac31394ab0d9538d1e3d3bac3580..65b3d94db0fabce9c6824d585317fc66a65251ce 100644 (file)
@@ -391,6 +391,8 @@ without any check. If only negative patterns are provided, only one
 IPv4 and one IPv6 addresses are chosen. Otherwise, many of them can be
 selected. If you want to blacklist IPv6 addresses, you can use
 .Em !*:* .
+If an interface name is matched, the first IPv4 address and the first
+IPv6 address associated to this interface will be chosen.
 .Ed
 
 .Cd unconfigure
index 458e02cddb3e01f84c6db9c195c291669b957c98..341490a5ab6031a79d3491d205c3501faede2572 100644 (file)
@@ -672,7 +672,7 @@ interfaces_update(struct lldpd *cfg)
 #ifdef ENABLE_DOT1
        interfaces_helper_vlan(cfg, interfaces);
 #endif
-       interfaces_helper_mgmt(cfg, addresses);
+       interfaces_helper_mgmt(cfg, addresses, interfaces);
        interfaces_helper_chassis(cfg, interfaces);
 
        /* Mac/PHY */
index a8280c851ea9200e58cda2d3e93655192ca76c9c..b57758d37191ec4e49b3da59eb215b2b49984c9c 100644 (file)
@@ -1020,7 +1020,7 @@ interfaces_update(struct lldpd *cfg)
 #ifdef ENABLE_DOT1
        interfaces_helper_vlan(cfg, interfaces);
 #endif
-       interfaces_helper_mgmt(cfg, addresses);
+       interfaces_helper_mgmt(cfg, addresses, interfaces);
        interfaces_helper_chassis(cfg, interfaces);
 
        /* Mac/PHY */
index 0f9f5e5380102195170ac130eb24d0d9df12132e..f9d8bc5232132b9f3b767eeece97b4243b466907 100644 (file)
@@ -164,7 +164,7 @@ interfaces_update(struct lldpd *cfg) {
        interfaces_helper_whitelist(cfg, interfaces);
        interfaces_helper_physical(cfg, interfaces,
            &bpf_ops, ifbpf_phys_init);
-       interfaces_helper_mgmt(cfg, addresses);
+       interfaces_helper_mgmt(cfg, addresses, interfaces);
        interfaces_helper_chassis(cfg, interfaces);
 
        /* Mac/PHY */
index e6fcc551defc382b63780b589f87cf79414e8509..953e9711600bb5d0475f0ded0be9650ea52c648f 100644 (file)
@@ -390,9 +390,11 @@ static int
 interfaces_helper_mgmt_for_af(struct lldpd *cfg,
     int af,
     struct interfaces_address_list *addrs,
+    struct interfaces_device_list *interfaces,
     int global, int allnegative)
 {
        struct interfaces_address *addr;
+       struct interfaces_device *device;
        struct lldpd_mgmt *mgmt;
        char addrstrbuf[INET6_ADDRSTRLEN];
        int found = 0;
@@ -438,7 +440,11 @@ interfaces_helper_mgmt_for_af(struct lldpd *cfg,
                        continue;
                }
                if (cfg->g_config.c_mgmt_pattern == NULL ||
-                   pattern_match(addrstrbuf, cfg->g_config.c_mgmt_pattern, allnegative)) {
+                   /* Match on IP address */
+                   pattern_match(addrstrbuf, cfg->g_config.c_mgmt_pattern, allnegative) ||
+                   /* Match on interface name */
+                   ((device = interfaces_indextointerface(interfaces, addr->index)) &&
+                   pattern_match(device->name, cfg->g_config.c_mgmt_pattern, allnegative))) {
                        mgmt = lldpd_alloc_mgmt(af, &in_addr, in_addr_size,
                            addr->index);
                        if (mgmt == NULL) {
@@ -463,7 +469,8 @@ interfaces_helper_mgmt_for_af(struct lldpd *cfg,
    to the local chassis). */
 void
 interfaces_helper_mgmt(struct lldpd *cfg,
-    struct interfaces_address_list *addrs)
+    struct interfaces_address_list *addrs,
+    struct interfaces_device_list *interfaces)
 {
        int allnegative = 0;
        int af;
@@ -490,39 +497,36 @@ interfaces_helper_mgmt(struct lldpd *cfg,
                        if (inet_pton(lldpd_af(af), pattern, &addr) == 1)
                                break;
                }
-               if (af == LLDPD_AF_LAST) {
-                       log_debug("interfaces",
-                           "interface management pattern is an incorrect IP");
-                       return;
-               }
-
-               /* Try to get the index if possible. */
-               TAILQ_FOREACH(ifaddr, addrs, next) {
-                       if (ifaddr->address.ss_family != lldpd_af(af))
-                               continue;
-                       if (LLDPD_AF_IPV4 == af) {
-                               struct sockaddr_in *sa_sin;
-                               sa_sin = (struct sockaddr_in *)&ifaddr->address;
-                               if ((sa_sin->sin_addr.s_addr) == ((struct in_addr *)&addr)->s_addr)
-                                       break;
-                       }
-                       else if (LLDPD_AF_IPV6 == af) {
-                               if (0 == memcmp(&addr,
-                                   &((struct sockaddr_in6 *)&ifaddr->address)->sin6_addr,
-                                   addr_size))
-                                       break;
+               if (af != LLDPD_AF_LAST) {
+                       /* Try to get the index if possible. */
+                       TAILQ_FOREACH(ifaddr, addrs, next) {
+                               if (ifaddr->address.ss_family != lldpd_af(af))
+                                       continue;
+                               if (LLDPD_AF_IPV4 == af) {
+                                       struct sockaddr_in *sa_sin;
+                                       sa_sin = (struct sockaddr_in *)&ifaddr->address;
+                                       if ((sa_sin->sin_addr.s_addr) == ((struct in_addr *)&addr)->s_addr)
+                                               break;
+                               }
+                               else if (LLDPD_AF_IPV6 == af) {
+                                       if (0 == memcmp(&addr,
+                                           &((struct sockaddr_in6 *)&ifaddr->address)->sin6_addr,
+                                           addr_size))
+                                               break;
+                               }
                        }
-               }
 
-               mgmt = lldpd_alloc_mgmt(af, &addr, addr_size, ifaddr ? ifaddr->index : 0);
-               if (mgmt == NULL) {
-                       log_warn("interfaces", "out of memory error");
+                       mgmt = lldpd_alloc_mgmt(af, &addr, addr_size, ifaddr ? ifaddr->index : 0);
+                       if (mgmt == NULL) {
+                               log_warn("interfaces", "out of memory error");
+                               return;
+                       }
+                       log_debug("interfaces", "add exact management address %s",
+                           pattern);
+                       TAILQ_INSERT_TAIL(&LOCAL_CHASSIS(cfg)->c_mgmt, mgmt, m_entries);
                        return;
                }
-               log_debug("interfaces", "add exact management address %s",
-                   pattern);
-               TAILQ_INSERT_TAIL(&LOCAL_CHASSIS(cfg)->c_mgmt, mgmt, m_entries);
-               return;
+               /* else: could be an interface name */
        }
 
        /* Is the pattern provided all negative? */
@@ -538,8 +542,8 @@ interfaces_helper_mgmt(struct lldpd *cfg,
 
        /* Find management addresses */
        for (af = LLDPD_AF_UNSPEC + 1; af != LLDPD_AF_LAST; af++) {
-               (void)(interfaces_helper_mgmt_for_af(cfg, af, addrs, 1, allnegative) ||
-                   interfaces_helper_mgmt_for_af(cfg, af, addrs, 0, allnegative));
+               (void)(interfaces_helper_mgmt_for_af(cfg, af, addrs, interfaces, 1, allnegative) ||
+                   interfaces_helper_mgmt_for_af(cfg, af, addrs, interfaces, 0, allnegative));
        }
 }
 
index 9534ebb0f6be30e8fa41025a41157e79ba196738..e50404340b1d28b85251c6d74ff8533dcb97dc24 100644 (file)
@@ -198,6 +198,8 @@ without any check. If only negative patterns are provided, only one
 IPv4 and one IPv6 addresses are chosen. Otherwise, many of them can be
 selected. If you want to blacklist IPv6 addresses, you can use
 .Em !*:* .
+If an interface name is matched, the first IPv4 address and the first
+IPv6 address associated to this interface will be chosen.
 .It Fl u Ar file
 Specify the Unix-domain socket used for communication with
 .Xr lldpctl 8 .
index cf25dd678d379e6b8cb4e033e11aa8ca5cd68660..12c745edd19547a8607337456cad266d66a8b95a 100644 (file)
@@ -361,7 +361,8 @@ void interfaces_helper_port_name_desc(struct lldpd *,
     struct lldpd_hardware *,
     struct interfaces_device *);
 void interfaces_helper_mgmt(struct lldpd *,
-    struct interfaces_address_list *);
+    struct interfaces_address_list *,
+    struct interfaces_device_list *);
 #ifdef ENABLE_DOT1
 void interfaces_helper_vlan(struct lldpd *,
     struct interfaces_device_list *);
index 3e31d5327bc6f545af2b4a237e366a89166cce34..e0f1329d3c8026a943d04dd1d51aa4298a85288e 100644 (file)
@@ -180,6 +180,22 @@ def test_management_address(lldpd1, lldpd, lldpcli, links, namespaces):
         assert out["lldp.eth0.chassis.mgmt-iface"] == "2"
 
 
+def test_management_interface(lldpd1, lldpd, lldpcli, links, namespaces):
+    links(namespaces(1), namespaces(2), 4)
+    with namespaces(2):
+        ipr = pyroute2.IPRoute()
+        idx = ipr.link_lookup(ifname="eth1")[0]
+        ipr.addr('add', index=idx, address="192.168.14.2", mask=24)
+        idx = ipr.link_lookup(ifname="eth3")[0]
+        ipr.addr('add', index=idx, address="172.25.21.47", mask=24)
+        lldpd("-m", "eth3")
+    with namespaces(1):
+        out = lldpcli("-f", "keyvalue", "show", "neighbors")
+        assert out["lldp.eth0.chassis.mgmt-ip"] == ["172.25.21.47",
+                                                    "fe80::200:ff:fe00:4"]
+        assert out["lldp.eth0.chassis.mgmt-iface"] == ["4", "4"]
+
+
 def test_change_management_address(lldpd1, lldpd, lldpcli, links, namespaces):
     with namespaces(2):
         ipr = pyroute2.IPRoute()