From: Vincent Bernat Date: Thu, 15 Mar 2012 22:28:55 +0000 (+0100) Subject: mgmt: allow one to provide a pattern to specify management addresses X-Git-Tag: 0.6.0~30 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d4e4c80427cfad89861ed8270e031e68292a58b0;p=thirdparty%2Flldpd.git mgmt: allow one to provide a pattern to specify management addresses --- diff --git a/man/lldpd.8 b/man/lldpd.8 index 3a5dbdb8..4cf0ee31 100644 --- a/man/lldpd.8 +++ b/man/lldpd.8 @@ -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 diff --git a/src/interfaces.c b/src/interfaces.c index ea916e00..e22dd115 100644 --- a/src/interfaces.c +++ b/src/interfaces.c @@ -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, diff --git a/src/lldpd.c b/src/lldpd.c index 628fb71b..f91e6a15 100644 --- a/src/lldpd.c +++ b/src/lldpd.c @@ -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; diff --git a/src/lldpd.h b/src/lldpd.h index 0af9c557..6466e56e 100644 --- a/src/lldpd.h +++ b/src/lldpd.h @@ -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;