From: Vincent Bernat Date: Tue, 2 Jul 2013 22:18:41 +0000 (+0200) Subject: interfaces: overwrite interface description with neighbor found X-Git-Tag: 0.7.6~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=47820fc416ccc14dd4e08be17410086f1232bab3;p=thirdparty%2Flldpd.git interfaces: overwrite interface description with neighbor found If no neighbor is found, interface name is `lldpd: no neighbor found`. If one neighbor is found, this is `lldpd: connected to XXXXX` and if several neighbors are found, this is `lldpd: XXX neighbors`. Smart filter is used to count neighbors. Currently, this is not possible to disable this. Works with FreeBSD, OpenBSD and Linux. --- diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am index dd803abd..339c2913 100644 --- a/src/daemon/Makefile.am +++ b/src/daemon/Makefile.am @@ -36,7 +36,7 @@ liblldpd_la_SOURCES += \ interfaces-bpf.c \ interfaces-bsd.c \ dmi-dummy.c \ - priv-bpf.c + priv-bsd.c endif if HOST_OS_FREEBSD liblldpd_la_SOURCES += \ @@ -44,7 +44,7 @@ liblldpd_la_SOURCES += \ interfaces-bpf.c \ interfaces-bsd.c \ dmi-freebsd.c \ - priv-bpf.c + priv-bsd.c endif if HOST_OS_OPENBSD liblldpd_la_SOURCES += \ @@ -52,7 +52,7 @@ liblldpd_la_SOURCES += \ forward-bsd.c \ interfaces-bsd.c \ dmi-openbsd.c \ - priv-bpf.c + priv-bsd.c endif if HOST_OS_NETBSD liblldpd_la_SOURCES += \ @@ -60,7 +60,7 @@ liblldpd_la_SOURCES += \ interfaces-bpf.c \ interfaces-bsd.c \ dmi-dummy.c \ - priv-bpf.c + priv-bsd.c endif if HOST_OS_OSX liblldpd_la_SOURCES += \ @@ -68,7 +68,7 @@ liblldpd_la_SOURCES += \ interfaces-bpf.c \ interfaces-bsd.c \ dmi-osx.c \ - priv-bpf.c + priv-bsd.c liblldpd_la_LDFLAGS = -framework Foundation liblldpd_la_LDFLAGS += -framework CoreFoundation -framework IOKit liblldpd_la_LDFLAGS += -framework IOKit @@ -79,7 +79,7 @@ liblldpd_la_SOURCES += \ interfaces-bpf.c \ interfaces-solaris.c \ dmi-dummy.c \ - priv-bpf.c + priv-bsd.c endif # Add SNMP support if needed diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c index de7f085d..27e7ef71 100644 --- a/src/daemon/lldpd.c +++ b/src/daemon/lldpd.c @@ -213,6 +213,40 @@ lldpd_hardware_cleanup(struct lldpd *cfg, struct lldpd_hardware *hardware) free(hardware); } +static void +lldpd_display_neighbors(struct lldpd *cfg) +{ + struct lldpd_hardware *hardware; + TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) { + struct lldpd_port *port; + char *description; + const char *neighbor = NULL; + unsigned neighbors = 0; + TAILQ_FOREACH(port, &hardware->h_rports, p_entries) { + if (SMART_HIDDEN(port)) continue; + neighbors++; + neighbor = port->p_chassis->c_name; + } + if (neighbors == 0) + priv_iface_description(hardware->h_ifname, + "lldpd: no neighbor found"); + else if (neighbors == 1 && neighbor) { + if (asprintf(&description, "lldpd: connected to %s", + neighbor) != -1) { + priv_iface_description(hardware->h_ifname, description); + free(description); + } + } else { + if (asprintf(&description, "lldpd: %d neighbor%s", + neighbors, (neighbors > 1)?"s":"") != -1) { + priv_iface_description(hardware->h_ifname, + description); + free(description); + } + } + } +} + static void lldpd_count_neighbors(struct lldpd *cfg) { @@ -232,9 +266,8 @@ lldpd_count_neighbors(struct lldpd *cfg) else setproctitle("%d neighbor%s", neighbors, (neighbors > 1)?"s":""); -#else - (void)cfg; #endif + lldpd_display_neighbors(cfg); } static void diff --git a/src/daemon/lldpd.h b/src/daemon/lldpd.h index 3ed65d0d..6b2d06ca 100644 --- a/src/daemon/lldpd.h +++ b/src/daemon/lldpd.h @@ -222,6 +222,8 @@ void asroot_ethtool(void); int priv_iface_init(int, char *); int asroot_iface_init_os(int, char *, int *); int priv_iface_multicast(const char *, u_int8_t *, int); +int priv_iface_description(const char *, const char *); +int asroot_iface_description_os(const char *, const char *); int priv_snmp_socket(struct sockaddr_un *); enum { @@ -232,6 +234,7 @@ enum { PRIV_ETHTOOL, PRIV_IFACE_INIT, PRIV_IFACE_MULTICAST, + PRIV_IFACE_DESCRIPTION, PRIV_SNMP_SOCKET, } priv_cmd; diff --git a/src/daemon/priv-bpf.c b/src/daemon/priv-bsd.c similarity index 79% rename from src/daemon/priv-bpf.c rename to src/daemon/priv-bsd.c index ea9bb71b..2f9c5d3b 100644 --- a/src/daemon/priv-bpf.c +++ b/src/daemon/priv-bsd.c @@ -134,3 +134,43 @@ asroot_iface_init_os(int ifindex, char *name, int *fd) #endif return 0; } + +int +asroot_iface_description_os(const char *name, const char *description) +{ +#ifdef IFDESCRSIZE +#if defined HOST_OS_FREEBSD || defined HOST_OS_OPENBSD + char descr[IFDESCRSIZE]; + int rc, sock = -1; + strlcpy(descr, description, IFDESCRSIZE); +#if defined HOST_OS_FREEBSD + struct ifreq ifr = { + .ifr_buffer = { .buffer = descr, + .length = strlen(descr) + 1 } + }; +#else + struct ifreq ifr = { + .ifr_data = (caddr_t)descr + }; +#endif + strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1 || + ioctl(sock, SIOCSIFDESCR, (caddr_t)&ifr) < 0) { + rc = errno; + log_warnx("privsep", "unable to set description of %s", + name); + if (sock != -1) close(sock); + return rc; + } + close(sock); + return 0; +#endif +#endif /* IFDESCRSIZE */ + static int once = 0; + if (!once) { + log_warnx("privsep", "cannot set interface description for this OS"); + once = 1; + } + return 0; +} + diff --git a/src/daemon/priv-linux.c b/src/daemon/priv-linux.c index 32efc192..5efa3f01 100644 --- a/src/daemon/priv-linux.c +++ b/src/daemon/priv-linux.c @@ -199,3 +199,36 @@ asroot_iface_init_os(int ifindex, char *name, int *fd) return 0; } + +int +asroot_iface_description_os(const char *name, const char *description) +{ + /* We could use netlink but this is a lot to do in a privileged + * process. Just write to /sys/class/net/XXXX/ifalias. */ + char *file; + int fd, rc; + if (name[0] == '\0' || name[0] == '.') { + log_warnx("privsep", "odd interface name %s", name); + return -1; + } + if (asprintf(&file, SYSFS_CLASS_NET "%s/ifalias", name) == -1) { + log_warn("privsep", "unable to allocate memory for setting description"); + return -1; + } + if ((fd = open(file, O_WRONLY)) == -1) { + free(file); + log_debug("privsep", "cannot set interface description for %s, file missing", + name); + return -1; + } + free(file); + while ((rc = write(fd, description, strlen(description)) == -1) && + ((errno == EINTR || errno == EAGAIN))); + if (rc == -1) { + log_debug("privsep", "cannot write interface description for %s", + name); + return -1; + } + close(fd); + return 0; +} diff --git a/src/daemon/priv.c b/src/daemon/priv.c index 7c95c5a9..bc2b4057 100644 --- a/src/daemon/priv.c +++ b/src/daemon/priv.c @@ -129,6 +129,20 @@ priv_iface_multicast(const char *name, u_int8_t *mac, int add) return rc; } +int +priv_iface_description(const char *name, const char *description) +{ + int cmd, rc; + int len = strlen(description); + cmd = PRIV_IFACE_DESCRIPTION; + must_write(&cmd, sizeof(int)); + must_write(name, IFNAMSIZ); + must_write(&len, sizeof(int)); + must_write(description, len); + must_read(&rc, sizeof(int)); + return rc; +} + int priv_snmp_socket(struct sockaddr_un *addr) { @@ -248,6 +262,24 @@ asroot_iface_multicast() must_write(&rc, sizeof(rc)); } +static void +asroot_iface_description() +{ + char name[IFNAMSIZ]; + char *description; + int len, rc; + must_read(&name, sizeof(name)); + name[sizeof(name) - 1] = '\0'; + must_read(&len, sizeof(int)); + if ((description = (char*)malloc(len+1)) == NULL) + fatal("description", NULL); + + must_read(description, len); + description[len] = 0; + rc = asroot_iface_description_os(name, description); + must_write(&rc, sizeof(rc)); +} + static void asroot_snmp_socket() { @@ -300,6 +332,7 @@ static struct dispatch_actions actions[] = { #endif {PRIV_IFACE_INIT, asroot_iface_init}, {PRIV_IFACE_MULTICAST, asroot_iface_multicast}, + {PRIV_IFACE_DESCRIPTION, asroot_iface_description}, {PRIV_SNMP_SOCKET, asroot_snmp_socket}, {-1, NULL} };