]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-lldp: filter out LLDP messages coming from our own MAC address
authorLennart Poettering <lennart@poettering.net>
Sun, 21 Feb 2016 13:11:34 +0000 (14:11 +0100)
committerLennart Poettering <lennart@poettering.net>
Sun, 21 Feb 2016 19:40:58 +0000 (20:40 +0100)
Let's not get confused should we be connected to some bridge that mirrors back
our packets.

src/basic/ether-addr-util.c
src/basic/ether-addr-util.h
src/libsystemd-network/lldp-internal.h
src/libsystemd-network/sd-lldp.c
src/network/networkd-link.c
src/systemd/sd-lldp.h

index ded6d31f4be61a30765660b32dc85610ddf11119..d2c030903b834443cc5f24d7bf2681f4a6349b27 100644 (file)
@@ -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];
+}
index 4487149efd5cd90e4199708e4ce2cee5626a4642..00c5159fe8a1755652ffdc6e144ff0cbabd4a753 100644 (file)
 ***/
 
 #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);
index 279975b5c209ab0e6ac6b16d590bd0ab7aaa5097..7592bc4305c52fba8cfd27b384d2be26642b7948 100644 (file)
@@ -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__)
index 65cfa4e1847d8705ab3f12005339c8f3725d6a80..3af6133a4ea4f45fc37f8dcf7a02b7e93585dc31 100644 (file)
@@ -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;
+}
index 5c3e45fb3c98acb764fa79c4b50223238d186744..2bc6e3c8425cbe231c8aa92f69bb02739634c3fe 100644 (file)
@@ -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;
index 11b89258eda7e40f6853f10f4b0c8ef2ac5b204e..2ee32a534c23bb29786ef57d39f7d6c724915553 100644 (file)
@@ -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);