]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
mgmt: allow one to provide a pattern to specify management addresses
authorVincent Bernat <bernat@luffy.cx>
Thu, 15 Mar 2012 22:28:55 +0000 (23:28 +0100)
committerVincent Bernat <bernat@luffy.cx>
Thu, 15 Mar 2012 22:30:25 +0000 (23:30 +0100)
man/lldpd.8
src/interfaces.c
src/lldpd.c
src/lldpd.h

index 3a5dbdb86e35185e6804b74dec0bd7166d40b5c1..4cf0ee31ea3475db85a0beac1a3cddb365e502a6 100644 (file)
@@ -117,11 +117,13 @@ Receive-only mode. With this switch,
 .Nm
 will not send any frame. It will only listen to neighbors.
 .It Fl m Ar management
-Specify the management address of this system.
-.Nm
-only sends one management address. It will use the first one that it
-finds or the one that you specify with this option. This option can
-use wildcards.
+Specify the management addresses of this system. As for interfaces
+(described below), this option can use wildcards and inversions.
+Without this option, the first IPv4 and the first IPv6 are used. If
+only negative patterns are provided, only one IPv4 and one IPv6
+addresses are choosen. Otherwise, many of them can be selected. If you
+want to blacklist IPv6 addresses, you can use
+.Em !*:* .
 .It Fl I Ar interfaces
 Specify which interface to listen to. Without this option,
 .Nm
index ea916e00ee6b057f151f5d78a464eb751bb7748f..e22dd115d4acce48e51f770a3b0c3f3ad1ba3fbd 100644 (file)
@@ -93,11 +93,10 @@ struct lldpd_ops eth_ops;
 struct lldpd_ops bond_ops;
 
 static int
-iface_match(char *iface, char *list)
+pattern_match(char *iface, char *list, int found)
 {
        char *interfaces = NULL;
        char *pattern;
-       int   found      = 0;
 
        if ((interfaces = strdup(list)) == NULL) {
                LLOG_WARNX("unable to allocate memory");
@@ -772,7 +771,7 @@ lldpd_ifh_whitelist(struct lldpd *cfg, struct ifaddrs *ifap)
 
        for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
                if (ifa->ifa_flags == 0) continue; /* Already handled by someone else */
-               if (!iface_match(ifa->ifa_name, cfg->g_interfaces)) {
+               if (!pattern_match(ifa->ifa_name, cfg->g_interfaces, 0)) {
                        /* This interface was not found. We flag it. */
                        LLOG_DEBUG("blacklist %s", ifa->ifa_name);
                        ifa->ifa_flags = 0;
@@ -1066,41 +1065,61 @@ lldpd_ifh_mgmt(struct lldpd *cfg, struct ifaddrs *ifap)
        struct lldpd_mgmt *mgmt;
        void *sin_addr_ptr;
        size_t sin_addr_size;
-       char *mgmt_pattern_ptr;
        int af;
+       int allnegative = 0;
 
        lldpd_chassis_mgmt_cleanup(LOCAL_CHASSIS(cfg));
 
+       /* Is the pattern provided all negative? */
+       if (cfg->g_mgmt_pattern == NULL) allnegative = 1;
+       else if (cfg->g_mgmt_pattern[0] == '!') {
+               /* If each comma is followed by '!', its an all
+                  negative pattern */
+               char *sep = cfg->g_mgmt_pattern;
+               while ((sep = strchr(sep, ',')) &&
+                      (*(++sep) == '!'));
+               if (sep == NULL) allnegative = 1;
+       }
+
        /* Find management addresses */
        for (af = LLDPD_AF_UNSPEC + 1; af != LLDPD_AF_LAST; af++) {
-               /* We only take one of each address family */
-               mgmt = NULL;
-               for (ifa = ifap; ifa != NULL && mgmt == NULL; ifa = ifa->ifa_next) {
+               /* We only take one of each address family, unless a
+                  pattern is provided and is not all negative. For
+                  example !*:*,!10.* will only blacklist
+                  addresses. We will pick the first IPv4 address not
+                  matching 10.*. */
+               for (ifa = ifap;
+                    ifa != NULL;
+                    ifa = ifa->ifa_next) {
                        if (ifa->ifa_addr == NULL)
                                continue;
                        if (ifa->ifa_addr->sa_family != lldpd_af(af))
                                continue;
+
                        switch (af) {
                        case LLDPD_AF_IPV4:
                                sin_addr_ptr = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
                                sin_addr_size = sizeof(struct in_addr);
                                if (!IN_IS_ADDR_GLOBAL((struct in_addr *)sin_addr_ptr))
                                        continue;
-                               mgmt_pattern_ptr = cfg->g_mgmt_pattern;
                                break;
                        case LLDPD_AF_IPV6:
                                sin_addr_ptr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
                                sin_addr_size = sizeof(struct in6_addr);
                                if (!IN6_IS_ADDR_GLOBAL((struct in6_addr *)sin_addr_ptr))
                                        continue;
-                               mgmt_pattern_ptr = cfg->g_mgmt_pattern6;
                                break;
                        default:
                                assert(0);
+                               continue;
                        }
-                       inet_ntop(lldpd_af(af), sin_addr_ptr, addrstrbuf, sizeof(addrstrbuf));
-                       if (mgmt_pattern_ptr == NULL || 
-                                       fnmatch(mgmt_pattern_ptr, addrstrbuf, 0) == 0) {
+                       if (inet_ntop(lldpd_af(af), sin_addr_ptr,
+                                     addrstrbuf, sizeof(addrstrbuf)) == NULL) {
+                               LLOG_WARN("unable to convert IP address to a string");
+                               continue;
+                       }
+                       if (cfg->g_mgmt_pattern == NULL ||
+                           pattern_match(addrstrbuf, cfg->g_mgmt_pattern, allnegative)) {
                                mgmt = lldpd_alloc_mgmt(af, sin_addr_ptr, sin_addr_size,
                                                        if_nametoindex(ifa->ifa_name));
                                if (mgmt == NULL) {
@@ -1109,6 +1128,9 @@ lldpd_ifh_mgmt(struct lldpd *cfg, struct ifaddrs *ifap)
                                        return;
                                }
                                TAILQ_INSERT_TAIL(&LOCAL_CHASSIS(cfg)->c_mgmt, mgmt, m_entries);
+
+                               /* Don't take additional address if the pattern is all negative. */
+                               if (allnegative) break;
                        }
                }
        }
@@ -1130,7 +1152,7 @@ lldpd_ifh_chassis(struct lldpd *cfg, struct ifaddrs *ifap)
        for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
                if (ifa->ifa_flags) continue;
                if (cfg->g_cid_pattern &&
-                   !iface_match(ifa->ifa_name, cfg->g_cid_pattern)) continue;
+                   !pattern_match(ifa->ifa_name, cfg->g_cid_pattern, 0)) continue;
 
                if ((hardware = lldpd_get_hardware(cfg,
                            ifa->ifa_name,
index 628fb71badf4ca4544983de22537101724a6c1d7..f91e6a159a6c2608906089691e0bdb318279572d 100644 (file)
@@ -95,9 +95,7 @@ usage(void)
        fprintf(stderr, "-k       Disable advertising of kernel release, version, machine.\n");
        fprintf(stderr, "-S descr Override the default system description.\n");
        fprintf(stderr, "-P name  Override the default hardware platform.\n");
-       fprintf(stderr, "-4 IP    Specify the IPv4 management address of this system.\n");
-       fprintf(stderr, "-m IP    Same as '-4', for backward compatibility.\n");
-       fprintf(stderr, "-6 IP    Specify the IPv6 management address of this system.\n");
+       fprintf(stderr, "-m IP    Specify the IPv4 management addresses of this system.\n");
        fprintf(stderr, "-H mode  Specify the behaviour when detecting multiple neighbors.\n");
        fprintf(stderr, "-I iface Limit interfaces to use.\n");
 #ifdef ENABLE_LLDPMED
@@ -1163,7 +1161,7 @@ lldpd_main(int argc, char *argv[])
        int snmp = 0;
        char *agentx = NULL;    /* AgentX socket */
 #endif
-       char *mgmtp = NULL, *mgmtp6 = NULL;
+       char *mgmtp = NULL;
        char *cidp = NULL;
        char *interfaces = NULL;
        char *popt, opts[] = 
@@ -1198,12 +1196,9 @@ lldpd_main(int argc, char *argv[])
                case 'r':
                        receiveonly = 1;
                        break;
-               case 'm': /* fall through */
-               case '4':
+               case 'm':
                        mgmtp = optarg;
                        break;
-               case '6':
-                       mgmtp6 = optarg;
                case 'I':
                        interfaces = optarg;
                        break;
@@ -1314,7 +1309,6 @@ lldpd_main(int argc, char *argv[])
                fatal(NULL);
 
        cfg->g_mgmt_pattern = mgmtp;
-       cfg->g_mgmt_pattern6 = mgmtp6;
        cfg->g_cid_pattern = cidp;
        cfg->g_interfaces = interfaces;
        cfg->g_smart = smart;
index 0af9c557bfbe1b3f984c07c4a0237c1d0c4dde8f..6466e56efd7431398b7ea0af55b9710f907415b8 100644 (file)
@@ -452,7 +452,7 @@ struct lldpd {
 
        TAILQ_HEAD(, lldpd_callback) g_callbacks;
 
-       char                    *g_mgmt_pattern, *g_mgmt_pattern6;
+       char                    *g_mgmt_pattern;
        char                    *g_cid_pattern;
        char                    *g_interfaces;