From: Vincent Bernat Date: Tue, 1 Oct 2019 04:18:52 +0000 (+0200) Subject: interfaces: only register protocol handler for LLDP when only LLDP enabled X-Git-Tag: 1.0.5~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fc5526dae75fa1e182fe46cef01045226cd92b36;p=thirdparty%2Flldpd.git interfaces: only register protocol handler for LLDP when only LLDP enabled 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. --- diff --git a/NEWS b/NEWS index 0a27324a..6a27a6bb 100644 --- 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: diff --git a/src/daemon/interfaces-bpf.c b/src/daemon/interfaces-bpf.c index 5237ee75..2ad579e7 100644 --- a/src/daemon/interfaces-bpf.c +++ b/src/daemon/interfaces-bpf.c @@ -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 */ diff --git a/src/daemon/interfaces-linux.c b/src/daemon/interfaces-linux.c index b57758d3..446e8a14 100644 --- a/src/daemon/interfaces-linux.c +++ b/src/daemon/interfaces-linux.c @@ -41,6 +41,21 @@ #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; } diff --git a/src/daemon/lldpd.h b/src/daemon/lldpd.h index 12c745ed..900680af 100644 --- a/src/daemon/lldpd.h +++ b/src/daemon/lldpd.h @@ -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 }, \ diff --git a/src/daemon/priv-bsd.c b/src/daemon/priv-bsd.c index f32f990c..14085b17 100644 --- a/src/daemon/priv-bsd.c +++ b/src/daemon/priv-bsd.c @@ -27,7 +27,7 @@ #include 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 }; diff --git a/src/daemon/priv-linux.c b/src/daemon/priv-linux.c index 950f0781..9a409150 100644 --- a/src/daemon/priv-linux.c +++ b/src/daemon/priv-linux.c @@ -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; } diff --git a/src/daemon/priv.c b/src/daemon/priv.c index ba5ae58c..551cac16 100644 --- a/src/daemon/priv.c +++ b/src/daemon/priv.c @@ -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);