sd-lldp: rename sd-lldp.[ch] -> sd-lldp-rx.[ch]
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 26 Sep 2021 02:51:17 +0000 (11:51 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 27 Sep 2021 14:55:11 +0000 (23:55 +0900)
15 files changed:
src/libsystemd-network/fuzz-lldp.c
src/libsystemd-network/lldp-internal.h [deleted file]
src/libsystemd-network/lldp-neighbor.c
src/libsystemd-network/lldp-neighbor.h
src/libsystemd-network/lldp-rx-internal.h [new file with mode: 0644]
src/libsystemd-network/meson.build
src/libsystemd-network/sd-lldp-rx.c [new file with mode: 0644]
src/libsystemd-network/sd-lldp.c [deleted file]
src/libsystemd-network/test-lldp.c
src/network/networkctl.c
src/network/networkd-link.h
src/network/test-network-tables.c
src/systemd/meson.build
src/systemd/sd-lldp-rx.h [new file with mode: 0644]
src/systemd/sd-lldp.h [deleted file]

index 5747135b32f7a7ec077b9392d58323f13b261e22..6c4d3e2e566e85c2d9bcd2ff8f76fb32d09b721e 100644 (file)
@@ -4,7 +4,7 @@
 #include <unistd.h>
 
 #include "sd-event.h"
-#include "sd-lldp.h"
+#include "sd-lldp-rx.h"
 
 #include "fd-util.h"
 #include "fuzz.h"
diff --git a/src/libsystemd-network/lldp-internal.h b/src/libsystemd-network/lldp-internal.h
deleted file mode 100644 (file)
index cf0578c..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-#include "sd-event.h"
-#include "sd-lldp.h"
-
-#include "hashmap.h"
-#include "log-link.h"
-#include "prioq.h"
-
-struct sd_lldp {
-        unsigned n_ref;
-
-        int ifindex;
-        char *ifname;
-        int fd;
-
-        sd_event *event;
-        int64_t event_priority;
-        sd_event_source *io_event_source;
-        sd_event_source *timer_event_source;
-
-        Prioq *neighbor_by_expiry;
-        Hashmap *neighbor_by_id;
-
-        uint64_t neighbors_max;
-
-        sd_lldp_callback_t callback;
-        void *userdata;
-
-        uint16_t capability_mask;
-
-        struct ether_addr filter_address;
-};
-
-const char* lldp_event_to_string(sd_lldp_event_t e) _const_;
-sd_lldp_event_t lldp_event_from_string(const char *s) _pure_;
-
-#define log_lldp_errno(lldp, error, fmt, ...)           \
-        log_interface_prefix_full_errno(                \
-                "LLDP: ",                               \
-                sd_lldp_get_ifname(lldp),               \
-                error, fmt, ##__VA_ARGS__)
-#define log_lldp(lldp, fmt, ...)                        \
-        log_interface_prefix_full_errno_zerook(         \
-                "LLDP: ",                               \
-                sd_lldp_get_ifname(lldp),               \
-                0, fmt, ##__VA_ARGS__)
index 3bd775158efdbb6c3ea8858f5f9241f415ea0b9c..ba5f288aa5c3bf10602ca2f3a1261e4c5d89d231 100644 (file)
@@ -5,7 +5,6 @@
 #include "ether-addr-util.h"
 #include "hexdecoct.h"
 #include "in-addr-util.h"
-#include "lldp-internal.h"
 #include "lldp-neighbor.h"
 #include "memory-util.h"
 #include "missing_network.h"
index a5718c8c31e48516dc98505b4e27665ad94db860..82735ee0c3e2d26eb157b6dc4c078e42b2951489 100644 (file)
@@ -5,10 +5,10 @@
 #include <stdbool.h>
 #include <sys/types.h>
 
-#include "sd-lldp.h"
+#include "sd-lldp-rx.h"
 
 #include "hash-funcs.h"
-#include "lldp-internal.h"
+#include "lldp-rx-internal.h"
 #include "time-util.h"
 
 typedef struct LLDPNeighborID {
diff --git a/src/libsystemd-network/lldp-rx-internal.h b/src/libsystemd-network/lldp-rx-internal.h
new file mode 100644 (file)
index 0000000..ad6ee5a
--- /dev/null
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "sd-event.h"
+#include "sd-lldp-rx.h"
+
+#include "hashmap.h"
+#include "log-link.h"
+#include "prioq.h"
+
+struct sd_lldp {
+        unsigned n_ref;
+
+        int ifindex;
+        char *ifname;
+        int fd;
+
+        sd_event *event;
+        int64_t event_priority;
+        sd_event_source *io_event_source;
+        sd_event_source *timer_event_source;
+
+        Prioq *neighbor_by_expiry;
+        Hashmap *neighbor_by_id;
+
+        uint64_t neighbors_max;
+
+        sd_lldp_callback_t callback;
+        void *userdata;
+
+        uint16_t capability_mask;
+
+        struct ether_addr filter_address;
+};
+
+const char* lldp_event_to_string(sd_lldp_event_t e) _const_;
+sd_lldp_event_t lldp_event_from_string(const char *s) _pure_;
+
+#define log_lldp_errno(lldp, error, fmt, ...)           \
+        log_interface_prefix_full_errno(                \
+                "LLDP: ",                               \
+                sd_lldp_get_ifname(lldp),               \
+                error, fmt, ##__VA_ARGS__)
+#define log_lldp(lldp, fmt, ...)                        \
+        log_interface_prefix_full_errno_zerook(         \
+                "LLDP: ",                               \
+                sd_lldp_get_ifname(lldp),               \
+                0, fmt, ##__VA_ARGS__)
index 83f902ebbf6a500dc0573c08b7af69f7f17421f2..df0bc4d8c2a925e7aca7c09e6529a8713df3fa22 100644 (file)
@@ -20,11 +20,11 @@ sources = files('''
         dhcp6-protocol.h
         icmp6-util.c
         icmp6-util.h
-        lldp-internal.h
         lldp-neighbor.c
         lldp-neighbor.h
         lldp-network.c
         lldp-network.h
+        lldp-rx-internal.h
         ndisc-internal.h
         ndisc-router.c
         ndisc-router.h
@@ -40,7 +40,7 @@ sources = files('''
         sd-dhcp6-lease.c
         sd-ipv4acd.c
         sd-ipv4ll.c
-        sd-lldp.c
+        sd-lldp-rx.c
         sd-ndisc.c
         sd-radv.c
 '''.split())
diff --git a/src/libsystemd-network/sd-lldp-rx.c b/src/libsystemd-network/sd-lldp-rx.c
new file mode 100644 (file)
index 0000000..06861c0
--- /dev/null
@@ -0,0 +1,523 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <arpa/inet.h>
+#include <linux/sockios.h>
+#include <sys/ioctl.h>
+
+#include "sd-lldp-rx.h"
+
+#include "alloc-util.h"
+#include "ether-addr-util.h"
+#include "event-util.h"
+#include "fd-util.h"
+#include "lldp-neighbor.h"
+#include "lldp-network.h"
+#include "lldp-rx-internal.h"
+#include "memory-util.h"
+#include "network-common.h"
+#include "socket-util.h"
+#include "sort-util.h"
+#include "string-table.h"
+
+#define LLDP_DEFAULT_NEIGHBORS_MAX 128U
+
+static const char * const lldp_event_table[_SD_LLDP_EVENT_MAX] = {
+        [SD_LLDP_EVENT_ADDED]     = "added",
+        [SD_LLDP_EVENT_REMOVED]   = "removed",
+        [SD_LLDP_EVENT_UPDATED]   = "updated",
+        [SD_LLDP_EVENT_REFRESHED] = "refreshed",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(lldp_event, sd_lldp_event_t);
+
+static void lldp_flush_neighbors(sd_lldp *lldp) {
+        assert(lldp);
+
+        hashmap_clear(lldp->neighbor_by_id);
+}
+
+static void lldp_callback(sd_lldp *lldp, sd_lldp_event_t event, sd_lldp_neighbor *n) {
+        assert(lldp);
+        assert(event >= 0 && event < _SD_LLDP_EVENT_MAX);
+
+        if (!lldp->callback)
+                return (void) log_lldp(lldp, "Received '%s' event.", lldp_event_to_string(event));
+
+        log_lldp(lldp, "Invoking callback for '%s' event.", lldp_event_to_string(event));
+        lldp->callback(lldp, event, n, lldp->userdata);
+}
+
+static int lldp_make_space(sd_lldp *lldp, size_t extra) {
+        usec_t t = USEC_INFINITY;
+        bool changed = false;
+
+        assert(lldp);
+
+        /* Remove all entries that are past their TTL, and more until at least the specified number of extra entries
+         * are free. */
+
+        for (;;) {
+                _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
+
+                n = prioq_peek(lldp->neighbor_by_expiry);
+                if (!n)
+                        break;
+
+                sd_lldp_neighbor_ref(n);
+
+                if (hashmap_size(lldp->neighbor_by_id) > LESS_BY(lldp->neighbors_max, extra))
+                        goto remove_one;
+
+                if (t == USEC_INFINITY)
+                        t = now(clock_boottime_or_monotonic());
+
+                if (n->until > t)
+                        break;
+
+        remove_one:
+                lldp_neighbor_unlink(n);
+                lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, n);
+                changed = true;
+        }
+
+        return changed;
+}
+
+static bool lldp_keep_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
+        assert(lldp);
+        assert(n);
+
+        /* Don't keep data with a zero TTL */
+        if (n->ttl <= 0)
+                return false;
+
+        /* Filter out data from the filter address */
+        if (!ether_addr_is_null(&lldp->filter_address) &&
+            ether_addr_equal(&lldp->filter_address, &n->source_address))
+                return false;
+
+        /* 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 &&
+            (n->enabled_capabilities & lldp->capability_mask) == 0)
+                return false;
+
+        /* Keep everything else */
+        return true;
+}
+
+static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor);
+
+static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
+        _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *old = NULL;
+        bool keep;
+        int r;
+
+        assert(lldp);
+        assert(n);
+        assert(!n->lldp);
+
+        keep = lldp_keep_neighbor(lldp, n);
+
+        /* First retrieve the old entry for this MSAP */
+        old = hashmap_get(lldp->neighbor_by_id, &n->id);
+        if (old) {
+                sd_lldp_neighbor_ref(old);
+
+                if (!keep) {
+                        lldp_neighbor_unlink(old);
+                        lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old);
+                        return 0;
+                }
+
+                if (lldp_neighbor_equal(n, old)) {
+                        /* Is this equal, then restart the TTL counter, but don't do anything else. */
+                        old->timestamp = n->timestamp;
+                        lldp_start_timer(lldp, old);
+                        lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old);
+                        return 0;
+                }
+
+                /* Data changed, remove the old entry, and add a new one */
+                lldp_neighbor_unlink(old);
+
+        } else if (!keep)
+                return 0;
+
+        /* Then, make room for at least one new neighbor */
+        lldp_make_space(lldp, 1);
+
+        r = hashmap_put(lldp->neighbor_by_id, &n->id, n);
+        if (r < 0)
+                goto finish;
+
+        r = prioq_put(lldp->neighbor_by_expiry, n, &n->prioq_idx);
+        if (r < 0) {
+                assert_se(hashmap_remove(lldp->neighbor_by_id, &n->id) == n);
+                goto finish;
+        }
+
+        n->lldp = lldp;
+
+        lldp_start_timer(lldp, n);
+        lldp_callback(lldp, old ? SD_LLDP_EVENT_UPDATED : SD_LLDP_EVENT_ADDED, n);
+
+        return 1;
+
+finish:
+        if (old)
+                lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old);
+
+        return r;
+}
+
+static int lldp_handle_datagram(sd_lldp *lldp, sd_lldp_neighbor *n) {
+        int r;
+
+        assert(lldp);
+        assert(n);
+
+        r = lldp_neighbor_parse(n);
+        if (r == -EBADMSG) /* Ignore bad messages */
+                return 0;
+        if (r < 0)
+                return r;
+
+        r = lldp_add_neighbor(lldp, n);
+        if (r < 0) {
+                log_lldp_errno(lldp, r, "Failed to add datagram. Ignoring.");
+                return 0;
+        }
+
+        log_lldp(lldp, "Successfully processed LLDP datagram.");
+        return 0;
+}
+
+static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
+        ssize_t space, length;
+        sd_lldp *lldp = userdata;
+        struct timespec ts;
+
+        assert(fd >= 0);
+        assert(lldp);
+
+        space = next_datagram_size_fd(fd);
+        if (space < 0) {
+                log_lldp_errno(lldp, space, "Failed to determine datagram size to read, ignoring: %m");
+                return 0;
+        }
+
+        n = lldp_neighbor_new(space);
+        if (!n)
+                return -ENOMEM;
+
+        length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT);
+        if (length < 0) {
+                if (IN_SET(errno, EAGAIN, EINTR))
+                        return 0;
+
+                log_lldp_errno(lldp, errno, "Failed to read LLDP datagram, ignoring: %m");
+                return 0;
+        }
+
+        if ((size_t) length != n->raw_size) {
+                log_lldp(lldp, "Packet size mismatch, ignoring");
+                return 0;
+        }
+
+        /* Try to get the timestamp of this packet if it is known */
+        if (ioctl(fd, SIOCGSTAMPNS, &ts) >= 0)
+                triple_timestamp_from_realtime(&n->timestamp, timespec_load(&ts));
+        else
+                triple_timestamp_get(&n->timestamp);
+
+        return lldp_handle_datagram(lldp, n);
+}
+
+static void lldp_reset(sd_lldp *lldp) {
+        assert(lldp);
+
+        (void) event_source_disable(lldp->timer_event_source);
+        lldp->io_event_source = sd_event_source_disable_unref(lldp->io_event_source);
+        lldp->fd = safe_close(lldp->fd);
+}
+
+_public_ int sd_lldp_start(sd_lldp *lldp) {
+        int r;
+
+        assert_return(lldp, -EINVAL);
+        assert_return(lldp->event, -EINVAL);
+        assert_return(lldp->ifindex > 0, -EINVAL);
+
+        if (lldp->fd >= 0)
+                return 0;
+
+        assert(!lldp->io_event_source);
+
+        lldp->fd = lldp_network_bind_raw_socket(lldp->ifindex);
+        if (lldp->fd < 0)
+                return lldp->fd;
+
+        r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io");
+
+        log_lldp(lldp, "Started LLDP client");
+        return 1;
+
+fail:
+        lldp_reset(lldp);
+        return r;
+}
+
+_public_ int sd_lldp_stop(sd_lldp *lldp) {
+        if (!lldp)
+                return 0;
+
+        if (lldp->fd < 0)
+                return 0;
+
+        log_lldp(lldp, "Stopping LLDP client");
+
+        lldp_reset(lldp);
+        lldp_flush_neighbors(lldp);
+
+        return 1;
+}
+
+_public_ int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority) {
+        int r;
+
+        assert_return(lldp, -EINVAL);
+        assert_return(lldp->fd < 0, -EBUSY);
+        assert_return(!lldp->event, -EBUSY);
+
+        if (event)
+                lldp->event = sd_event_ref(event);
+        else {
+                r = sd_event_default(&lldp->event);
+                if (r < 0)
+                        return r;
+        }
+
+        lldp->event_priority = priority;
+
+        return 0;
+}
+
+_public_ int sd_lldp_detach_event(sd_lldp *lldp) {
+
+        assert_return(lldp, -EINVAL);
+        assert_return(lldp->fd < 0, -EBUSY);
+
+        lldp->event = sd_event_unref(lldp->event);
+        return 0;
+}
+
+_public_ sd_event* sd_lldp_get_event(sd_lldp *lldp) {
+        assert_return(lldp, NULL);
+
+        return lldp->event;
+}
+
+_public_ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata) {
+        assert_return(lldp, -EINVAL);
+
+        lldp->callback = cb;
+        lldp->userdata = userdata;
+
+        return 0;
+}
+
+_public_ int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex) {
+        assert_return(lldp, -EINVAL);
+        assert_return(ifindex > 0, -EINVAL);
+        assert_return(lldp->fd < 0, -EBUSY);
+
+        lldp->ifindex = ifindex;
+        return 0;
+}
+
+int sd_lldp_set_ifname(sd_lldp *lldp, const char *ifname) {
+        assert_return(lldp, -EINVAL);
+        assert_return(ifname, -EINVAL);
+
+        if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
+                return -EINVAL;
+
+        return free_and_strdup(&lldp->ifname, ifname);
+}
+
+const char *sd_lldp_get_ifname(sd_lldp *lldp) {
+        if (!lldp)
+                return NULL;
+
+        return get_ifname(lldp->ifindex, &lldp->ifname);
+}
+
+static sd_lldp* lldp_free(sd_lldp *lldp) {
+        assert(lldp);
+
+        lldp_reset(lldp);
+
+        sd_event_source_unref(lldp->timer_event_source);
+        sd_lldp_detach_event(lldp);
+
+        lldp_flush_neighbors(lldp);
+
+        hashmap_free(lldp->neighbor_by_id);
+        prioq_free(lldp->neighbor_by_expiry);
+        free(lldp->ifname);
+        return mfree(lldp);
+}
+
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_lldp, sd_lldp, lldp_free);
+
+_public_ int sd_lldp_new(sd_lldp **ret) {
+        _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL;
+        int r;
+
+        assert_return(ret, -EINVAL);
+
+        lldp = new(sd_lldp, 1);
+        if (!lldp)
+                return -ENOMEM;
+
+        *lldp = (sd_lldp) {
+                .n_ref = 1,
+                .fd = -1,
+                .neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX,
+                .capability_mask = UINT16_MAX,
+        };
+
+        lldp->neighbor_by_id = hashmap_new(&lldp_neighbor_hash_ops);
+        if (!lldp->neighbor_by_id)
+                return -ENOMEM;
+
+        r = prioq_ensure_allocated(&lldp->neighbor_by_expiry, lldp_neighbor_prioq_compare_func);
+        if (r < 0)
+                return r;
+
+        *ret = TAKE_PTR(lldp);
+
+        return 0;
+}
+
+static int neighbor_compare_func(sd_lldp_neighbor * const *a, sd_lldp_neighbor * const *b) {
+        return lldp_neighbor_id_compare_func(&(*a)->id, &(*b)->id);
+}
+
+static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
+        sd_lldp *lldp = userdata;
+        int r;
+
+        r = lldp_make_space(lldp, 0);
+        if (r < 0) {
+                log_lldp_errno(lldp, r, "Failed to make space, ignoring: %m");
+                return 0;
+        }
+
+        r = lldp_start_timer(lldp, NULL);
+        if (r < 0) {
+                log_lldp_errno(lldp, r, "Failed to restart timer, ignoring: %m");
+                return 0;
+        }
+
+        return 0;
+}
+
+static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) {
+        sd_lldp_neighbor *n;
+
+        assert(lldp);
+
+        if (neighbor)
+                lldp_neighbor_start_ttl(neighbor);
+
+        n = prioq_peek(lldp->neighbor_by_expiry);
+        if (!n)
+                return event_source_disable(lldp->timer_event_source);
+
+        if (!lldp->event)
+                return 0;
+
+        return event_reset_time(lldp->event, &lldp->timer_event_source,
+                                clock_boottime_or_monotonic(),
+                                n->until, 0,
+                                on_timer_event, lldp,
+                                lldp->event_priority, "lldp-timer", true);
+}
+
+_public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) {
+        sd_lldp_neighbor **l = NULL, *n;
+        int k = 0, r;
+
+        assert_return(lldp, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        if (hashmap_isempty(lldp->neighbor_by_id)) { /* Special shortcut */
+                *ret = NULL;
+                return 0;
+        }
+
+        l = new0(sd_lldp_neighbor*, hashmap_size(lldp->neighbor_by_id));
+        if (!l)
+                return -ENOMEM;
+
+        r = lldp_start_timer(lldp, NULL);
+        if (r < 0) {
+                free(l);
+                return r;
+        }
+
+        HASHMAP_FOREACH(n, lldp->neighbor_by_id)
+                l[k++] = sd_lldp_neighbor_ref(n);
+
+        assert((size_t) k == hashmap_size(lldp->neighbor_by_id));
+
+        /* Return things in a stable order */
+        typesafe_qsort(l, k, neighbor_compare_func);
+        *ret = l;
+
+        return k;
+}
+
+_public_ int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t m) {
+        assert_return(lldp, -EINVAL);
+        assert_return(m > 0, -EINVAL);
+
+        lldp->neighbors_max = m;
+        lldp_make_space(lldp, 0);
+
+        return 0;
+}
+
+_public_ int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask) {
+        assert_return(lldp, -EINVAL);
+        assert_return(mask != 0, -EINVAL);
+
+        lldp->capability_mask = 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)
+                lldp->filter_address = *addr;
+        else
+                zero(lldp->filter_address);
+
+        return 0;
+}
diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
deleted file mode 100644 (file)
index b38d6db..0000000
+++ /dev/null
@@ -1,523 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include <arpa/inet.h>
-#include <linux/sockios.h>
-#include <sys/ioctl.h>
-
-#include "sd-lldp.h"
-
-#include "alloc-util.h"
-#include "ether-addr-util.h"
-#include "event-util.h"
-#include "fd-util.h"
-#include "lldp-internal.h"
-#include "lldp-neighbor.h"
-#include "lldp-network.h"
-#include "memory-util.h"
-#include "network-common.h"
-#include "socket-util.h"
-#include "sort-util.h"
-#include "string-table.h"
-
-#define LLDP_DEFAULT_NEIGHBORS_MAX 128U
-
-static const char * const lldp_event_table[_SD_LLDP_EVENT_MAX] = {
-        [SD_LLDP_EVENT_ADDED]     = "added",
-        [SD_LLDP_EVENT_REMOVED]   = "removed",
-        [SD_LLDP_EVENT_UPDATED]   = "updated",
-        [SD_LLDP_EVENT_REFRESHED] = "refreshed",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(lldp_event, sd_lldp_event_t);
-
-static void lldp_flush_neighbors(sd_lldp *lldp) {
-        assert(lldp);
-
-        hashmap_clear(lldp->neighbor_by_id);
-}
-
-static void lldp_callback(sd_lldp *lldp, sd_lldp_event_t event, sd_lldp_neighbor *n) {
-        assert(lldp);
-        assert(event >= 0 && event < _SD_LLDP_EVENT_MAX);
-
-        if (!lldp->callback)
-                return (void) log_lldp(lldp, "Received '%s' event.", lldp_event_to_string(event));
-
-        log_lldp(lldp, "Invoking callback for '%s' event.", lldp_event_to_string(event));
-        lldp->callback(lldp, event, n, lldp->userdata);
-}
-
-static int lldp_make_space(sd_lldp *lldp, size_t extra) {
-        usec_t t = USEC_INFINITY;
-        bool changed = false;
-
-        assert(lldp);
-
-        /* Remove all entries that are past their TTL, and more until at least the specified number of extra entries
-         * are free. */
-
-        for (;;) {
-                _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
-
-                n = prioq_peek(lldp->neighbor_by_expiry);
-                if (!n)
-                        break;
-
-                sd_lldp_neighbor_ref(n);
-
-                if (hashmap_size(lldp->neighbor_by_id) > LESS_BY(lldp->neighbors_max, extra))
-                        goto remove_one;
-
-                if (t == USEC_INFINITY)
-                        t = now(clock_boottime_or_monotonic());
-
-                if (n->until > t)
-                        break;
-
-        remove_one:
-                lldp_neighbor_unlink(n);
-                lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, n);
-                changed = true;
-        }
-
-        return changed;
-}
-
-static bool lldp_keep_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
-        assert(lldp);
-        assert(n);
-
-        /* Don't keep data with a zero TTL */
-        if (n->ttl <= 0)
-                return false;
-
-        /* Filter out data from the filter address */
-        if (!ether_addr_is_null(&lldp->filter_address) &&
-            ether_addr_equal(&lldp->filter_address, &n->source_address))
-                return false;
-
-        /* 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 &&
-            (n->enabled_capabilities & lldp->capability_mask) == 0)
-                return false;
-
-        /* Keep everything else */
-        return true;
-}
-
-static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor);
-
-static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
-        _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *old = NULL;
-        bool keep;
-        int r;
-
-        assert(lldp);
-        assert(n);
-        assert(!n->lldp);
-
-        keep = lldp_keep_neighbor(lldp, n);
-
-        /* First retrieve the old entry for this MSAP */
-        old = hashmap_get(lldp->neighbor_by_id, &n->id);
-        if (old) {
-                sd_lldp_neighbor_ref(old);
-
-                if (!keep) {
-                        lldp_neighbor_unlink(old);
-                        lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old);
-                        return 0;
-                }
-
-                if (lldp_neighbor_equal(n, old)) {
-                        /* Is this equal, then restart the TTL counter, but don't do anything else. */
-                        old->timestamp = n->timestamp;
-                        lldp_start_timer(lldp, old);
-                        lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old);
-                        return 0;
-                }
-
-                /* Data changed, remove the old entry, and add a new one */
-                lldp_neighbor_unlink(old);
-
-        } else if (!keep)
-                return 0;
-
-        /* Then, make room for at least one new neighbor */
-        lldp_make_space(lldp, 1);
-
-        r = hashmap_put(lldp->neighbor_by_id, &n->id, n);
-        if (r < 0)
-                goto finish;
-
-        r = prioq_put(lldp->neighbor_by_expiry, n, &n->prioq_idx);
-        if (r < 0) {
-                assert_se(hashmap_remove(lldp->neighbor_by_id, &n->id) == n);
-                goto finish;
-        }
-
-        n->lldp = lldp;
-
-        lldp_start_timer(lldp, n);
-        lldp_callback(lldp, old ? SD_LLDP_EVENT_UPDATED : SD_LLDP_EVENT_ADDED, n);
-
-        return 1;
-
-finish:
-        if (old)
-                lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old);
-
-        return r;
-}
-
-static int lldp_handle_datagram(sd_lldp *lldp, sd_lldp_neighbor *n) {
-        int r;
-
-        assert(lldp);
-        assert(n);
-
-        r = lldp_neighbor_parse(n);
-        if (r == -EBADMSG) /* Ignore bad messages */
-                return 0;
-        if (r < 0)
-                return r;
-
-        r = lldp_add_neighbor(lldp, n);
-        if (r < 0) {
-                log_lldp_errno(lldp, r, "Failed to add datagram. Ignoring.");
-                return 0;
-        }
-
-        log_lldp(lldp, "Successfully processed LLDP datagram.");
-        return 0;
-}
-
-static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
-        _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
-        ssize_t space, length;
-        sd_lldp *lldp = userdata;
-        struct timespec ts;
-
-        assert(fd >= 0);
-        assert(lldp);
-
-        space = next_datagram_size_fd(fd);
-        if (space < 0) {
-                log_lldp_errno(lldp, space, "Failed to determine datagram size to read, ignoring: %m");
-                return 0;
-        }
-
-        n = lldp_neighbor_new(space);
-        if (!n)
-                return -ENOMEM;
-
-        length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT);
-        if (length < 0) {
-                if (IN_SET(errno, EAGAIN, EINTR))
-                        return 0;
-
-                log_lldp_errno(lldp, errno, "Failed to read LLDP datagram, ignoring: %m");
-                return 0;
-        }
-
-        if ((size_t) length != n->raw_size) {
-                log_lldp(lldp, "Packet size mismatch, ignoring");
-                return 0;
-        }
-
-        /* Try to get the timestamp of this packet if it is known */
-        if (ioctl(fd, SIOCGSTAMPNS, &ts) >= 0)
-                triple_timestamp_from_realtime(&n->timestamp, timespec_load(&ts));
-        else
-                triple_timestamp_get(&n->timestamp);
-
-        return lldp_handle_datagram(lldp, n);
-}
-
-static void lldp_reset(sd_lldp *lldp) {
-        assert(lldp);
-
-        (void) event_source_disable(lldp->timer_event_source);
-        lldp->io_event_source = sd_event_source_disable_unref(lldp->io_event_source);
-        lldp->fd = safe_close(lldp->fd);
-}
-
-_public_ int sd_lldp_start(sd_lldp *lldp) {
-        int r;
-
-        assert_return(lldp, -EINVAL);
-        assert_return(lldp->event, -EINVAL);
-        assert_return(lldp->ifindex > 0, -EINVAL);
-
-        if (lldp->fd >= 0)
-                return 0;
-
-        assert(!lldp->io_event_source);
-
-        lldp->fd = lldp_network_bind_raw_socket(lldp->ifindex);
-        if (lldp->fd < 0)
-                return lldp->fd;
-
-        r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp);
-        if (r < 0)
-                goto fail;
-
-        r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority);
-        if (r < 0)
-                goto fail;
-
-        (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io");
-
-        log_lldp(lldp, "Started LLDP client");
-        return 1;
-
-fail:
-        lldp_reset(lldp);
-        return r;
-}
-
-_public_ int sd_lldp_stop(sd_lldp *lldp) {
-        if (!lldp)
-                return 0;
-
-        if (lldp->fd < 0)
-                return 0;
-
-        log_lldp(lldp, "Stopping LLDP client");
-
-        lldp_reset(lldp);
-        lldp_flush_neighbors(lldp);
-
-        return 1;
-}
-
-_public_ int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority) {
-        int r;
-
-        assert_return(lldp, -EINVAL);
-        assert_return(lldp->fd < 0, -EBUSY);
-        assert_return(!lldp->event, -EBUSY);
-
-        if (event)
-                lldp->event = sd_event_ref(event);
-        else {
-                r = sd_event_default(&lldp->event);
-                if (r < 0)
-                        return r;
-        }
-
-        lldp->event_priority = priority;
-
-        return 0;
-}
-
-_public_ int sd_lldp_detach_event(sd_lldp *lldp) {
-
-        assert_return(lldp, -EINVAL);
-        assert_return(lldp->fd < 0, -EBUSY);
-
-        lldp->event = sd_event_unref(lldp->event);
-        return 0;
-}
-
-_public_ sd_event* sd_lldp_get_event(sd_lldp *lldp) {
-        assert_return(lldp, NULL);
-
-        return lldp->event;
-}
-
-_public_ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata) {
-        assert_return(lldp, -EINVAL);
-
-        lldp->callback = cb;
-        lldp->userdata = userdata;
-
-        return 0;
-}
-
-_public_ int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex) {
-        assert_return(lldp, -EINVAL);
-        assert_return(ifindex > 0, -EINVAL);
-        assert_return(lldp->fd < 0, -EBUSY);
-
-        lldp->ifindex = ifindex;
-        return 0;
-}
-
-int sd_lldp_set_ifname(sd_lldp *lldp, const char *ifname) {
-        assert_return(lldp, -EINVAL);
-        assert_return(ifname, -EINVAL);
-
-        if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
-                return -EINVAL;
-
-        return free_and_strdup(&lldp->ifname, ifname);
-}
-
-const char *sd_lldp_get_ifname(sd_lldp *lldp) {
-        if (!lldp)
-                return NULL;
-
-        return get_ifname(lldp->ifindex, &lldp->ifname);
-}
-
-static sd_lldp* lldp_free(sd_lldp *lldp) {
-        assert(lldp);
-
-        lldp_reset(lldp);
-
-        sd_event_source_unref(lldp->timer_event_source);
-        sd_lldp_detach_event(lldp);
-
-        lldp_flush_neighbors(lldp);
-
-        hashmap_free(lldp->neighbor_by_id);
-        prioq_free(lldp->neighbor_by_expiry);
-        free(lldp->ifname);
-        return mfree(lldp);
-}
-
-DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_lldp, sd_lldp, lldp_free);
-
-_public_ int sd_lldp_new(sd_lldp **ret) {
-        _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL;
-        int r;
-
-        assert_return(ret, -EINVAL);
-
-        lldp = new(sd_lldp, 1);
-        if (!lldp)
-                return -ENOMEM;
-
-        *lldp = (sd_lldp) {
-                .n_ref = 1,
-                .fd = -1,
-                .neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX,
-                .capability_mask = UINT16_MAX,
-        };
-
-        lldp->neighbor_by_id = hashmap_new(&lldp_neighbor_hash_ops);
-        if (!lldp->neighbor_by_id)
-                return -ENOMEM;
-
-        r = prioq_ensure_allocated(&lldp->neighbor_by_expiry, lldp_neighbor_prioq_compare_func);
-        if (r < 0)
-                return r;
-
-        *ret = TAKE_PTR(lldp);
-
-        return 0;
-}
-
-static int neighbor_compare_func(sd_lldp_neighbor * const *a, sd_lldp_neighbor * const *b) {
-        return lldp_neighbor_id_compare_func(&(*a)->id, &(*b)->id);
-}
-
-static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
-        sd_lldp *lldp = userdata;
-        int r;
-
-        r = lldp_make_space(lldp, 0);
-        if (r < 0) {
-                log_lldp_errno(lldp, r, "Failed to make space, ignoring: %m");
-                return 0;
-        }
-
-        r = lldp_start_timer(lldp, NULL);
-        if (r < 0) {
-                log_lldp_errno(lldp, r, "Failed to restart timer, ignoring: %m");
-                return 0;
-        }
-
-        return 0;
-}
-
-static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) {
-        sd_lldp_neighbor *n;
-
-        assert(lldp);
-
-        if (neighbor)
-                lldp_neighbor_start_ttl(neighbor);
-
-        n = prioq_peek(lldp->neighbor_by_expiry);
-        if (!n)
-                return event_source_disable(lldp->timer_event_source);
-
-        if (!lldp->event)
-                return 0;
-
-        return event_reset_time(lldp->event, &lldp->timer_event_source,
-                                clock_boottime_or_monotonic(),
-                                n->until, 0,
-                                on_timer_event, lldp,
-                                lldp->event_priority, "lldp-timer", true);
-}
-
-_public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) {
-        sd_lldp_neighbor **l = NULL, *n;
-        int k = 0, r;
-
-        assert_return(lldp, -EINVAL);
-        assert_return(ret, -EINVAL);
-
-        if (hashmap_isempty(lldp->neighbor_by_id)) { /* Special shortcut */
-                *ret = NULL;
-                return 0;
-        }
-
-        l = new0(sd_lldp_neighbor*, hashmap_size(lldp->neighbor_by_id));
-        if (!l)
-                return -ENOMEM;
-
-        r = lldp_start_timer(lldp, NULL);
-        if (r < 0) {
-                free(l);
-                return r;
-        }
-
-        HASHMAP_FOREACH(n, lldp->neighbor_by_id)
-                l[k++] = sd_lldp_neighbor_ref(n);
-
-        assert((size_t) k == hashmap_size(lldp->neighbor_by_id));
-
-        /* Return things in a stable order */
-        typesafe_qsort(l, k, neighbor_compare_func);
-        *ret = l;
-
-        return k;
-}
-
-_public_ int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t m) {
-        assert_return(lldp, -EINVAL);
-        assert_return(m > 0, -EINVAL);
-
-        lldp->neighbors_max = m;
-        lldp_make_space(lldp, 0);
-
-        return 0;
-}
-
-_public_ int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask) {
-        assert_return(lldp, -EINVAL);
-        assert_return(mask != 0, -EINVAL);
-
-        lldp->capability_mask = 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)
-                lldp->filter_address = *addr;
-        else
-                zero(lldp->filter_address);
-
-        return 0;
-}
index 0331e387f0334131dd0987d8589acb507ecebcd0..09aacfd9fba86aeae2bd4ac74cc0c00d6d79ec7c 100644 (file)
@@ -7,7 +7,7 @@
 #include <unistd.h>
 
 #include "sd-event.h"
-#include "sd-lldp.h"
+#include "sd-lldp-rx.h"
 
 #include "alloc-util.h"
 #include "fd-util.h"
index 09a19192bcf698c3519a1de222b01130fd3bba6d..d4a7da9f71febbb847400e6e4d2bda7dfeeb5cbf 100644 (file)
@@ -15,7 +15,7 @@
 #include "sd-device.h"
 #include "sd-dhcp-client.h"
 #include "sd-hwdb.h"
-#include "sd-lldp.h"
+#include "sd-lldp-rx.h"
 #include "sd-netlink.h"
 #include "sd-network.h"
 
index 7190310a13210c14d268dd8f22be921367c93122..4946452e281ff1226120224dc17ea085deeb1bb3 100644 (file)
@@ -11,7 +11,7 @@
 #include "sd-dhcp6-client.h"
 #include "sd-ipv4acd.h"
 #include "sd-ipv4ll.h"
-#include "sd-lldp.h"
+#include "sd-lldp-rx.h"
 #include "sd-ndisc.h"
 #include "sd-radv.h"
 #include "sd-netlink.h"
index b7b536f3b542530abf311bfdbd5b1c72f305a474..a13c8d7a7b9b3cd87b044449db90aea4159ad1cd 100644 (file)
@@ -5,7 +5,7 @@
 #include "dhcp6-protocol.h"
 #include "ethtool-util.h"
 #include "ipvlan.h"
-#include "lldp-internal.h"
+#include "lldp-rx-internal.h"
 #include "macvlan.h"
 #include "ndisc-internal.h"
 #include "networkd-link.h"
index 6cae6a5767c3ee794ceb70d3f0226a30b3522abf..a854887ecc7cca530bac2d70b9d30e580c82e404 100644 (file)
@@ -28,7 +28,7 @@ _not_installed_headers = '''
         sd-dhcp-server.h
         sd-ipv4acd.h
         sd-ipv4ll.h
-        sd-lldp.h
+        sd-lldp-rx.h
         sd-ndisc.h
         sd-netlink.h
         sd-network.h
diff --git a/src/systemd/sd-lldp-rx.h b/src/systemd/sd-lldp-rx.h
new file mode 100644 (file)
index 0000000..ac4bb60
--- /dev/null
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#ifndef foosdlldprxhfoo
+#define foosdlldprxhfoo
+
+/***
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <inttypes.h>
+#include <net/ethernet.h>
+#include <sys/types.h>
+
+#include "sd-event.h"
+
+#include "_sd-common.h"
+
+_SD_BEGIN_DECLARATIONS;
+
+/* IEEE 802.1AB-2009 Clause 8: TLV Types */
+enum {
+        SD_LLDP_TYPE_END                 = 0,
+        SD_LLDP_TYPE_CHASSIS_ID          = 1,
+        SD_LLDP_TYPE_PORT_ID             = 2,
+        SD_LLDP_TYPE_TTL                 = 3,
+        SD_LLDP_TYPE_PORT_DESCRIPTION    = 4,
+        SD_LLDP_TYPE_SYSTEM_NAME         = 5,
+        SD_LLDP_TYPE_SYSTEM_DESCRIPTION  = 6,
+        SD_LLDP_TYPE_SYSTEM_CAPABILITIES = 7,
+        SD_LLDP_TYPE_MGMT_ADDRESS        = 8,
+        SD_LLDP_TYPE_PRIVATE             = 127,
+};
+
+/* IEEE 802.1AB-2009 Clause 8.5.2: Chassis subtypes */
+enum {
+        SD_LLDP_CHASSIS_SUBTYPE_RESERVED            = 0,
+        SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT   = 1,
+        SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS     = 2,
+        SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT      = 3,
+        SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS         = 4,
+        SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS     = 5,
+        SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME      = 6,
+        SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED    = 7,
+};
+
+/* IEEE 802.1AB-2009 Clause 8.5.3: Port subtype */
+enum {
+        SD_LLDP_PORT_SUBTYPE_RESERVED         = 0,
+        SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS  = 1,
+        SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT   = 2,
+        SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS      = 3,
+        SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS  = 4,
+        SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME   = 5,
+        SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6,
+        SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7,
+};
+
+/* IEEE 802.1AB-2009 Clause 8.5.8: System capabilities */
+enum {
+        SD_LLDP_SYSTEM_CAPABILITIES_OTHER    = 1 << 0,
+        SD_LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1,
+        SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE   = 1 << 2,
+        SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP  = 1 << 3,
+        SD_LLDP_SYSTEM_CAPABILITIES_ROUTER   = 1 << 4,
+        SD_LLDP_SYSTEM_CAPABILITIES_PHONE    = 1 << 5,
+        SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS   = 1 << 6,
+        SD_LLDP_SYSTEM_CAPABILITIES_STATION  = 1 << 7,
+        SD_LLDP_SYSTEM_CAPABILITIES_CVLAN    = 1 << 8,
+        SD_LLDP_SYSTEM_CAPABILITIES_SVLAN    = 1 << 9,
+        SD_LLDP_SYSTEM_CAPABILITIES_TPMR     = 1 << 10,
+};
+
+#define SD_LLDP_SYSTEM_CAPABILITIES_ALL UINT16_MAX
+
+#define SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS                         \
+        ((uint16_t)                                                     \
+         (SD_LLDP_SYSTEM_CAPABILITIES_REPEATER|                         \
+          SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|                           \
+          SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP|                          \
+          SD_LLDP_SYSTEM_CAPABILITIES_ROUTER|                           \
+          SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS|                           \
+          SD_LLDP_SYSTEM_CAPABILITIES_CVLAN|                            \
+          SD_LLDP_SYSTEM_CAPABILITIES_SVLAN|                            \
+          SD_LLDP_SYSTEM_CAPABILITIES_TPMR))
+
+#define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
+#define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }
+
+#define SD_LLDP_OUI_MUD   (uint8_t[]) { 0x00, 0x00, 0x5E }
+#define SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION  0x01
+
+/* IEEE 802.1AB-2009 Annex E */
+enum {
+        SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID          = 1,
+        SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2,
+        SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME             = 3,
+        SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY     = 4,
+        SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST      = 5,
+        SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID        = 6,
+        SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION      = 7,
+};
+
+/* IEEE 802.1AB-2009 Annex F */
+enum {
+        SD_LLDP_OUI_802_3_SUBTYPE_MAC_PHY_CONFIG_STATUS = 1,
+        SD_LLDP_OUI_802_3_SUBTYPE_POWER_VIA_MDI         = 2,
+        SD_LLDP_OUI_802_3_SUBTYPE_LINK_AGGREGATION      = 3,
+        SD_LLDP_OUI_802_3_SUBTYPE_MAXIMUM_FRAME_SIZE    = 4,
+};
+
+typedef struct sd_lldp sd_lldp;
+typedef struct sd_lldp_neighbor sd_lldp_neighbor;
+
+typedef enum sd_lldp_event_t {
+        SD_LLDP_EVENT_ADDED,
+        SD_LLDP_EVENT_REMOVED,
+        SD_LLDP_EVENT_UPDATED,
+        SD_LLDP_EVENT_REFRESHED,
+        _SD_LLDP_EVENT_MAX,
+        _SD_LLDP_EVENT_INVALID = -EINVAL,
+        _SD_ENUM_FORCE_S64(LLDP_EVENT),
+} sd_lldp_event_t;
+
+typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event_t event, sd_lldp_neighbor *n, void *userdata);
+
+int sd_lldp_new(sd_lldp **ret);
+sd_lldp* sd_lldp_ref(sd_lldp *lldp);
+sd_lldp* sd_lldp_unref(sd_lldp *lldp);
+
+int sd_lldp_start(sd_lldp *lldp);
+int sd_lldp_stop(sd_lldp *lldp);
+
+int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority);
+int sd_lldp_detach_event(sd_lldp *lldp);
+sd_event *sd_lldp_get_event(sd_lldp *lldp);
+
+int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata);
+int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex);
+int sd_lldp_set_ifname(sd_lldp *lldp, const char *ifname);
+const char *sd_lldp_get_ifname(sd_lldp *lldp);
+
+/* 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);
+
+int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size);
+sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n);
+sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n);
+
+/* Access to LLDP frame metadata */
+int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address);
+int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address);
+int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret);
+int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size);
+
+/* High-level, direct, parsed out field access. These fields exist at most once, hence may be queried directly. */
+int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size);
+int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret);
+int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size);
+int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret);
+int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec);
+int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret);
+int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret);
+int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret);
+int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret);
+int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
+int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
+
+/* Low-level, iterative TLV access. This is for everything else, it iteratively goes through all available TLVs
+ * (including the ones covered with the calls above), and allows multiple TLVs for the same fields. */
+int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n);
+int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n);
+int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type);
+int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type);
+int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t *subtype);
+int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t subtype);
+int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size);
+
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp, sd_lldp_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp_neighbor, sd_lldp_neighbor_unref);
+
+_SD_END_DECLARATIONS;
+
+#endif
diff --git a/src/systemd/sd-lldp.h b/src/systemd/sd-lldp.h
deleted file mode 100644 (file)
index 64047ee..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#ifndef foosdlldphfoo
-#define foosdlldphfoo
-
-/***
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <inttypes.h>
-#include <net/ethernet.h>
-#include <sys/types.h>
-
-#include "sd-event.h"
-
-#include "_sd-common.h"
-
-_SD_BEGIN_DECLARATIONS;
-
-/* IEEE 802.1AB-2009 Clause 8: TLV Types */
-enum {
-        SD_LLDP_TYPE_END                 = 0,
-        SD_LLDP_TYPE_CHASSIS_ID          = 1,
-        SD_LLDP_TYPE_PORT_ID             = 2,
-        SD_LLDP_TYPE_TTL                 = 3,
-        SD_LLDP_TYPE_PORT_DESCRIPTION    = 4,
-        SD_LLDP_TYPE_SYSTEM_NAME         = 5,
-        SD_LLDP_TYPE_SYSTEM_DESCRIPTION  = 6,
-        SD_LLDP_TYPE_SYSTEM_CAPABILITIES = 7,
-        SD_LLDP_TYPE_MGMT_ADDRESS        = 8,
-        SD_LLDP_TYPE_PRIVATE             = 127,
-};
-
-/* IEEE 802.1AB-2009 Clause 8.5.2: Chassis subtypes */
-enum {
-        SD_LLDP_CHASSIS_SUBTYPE_RESERVED            = 0,
-        SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT   = 1,
-        SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS     = 2,
-        SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT      = 3,
-        SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS         = 4,
-        SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS     = 5,
-        SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME      = 6,
-        SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED    = 7,
-};
-
-/* IEEE 802.1AB-2009 Clause 8.5.3: Port subtype */
-enum {
-        SD_LLDP_PORT_SUBTYPE_RESERVED         = 0,
-        SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS  = 1,
-        SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT   = 2,
-        SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS      = 3,
-        SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS  = 4,
-        SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME   = 5,
-        SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6,
-        SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7,
-};
-
-/* IEEE 802.1AB-2009 Clause 8.5.8: System capabilities */
-enum {
-        SD_LLDP_SYSTEM_CAPABILITIES_OTHER    = 1 << 0,
-        SD_LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1,
-        SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE   = 1 << 2,
-        SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP  = 1 << 3,
-        SD_LLDP_SYSTEM_CAPABILITIES_ROUTER   = 1 << 4,
-        SD_LLDP_SYSTEM_CAPABILITIES_PHONE    = 1 << 5,
-        SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS   = 1 << 6,
-        SD_LLDP_SYSTEM_CAPABILITIES_STATION  = 1 << 7,
-        SD_LLDP_SYSTEM_CAPABILITIES_CVLAN    = 1 << 8,
-        SD_LLDP_SYSTEM_CAPABILITIES_SVLAN    = 1 << 9,
-        SD_LLDP_SYSTEM_CAPABILITIES_TPMR     = 1 << 10,
-};
-
-#define SD_LLDP_SYSTEM_CAPABILITIES_ALL UINT16_MAX
-
-#define SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS                         \
-        ((uint16_t)                                                     \
-         (SD_LLDP_SYSTEM_CAPABILITIES_REPEATER|                         \
-          SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|                           \
-          SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP|                          \
-          SD_LLDP_SYSTEM_CAPABILITIES_ROUTER|                           \
-          SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS|                           \
-          SD_LLDP_SYSTEM_CAPABILITIES_CVLAN|                            \
-          SD_LLDP_SYSTEM_CAPABILITIES_SVLAN|                            \
-          SD_LLDP_SYSTEM_CAPABILITIES_TPMR))
-
-#define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
-#define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }
-
-#define SD_LLDP_OUI_MUD   (uint8_t[]) { 0x00, 0x00, 0x5E }
-#define SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION  0x01
-
-/* IEEE 802.1AB-2009 Annex E */
-enum {
-        SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID          = 1,
-        SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2,
-        SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME             = 3,
-        SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY     = 4,
-        SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST      = 5,
-        SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID        = 6,
-        SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION      = 7,
-};
-
-/* IEEE 802.1AB-2009 Annex F */
-enum {
-        SD_LLDP_OUI_802_3_SUBTYPE_MAC_PHY_CONFIG_STATUS = 1,
-        SD_LLDP_OUI_802_3_SUBTYPE_POWER_VIA_MDI         = 2,
-        SD_LLDP_OUI_802_3_SUBTYPE_LINK_AGGREGATION      = 3,
-        SD_LLDP_OUI_802_3_SUBTYPE_MAXIMUM_FRAME_SIZE    = 4,
-};
-
-typedef struct sd_lldp sd_lldp;
-typedef struct sd_lldp_neighbor sd_lldp_neighbor;
-
-typedef enum sd_lldp_event_t {
-        SD_LLDP_EVENT_ADDED,
-        SD_LLDP_EVENT_REMOVED,
-        SD_LLDP_EVENT_UPDATED,
-        SD_LLDP_EVENT_REFRESHED,
-        _SD_LLDP_EVENT_MAX,
-        _SD_LLDP_EVENT_INVALID = -EINVAL,
-        _SD_ENUM_FORCE_S64(LLDP_EVENT),
-} sd_lldp_event_t;
-
-typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event_t event, sd_lldp_neighbor *n, void *userdata);
-
-int sd_lldp_new(sd_lldp **ret);
-sd_lldp* sd_lldp_ref(sd_lldp *lldp);
-sd_lldp* sd_lldp_unref(sd_lldp *lldp);
-
-int sd_lldp_start(sd_lldp *lldp);
-int sd_lldp_stop(sd_lldp *lldp);
-
-int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority);
-int sd_lldp_detach_event(sd_lldp *lldp);
-sd_event *sd_lldp_get_event(sd_lldp *lldp);
-
-int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata);
-int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex);
-int sd_lldp_set_ifname(sd_lldp *lldp, const char *ifname);
-const char *sd_lldp_get_ifname(sd_lldp *lldp);
-
-/* 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);
-
-int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size);
-sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n);
-sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n);
-
-/* Access to LLDP frame metadata */
-int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address);
-int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address);
-int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret);
-int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size);
-
-/* High-level, direct, parsed out field access. These fields exist at most once, hence may be queried directly. */
-int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size);
-int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret);
-int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size);
-int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret);
-int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec);
-int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret);
-int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret);
-int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret);
-int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret);
-int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
-int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
-
-/* Low-level, iterative TLV access. This is for everything else, it iteratively goes through all available TLVs
- * (including the ones covered with the calls above), and allows multiple TLVs for the same fields. */
-int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n);
-int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n);
-int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type);
-int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type);
-int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t *subtype);
-int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t subtype);
-int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size);
-
-_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp, sd_lldp_unref);
-_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp_neighbor, sd_lldp_neighbor_unref);
-
-_SD_END_DECLARATIONS;
-
-#endif