summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-02-21 14:11:34 +0100
committerLennart Poettering <lennart@poettering.net>2016-02-21 20:40:58 +0100
commitb553a6b13c68cb72addde48281abe3f3b46e16a4 (patch)
treed8f8548603e1bd3a2812257eae233fba546e2e24
parent33859a6bf5fd2b62a562a751a509708617e19776 (diff)
sd-lldp: filter out LLDP messages coming from our own MAC address
Let's not get confused should we be connected to some bridge that mirrors back our packets.
-rw-r--r--src/basic/ether-addr-util.c23
-rw-r--r--src/basic/ether-addr-util.h5
-rw-r--r--src/libsystemd-network/lldp-internal.h2
-rw-r--r--src/libsystemd-network/sd-lldp.c21
-rw-r--r--src/network/networkd-link.c4
-rw-r--r--src/systemd/sd-lldp.h1
6 files changed, 55 insertions, 1 deletions
diff --git a/src/basic/ether-addr-util.c b/src/basic/ether-addr-util.c
index ded6d31f4b..d2c030903b 100644
--- a/src/basic/ether-addr-util.c
+++ b/src/basic/ether-addr-util.c
@@ -42,3 +42,26 @@ char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR
return buffer;
}
+
+bool ether_addr_is_null(const struct ether_addr *addr) {
+ assert(addr);
+
+ return addr->ether_addr_octet[0] == 0 &&
+ addr->ether_addr_octet[1] == 0 &&
+ addr->ether_addr_octet[2] == 0 &&
+ addr->ether_addr_octet[3] == 0 &&
+ addr->ether_addr_octet[4] == 0 &&
+ addr->ether_addr_octet[5] == 0;
+}
+
+bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
+ assert(a);
+ assert(b);
+
+ return a->ether_addr_octet[0] == b->ether_addr_octet[0] &&
+ a->ether_addr_octet[1] == b->ether_addr_octet[1] &&
+ a->ether_addr_octet[2] == b->ether_addr_octet[2] &&
+ a->ether_addr_octet[3] == b->ether_addr_octet[3] &&
+ a->ether_addr_octet[4] == b->ether_addr_octet[4] &&
+ a->ether_addr_octet[5] == b->ether_addr_octet[5];
+}
diff --git a/src/basic/ether-addr-util.h b/src/basic/ether-addr-util.h
index 4487149efd..00c5159fe8 100644
--- a/src/basic/ether-addr-util.h
+++ b/src/basic/ether-addr-util.h
@@ -20,10 +20,13 @@
***/
#include <net/ethernet.h>
+#include <stdbool.h>
#define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X"
#define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5]
#define ETHER_ADDR_TO_STRING_MAX (3*6)
-
char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]);
+
+bool ether_addr_is_null(const struct ether_addr *addr);
+bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b);
diff --git a/src/libsystemd-network/lldp-internal.h b/src/libsystemd-network/lldp-internal.h
index 279975b5c2..7592bc4305 100644
--- a/src/libsystemd-network/lldp-internal.h
+++ b/src/libsystemd-network/lldp-internal.h
@@ -45,6 +45,8 @@ struct sd_lldp {
void *userdata;
uint16_t capability_mask;
+
+ struct ether_addr filter_address;
};
#define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__)
diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
index 65cfa4e184..3af6133a4e 100644
--- a/src/libsystemd-network/sd-lldp.c
+++ b/src/libsystemd-network/sd-lldp.c
@@ -28,6 +28,7 @@
#include "lldp-neighbor.h"
#include "lldp-network.h"
#include "socket-util.h"
+#include "ether-addr-util.h"
#define LLDP_DEFAULT_NEIGHBORS_MAX 128U
@@ -99,6 +100,11 @@ static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
if (n->ttl <= 0)
return changed;
+ /* Filter out the filter address */
+ if (!ether_addr_is_null(&lldp->filter_address) &&
+ ether_addr_equal(&lldp->filter_address, &n->source_address))
+ return changed;
+
/* Only add if the neighbor has a capability we are interested in. Note that we also store all neighbors with
* no caps field set. */
if (n->has_capabilities &&
@@ -438,3 +444,18 @@ _public_ int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask) {
return 0;
}
+
+_public_ int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *addr) {
+ assert_return(lldp, -EINVAL);
+
+ /* In order to deal nicely with bridges that send back our own packets, allow one address to be filtered, so
+ * that our own can be filtered out here. */
+
+ if (!addr) {
+ zero(lldp->filter_address);
+ return 0;
+ }
+
+ lldp->filter_address = *addr;
+ return 0;
+}
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 5c3e45fb3c..2bc6e3c842 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2203,6 +2203,10 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
+ r = sd_lldp_set_filter_address(link->lldp, &link->mac);
+ if (r < 0)
+ return r;
+
r = sd_lldp_attach_event(link->lldp, NULL, 0);
if (r < 0)
return r;
diff --git a/src/systemd/sd-lldp.h b/src/systemd/sd-lldp.h
index 11b89258ed..2ee32a534c 100644
--- a/src/systemd/sd-lldp.h
+++ b/src/systemd/sd-lldp.h
@@ -49,6 +49,7 @@ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata);
/* Controls how much and what to store in the neighbors database */
int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t n);
int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask);
+int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *address);
int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***neighbors);