]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
interfaces: only register protocol handler for LLDP when only LLDP enabled
authorVincent Bernat <vincent@bernat.ch>
Tue, 1 Oct 2019 04:18:52 +0000 (06:18 +0200)
committerVincent Bernat <vincent@bernat.ch>
Tue, 1 Oct 2019 05:21:40 +0000 (07:21 +0200)
On Linux, the drop counter is increased on unhandled packets. We are
using a raw socket with ETH_P_ALL, so we get a copy of the packet. The
original packet is ultimately dropped later and this increases the
drop counter associated to the interface on Linux.

When listening only to LLDP, use ETH_P_LLDP instead of ETH_P_ALL to
avoid this.

Fix #296.

NEWS
src/daemon/interfaces-bpf.c
src/daemon/interfaces-linux.c
src/daemon/lldpd.h
src/daemon/priv-bsd.c
src/daemon/priv-linux.c
src/daemon/priv.c

diff --git a/NEWS b/NEWS
index 0a27324a5b6c46d87dcd3473ceb36f54b7d06062..6a27a6bbc2058dc3c0974b44be982861ec37b438 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,8 @@
 lldpd (1.0.5)
   * Changes:
     + Interface names are also matched for management addresses.
+    + On Linux, only register protocol handler for LLDP when only LLDP
+      is enabled.
 
 lldpd (1.0.4)
   * Changes:
index 5237ee75370e3493b887ef0030d0a607992c2a75..2ad579e7fe6ef2c4716fcddd39e34075e7bf72c4 100644 (file)
@@ -34,7 +34,7 @@ ifbpf_phys_init(struct lldpd *cfg,
 
        log_debug("interfaces", "initialize ethernet device %s",
            hardware->h_ifname);
-       if ((fd = priv_iface_init(hardware->h_ifindex, hardware->h_ifname)) == -1)
+       if ((fd = priv_iface_init(hardware->h_ifindex, hardware->h_ifname, 0)) == -1)
                return -1;
 
        /* Allocate receive buffer */
index b57758d37191ec4e49b3da59eb215b2b49984c9c..446e8a14b8d48982b1d30ad0af8565d1fa452bef 100644 (file)
 #define MAX_PORTS 1024
 #define MAX_BRIDGES 1024
 
+static int
+only_lldp(struct lldpd *cfg)
+{
+       int lldp_enabled = 0;
+       int other_enabled = 0;
+       size_t i;
+       for (i=0; cfg->g_protocols[i].mode != 0; i++) {
+               if (cfg->g_protocols[i].mode == LLDPD_MODE_LLDP)
+                       lldp_enabled = cfg->g_protocols[i].enabled;
+               else other_enabled = other_enabled || cfg->g_protocols[i].enabled;
+       }
+       return lldp_enabled && !other_enabled;
+
+}
+
 static int
 iflinux_eth_init(struct lldpd *cfg, struct lldpd_hardware *hardware)
 {
@@ -48,7 +63,8 @@ iflinux_eth_init(struct lldpd *cfg, struct lldpd_hardware *hardware)
 
        log_debug("interfaces", "initialize ethernet device %s",
            hardware->h_ifname);
-       if ((fd = priv_iface_init(hardware->h_ifindex, hardware->h_ifname)) == -1)
+       if ((fd = priv_iface_init(hardware->h_ifindex, hardware->h_ifname,
+           only_lldp(cfg)?ETH_P_LLDP:ETH_P_ALL)) == -1)
                return -1;
        hardware->h_sendfd = fd; /* Send */
 
@@ -660,6 +676,7 @@ iface_bond_init(struct lldpd *cfg, struct lldpd_hardware *hardware)
        struct bond_master *master = hardware->h_data;
        int fd;
        int un = 1;
+       int proto;
 
        if (!master) return -1;
 
@@ -667,8 +684,9 @@ iface_bond_init(struct lldpd *cfg, struct lldpd_hardware *hardware)
            hardware->h_ifname);
 
        /* First, we get a socket to the raw physical interface */
+       proto = only_lldp(cfg)?ETH_P_LLDP:ETH_P_ALL;
        if ((fd = priv_iface_init(hardware->h_ifindex,
-                       hardware->h_ifname)) == -1)
+           hardware->h_ifname, proto)) == -1)
                return -1;
        hardware->h_sendfd = fd;
        interfaces_setup_multicast(cfg, hardware->h_ifname, 0);
@@ -676,7 +694,7 @@ iface_bond_init(struct lldpd *cfg, struct lldpd_hardware *hardware)
        /* Then, we open a raw interface for the master */
        log_debug("interfaces", "enslaved device %s has master %s(%d)",
            hardware->h_ifname, master->name, master->index);
-       if ((fd = priv_iface_init(master->index, master->name)) == -1) {
+       if ((fd = priv_iface_init(master->index, master->name, proto)) == -1) {
                close(hardware->h_sendfd);
                return -1;
        }
index 12c745edd19547a8607337456cad266d66a8b95a..900680afb361be4b1662aea671ba79e01bdbcaf6 100644 (file)
@@ -201,8 +201,8 @@ char        *priv_gethostname(void);
 int             priv_open(char*);
 void    asroot_open(void);
 #endif
-int             priv_iface_init(int, char *);
-int     asroot_iface_init_os(int, char *, int *);
+int             priv_iface_init(int, char *, int);
+int     asroot_iface_init_os(int, char *, int *, int);
 int     priv_iface_multicast(const char *, const u_int8_t *, int);
 int     priv_iface_description(const char *, const char *);
 int     asroot_iface_description_os(const char *, const char *);
@@ -262,12 +262,13 @@ void       send_fd(enum priv_context, int);
                 (ether dst 00:e0:2b:00:00:00)"
 */
 
+#define ETH_P_LLDP 0x88cc
 #define LLDPD_FILTER_F                         \
        { 0x30, 0, 0, 0x00000000 },             \
        { 0x54, 0, 0, 0x00000001 },             \
        { 0x15, 0, 16, 0x00000001 },            \
        { 0x28, 0, 0, 0x0000000c },             \
-       { 0x15, 0, 6, 0x000088cc },             \
+       { 0x15, 0, 6, ETH_P_LLDP },             \
        { 0x20, 0, 0, 0x00000002 },             \
        { 0x15, 2, 0, 0xc200000e },             \
        { 0x15, 1, 0, 0xc2000003 },             \
index f32f990cb15269d1da5b776a86971512691725d3..14085b17e3b27ff79f553cac8bde452736b0bb64 100644 (file)
@@ -27,7 +27,7 @@
 #include <string.h>
 
 int
-asroot_iface_init_os(int ifindex, char *name, int *fd)
+asroot_iface_init_os(int ifindex, char *name, int *fd, int proto)
 {
        int enable, required, rc;
        struct bpf_insn filter[] = { LLDPD_FILTER_F };
index 950f0781a7b43542910e25852a5e8ffb06da597b..9a40915059c9653673405866e7272c2ffdb9d0de 100644 (file)
@@ -115,12 +115,12 @@ asroot_open()
 }
 
 int
-asroot_iface_init_os(int ifindex, char *name, int *fd)
+asroot_iface_init_os(int ifindex, char *name, int *fd, int proto)
 {
        int rc;
        /* Open listening socket to receive/send frames */
        if ((*fd = socket(PF_PACKET, SOCK_RAW,
-                   htons(ETH_P_ALL))) < 0) {
+                   htons(proto))) < 0) {
                rc = errno;
                return rc;
        }
index ba5ae58c7392476bf13e455f95b7c3ef50a4a8e9..551cac168437c58218ffdf407f2dc3b686bbaf66 100644 (file)
@@ -120,7 +120,7 @@ priv_gethostname()
 
 
 int
-priv_iface_init(int index, char *iface)
+priv_iface_init(int index, char *iface, int proto)
 {
        int rc;
        char dev[IFNAMSIZ] = {};
@@ -129,6 +129,7 @@ priv_iface_init(int index, char *iface)
        must_write(PRIV_UNPRIVILEGED, &index, sizeof(int));
        strlcpy(dev, iface, IFNAMSIZ);
        must_write(PRIV_UNPRIVILEGED, dev, IFNAMSIZ);
+       must_write(PRIV_UNPRIVILEGED, &proto, sizeof(int));
        priv_wait();
        must_read(PRIV_UNPRIVILEGED, &rc, sizeof(int));
        if (rc != 0) return -1;
@@ -250,13 +251,15 @@ asroot_iface_init()
 {
        int rc = -1, fd = -1;
        int ifindex;
+       int proto;
        char name[IFNAMSIZ];
        must_read(PRIV_PRIVILEGED, &ifindex, sizeof(ifindex));
        must_read(PRIV_PRIVILEGED, &name, sizeof(name));
        name[sizeof(name) - 1] = '\0';
+       must_read(PRIV_PRIVILEGED, &proto, sizeof(proto))
 
        TRACE(LLDPD_PRIV_INTERFACE_INIT(name));
-       rc = asroot_iface_init_os(ifindex, name, &fd);
+       rc = asroot_iface_init_os(ifindex, name, &fd, proto);
        must_write(PRIV_PRIVILEGED, &rc, sizeof(rc));
        if (rc == 0 && fd >=0) send_fd(PRIV_PRIVILEGED, fd);
        if (fd >= 0) close(fd);