]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
interfaces: overwrite interface description with neighbor found
authorVincent Bernat <bernat@luffy.cx>
Tue, 2 Jul 2013 22:18:41 +0000 (00:18 +0200)
committerVincent Bernat <bernat@luffy.cx>
Tue, 2 Jul 2013 22:18:41 +0000 (00:18 +0200)
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.

src/daemon/Makefile.am
src/daemon/lldpd.c
src/daemon/lldpd.h
src/daemon/priv-bsd.c [moved from src/daemon/priv-bpf.c with 79% similarity]
src/daemon/priv-linux.c
src/daemon/priv.c

index dd803abddad70f1fd03fa8ea03535efa0c50a981..339c2913b315b33175d3892c10f69fb782eba5fb 100644 (file)
@@ -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
index de7f085da8b42a3121dc5220fb2c9a2fe4ac7c71..27e7ef7106e08603d43a2711ec16edbcfd6b4920 100644 (file)
@@ -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
index 3ed65d0d8849e2c0fa707adfeffe000c36cde691..6b2d06cabe650590b175a0c00600015a2b2230f3 100644 (file)
@@ -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;
 
similarity index 79%
rename from src/daemon/priv-bpf.c
rename to src/daemon/priv-bsd.c
index ea9bb71ba6c693effbef54c63db335cd100c4003..2f9c5d3b772ad241b34f05f04874ba9ea7f31fe3 100644 (file)
@@ -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;
+}
+
index 32efc192fd765bbeaff319f81076fbd514b43273..5efa3f014afcc974132973a82cc8215502214d8d 100644 (file)
@@ -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;
+}
index 7c95c5a9a33c85c1a7b37d71d474cd4b0cdb9c1a..bc2b405792410c49920455a362e3d9438e3c738d 100644 (file)
@@ -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}
 };