diff options
author | Thomas Haller <thaller@redhat.com> | 2022-10-24 22:35:04 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-10-25 11:04:47 +0200 |
commit | 5afa09e966ca57b8fc3b898cc6116465d71cc53e (patch) | |
tree | cbfae5c250fefccd3a5a7e0fc658e692ff3343ac | |
parent | a3460730f27ebba85710d7f085619dce78ff481c (diff) | |
download | NetworkManager-5afa09e966ca57b8fc3b898cc6116465d71cc53e.tar.gz |
systemd: update code from upstream (2022-10-25)
This is a direct dump from systemd git.
$ git clean -fdx && \
git cat-file -p HEAD | sed '1,/^======$/ d' | bash - && \
git add .
======
SYSTEMD_DIR=../systemd
COMMIT=4117366a283657295264723e559d7ead79a7cfd3
(
cd "$SYSTEMD_DIR"
git checkout "$COMMIT"
git reset --hard
git clean -fdx
)
git ls-files -z :/src/libnm-systemd-core/src/ \
:/src/libnm-systemd-shared/src/ \
:/src/libnm-std-aux/unaligned.h | \
xargs -0 rm -f
nm_copy_sd_shared() {
mkdir -p "./src/libnm-systemd-shared/$(dirname "$1")"
cp "$SYSTEMD_DIR/$1" "./src/libnm-systemd-shared/$1"
}
nm_copy_sd_core() {
mkdir -p "./src/libnm-systemd-core/$(dirname "$1")"
cp "$SYSTEMD_DIR/$1" "./src/libnm-systemd-core/$1"
}
nm_copy_sd_stdaux() {
mkdir -p "./src/libnm-std-aux/"
cp "$SYSTEMD_DIR/$1" "./src/libnm-std-aux/${1##*/}"
}
nm_copy_sd_core "src/libsystemd-network/arp-util.c"
nm_copy_sd_core "src/libsystemd-network/arp-util.h"
nm_copy_sd_core "src/libsystemd-network/dhcp-identifier.c"
nm_copy_sd_core "src/libsystemd-network/dhcp-identifier.h"
nm_copy_sd_core "src/libsystemd-network/dhcp-lease-internal.h"
nm_copy_sd_core "src/libsystemd-network/dhcp6-internal.h"
nm_copy_sd_core "src/libsystemd-network/dhcp6-lease-internal.h"
nm_copy_sd_core "src/libsystemd-network/dhcp6-network.c"
nm_copy_sd_core "src/libsystemd-network/dhcp6-option.c"
nm_copy_sd_core "src/libsystemd-network/dhcp6-option.h"
nm_copy_sd_core "src/libsystemd-network/dhcp6-protocol.c"
nm_copy_sd_core "src/libsystemd-network/dhcp6-protocol.h"
nm_copy_sd_core "src/libsystemd-network/network-common.c"
nm_copy_sd_core "src/libsystemd-network/network-common.h"
nm_copy_sd_core "src/libsystemd-network/network-internal.h"
nm_copy_sd_core "src/libsystemd-network/sd-dhcp6-client.c"
nm_copy_sd_core "src/libsystemd-network/sd-dhcp6-lease.c"
nm_copy_sd_core "src/libsystemd/sd-event/event-source.h"
nm_copy_sd_core "src/libsystemd/sd-event/event-util.c"
nm_copy_sd_core "src/libsystemd/sd-event/event-util.h"
nm_copy_sd_core "src/libsystemd/sd-event/sd-event.c"
nm_copy_sd_core "src/libsystemd/sd-id128/id128-util.c"
nm_copy_sd_core "src/libsystemd/sd-id128/id128-util.h"
nm_copy_sd_core "src/libsystemd/sd-id128/sd-id128.c"
nm_copy_sd_core "src/systemd/_sd-common.h"
nm_copy_sd_core "src/systemd/sd-dhcp6-client.h"
nm_copy_sd_core "src/systemd/sd-dhcp6-lease.h"
nm_copy_sd_core "src/systemd/sd-dhcp6-option.h"
nm_copy_sd_core "src/systemd/sd-event.h"
nm_copy_sd_core "src/systemd/sd-id128.h"
nm_copy_sd_core "src/systemd/sd-ndisc.h"
nm_copy_sd_shared "src/basic/alloc-util.c"
nm_copy_sd_shared "src/basic/alloc-util.h"
nm_copy_sd_shared "src/basic/async.h"
nm_copy_sd_shared "src/basic/cgroup-util.h"
nm_copy_sd_shared "src/basic/dns-def.h"
nm_copy_sd_shared "src/basic/env-file.c"
nm_copy_sd_shared "src/basic/env-file.h"
nm_copy_sd_shared "src/basic/env-util.c"
nm_copy_sd_shared "src/basic/env-util.h"
nm_copy_sd_shared "src/basic/errno-util.h"
nm_copy_sd_shared "src/basic/escape.c"
nm_copy_sd_shared "src/basic/escape.h"
nm_copy_sd_shared "src/basic/ether-addr-util.c"
nm_copy_sd_shared "src/basic/ether-addr-util.h"
nm_copy_sd_shared "src/basic/extract-word.c"
nm_copy_sd_shared "src/basic/extract-word.h"
nm_copy_sd_shared "src/basic/fd-util.c"
nm_copy_sd_shared "src/basic/fd-util.h"
nm_copy_sd_shared "src/basic/fileio.c"
nm_copy_sd_shared "src/basic/fileio.h"
nm_copy_sd_shared "src/basic/format-util.c"
nm_copy_sd_shared "src/basic/format-util.h"
nm_copy_sd_shared "src/basic/fs-util.c"
nm_copy_sd_shared "src/basic/fs-util.h"
nm_copy_sd_shared "src/basic/glyph-util.c"
nm_copy_sd_shared "src/basic/glyph-util.h"
nm_copy_sd_shared "src/basic/hash-funcs.c"
nm_copy_sd_shared "src/basic/hash-funcs.h"
nm_copy_sd_shared "src/basic/hashmap.c"
nm_copy_sd_shared "src/basic/hashmap.h"
nm_copy_sd_shared "src/basic/hexdecoct.c"
nm_copy_sd_shared "src/basic/hexdecoct.h"
nm_copy_sd_shared "src/basic/hostname-util.c"
nm_copy_sd_shared "src/basic/hostname-util.h"
nm_copy_sd_shared "src/basic/in-addr-util.c"
nm_copy_sd_shared "src/basic/in-addr-util.h"
nm_copy_sd_shared "src/basic/inotify-util.c"
nm_copy_sd_shared "src/basic/inotify-util.h"
nm_copy_sd_shared "src/basic/io-util.c"
nm_copy_sd_shared "src/basic/io-util.h"
nm_copy_sd_shared "src/basic/list.h"
nm_copy_sd_shared "src/basic/locale-util.c"
nm_copy_sd_shared "src/basic/locale-util.h"
nm_copy_sd_shared "src/basic/log.h"
nm_copy_sd_shared "src/basic/macro.h"
nm_copy_sd_shared "src/basic/memory-util.c"
nm_copy_sd_shared "src/basic/memory-util.h"
nm_copy_sd_shared "src/basic/mempool.c"
nm_copy_sd_shared "src/basic/mempool.h"
nm_copy_sd_shared "src/basic/missing_fcntl.h"
nm_copy_sd_shared "src/basic/missing_random.h"
nm_copy_sd_shared "src/basic/missing_socket.h"
nm_copy_sd_shared "src/basic/missing_stat.h"
nm_copy_sd_shared "src/basic/missing_syscall.h"
nm_copy_sd_shared "src/basic/missing_type.h"
nm_copy_sd_shared "src/basic/ordered-set.c"
nm_copy_sd_shared "src/basic/ordered-set.h"
nm_copy_sd_shared "src/basic/parse-util.c"
nm_copy_sd_shared "src/basic/parse-util.h"
nm_copy_sd_shared "src/basic/path-util.c"
nm_copy_sd_shared "src/basic/path-util.h"
nm_copy_sd_shared "src/basic/prioq.c"
nm_copy_sd_shared "src/basic/prioq.h"
nm_copy_sd_shared "src/basic/process-util.c"
nm_copy_sd_shared "src/basic/process-util.h"
nm_copy_sd_shared "src/basic/random-util.c"
nm_copy_sd_shared "src/basic/random-util.h"
nm_copy_sd_shared "src/basic/ratelimit.c"
nm_copy_sd_shared "src/basic/ratelimit.h"
nm_copy_sd_shared "src/basic/set.h"
nm_copy_sd_shared "src/basic/signal-util.c"
nm_copy_sd_shared "src/basic/signal-util.h"
nm_copy_sd_shared "src/basic/siphash24.h"
nm_copy_sd_shared "src/basic/socket-util.c"
nm_copy_sd_shared "src/basic/socket-util.h"
nm_copy_sd_shared "src/basic/sort-util.h"
nm_copy_sd_shared "src/basic/sparse-endian.h"
nm_copy_sd_shared "src/basic/stat-util.c"
nm_copy_sd_shared "src/basic/stat-util.h"
nm_copy_sd_shared "src/basic/stdio-util.h"
nm_copy_sd_shared "src/basic/string-table.c"
nm_copy_sd_shared "src/basic/string-table.h"
nm_copy_sd_shared "src/basic/string-util.c"
nm_copy_sd_shared "src/basic/string-util.h"
nm_copy_sd_shared "src/basic/strv.c"
nm_copy_sd_shared "src/basic/strv.h"
nm_copy_sd_shared "src/basic/strxcpyx.c"
nm_copy_sd_shared "src/basic/strxcpyx.h"
nm_copy_sd_shared "src/basic/time-util.c"
nm_copy_sd_shared "src/basic/time-util.h"
nm_copy_sd_shared "src/basic/tmpfile-util.c"
nm_copy_sd_shared "src/basic/tmpfile-util.h"
nm_copy_sd_shared "src/basic/umask-util.h"
nm_copy_sd_shared "src/basic/user-util.h"
nm_copy_sd_shared "src/basic/utf8.c"
nm_copy_sd_shared "src/basic/utf8.h"
nm_copy_sd_shared "src/basic/util.c"
nm_copy_sd_shared "src/basic/util.h"
nm_copy_sd_shared "src/fundamental/macro-fundamental.h"
nm_copy_sd_shared "src/fundamental/sha256.c"
nm_copy_sd_shared "src/fundamental/sha256.h"
nm_copy_sd_shared "src/fundamental/string-util-fundamental.c"
nm_copy_sd_shared "src/fundamental/string-util-fundamental.h"
nm_copy_sd_shared "src/shared/dns-domain.c"
nm_copy_sd_shared "src/shared/dns-domain.h"
nm_copy_sd_shared "src/shared/log-link.h"
nm_copy_sd_shared "src/shared/web-util.c"
nm_copy_sd_shared "src/shared/web-util.h"
nm_copy_sd_stdaux "src/basic/unaligned.h"
18 files changed, 190 insertions, 1993 deletions
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c index 5e91e86f53..62873e0111 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c @@ -211,47 +211,55 @@ bool dhcp6_option_can_request(uint16_t option) { } } -static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode, size_t optlen) { - assert_return(buf, -EINVAL); - assert_return(*buf, -EINVAL); - assert_return(buflen, -EINVAL); +static int option_append_hdr(uint8_t **buf, size_t *offset, uint16_t optcode, size_t optlen) { + assert(buf); + assert(*buf); + assert(offset); - if (optlen > 0xffff || *buflen < optlen + offsetof(DHCP6Option, data)) + if (optlen > 0xffff) return -ENOBUFS; - unaligned_write_be16(*buf + offsetof(DHCP6Option, code), optcode); - unaligned_write_be16(*buf + offsetof(DHCP6Option, len), optlen); + if (optlen + offsetof(DHCP6Option, data) > SIZE_MAX - *offset) + return -ENOBUFS; - *buf += offsetof(DHCP6Option, data); - *buflen -= offsetof(DHCP6Option, data); + if (!GREEDY_REALLOC(*buf, *offset + optlen + offsetof(DHCP6Option, data))) + return -ENOMEM; + + unaligned_write_be16(*buf + *offset + offsetof(DHCP6Option, code), optcode); + unaligned_write_be16(*buf + *offset + offsetof(DHCP6Option, len), optlen); + *offset += offsetof(DHCP6Option, data); return 0; } -int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, - size_t optlen, const void *optval) { +int dhcp6_option_append( + uint8_t **buf, + size_t *offset, + uint16_t code, + size_t optlen, + const void *optval) { + int r; - assert_return(optval || optlen == 0, -EINVAL); + assert(optval || optlen == 0); - r = option_append_hdr(buf, buflen, code, optlen); + r = option_append_hdr(buf, offset, code, optlen); if (r < 0) return r; - *buf = mempcpy_safe(*buf, optval, optlen); - *buflen -= optlen; + memcpy_safe(*buf + *offset, optval, optlen); + *offset += optlen; return 0; } -int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedSet *vendor_options) { +int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *offset, OrderedSet *vendor_options) { sd_dhcp6_option *options; int r; assert(buf); assert(*buf); - assert(buflen); - assert(vendor_options); + assert(offset); ORDERED_SET_FOREACH(options, vendor_options) { _cleanup_free_ uint8_t *p = NULL; @@ -268,7 +276,7 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedSet unaligned_write_be16(p + 6, options->length); memcpy(p + 8, options->data, options->length); - r = dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_VENDOR_OPTS, total, p); + r = dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_VENDOR_OPTS, total, p); if (r < 0) return r; } @@ -276,69 +284,48 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedSet return 0; } -static int option_append_ia_address(uint8_t **buf, size_t *buflen, const struct iaaddr *address) { - struct iaaddr a; - int r; - +static int option_append_ia_address(uint8_t **buf, size_t *offset, const struct iaaddr *address) { assert(buf); assert(*buf); - assert(buflen); + assert(offset); assert(address); /* Do not append T1 and T2. */ - a = (struct iaaddr) { + const struct iaaddr a = { .address = address->address, }; - r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR, sizeof(struct iaaddr)); - if (r < 0) - return r; - - *buf = mempcpy(*buf, &a, sizeof(struct iaaddr)); - *buflen -= sizeof(struct iaaddr); - - return offsetof(DHCP6Option, data) + sizeof(struct iaaddr); + return dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_IAADDR, sizeof(struct iaaddr), &a); } -static int option_append_pd_prefix(uint8_t **buf, size_t *buflen, const struct iapdprefix *prefix) { - struct iapdprefix p; - int r; - +static int option_append_pd_prefix(uint8_t **buf, size_t *offset, const struct iapdprefix *prefix) { assert(buf); assert(*buf); - assert(buflen); + assert(offset); assert(prefix); if (prefix->prefixlen == 0) return -EINVAL; /* Do not append T1 and T2. */ - p = (struct iapdprefix) { + const struct iapdprefix p = { .prefixlen = prefix->prefixlen, .address = prefix->address, }; - r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IA_PD_PREFIX, sizeof(struct iapdprefix)); - if (r < 0) - return r; - - *buf = mempcpy(*buf, &p, sizeof(struct iapdprefix)); - *buflen -= sizeof(struct iapdprefix); - - return offsetof(DHCP6Option, data) + sizeof(struct iapdprefix); + return dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_IA_PD_PREFIX, sizeof(struct iapdprefix), &p); } -int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) { +int dhcp6_option_append_ia(uint8_t **buf, size_t *offset, const DHCP6IA *ia) { + _cleanup_free_ uint8_t *data = NULL; struct ia_header header; - size_t ia_buflen; - uint8_t *ia_hdr; - uint16_t len; + size_t len; int r; - assert_return(buf, -EINVAL); - assert_return(*buf, -EINVAL); - assert_return(buflen, -EINVAL); - assert_return(ia, -EINVAL); + assert(buf); + assert(*buf); + assert(offset); + assert(ia); /* client should not send set T1 and T2. See, RFC 8415, and issue #18090. */ @@ -362,43 +349,38 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) { assert_not_reached(); } - if (*buflen < offsetof(DHCP6Option, data) + len) - return -ENOBUFS; - - ia_hdr = *buf; - ia_buflen = *buflen; - - /* The header will be written at the end of this function. */ - *buf += offsetof(DHCP6Option, data); - *buflen -= offsetof(DHCP6Option, data); + if (!GREEDY_REALLOC(data, len)) + return -ENOMEM; - *buf = mempcpy(*buf, &header, len); - *buflen -= len; + memcpy(data, &header, len); LIST_FOREACH(addresses, addr, ia->addresses) { if (ia->type == SD_DHCP6_OPTION_IA_PD) - r = option_append_pd_prefix(buf, buflen, &addr->iapdprefix); + r = option_append_pd_prefix(&data, &len, &addr->iapdprefix); else - r = option_append_ia_address(buf, buflen, &addr->iaaddr); + r = option_append_ia_address(&data, &len, &addr->iaaddr); if (r < 0) return r; - - len += r; } - return option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len); + return dhcp6_option_append(buf, offset, ia->type, len, data); } -int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) { +int dhcp6_option_append_fqdn(uint8_t **buf, size_t *offset, const char *fqdn) { uint8_t buffer[1 + DNS_WIRE_FORMAT_HOSTNAME_MAX]; int r; - assert_return(buf && *buf && buflen && fqdn, -EINVAL); + assert(buf); + assert(*buf); + assert(offset); + + if (isempty(fqdn)) + return 0; buffer[0] = DHCP6_FQDN_FLAG_S; /* Request server to perform AAAA RR DNS updates */ /* Store domain name after flags field */ - r = dns_name_to_wire_format(fqdn, buffer + 1, sizeof(buffer) - 1, false); + r = dns_name_to_wire_format(fqdn, buffer + 1, sizeof(buffer) - 1, false); if (r <= 0) return r; @@ -411,82 +393,70 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) { if (dns_name_is_single_label(fqdn)) r--; - r = dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_CLIENT_FQDN, 1 + r, buffer); - - return r; + return dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_CLIENT_FQDN, 1 + r, buffer); } -int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char * const *user_class) { +int dhcp6_option_append_user_class(uint8_t **buf, size_t *offset, char * const *user_class) { _cleanup_free_ uint8_t *p = NULL; - size_t total = 0, offset = 0; + size_t n = 0; assert(buf); assert(*buf); - assert(buflen); - assert(!strv_isempty(user_class)); + assert(offset); + + if (strv_isempty(user_class)) + return 0; STRV_FOREACH(s, user_class) { size_t len = strlen(*s); - uint8_t *q; - if (len > 0xffff || len == 0) + if (len > UINT16_MAX || len == 0) return -EINVAL; - q = realloc(p, total + len + 2); - if (!q) - return -ENOMEM; - p = q; - - unaligned_write_be16(&p[offset], len); - memcpy(&p[offset + 2], *s, len); + if (!GREEDY_REALLOC(p, n + len + 2)) + return -ENOMEM; - offset += 2 + len; - total += 2 + len; + unaligned_write_be16(p + n, len); + memcpy(p + n + 2, *s, len); + n += len + 2; } - return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_USER_CLASS, total, p); + return dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_USER_CLASS, n, p); } -int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char * const *vendor_class) { +int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *offset, char * const *vendor_class) { _cleanup_free_ uint8_t *p = NULL; - uint32_t enterprise_identifier; - size_t total, offset; + size_t n = 0; assert(buf); assert(*buf); - assert(buflen); - assert(!strv_isempty(vendor_class)); + assert(offset); - enterprise_identifier = htobe32(SYSTEMD_PEN); + if (strv_isempty(vendor_class)) + return 0; - p = memdup(&enterprise_identifier, sizeof(enterprise_identifier)); - if (!p) + if (!GREEDY_REALLOC(p, sizeof(be32_t))) return -ENOMEM; - total = sizeof(enterprise_identifier); - offset = total; + /* Enterprise Identifier */ + unaligned_write_be32(p, SYSTEMD_PEN); + n += sizeof(be32_t); STRV_FOREACH(s, vendor_class) { size_t len = strlen(*s); - uint8_t *q; if (len > UINT16_MAX || len == 0) return -EINVAL; - q = realloc(p, total + len + 2); - if (!q) + if (!GREEDY_REALLOC(p, n + len + 2)) return -ENOMEM; - p = q; - - unaligned_write_be16(&p[offset], len); - memcpy(&p[offset + 2], *s, len); - - offset += 2 + len; - total += 2 + len; + unaligned_write_be16(p + n, len); + memcpy(p + n + 2, *s, len); + n += len + 2; } - return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_VENDOR_CLASS, total, p); + return dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_VENDOR_CLASS, n, p); } int dhcp6_option_parse( diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.h index 80aba7f37f..36841dd270 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.h +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.h @@ -72,13 +72,13 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DHCP6IA*, dhcp6_ia_free); bool dhcp6_option_can_request(uint16_t option); -int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, +int dhcp6_option_append(uint8_t **buf, size_t *offset, uint16_t code, size_t optlen, const void *optval); -int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia); -int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn); -int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char * const *user_class); -int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char * const *user_class); -int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedSet *vendor_options); +int dhcp6_option_append_ia(uint8_t **buf, size_t *offset, const DHCP6IA *ia); +int dhcp6_option_append_fqdn(uint8_t **buf, size_t *offset, const char *fqdn); +int dhcp6_option_append_user_class(uint8_t **buf, size_t *offset, char * const *user_class); +int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *offset, char * const *vendor_class); +int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *offset, OrderedSet *vendor_options); int dhcp6_option_parse( const uint8_t *buf, diff --git a/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.c b/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.c deleted file mode 100644 index 6672409d75..0000000000 --- a/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.c +++ /dev/null @@ -1,796 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "alloc-util.h" -#include "escape.h" -#include "ether-addr-util.h" -#include "hexdecoct.h" -#include "in-addr-util.h" -#include "lldp-neighbor.h" -#include "memory-util.h" -#include "missing_network.h" -#include "unaligned.h" - -static void lldp_neighbor_id_hash_func(const LLDPNeighborID *id, struct siphash *state) { - assert(id); - assert(state); - - siphash24_compress(id->chassis_id, id->chassis_id_size, state); - siphash24_compress(&id->chassis_id_size, sizeof(id->chassis_id_size), state); - siphash24_compress(id->port_id, id->port_id_size, state); - siphash24_compress(&id->port_id_size, sizeof(id->port_id_size), state); -} - -int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y) { - assert(x); - assert(y); - - return memcmp_nn(x->chassis_id, x->chassis_id_size, y->chassis_id, y->chassis_id_size) - ?: memcmp_nn(x->port_id, x->port_id_size, y->port_id, y->port_id_size); -} - -DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( - lldp_neighbor_hash_ops, - LLDPNeighborID, - lldp_neighbor_id_hash_func, - lldp_neighbor_id_compare_func, - sd_lldp_neighbor, - lldp_neighbor_unlink); - -int lldp_neighbor_prioq_compare_func(const void *a, const void *b) { - const sd_lldp_neighbor *x = a, *y = b; - - assert(x); - assert(y); - - return CMP(x->until, y->until); -} - -sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) { - if (!n) - return NULL; - - assert(n->n_ref > 0 || n->lldp_rx); - n->n_ref++; - - return n; -} - -static sd_lldp_neighbor *lldp_neighbor_free(sd_lldp_neighbor *n) { - if (!n) - return NULL; - - free(n->id.port_id); - free(n->id.chassis_id); - free(n->port_description); - free(n->system_name); - free(n->system_description); - free(n->mud_url); - free(n->chassis_id_as_string); - free(n->port_id_as_string); - return mfree(n); -} - -sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n) { - - /* Drops one reference from the neighbor. Note that the object is not freed unless it is already unlinked from - * the sd_lldp object. */ - - if (!n) - return NULL; - - assert(n->n_ref > 0); - n->n_ref--; - - if (n->n_ref <= 0 && !n->lldp_rx) - lldp_neighbor_free(n); - - return NULL; -} - -sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n) { - - /* Removes the neighbor object from the LLDP object, and frees it if it also has no other reference. */ - - if (!n) - return NULL; - - if (!n->lldp_rx) - return NULL; - - /* Only remove the neighbor object from the hash table if it's in there, don't complain if it isn't. This is - * because we are used as destructor call for hashmap_clear() and thus sometimes are called to de-register - * ourselves from the hashtable and sometimes are called after we already are de-registered. */ - - (void) hashmap_remove_value(n->lldp_rx->neighbor_by_id, &n->id, n); - - assert_se(prioq_remove(n->lldp_rx->neighbor_by_expiry, n, &n->prioq_idx) >= 0); - - n->lldp_rx = NULL; - - if (n->n_ref <= 0) - lldp_neighbor_free(n); - - return NULL; -} - -sd_lldp_neighbor *lldp_neighbor_new(size_t raw_size) { - sd_lldp_neighbor *n; - - if (raw_size > SIZE_MAX - ALIGN(sizeof(sd_lldp_neighbor))) - return NULL; - - n = malloc0(ALIGN(sizeof(sd_lldp_neighbor)) + raw_size); - if (!n) - return NULL; - - n->raw_size = raw_size; - n->n_ref = 1; - - return n; -} - -static int parse_string(sd_lldp_rx *lldp_rx, char **s, const void *q, size_t n) { - const char *p = q; - char *k; - - assert(s); - assert(p || n == 0); - - if (*s) { - log_lldp_rx(lldp_rx, "Found duplicate string, ignoring field."); - return 0; - } - - /* Strip trailing NULs, just to be nice */ - while (n > 0 && p[n-1] == 0) - n--; - - if (n <= 0) /* Ignore empty strings */ - return 0; - - /* Look for inner NULs */ - if (memchr(p, 0, n)) { - log_lldp_rx(lldp_rx, "Found inner NUL in string, ignoring field."); - return 0; - } - - /* Let's escape weird chars, for security reasons */ - k = cescape_length(p, n); - if (!k) - return log_oom_debug(); - - free(*s); - *s = k; - - return 1; -} - -int lldp_neighbor_parse(sd_lldp_neighbor *n) { - struct ether_header h; - const uint8_t *p; - size_t left; - int r; - - assert(n); - - if (n->raw_size < sizeof(struct ether_header)) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "Received truncated packet, ignoring."); - - memcpy(&h, LLDP_NEIGHBOR_RAW(n), sizeof(h)); - - if (h.ether_type != htobe16(ETHERTYPE_LLDP)) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "Received packet with wrong type, ignoring."); - - if (h.ether_dhost[0] != 0x01 || - h.ether_dhost[1] != 0x80 || - h.ether_dhost[2] != 0xc2 || - h.ether_dhost[3] != 0x00 || - h.ether_dhost[4] != 0x00 || - !IN_SET(h.ether_dhost[5], 0x00, 0x03, 0x0e)) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "Received packet with wrong destination address, ignoring."); - - memcpy(&n->source_address, h.ether_shost, sizeof(struct ether_addr)); - memcpy(&n->destination_address, h.ether_dhost, sizeof(struct ether_addr)); - - p = (const uint8_t*) LLDP_NEIGHBOR_RAW(n) + sizeof(struct ether_header); - left = n->raw_size - sizeof(struct ether_header); - - for (;;) { - uint8_t type; - uint16_t length; - - if (left < 2) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "TLV lacks header, ignoring."); - - type = p[0] >> 1; - length = p[1] + (((uint16_t) (p[0] & 1)) << 8); - p += 2, left -= 2; - - if (left < length) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "TLV truncated, ignoring datagram."); - - switch (type) { - - case SD_LLDP_TYPE_END: - if (length != 0) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "End marker TLV not zero-sized, ignoring datagram."); - - /* Note that after processing the SD_LLDP_TYPE_END left could still be > 0 - * as the message may contain padding (see IEEE 802.1AB-2016, sec. 8.5.12) */ - - goto end_marker; - - case SD_LLDP_TYPE_CHASSIS_ID: - if (length < 2 || length > 256) - /* includes the chassis subtype, hence one extra byte */ - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "Chassis ID field size out of range, ignoring datagram."); - - if (n->id.chassis_id) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "Duplicate chassis ID field, ignoring datagram."); - - n->id.chassis_id = memdup(p, length); - if (!n->id.chassis_id) - return log_oom_debug(); - - n->id.chassis_id_size = length; - break; - - case SD_LLDP_TYPE_PORT_ID: - if (length < 2 || length > 256) - /* includes the port subtype, hence one extra byte */ - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "Port ID field size out of range, ignoring datagram."); - - if (n->id.port_id) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "Duplicate port ID field, ignoring datagram."); - - n->id.port_id = memdup(p, length); - if (!n->id.port_id) - return log_oom_debug(); - - n->id.port_id_size = length; - break; - - case SD_LLDP_TYPE_TTL: - if (length != 2) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "TTL field has wrong size, ignoring datagram."); - - if (n->has_ttl) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "Duplicate TTL field, ignoring datagram."); - - n->ttl = unaligned_read_be16(p); - n->has_ttl = true; - break; - - case SD_LLDP_TYPE_PORT_DESCRIPTION: - r = parse_string(n->lldp_rx, &n->port_description, p, length); - if (r < 0) - return r; - break; - - case SD_LLDP_TYPE_SYSTEM_NAME: - r = parse_string(n->lldp_rx, &n->system_name, p, length); - if (r < 0) - return r; - break; - - case SD_LLDP_TYPE_SYSTEM_DESCRIPTION: - r = parse_string(n->lldp_rx, &n->system_description, p, length); - if (r < 0) - return r; - break; - - case SD_LLDP_TYPE_SYSTEM_CAPABILITIES: - if (length != 4) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "System capabilities field has wrong size."); - - n->system_capabilities = unaligned_read_be16(p); - n->enabled_capabilities = unaligned_read_be16(p + 2); - n->has_capabilities = true; - break; - - case SD_LLDP_TYPE_PRIVATE: - if (length < 4) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "Found private TLV that is too short, ignoring."); - - /* RFC 8520: MUD URL */ - if (memcmp(p, SD_LLDP_OUI_IANA_MUD, sizeof(SD_LLDP_OUI_IANA_MUD)) == 0) { - r = parse_string(n->lldp_rx, &n->mud_url, p + sizeof(SD_LLDP_OUI_IANA_MUD), - length - sizeof(SD_LLDP_OUI_IANA_MUD)); - if (r < 0) - return r; - } - break; - } - - p += length, left -= length; - } - -end_marker: - if (!n->id.chassis_id || !n->id.port_id || !n->has_ttl) - return log_lldp_rx_errno(n->lldp_rx, SYNTHETIC_ERRNO(EBADMSG), - "One or more mandatory TLV missing in datagram. Ignoring."); - - n->rindex = sizeof(struct ether_header); - - return 0; -} - -void lldp_neighbor_start_ttl(sd_lldp_neighbor *n) { - assert(n); - - if (n->ttl > 0) { - usec_t base; - - /* Use the packet's timestamp if there is one known */ - base = triple_timestamp_by_clock(&n->timestamp, CLOCK_BOOTTIME); - if (!timestamp_is_set(base)) - base = now(CLOCK_BOOTTIME); /* Otherwise, take the current time */ - - n->until = usec_add(base, n->ttl * USEC_PER_SEC); - } else - n->until = 0; - - if (n->lldp_rx) - prioq_reshuffle(n->lldp_rx->neighbor_by_expiry, n, &n->prioq_idx); -} - -bool lldp_neighbor_equal(const sd_lldp_neighbor *a, const sd_lldp_neighbor *b) { - if (a == b) - return true; - - if (!a || !b) - return false; - - if (a->raw_size != b->raw_size) - return false; - - return memcmp(LLDP_NEIGHBOR_RAW(a), LLDP_NEIGHBOR_RAW(b), a->raw_size) == 0; -} - -int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address) { - assert_return(n, -EINVAL); - assert_return(address, -EINVAL); - - *address = n->source_address; - return 0; -} - -int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address) { - assert_return(n, -EINVAL); - assert_return(address, -EINVAL); - - *address = n->destination_address; - return 0; -} - -int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(size, -EINVAL); - - *ret = LLDP_NEIGHBOR_RAW(n); - *size = n->raw_size; - - return 0; -} - -int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) { - assert_return(n, -EINVAL); - assert_return(type, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(size, -EINVAL); - - assert(n->id.chassis_id_size > 0); - - *type = *(uint8_t*) n->id.chassis_id; - *ret = (uint8_t*) n->id.chassis_id + 1; - *size = n->id.chassis_id_size - 1; - - return 0; -} - -static int format_mac_address(const void *data, size_t sz, char **ret) { - struct ether_addr a; - char *k; - - assert(data || sz <= 0); - - if (sz != 7) - return 0; - - memcpy(&a, (uint8_t*) data + 1, sizeof(a)); - - k = new(char, ETHER_ADDR_TO_STRING_MAX); - if (!k) - return -ENOMEM; - - *ret = ether_addr_to_string(&a, k); - return 1; -} - -static int format_network_address(const void *data, size_t sz, char **ret) { - union in_addr_union a; - int family, r; - - if (sz == 6 && ((uint8_t*) data)[1] == 1) { - memcpy(&a.in, (uint8_t*) data + 2, sizeof(a.in)); - family = AF_INET; - } else if (sz == 18 && ((uint8_t*) data)[1] == 2) { - memcpy(&a.in6, (uint8_t*) data + 2, sizeof(a.in6)); - family = AF_INET6; - } else - return 0; - - r = in_addr_to_string(family, &a, ret); - if (r < 0) - return r; - return 1; -} - -int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret) { - char *k; - int r; - - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (n->chassis_id_as_string) { - *ret = n->chassis_id_as_string; - return 0; - } - - assert(n->id.chassis_id_size > 0); - - switch (*(uint8_t*) n->id.chassis_id) { - - case SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT: - case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS: - case SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT: - case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME: - case SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED: - k = cescape_length((char*) n->id.chassis_id + 1, n->id.chassis_id_size - 1); - if (!k) - return -ENOMEM; - - goto done; - - case SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: - r = format_mac_address(n->id.chassis_id, n->id.chassis_id_size, &k); - if (r < 0) - return r; - if (r > 0) - goto done; - - break; - - case SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS: - r = format_network_address(n->id.chassis_id, n->id.chassis_id_size, &k); - if (r < 0) - return r; - if (r > 0) - goto done; - - break; - } - - /* Generic fallback */ - k = hexmem(n->id.chassis_id, n->id.chassis_id_size); - if (!k) - return -ENOMEM; - -done: - *ret = n->chassis_id_as_string = k; - return 0; -} - -int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) { - assert_return(n, -EINVAL); - assert_return(type, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(size, -EINVAL); - - assert(n->id.port_id_size > 0); - - *type = *(uint8_t*) n->id.port_id; - *ret = (uint8_t*) n->id.port_id + 1; - *size = n->id.port_id_size - 1; - - return 0; -} - -int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret) { - char *k; - int r; - - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (n->port_id_as_string) { - *ret = n->port_id_as_string; - return 0; - } - - assert(n->id.port_id_size > 0); - - switch (*(uint8_t*) n->id.port_id) { - - case SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: - case SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT: - case SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME: - case SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: - k = cescape_length((char*) n->id.port_id + 1, n->id.port_id_size - 1); - if (!k) - return -ENOMEM; - - goto done; - - case SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS: - r = format_mac_address(n->id.port_id, n->id.port_id_size, &k); - if (r < 0) - return r; - if (r > 0) - goto done; - - break; - - case SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS: - r = format_network_address(n->id.port_id, n->id.port_id_size, &k); - if (r < 0) - return r; - if (r > 0) - goto done; - - break; - } - - /* Generic fallback */ - k = hexmem(n->id.port_id, n->id.port_id_size); - if (!k) - return -ENOMEM; - -done: - *ret = n->port_id_as_string = k; - return 0; -} - -int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec) { - assert_return(n, -EINVAL); - assert_return(ret_sec, -EINVAL); - - *ret_sec = n->ttl; - return 0; -} - -int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (!n->system_name) - return -ENODATA; - - *ret = n->system_name; - return 0; -} - -int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (!n->system_description) - return -ENODATA; - - *ret = n->system_description; - return 0; -} - -int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (!n->port_description) - return -ENODATA; - - *ret = n->port_description; - return 0; -} - -int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (!n->mud_url) - return -ENODATA; - - *ret = n->mud_url; - return 0; -} - -int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (!n->has_capabilities) - return -ENODATA; - - *ret = n->system_capabilities; - return 0; -} - -int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - - if (!n->has_capabilities) - return -ENODATA; - - *ret = n->enabled_capabilities; - return 0; -} - -int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) { - _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; - int r; - - assert_return(ret, -EINVAL); - assert_return(raw || raw_size <= 0, -EINVAL); - - n = lldp_neighbor_new(raw_size); - if (!n) - return -ENOMEM; - - memcpy_safe(LLDP_NEIGHBOR_RAW(n), raw, raw_size); - - r = lldp_neighbor_parse(n); - if (r < 0) - return r; - - *ret = TAKE_PTR(n); - - return r; -} - -int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n) { - assert_return(n, -EINVAL); - - assert(n->raw_size >= sizeof(struct ether_header)); - n->rindex = sizeof(struct ether_header); - - return n->rindex < n->raw_size; -} - -int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) { - size_t length; - - assert_return(n, -EINVAL); - - if (n->rindex == n->raw_size) /* EOF */ - return -ESPIPE; - - if (n->rindex + 2 > n->raw_size) /* Truncated message */ - return -EBADMSG; - - length = LLDP_NEIGHBOR_TLV_LENGTH(n); - if (n->rindex + 2 + length > n->raw_size) - return -EBADMSG; - - n->rindex += 2 + length; - return n->rindex < n->raw_size; -} - -int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type) { - assert_return(n, -EINVAL); - assert_return(type, -EINVAL); - - if (n->rindex == n->raw_size) /* EOF */ - return -ESPIPE; - - if (n->rindex + 2 > n->raw_size) - return -EBADMSG; - - *type = LLDP_NEIGHBOR_TLV_TYPE(n); - return 0; -} - -int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type) { - uint8_t k; - int r; - - assert_return(n, -EINVAL); - - r = sd_lldp_neighbor_tlv_get_type(n, &k); - if (r < 0) - return r; - - return type == k; -} - -int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t *subtype) { - const uint8_t *d; - size_t length; - int r; - - assert_return(n, -EINVAL); - assert_return(oui, -EINVAL); - assert_return(subtype, -EINVAL); - - r = sd_lldp_neighbor_tlv_is_type(n, SD_LLDP_TYPE_PRIVATE); - if (r < 0) - return r; - if (r == 0) - return -ENXIO; - - length = LLDP_NEIGHBOR_TLV_LENGTH(n); - if (length < 4) - return -EBADMSG; - - if (n->rindex + 2 + length > n->raw_size) - return -EBADMSG; - - d = LLDP_NEIGHBOR_TLV_DATA(n); - memcpy(oui, d, 3); - *subtype = d[3]; - - return 0; -} - -int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t subtype) { - uint8_t k[3], st; - int r; - - r = sd_lldp_neighbor_tlv_get_oui(n, k, &st); - if (r == -ENXIO) - return 0; - if (r < 0) - return r; - - return memcmp(k, oui, 3) == 0 && st == subtype; -} - -int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) { - size_t length; - - assert_return(n, -EINVAL); - assert_return(ret, -EINVAL); - assert_return(size, -EINVAL); - - /* Note that this returns the full TLV, including the TLV header */ - - if (n->rindex + 2 > n->raw_size) - return -EBADMSG; - - length = LLDP_NEIGHBOR_TLV_LENGTH(n); - if (n->rindex + 2 + length > n->raw_size) - return -EBADMSG; - - *ret = (uint8_t*) LLDP_NEIGHBOR_RAW(n) + n->rindex; - *size = length + 2; - - return 0; -} - -int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret) { - assert_return(n, -EINVAL); - assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP); - assert_return(clock_supported(clock), -EOPNOTSUPP); - assert_return(ret, -EINVAL); - - if (!triple_timestamp_is_set(&n->timestamp)) - return -ENODATA; - - *ret = triple_timestamp_by_clock(&n->timestamp, clock); - return 0; -} diff --git a/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.h b/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.h deleted file mode 100644 index 016286b17d..0000000000 --- a/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.h +++ /dev/null @@ -1,92 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include <inttypes.h> -#include <stdbool.h> -#include <sys/types.h> - -#include "sd-lldp-rx.h" - -#include "hash-funcs.h" -#include "lldp-rx-internal.h" -#include "time-util.h" - -typedef struct LLDPNeighborID { - /* The spec calls this an "MSAP identifier" */ - void *chassis_id; - size_t chassis_id_size; - - void *port_id; - size_t port_id_size; -} LLDPNeighborID; - -struct sd_lldp_neighbor { - /* Neighbor objects stay around as long as they are linked into an "sd_lldp_rx" object or n_ref > 0. */ - sd_lldp_rx *lldp_rx; - unsigned n_ref; - - triple_timestamp timestamp; - - usec_t until; - unsigned prioq_idx; - - struct ether_addr source_address; - struct ether_addr destination_address; - - LLDPNeighborID id; - - /* The raw packet size. The data is appended to the object, accessible via LLDP_NEIGHBOR_RAW() */ - size_t raw_size; - - /* The current read index for the iterative TLV interface */ - size_t rindex; - - /* And a couple of fields parsed out. */ - bool has_ttl:1; - bool has_capabilities:1; - bool has_port_vlan_id:1; - - uint16_t ttl; - - uint16_t system_capabilities; - uint16_t enabled_capabilities; - - char *port_description; - char *system_name; - char *system_description; - char *mud_url; - - uint16_t port_vlan_id; - - char *chassis_id_as_string; - char *port_id_as_string; -}; - -static inline void *LLDP_NEIGHBOR_RAW(const sd_lldp_neighbor *n) { - return (uint8_t*) n + ALIGN(sizeof(sd_lldp_neighbor)); -} - -static inline uint8_t LLDP_NEIGHBOR_TLV_TYPE(const sd_lldp_neighbor *n) { - return ((uint8_t*) LLDP_NEIGHBOR_RAW(n))[n->rindex] >> 1; -} - -static inline size_t LLDP_NEIGHBOR_TLV_LENGTH(const sd_lldp_neighbor *n) { - uint8_t *p; - - p = (uint8_t*) LLDP_NEIGHBOR_RAW(n) + n->rindex; - return p[1] + (((size_t) (p[0] & 1)) << 8); -} - -static inline void* LLDP_NEIGHBOR_TLV_DATA(const sd_lldp_neighbor *n) { - return ((uint8_t*) LLDP_NEIGHBOR_RAW(n)) + n->rindex + 2; -} - -extern const struct hash_ops lldp_neighbor_hash_ops; -int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y); -int lldp_neighbor_prioq_compare_func(const void *a, const void *b); - -sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n); -sd_lldp_neighbor *lldp_neighbor_new(size_t raw_size); -int lldp_neighbor_parse(sd_lldp_neighbor *n); -void lldp_neighbor_start_ttl(sd_lldp_neighbor *n); -bool lldp_neighbor_equal(const sd_lldp_neighbor *a, const sd_lldp_neighbor *b); diff --git a/src/libnm-systemd-core/src/libsystemd-network/lldp-network.c b/src/libnm-systemd-core/src/libsystemd-network/lldp-network.c deleted file mode 100644 index 24edc371db..0000000000 --- a/src/libnm-systemd-core/src/libsystemd-network/lldp-network.c +++ /dev/null @@ -1,70 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include <linux/filter.h> -#include <netinet/if_ether.h> - -#include "fd-util.h" -#include "lldp-network.h" -#include "missing_network.h" -#include "socket-util.h" - -int lldp_network_bind_raw_socket(int ifindex) { - static const struct sock_filter filter[] = { - BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ethhdr, h_dest)), /* A <- 4 bytes of destination MAC */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0180c200, 1, 0), /* A != 01:80:c2:00 */ - BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_dest) + 4), /* A <- remaining 2 bytes of destination MAC */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0000, 3, 0), /* A != 00:00 */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0003, 2, 0), /* A != 00:03 */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x000e, 1, 0), /* A != 00:0e */ - BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_proto)), /* A <- protocol */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_LLDP, 1, 0), /* A != ETHERTYPE_LLDP */ - BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ - BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept packet */ - }; - static const struct sock_fprog fprog = { - .len = ELEMENTSOF(filter), - .filter = (struct sock_filter*) filter, - }; - struct packet_mreq mreq = { - .mr_ifindex = ifindex, - .mr_type = PACKET_MR_MULTICAST, - .mr_alen = ETH_ALEN, - .mr_address = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00 } - }; - union sockaddr_union saddrll = { - .ll.sll_family = AF_PACKET, - .ll.sll_ifindex = ifindex, - }; - _cleanup_close_ int fd = -1; - - assert(ifindex > 0); - - fd = socket(AF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, - htobe16(ETHERTYPE_LLDP)); - if (fd < 0) - return -errno; - - if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) < 0) - return -errno; - - /* customer bridge */ - if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) - return -errno; - - /* non TPMR bridge */ - mreq.mr_address[ETH_ALEN - 1] = 0x03; - if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) - return -errno; - - /* nearest bridge */ - mreq.mr_address[ETH_ALEN - 1] = 0x0E; - if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) - return -errno; - - if (bind(fd, &saddrll.sa, sizeof(saddrll.ll)) < 0) - return -errno; - - return TAKE_FD(fd); -} diff --git a/src/libnm-systemd-core/src/libsystemd-network/lldp-network.h b/src/libnm-systemd-core/src/libsystemd-network/lldp-network.h deleted file mode 100644 index bc69b324c2..0000000000 --- a/src/libnm-systemd-core/src/libsystemd-network/lldp-network.h +++ /dev/null @@ -1,6 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include "sd-event.h" - -int lldp_network_bind_raw_socket(int ifindex); diff --git a/src/libnm-systemd-core/src/libsystemd-network/lldp-rx-internal.h b/src/libnm-systemd-core/src/libsystemd-network/lldp-rx-internal.h deleted file mode 100644 index 83d0bc460d..0000000000 --- a/src/libnm-systemd-core/src/libsystemd-network/lldp-rx-internal.h +++ /dev/null @@ -1,48 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include "sd-event.h" -#include "sd-lldp-rx.h" - -#include "hashmap.h" -#include "network-common.h" -#include "prioq.h" - -struct sd_lldp_rx { - 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_rx_callback_t callback; - void *userdata; - - uint16_t capability_mask; - - struct ether_addr filter_address; -}; - -const char* lldp_rx_event_to_string(sd_lldp_rx_event_t e) _const_; -sd_lldp_rx_event_t lldp_rx_event_from_string(const char *s) _pure_; - -#define log_lldp_rx_errno(lldp_rx, error, fmt, ...) \ - log_interface_prefix_full_errno( \ - "LLDP Rx: ", \ - sd_lldp_rx, lldp_rx, \ - error, fmt, ##__VA_ARGS__) -#define log_lldp_rx(lldp_rx, fmt, ...) \ - log_interface_prefix_full_errno_zerook( \ - "LLDP Rx: ", \ - sd_lldp_rx, lldp_rx, \ - 0, fmt, ##__VA_ARGS__) diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c index 606e48ce6f..375f984940 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c @@ -574,8 +574,8 @@ static void client_stop(sd_dhcp6_client *client, int error) { static int client_append_common_options_in_managed_mode( sd_dhcp6_client *client, - uint8_t **opt, - size_t *optlen, + uint8_t **buf, + size_t *offset, const DHCP6IA *ia_na, const DHCP6IA *ia_pd) { @@ -587,44 +587,37 @@ static int client_append_common_options_in_managed_mode( DHCP6_STATE_REQUEST, DHCP6_STATE_RENEW, DHCP6_STATE_REBIND)); - assert(opt); - assert(optlen); + assert(buf); + assert(*buf); + assert(offset); if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_NA) && ia_na) { - r = dhcp6_option_append_ia(opt, optlen, ia_na); + r = dhcp6_option_append_ia(buf, offset, ia_na); if (r < 0) return r; } if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_PD) && ia_pd) { - r = dhcp6_option_append_ia(opt, optlen, ia_pd); + r = dhcp6_option_append_ia(buf, offset, ia_pd); if (r < 0) return r; } - if (client->fqdn) { - r = dhcp6_option_append_fqdn(opt, optlen, client->fqdn); - if (r < 0) - return r; - } + r = dhcp6_option_append_fqdn(buf, offset, client->fqdn); + if (r < 0) + return r; - if (client->user_class) { - r = dhcp6_option_append_user_class(opt, optlen, client->user_class); - if (r < 0) - return r; - } + r = dhcp6_option_append_user_class(buf, offset, client->user_class); + if (r < 0) + return r; - if (client->vendor_class) { - r = dhcp6_option_append_vendor_class(opt, optlen, client->vendor_class); - if (r < 0) - return r; - } + r = dhcp6_option_append_vendor_class(buf, offset, client->vendor_class); + if (r < 0) + return r; - if (!ordered_set_isempty(client->vendor_options)) { - r = dhcp6_option_append_vendor_option(opt, optlen, client->vendor_options); - if (r < 0) - return r; - } + r = dhcp6_option_append_vendor_option(buf, offset, client->vendor_options); + if (r < 0) + return r; return 0; } @@ -648,41 +641,42 @@ static DHCP6MessageType client_message_type_from_state(sd_dhcp6_client *client) } } -static int client_append_oro(sd_dhcp6_client *client, uint8_t **opt, size_t *optlen) { - _cleanup_free_ be16_t *buf = NULL; +static int client_append_oro(sd_dhcp6_client *client, uint8_t **buf, size_t *offset) { + _cleanup_free_ be16_t *p = NULL; be16_t *req_opts; size_t n; assert(client); - assert(opt); - assert(optlen); + assert(buf); + assert(*buf); + assert(offset); switch (client->state) { case DHCP6_STATE_INFORMATION_REQUEST: n = client->n_req_opts; - buf = new(be16_t, n + 2); - if (!buf) + p = new(be16_t, n + 2); + if (!p) return -ENOMEM; - memcpy_safe(buf, client->req_opts, n * sizeof(be16_t)); - buf[n++] = htobe16(SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME); /* RFC 8415 section 21.23 */ - buf[n++] = htobe16(SD_DHCP6_OPTION_INF_MAX_RT); /* RFC 8415 section 21.25 */ + memcpy_safe(p, client->req_opts, n * sizeof(be16_t)); + p[n++] = htobe16(SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME); /* RFC 8415 section 21.23 */ + p[n++] = htobe16(SD_DHCP6_OPTION_INF_MAX_RT); /* RFC 8415 section 21.25 */ - typesafe_qsort(buf, n, be16_compare_func); - req_opts = buf; + typesafe_qsort(p, n, be16_compare_func); + req_opts = p; break; case DHCP6_STATE_SOLICITATION: n = client->n_req_opts; - buf = new(be16_t, n + 1); - if (!buf) + p = new(be16_t, n + 1); + if (!p) return -ENOMEM; - memcpy_safe(buf, client->req_opts, n * sizeof(be16_t)); - buf[n++] = htobe16(SD_DHCP6_OPTION_SOL_MAX_RT); /* RFC 8415 section 21.24 */ + memcpy_safe(p, client->req_opts, n * sizeof(be16_t)); + p[n++] = htobe16(SD_DHCP6_OPTION_SOL_MAX_RT); /* RFC 8415 section 21.24 */ - typesafe_qsort(buf, n, be16_compare_func); - req_opts = buf; + typesafe_qsort(p, n, be16_compare_func); + req_opts = p; break; default: @@ -693,18 +687,18 @@ static int client_append_oro(sd_dhcp6_client *client, uint8_t **opt, size_t *opt if (n == 0) return 0; - return dhcp6_option_append(opt, optlen, SD_DHCP6_OPTION_ORO, n * sizeof(be16_t), req_opts); + return dhcp6_option_append(buf, offset, SD_DHCP6_OPTION_ORO, n * sizeof(be16_t), req_opts); } int dhcp6_client_send_message(sd_dhcp6_client *client) { - _cleanup_free_ DHCP6Message *message = NULL; + _cleanup_free_ uint8_t *buf = NULL; struct in6_addr all_servers = IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; struct sd_dhcp6_option *j; - size_t len, optlen = 512; - uint8_t *opt; usec_t elapsed_usec, time_now; be16_t elapsed_time; + DHCP6Message *message; + size_t offset; int r; assert(client); @@ -714,16 +708,13 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) { if (r < 0) return r; - len = sizeof(DHCP6Message) + optlen; - - message = malloc0(len); - if (!message) + if (!GREEDY_REALLOC0(buf, offsetof(DHCP6Message, options))) return -ENOMEM; - opt = (uint8_t *)(message + 1); - + message = (DHCP6Message*) buf; message->transaction_id = client->transaction_id; message->type = client_message_type_from_state(client); + offset = offsetof(DHCP6Message, options); switch (client->state) { case DHCP6_STATE_INFORMATION_REQUEST: @@ -731,12 +722,12 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) { case DHCP6_STATE_SOLICITATION: if (client->rapid_commit) { - r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL); + r = dhcp6_option_append(&buf, &offset, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL); if (r < 0) return r; } - r = client_append_common_options_in_managed_mode(client, &opt, &optlen, + r = client_append_common_options_in_managed_mode(client, &buf, &offset, &client->ia_na, &client->ia_pd); if (r < 0) return r; @@ -745,7 +736,7 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) { case DHCP6_STATE_REQUEST: case DHCP6_STATE_RENEW: - r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_SERVERID, + r = dhcp6_option_append(&buf, &offset, SD_DHCP6_OPTION_SERVERID, client->lease->serverid_len, client->lease->serverid); if (r < 0) @@ -756,7 +747,7 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) { assert(client->lease); - r = client_append_common_options_in_managed_mode(client, &opt, &optlen, + r = client_append_common_options_in_managed_mode(client, &buf, &offset, client->lease->ia_na, client->lease->ia_pd); if (r < 0) return r; @@ -769,24 +760,24 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) { } if (client->mudurl) { - r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_MUD_URL_V6, + r = dhcp6_option_append(&buf, &offset, SD_DHCP6_OPTION_MUD_URL_V6, strlen(client->mudurl), client->mudurl); if (r < 0) return r; } - r = client_append_oro(client, &opt, &optlen); + r = client_append_oro(client, &buf, &offset); if (r < 0) return r; - assert(client->duid_len); - r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_CLIENTID, + assert(client->duid_len > 0); + r = dhcp6_option_append(&buf, &offset, SD_DHCP6_OPTION_CLIENTID, client->duid_len, &client->duid); if (r < 0) return r; ORDERED_HASHMAP_FOREACH(j, client->extra_options) { - r = dhcp6_option_append(&opt, &optlen, j->option, j->length, j->data); + r = dhcp6_option_append(&buf, &offset, j->option, j->length, j->data); if (r < 0) return r; } @@ -796,18 +787,16 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) { * been trying to complete a DHCP message exchange. */ elapsed_usec = MIN(usec_sub_unsigned(time_now, client->transaction_start) / USEC_PER_MSEC / 10, (usec_t) UINT16_MAX); elapsed_time = htobe16(elapsed_usec); - r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ELAPSED_TIME, sizeof(elapsed_time), &elapsed_time); + r = dhcp6_option_append(&buf, &offset, SD_DHCP6_OPTION_ELAPSED_TIME, sizeof(elapsed_time), &elapsed_time); if (r < 0) return r; - r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message, - len - optlen); + r = dhcp6_network_send_udp_socket(client->fd, &all_servers, buf, offset); if (r < 0) return r; log_dhcp6_client(client, "Sent %s", - dhcp6_message_type_to_string(message->type)); - + dhcp6_message_type_to_string(client_message_type_from_state(client))); return 0; } diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-lldp-rx.c b/src/libnm-systemd-core/src/libsystemd-network/sd-lldp-rx.c deleted file mode 100644 index 0479cff5f5..0000000000 --- a/src/libnm-systemd-core/src/libsystemd-network/sd-lldp-rx.c +++ /dev/null @@ -1,525 +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-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_rx_event_table[_SD_LLDP_RX_EVENT_MAX] = { - [SD_LLDP_RX_EVENT_ADDED] = "added", - [SD_LLDP_RX_EVENT_REMOVED] = "removed", - [SD_LLDP_RX_EVENT_UPDATED] = "updated", - [SD_LLDP_RX_EVENT_REFRESHED] = "refreshed", -}; - -DEFINE_STRING_TABLE_LOOKUP(lldp_rx_event, sd_lldp_rx_event_t); - -static void lldp_rx_flush_neighbors(sd_lldp_rx *lldp_rx) { - assert(lldp_rx); - - hashmap_clear(lldp_rx->neighbor_by_id); -} - -static void lldp_rx_callback(sd_lldp_rx *lldp_rx, sd_lldp_rx_event_t event, sd_lldp_neighbor *n) { - assert(lldp_rx); - assert(event >= 0 && event < _SD_LLDP_RX_EVENT_MAX); - - if (!lldp_rx->callback) - return (void) log_lldp_rx(lldp_rx, "Received '%s' event.", lldp_rx_event_to_string(event)); - - log_lldp_rx(lldp_rx, "Invoking callback for '%s' event.", lldp_rx_event_to_string(event)); - lldp_rx->callback(lldp_rx, event, n, lldp_rx->userdata); -} - -static int lldp_rx_make_space(sd_lldp_rx *lldp_rx, size_t extra) { - usec_t t = USEC_INFINITY; - bool changed = false; - - assert(lldp_rx); - - /* 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_rx->neighbor_by_expiry); - if (!n) - break; - - sd_lldp_neighbor_ref(n); - - if (hashmap_size(lldp_rx->neighbor_by_id) > LESS_BY(lldp_rx->neighbors_max, extra)) - goto remove_one; - - if (t == USEC_INFINITY) - t = now(CLOCK_BOOTTIME); - - if (n->until > t) - break; - - remove_one: - lldp_neighbor_unlink(n); - lldp_rx_callback(lldp_rx, SD_LLDP_RX_EVENT_REMOVED, n); - changed = true; - } - - return changed; -} - -static bool lldp_rx_keep_neighbor(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *n) { - assert(lldp_rx); - 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_rx->filter_address) && - ether_addr_equal(&lldp_rx->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_rx->capability_mask) == 0) - return false; - - /* Keep everything else */ - return true; -} - -static int lldp_rx_start_timer(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *neighbor); - -static int lldp_rx_add_neighbor(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *n) { - _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *old = NULL; - bool keep; - int r; - - assert(lldp_rx); - assert(n); - assert(!n->lldp_rx); - - keep = lldp_rx_keep_neighbor(lldp_rx, n); - - /* First retrieve the old entry for this MSAP */ - old = hashmap_get(lldp_rx->neighbor_by_id, &n->id); - if (old) { - sd_lldp_neighbor_ref(old); - - if (!keep) { - lldp_neighbor_unlink(old); - lldp_rx_callback(lldp_rx, SD_LLDP_RX_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_rx_start_timer(lldp_rx, old); - lldp_rx_callback(lldp_rx, SD_LLDP_RX_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_rx_make_space(lldp_rx, 1); - - r = hashmap_ensure_put(&lldp_rx->neighbor_by_id, &lldp_neighbor_hash_ops, &n->id, n); - if (r < 0) - goto finish; - - r = prioq_ensure_put(&lldp_rx->neighbor_by_expiry, lldp_neighbor_prioq_compare_func, n, &n->prioq_idx); - if (r < 0) { - assert_se(hashmap_remove(lldp_rx->neighbor_by_id, &n->id) == n); - goto finish; - } - - n->lldp_rx = lldp_rx; - - lldp_rx_start_timer(lldp_rx, n); - lldp_rx_callback(lldp_rx, old ? SD_LLDP_RX_EVENT_UPDATED : SD_LLDP_RX_EVENT_ADDED, n); - - return 1; - -finish: - if (old) - lldp_rx_callback(lldp_rx, SD_LLDP_RX_EVENT_REMOVED, old); - - return r; -} - -static int lldp_rx_handle_datagram(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *n) { - int r; - - assert(lldp_rx); - assert(n); - - r = lldp_neighbor_parse(n); - if (r < 0) - return r; - - r = lldp_rx_add_neighbor(lldp_rx, n); - if (r < 0) - return log_lldp_rx_errno(lldp_rx, r, "Failed to add datagram. Ignoring."); - - log_lldp_rx(lldp_rx, "Successfully processed LLDP datagram."); - return 0; -} - -static int lldp_rx_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_rx *lldp_rx = ASSERT_PTR(userdata); - struct timespec ts; - - assert(fd >= 0); - - space = next_datagram_size_fd(fd); - if (space < 0) { - if (ERRNO_IS_TRANSIENT(space) || ERRNO_IS_DISCONNECT(space)) - return 0; - - log_lldp_rx_errno(lldp_rx, space, "Failed to determine datagram size to read, ignoring: %m"); - return 0; - } - - n = lldp_neighbor_new(space); - if (!n) { - log_oom_debug(); - return 0; - } - - length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT); - if (length < 0) { - if (ERRNO_IS_TRANSIENT(errno) || ERRNO_IS_DISCONNECT(errno)) - return 0; - - log_lldp_rx_errno(lldp_rx, errno, "Failed to read LLDP datagram, ignoring: %m"); - return 0; - } - - if ((size_t) length != n->raw_size) { - log_lldp_rx(lldp_rx, "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); - - (void) lldp_rx_handle_datagram(lldp_rx, n); - return 0; -} - -static void lldp_rx_reset(sd_lldp_rx *lldp_rx) { - assert(lldp_rx); - - (void) event_source_disable(lldp_rx->timer_event_source); - lldp_rx->io_event_source = sd_event_source_disable_unref(lldp_rx->io_event_source); - lldp_rx->fd = safe_close(lldp_rx->fd); -} - -int sd_lldp_rx_is_running(sd_lldp_rx *lldp_rx) { - if (!lldp_rx) - return false; - - return lldp_rx->fd >= 0; -} - -int sd_lldp_rx_start(sd_lldp_rx *lldp_rx) { - int r; - - assert_return(lldp_rx, -EINVAL); - assert_return(lldp_rx->event, -EINVAL); - assert_return(lldp_rx->ifindex > 0, -EINVAL); - - if (sd_lldp_rx_is_running(lldp_rx)) - return 0; - - assert(!lldp_rx->io_event_source); - - lldp_rx->fd = lldp_network_bind_raw_socket(lldp_rx->ifindex); - if (lldp_rx->fd < 0) - return lldp_rx->fd; - - r = sd_event_add_io(lldp_rx->event, &lldp_rx->io_event_source, lldp_rx->fd, EPOLLIN, lldp_rx_receive_datagram, lldp_rx); - if (r < 0) - goto fail; - - r = sd_event_source_set_priority(lldp_rx->io_event_source, lldp_rx->event_priority); - if (r < 0) - goto fail; - - (void) sd_event_source_set_description(lldp_rx->io_event_source, "lldp-rx-io"); - - log_lldp_rx(lldp_rx, "Started LLDP client"); - return 1; - -fail: - lldp_rx_reset(lldp_rx); - return r; -} - -int sd_lldp_rx_stop(sd_lldp_rx *lldp_rx) { - if (!sd_lldp_rx_is_running(lldp_rx)) - return 0; - - log_lldp_rx(lldp_rx, "Stopping LLDP client"); - - lldp_rx_reset(lldp_rx); - lldp_rx_flush_neighbors(lldp_rx); - - return 1; -} - -int sd_lldp_rx_attach_event(sd_lldp_rx *lldp_rx, sd_event *event, int64_t priority) { - int r; - - assert_return(lldp_rx, -EINVAL); - assert_return(!sd_lldp_rx_is_running(lldp_rx), -EBUSY); - assert_return(!lldp_rx->event, -EBUSY); - - if (event) - lldp_rx->event = sd_event_ref(event); - else { - r = sd_event_default(&lldp_rx->event); - if (r < 0) - return r; - } - - lldp_rx->event_priority = priority; - - return 0; -} - -int sd_lldp_rx_detach_event(sd_lldp_rx *lldp_rx) { - assert_return(lldp_rx, -EINVAL); - assert_return(!sd_lldp_rx_is_running(lldp_rx), -EBUSY); - - lldp_rx->io_event_source = sd_event_source_disable_unref(lldp_rx->io_event_source); - lldp_rx->timer_event_source = sd_event_source_disable_unref(lldp_rx->timer_event_source); - lldp_rx->event = sd_event_unref(lldp_rx->event); - return 0; -} - -sd_event* sd_lldp_rx_get_event(sd_lldp_rx *lldp_rx) { - assert_return(lldp_rx, NULL); - - return lldp_rx->event; -} - -int sd_lldp_rx_set_callback(sd_lldp_rx *lldp_rx, sd_lldp_rx_callback_t cb, void *userdata) { - assert_return(lldp_rx, -EINVAL); - - lldp_rx->callback = cb; - lldp_rx->userdata = userdata; - - return 0; -} - -int sd_lldp_rx_set_ifindex(sd_lldp_rx *lldp_rx, int ifindex) { - assert_return(lldp_rx, -EINVAL); - assert_return(ifindex > 0, -EINVAL); - assert_return(!sd_lldp_rx_is_running(lldp_rx), -EBUSY); - - lldp_rx->ifindex = ifindex; - return 0; -} - -int sd_lldp_rx_set_ifname(sd_lldp_rx *lldp_rx, const char *ifname) { - assert_return(lldp_rx, -EINVAL); - assert_return(ifname, -EINVAL); - - if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE)) - return -EINVAL; - - return free_and_strdup(&lldp_rx->ifname, ifname); -} - -int sd_lldp_rx_get_ifname(sd_lldp_rx *lldp_rx, const char **ret) { - int r; - - assert_return(lldp_rx, -EINVAL); - - r = get_ifname(lldp_rx->ifindex, &lldp_rx->ifname); - if (r < 0) - return r; - - if (ret) - *ret = lldp_rx->ifname; - - return 0; -} - -static sd_lldp_rx *lldp_rx_free(sd_lldp_rx *lldp_rx) { - if (!lldp_rx) - return NULL; - - lldp_rx_reset(lldp_rx); - - sd_lldp_rx_detach_event(lldp_rx); - - lldp_rx_flush_neighbors(lldp_rx); - - hashmap_free(lldp_rx->neighbor_by_id); - prioq_free(lldp_rx->neighbor_by_expiry); - free(lldp_rx->ifname); - return mfree(lldp_rx); -} - -DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_lldp_rx, sd_lldp_rx, lldp_rx_free); - -int sd_lldp_rx_new(sd_lldp_rx **ret) { - _cleanup_(sd_lldp_rx_unrefp) sd_lldp_rx *lldp_rx = NULL; - - assert_return(ret, -EINVAL); - - lldp_rx = new(sd_lldp_rx, 1); - if (!lldp_rx) - return -ENOMEM; - - *lldp_rx = (sd_lldp_rx) { - .n_ref = 1, - .fd = -1, - .neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX, - .capability_mask = UINT16_MAX, - }; - - *ret = TAKE_PTR(lldp_rx); - return 0; -} - -static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) { - sd_lldp_rx *lldp_rx = userdata; - int r; - - r = lldp_rx_make_space(lldp_rx, 0); - if (r < 0) { - log_lldp_rx_errno(lldp_rx, r, "Failed to make space, ignoring: %m"); - return 0; - } - - r = lldp_rx_start_timer(lldp_rx, NULL); - if (r < 0) { - log_lldp_rx_errno(lldp_rx, r, "Failed to restart timer, ignoring: %m"); - return 0; - } - - return 0; -} - -static int lldp_rx_start_timer(sd_lldp_rx *lldp_rx, sd_lldp_neighbor *neighbor) { - sd_lldp_neighbor *n; - - assert(lldp_rx); - assert(lldp_rx->event); - - if (neighbor) - lldp_neighbor_start_ttl(neighbor); - - n = prioq_peek(lldp_rx->neighbor_by_expiry); - if (!n) - return event_source_disable(lldp_rx->timer_event_source); - - return event_reset_time(lldp_rx->event, &lldp_rx->timer_event_source, - CLOCK_BOOTTIME, - n->until, 0, - on_timer_event, lldp_rx, - lldp_rx->event_priority, "lldp-rx-timer", true); -} - -static inline int neighbor_compare_func(sd_lldp_neighbor * const *a, sd_lldp_neighbor * const *b) { - assert(a); - assert(b); - assert(*a); - assert(*b); - - return lldp_neighbor_id_compare_func(&(*a)->id, &(*b)->id); -} - -int sd_lldp_rx_get_neighbors(sd_lldp_rx *lldp_rx, sd_lldp_neighbor ***ret) { - _cleanup_free_ sd_lldp_neighbor **l = NULL; - sd_lldp_neighbor *n; - int k = 0; - - assert_return(lldp_rx, -EINVAL); - assert_return(ret, -EINVAL); - - if (hashmap_isempty(lldp_rx->neighbor_by_id)) { /* Special shortcut */ - *ret = NULL; - return 0; - } - - l = new0(sd_lldp_neighbor*, hashmap_size(lldp_rx->neighbor_by_id)); - if (!l) - return -ENOMEM; - - HASHMAP_FOREACH(n, lldp_rx->neighbor_by_id) - l[k++] = sd_lldp_neighbor_ref(n); - - assert((size_t) k == hashmap_size(lldp_rx->neighbor_by_id)); - - /* Return things in a stable order */ - typesafe_qsort(l, k, neighbor_compare_func); - *ret = TAKE_PTR(l); - - return k; -} - -int sd_lldp_rx_set_neighbors_max(sd_lldp_rx *lldp_rx, uint64_t m) { - assert_return(lldp_rx, -EINVAL); - assert_return(m > 0, -EINVAL); - - lldp_rx->neighbors_max = m; - lldp_rx_make_space(lldp_rx, 0); - - return 0; -} - -int sd_lldp_rx_match_capabilities(sd_lldp_rx *lldp_rx, uint16_t mask) { - assert_return(lldp_rx, -EINVAL); - assert_return(mask != 0, -EINVAL); - - lldp_rx->capability_mask = mask; - - return 0; -} - -int sd_lldp_rx_set_filter_address(sd_lldp_rx *lldp_rx, const struct ether_addr *addr) { - assert_return(lldp_rx, -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_rx->filter_address = *addr; - else - zero(lldp_rx->filter_address); - - return 0; -} diff --git a/src/libnm-systemd-core/src/systemd/sd-lldp-rx.h b/src/libnm-systemd-core/src/systemd/sd-lldp-rx.h deleted file mode 100644 index 504d7f59c1..0000000000 --- a/src/libnm-systemd-core/src/systemd/sd-lldp-rx.h +++ /dev/null @@ -1,109 +0,0 @@ -/* 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 <https://www.gnu.org/licenses/>. -***/ - -#include <errno.h> -#include <inttypes.h> -#include <net/ethernet.h> -#include <sys/types.h> - -#include "sd-event.h" -#include "sd-lldp.h" - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -typedef struct sd_lldp_rx sd_lldp_rx; -typedef struct sd_lldp_neighbor sd_lldp_neighbor; - -__extension__ typedef enum sd_lldp_rx_event_t { - SD_LLDP_RX_EVENT_ADDED, - SD_LLDP_RX_EVENT_REMOVED, - SD_LLDP_RX_EVENT_UPDATED, - SD_LLDP_RX_EVENT_REFRESHED, - _SD_LLDP_RX_EVENT_MAX, - _SD_LLDP_RX_EVENT_INVALID = -EINVAL, - _SD_ENUM_FORCE_S64(LLDP_RX_EVENT) -} sd_lldp_rx_event_t; - -typedef void (*sd_lldp_rx_callback_t)(sd_lldp_rx *lldp_rx, sd_lldp_rx_event_t event, sd_lldp_neighbor *n, void *userdata); - -int sd_lldp_rx_new(sd_lldp_rx **ret); -sd_lldp_rx *sd_lldp_rx_ref(sd_lldp_rx *lldp_rx); -sd_lldp_rx *sd_lldp_rx_unref(sd_lldp_rx *lldp_rx); - -int sd_lldp_rx_start(sd_lldp_rx *lldp_rx); -int sd_lldp_rx_stop(sd_lldp_rx *lldp_rx); -int sd_lldp_rx_is_running(sd_lldp_rx *lldp_rx); - -int sd_lldp_rx_attach_event(sd_lldp_rx *lldp_rx, sd_event *event, int64_t priority); -int sd_lldp_rx_detach_event(sd_lldp_rx *lldp_rx); -sd_event *sd_lldp_rx_get_event(sd_lldp_rx *lldp_rx); - -int sd_lldp_rx_set_callback(sd_lldp_rx *lldp_rx, sd_lldp_rx_callback_t cb, void *userdata); -int sd_lldp_rx_set_ifindex(sd_lldp_rx *lldp_rx, int ifindex); -int sd_lldp_rx_set_ifname(sd_lldp_rx *lldp_rx, const char *ifname); -int sd_lldp_rx_get_ifname(sd_lldp_rx *lldp_rx, const char **ret); - -/* Controls how much and what to store in the neighbors database */ -int sd_lldp_rx_set_neighbors_max(sd_lldp_rx *lldp_rx, uint64_t n); -int sd_lldp_rx_match_capabilities(sd_lldp_rx *lldp_rx, uint16_t mask); -int sd_lldp_rx_set_filter_address(sd_lldp_rx *lldp_rx, const struct ether_addr *address); - -int sd_lldp_rx_get_neighbors(sd_lldp_rx *lldp_rx, 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_rx, sd_lldp_rx_unref); -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp_neighbor, sd_lldp_neighbor_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/libnm-systemd-core/src/systemd/sd-lldp.h b/src/libnm-systemd-core/src/systemd/sd-lldp.h deleted file mode 100644 index 4069c5b299..0000000000 --- a/src/libnm-systemd-core/src/systemd/sd-lldp.h +++ /dev/null @@ -1,123 +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 <https://www.gnu.org/licenses/>. -***/ - -#include <inttypes.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 (const uint8_t[]) { 0x00, 0x80, 0xc2 } -#define SD_LLDP_OUI_802_3 (const uint8_t[]) { 0x00, 0x12, 0x0f } - -#define _SD_LLDP_OUI_IANA 0x00, 0x00, 0x5E -#define SD_LLDP_OUI_IANA (const uint8_t[]) { _SD_LLDP_OUI_IANA } - -#define SD_LLDP_OUI_IANA_SUBTYPE_MUD 0x01 -#define SD_LLDP_OUI_IANA_MUD \ - (const uint8_t[]) { _SD_LLDP_OUI_IANA, SD_LLDP_OUI_IANA_SUBTYPE_MUD } - -/* 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 -}; - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/libnm-systemd-shared/src/basic/errno-util.h b/src/libnm-systemd-shared/src/basic/errno-util.h index 648de50eb4..091f99c590 100644 --- a/src/libnm-systemd-shared/src/basic/errno-util.h +++ b/src/libnm-systemd-shared/src/basic/errno-util.h @@ -6,6 +6,21 @@ #include "macro.h" +/* strerror(3) says that glibc uses a maximum length of 1024 bytes. */ +#define ERRNO_BUF_LEN 1024 + +/* Note: the lifetime of the compound literal is the immediately surrounding block, + * see C11 §6.5.2.5, and + * https://stackoverflow.com/questions/34880638/compound-literal-lifetime-and-if-blocks + * + * Note that we use the GNU variant of strerror_r() here. */ +#define STRERROR(errnum) strerror_r(abs(errnum), (char[ERRNO_BUF_LEN]){}, ERRNO_BUF_LEN) + +/* A helper to print an error message or message for functions that return 0 on EOF. + * Note that we can't use ({ … }) to define a temporary variable, so errnum is + * evaluated twice. */ +#define STRERROR_OR_EOF(errnum) ((errnum) != 0 ? STRERROR(errnum) : "Unexpected EOF") + static inline void _reset_errno_(int *saved_errno) { if (*saved_errno < 0) /* Invalidated by UNPROTECT_ERRNO? */ return; @@ -22,6 +37,10 @@ static inline void _reset_errno_(int *saved_errno) { _saved_errno_ = -1; \ } while (false) +#define LOCAL_ERRNO(value) \ + PROTECT_ERRNO; \ + errno = abs(value) + static inline int negative_errno(void) { /* This helper should be used to shut up gcc if you know 'errno' is * negative. Instead of "return -errno;", use "return negative_errno();" @@ -54,11 +73,6 @@ static inline int RET_NERRNO(int ret) { return ret; } -static inline const char *strerror_safe(int error) { - /* 'safe' here does NOT mean thread safety. */ - return strerror(abs(error)); /* lgtm [cpp/potentially-dangerous-function] */ -} - static inline int errno_or_else(int fallback) { /* To be used when invoking library calls where errno handling is not defined clearly: we return * errno if it is set, and the specified error otherwise. The idea is that the caller initializes @@ -153,3 +167,10 @@ static inline bool ERRNO_IS_DEVICE_ABSENT(int r) { ENXIO, ENOENT); } + +/* Quite often we want to handle cases where the backing FS doesn't support extended attributes at all and + * where it simply doesn't have the requested xattr the same way */ +static inline bool ERRNO_IS_XATTR_ABSENT(int r) { + return abs(r) == ENODATA || + ERRNO_IS_NOT_SUPPORTED(r); +} diff --git a/src/libnm-systemd-shared/src/basic/fd-util.c b/src/libnm-systemd-shared/src/basic/fd-util.c index 6c85a34896..cee20a9a81 100644 --- a/src/libnm-systemd-shared/src/basic/fd-util.c +++ b/src/libnm-systemd-shared/src/basic/fd-util.c @@ -2,7 +2,6 @@ #include <errno.h> #include <fcntl.h> -#include <linux/btrfs.h> #if WANT_LINUX_FS_H #include <linux/fs.h> #endif @@ -779,20 +778,6 @@ int read_nr_open(void) { return 1024 * 1024; } -/* This is here because it's fd-related and is called from sd-journal code. Other btrfs-related utilities are - * in src/shared, but libsystemd must not link to libsystemd-shared, see docs/ARCHITECTURE.md. */ -int btrfs_defrag_fd(int fd) { - int r; - - assert(fd >= 0); - - r = fd_verify_regular(fd); - if (r < 0) - return r; - - return RET_NERRNO(ioctl(fd, BTRFS_IOC_DEFRAG, NULL)); -} - int fd_get_diskseq(int fd, uint64_t *ret) { uint64_t diskseq; diff --git a/src/libnm-systemd-shared/src/basic/fd-util.h b/src/libnm-systemd-shared/src/basic/fd-util.h index 8543d0d5ea..d9896e27e8 100644 --- a/src/libnm-systemd-shared/src/basic/fd-util.h +++ b/src/libnm-systemd-shared/src/basic/fd-util.h @@ -108,7 +108,6 @@ static inline int make_null_stdio(void) { int fd_reopen(int fd, int flags); int read_nr_open(void); -int btrfs_defrag_fd(int fd); int fd_get_diskseq(int fd, uint64_t *ret); /* The maximum length a buffer for a /proc/self/fd/<fd> path needs */ diff --git a/src/libnm-systemd-shared/src/basic/in-addr-util.c b/src/libnm-systemd-shared/src/basic/in-addr-util.c index cefe3f7661..05c729d34d 100644 --- a/src/libnm-systemd-shared/src/basic/in-addr-util.c +++ b/src/libnm-systemd-shared/src/basic/in-addr-util.c @@ -66,7 +66,7 @@ bool in4_addr_is_link_local_dynamic(const struct in_addr *a) { bool in6_addr_is_link_local(const struct in6_addr *a) { assert(a); - return IN6_IS_ADDR_LINKLOCAL(a); /* lgtm [cpp/potentially-dangerous-function] */ + return IN6_IS_ADDR_LINKLOCAL(a); } int in_addr_is_link_local(int family, const union in_addr_union *u) { @@ -131,7 +131,7 @@ int in_addr_is_localhost(int family, const union in_addr_union *u) { return in4_addr_is_localhost(&u->in); if (family == AF_INET6) - return IN6_IS_ADDR_LOOPBACK(&u->in6); /* lgtm [cpp/potentially-dangerous-function] */ + return IN6_IS_ADDR_LOOPBACK(&u->in6); return -EAFNOSUPPORT; } @@ -144,7 +144,7 @@ int in_addr_is_localhost_one(int family, const union in_addr_union *u) { return be32toh(u->in.s_addr) == UINT32_C(0x7F000001); if (family == AF_INET6) - return IN6_IS_ADDR_LOOPBACK(&u->in6); /* lgtm [cpp/potentially-dangerous-function] */ + return IN6_IS_ADDR_LOOPBACK(&u->in6); return -EAFNOSUPPORT; } @@ -194,8 +194,7 @@ int in_addr_prefix_intersect( assert(a); assert(b); - /* Checks whether there are any addresses that are in both - * networks */ + /* Checks whether there are any addresses that are in both networks */ m = MIN(aprefixlen, bprefixlen); @@ -203,7 +202,7 @@ int in_addr_prefix_intersect( uint32_t x, nm; x = be32toh(a->in.s_addr ^ b->in.s_addr); - nm = (m == 0) ? 0 : 0xFFFFFFFFUL << (32 - m); + nm = m == 0 ? 0 : 0xFFFFFFFFUL << (32 - m); return (x & nm) == 0; } diff --git a/src/libnm-systemd-shared/src/basic/process-util.c b/src/libnm-systemd-shared/src/basic/process-util.c index 3dd6f4df59..fb0b38fa49 100644 --- a/src/libnm-systemd-shared/src/basic/process-util.c +++ b/src/libnm-systemd-shared/src/basic/process-util.c @@ -815,7 +815,7 @@ int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) { if (status.si_pid == pid) { /* This is the correct child. */ if (status.si_code == CLD_EXITED) - return (status.si_status == 0) ? 0 : -EPROTO; + return status.si_status == 0 ? 0 : -EPROTO; else return -EPROTO; } diff --git a/src/libnm-systemd-shared/src/basic/stdio-util.h b/src/libnm-systemd-shared/src/basic/stdio-util.h index 69d7062ec6..f647f125ac 100644 --- a/src/libnm-systemd-shared/src/basic/stdio-util.h +++ b/src/libnm-systemd-shared/src/basic/stdio-util.h @@ -9,16 +9,16 @@ #include "macro.h" #include "memory-util.h" -#define snprintf_ok(buf, len, fmt, ...) \ - ({ \ - char *_buf = (buf); \ - size_t _len = (len); \ - int _snpf = snprintf(_buf, _len, (fmt), __VA_ARGS__); \ - _snpf >= 0 && (size_t) _snpf < _len ? _buf : NULL; \ +#define snprintf_ok(buf, len, fmt, ...) \ + ({ \ + char *_buf = (buf); \ + size_t _len = (len); \ + int _snpf = snprintf(_buf, _len, (fmt), ##__VA_ARGS__); \ + _snpf >= 0 && (size_t) _snpf < _len ? _buf : NULL; \ }) #define xsprintf(buf, fmt, ...) \ - assert_message_se(snprintf_ok(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__), "xsprintf: " #buf "[] must be big enough") + assert_message_se(snprintf_ok(buf, ELEMENTSOF(buf), fmt, ##__VA_ARGS__), "xsprintf: " #buf "[] must be big enough") #define VA_FORMAT_ADVANCE(format, ap) \ do { \ diff --git a/src/libnm-systemd-shared/src/basic/string-util.h b/src/libnm-systemd-shared/src/basic/string-util.h index 0703c848f0..46681ced99 100644 --- a/src/libnm-systemd-shared/src/basic/string-util.h +++ b/src/libnm-systemd-shared/src/basic/string-util.h @@ -171,9 +171,12 @@ int split_pair(const char *s, const char *sep, char **l, char **r); int free_and_strdup(char **p, const char *s); static inline int free_and_strdup_warn(char **p, const char *s) { - if (free_and_strdup(p, s) < 0) + int r; + + r = free_and_strdup(p, s); + if (r < 0) return log_oom(); - return 0; + return r; } int free_and_strndup(char **p, const char *s, size_t l); |