summaryrefslogtreecommitdiff
path: root/src/systemd
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-08-24 15:46:13 +0200
committerThomas Haller <thaller@redhat.com>2018-08-26 15:48:17 +0200
commit8aa8d7471023aebed9b626a566fff9753a85e7ff (patch)
tree57cdd00e7ee0bd59c11e88b9617f90a122b44508 /src/systemd
parent353810ccc15b85b4e013fcc6903913c02aca1a0c (diff)
downloadNetworkManager-8aa8d7471023aebed9b626a566fff9753a85e7ff.tar.gz
systemd: update code from upstream (2018-08-26)
This is a direct dump from systemd git. ====== SYSTEMD_DIR=../systemd COMMIT=56663345dfb1dd3ff23cac5fbc955aba54477efa ( cd "$SYSTEMD_DIR" git checkout "$COMMIT" git reset --hard git clean -fdx ) git ls-files :/src/systemd/src/ \ :/shared/nm-utils/unaligned.h | \ xargs -d '\n' rm -f nm_copy_sd() { mkdir -p "./src/systemd/$(dirname "$1")" cp "$SYSTEMD_DIR/$1" "./src/systemd/$1" } nm_copy_sd_shared() { mkdir -p "./shared/nm-utils/" cp "$SYSTEMD_DIR/$1" "./shared/nm-utils/${1##*/}" } nm_copy_sd "src/basic/alloc-util.c" nm_copy_sd "src/basic/alloc-util.h" nm_copy_sd "src/basic/async.h" nm_copy_sd "src/basic/env-util.c" nm_copy_sd "src/basic/env-util.h" nm_copy_sd "src/basic/escape.c" nm_copy_sd "src/basic/escape.h" nm_copy_sd "src/basic/ether-addr-util.c" nm_copy_sd "src/basic/ether-addr-util.h" nm_copy_sd "src/basic/extract-word.c" nm_copy_sd "src/basic/extract-word.h" nm_copy_sd "src/basic/fileio.c" nm_copy_sd "src/basic/fileio.h" nm_copy_sd "src/basic/fd-util.c" nm_copy_sd "src/basic/fd-util.h" nm_copy_sd "src/basic/fs-util.c" nm_copy_sd "src/basic/fs-util.h" nm_copy_sd "src/basic/hash-funcs.c" nm_copy_sd "src/basic/hash-funcs.h" nm_copy_sd "src/basic/hashmap.c" nm_copy_sd "src/basic/hashmap.h" nm_copy_sd "src/basic/hexdecoct.c" nm_copy_sd "src/basic/hexdecoct.h" nm_copy_sd "src/basic/hostname-util.c" nm_copy_sd "src/basic/hostname-util.h" nm_copy_sd "src/basic/in-addr-util.c" nm_copy_sd "src/basic/in-addr-util.h" nm_copy_sd "src/basic/io-util.c" nm_copy_sd "src/basic/io-util.h" nm_copy_sd "src/basic/list.h" nm_copy_sd "src/basic/log.h" nm_copy_sd "src/basic/macro.h" nm_copy_sd "src/basic/mempool.h" nm_copy_sd "src/basic/mempool.c" nm_copy_sd "src/basic/parse-util.c" nm_copy_sd "src/basic/parse-util.h" nm_copy_sd "src/basic/path-util.c" nm_copy_sd "src/basic/path-util.h" nm_copy_sd "src/basic/prioq.h" nm_copy_sd "src/basic/prioq.c" nm_copy_sd "src/basic/process-util.h" nm_copy_sd "src/basic/process-util.c" nm_copy_sd "src/basic/random-util.c" nm_copy_sd "src/basic/random-util.h" nm_copy_sd "src/basic/refcnt.h" nm_copy_sd "src/basic/set.h" nm_copy_sd "src/basic/signal-util.h" nm_copy_sd "src/basic/siphash24.h" nm_copy_sd "src/basic/socket-util.c" nm_copy_sd "src/basic/socket-util.h" nm_copy_sd "src/basic/sparse-endian.h" nm_copy_sd "src/basic/stat-util.c" nm_copy_sd "src/basic/stat-util.h" nm_copy_sd "src/basic/stdio-util.h" nm_copy_sd "src/basic/string-table.c" nm_copy_sd "src/basic/string-table.h" nm_copy_sd "src/basic/string-util.c" nm_copy_sd "src/basic/string-util.h" nm_copy_sd "src/basic/strv.c" nm_copy_sd "src/basic/strv.h" nm_copy_sd "src/basic/time-util.c" nm_copy_sd "src/basic/time-util.h" nm_copy_sd "src/basic/umask-util.h" nm_copy_sd_shared "src/basic/unaligned.h" nm_copy_sd "src/basic/utf8.c" nm_copy_sd "src/basic/utf8.h" nm_copy_sd "src/basic/util.c" nm_copy_sd "src/basic/util.h" nm_copy_sd "src/libsystemd-network/arp-util.c" nm_copy_sd "src/libsystemd-network/arp-util.h" nm_copy_sd "src/libsystemd-network/dhcp6-internal.h" nm_copy_sd "src/libsystemd-network/dhcp6-lease-internal.h" nm_copy_sd "src/libsystemd-network/dhcp6-network.c" nm_copy_sd "src/libsystemd-network/dhcp6-option.c" nm_copy_sd "src/libsystemd-network/dhcp6-protocol.h" nm_copy_sd "src/libsystemd-network/dhcp-identifier.c" nm_copy_sd "src/libsystemd-network/dhcp-identifier.h" nm_copy_sd "src/libsystemd-network/dhcp-internal.h" nm_copy_sd "src/libsystemd-network/dhcp-lease-internal.h" nm_copy_sd "src/libsystemd-network/dhcp-network.c" nm_copy_sd "src/libsystemd-network/dhcp-option.c" nm_copy_sd "src/libsystemd-network/dhcp-packet.c" nm_copy_sd "src/libsystemd-network/dhcp-protocol.h" nm_copy_sd "src/libsystemd-network/lldp-internal.h" nm_copy_sd "src/libsystemd-network/lldp-neighbor.c" nm_copy_sd "src/libsystemd-network/lldp-neighbor.h" nm_copy_sd "src/libsystemd-network/lldp-network.c" nm_copy_sd "src/libsystemd-network/lldp-network.h" nm_copy_sd "src/libsystemd-network/network-internal.c" nm_copy_sd "src/libsystemd-network/network-internal.h" nm_copy_sd "src/libsystemd-network/sd-dhcp6-client.c" nm_copy_sd "src/libsystemd-network/sd-dhcp6-lease.c" nm_copy_sd "src/libsystemd-network/sd-dhcp-client.c" nm_copy_sd "src/libsystemd-network/sd-dhcp-lease.c" nm_copy_sd "src/libsystemd-network/sd-ipv4ll.c" nm_copy_sd "src/libsystemd-network/sd-ipv4acd.c" nm_copy_sd "src/libsystemd-network/sd-lldp.c" nm_copy_sd "src/libsystemd/sd-event/sd-event.c" nm_copy_sd "src/libsystemd/sd-id128/id128-util.c" nm_copy_sd "src/libsystemd/sd-id128/id128-util.h" nm_copy_sd "src/libsystemd/sd-id128/sd-id128.c" nm_copy_sd "src/shared/dns-domain.c" nm_copy_sd "src/shared/dns-domain.h" nm_copy_sd "src/systemd/_sd-common.h" nm_copy_sd "src/systemd/sd-dhcp6-client.h" nm_copy_sd "src/systemd/sd-dhcp6-lease.h" nm_copy_sd "src/systemd/sd-dhcp-client.h" nm_copy_sd "src/systemd/sd-dhcp-lease.h" nm_copy_sd "src/systemd/sd-event.h" nm_copy_sd "src/systemd/sd-ndisc.h" nm_copy_sd "src/systemd/sd-id128.h" nm_copy_sd "src/systemd/sd-ipv4acd.h" nm_copy_sd "src/systemd/sd-ipv4ll.h" nm_copy_sd "src/systemd/sd-lldp.h"
Diffstat (limited to 'src/systemd')
-rw-r--r--src/systemd/src/basic/env-util.c785
-rw-r--r--src/systemd/src/basic/env-util.h50
-rw-r--r--src/systemd/src/basic/ether-addr-util.c3
-rw-r--r--src/systemd/src/basic/ether-addr-util.h4
-rw-r--r--src/systemd/src/basic/fd-util.h8
-rw-r--r--src/systemd/src/basic/fileio.c40
-rw-r--r--src/systemd/src/basic/fs-util.c67
-rw-r--r--src/systemd/src/basic/fs-util.h4
-rw-r--r--src/systemd/src/basic/hash-funcs.c9
-rw-r--r--src/systemd/src/basic/hash-funcs.h4
-rw-r--r--src/systemd/src/basic/hashmap.c33
-rw-r--r--src/systemd/src/basic/hashmap.h4
-rw-r--r--src/systemd/src/basic/in-addr-util.c23
-rw-r--r--src/systemd/src/basic/in-addr-util.h5
-rw-r--r--src/systemd/src/basic/macro.h119
-rw-r--r--src/systemd/src/basic/mempool.c3
-rw-r--r--src/systemd/src/basic/mempool.h4
-rw-r--r--src/systemd/src/basic/parse-util.c7
-rw-r--r--src/systemd/src/basic/path-util.c5
-rw-r--r--src/systemd/src/basic/path-util.h6
-rw-r--r--src/systemd/src/basic/process-util.c9
-rw-r--r--src/systemd/src/basic/random-util.c61
-rw-r--r--src/systemd/src/basic/random-util.h2
-rw-r--r--src/systemd/src/basic/socket-util.c113
-rw-r--r--src/systemd/src/basic/socket-util.h10
-rw-r--r--src/systemd/src/basic/stat-util.c11
-rw-r--r--src/systemd/src/basic/stat-util.h1
-rw-r--r--src/systemd/src/basic/strv.c4
-rw-r--r--src/systemd/src/basic/time-util.c24
-rw-r--r--src/systemd/src/basic/utf8.c3
-rw-r--r--src/systemd/src/basic/util.c30
-rw-r--r--src/systemd/src/basic/util.h14
-rw-r--r--src/systemd/src/libsystemd-network/arp-util.c1
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.c106
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.h16
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-internal.h1
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-lease-internal.h1
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-packet.c1
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-lease-internal.h1
-rw-r--r--src/systemd/src/libsystemd-network/lldp-internal.h5
-rw-r--r--src/systemd/src/libsystemd-network/lldp-neighbor.c23
-rw-r--r--src/systemd/src/libsystemd-network/lldp-network.c4
-rw-r--r--src/systemd/src/libsystemd-network/lldp-network.h5
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.c15
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.h10
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c59
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-lease.c2
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-client.c63
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-lease.c1
-rw-r--r--src/systemd/src/libsystemd-network/sd-ipv4acd.c1
-rw-r--r--src/systemd/src/libsystemd-network/sd-ipv4ll.c1
-rw-r--r--src/systemd/src/libsystemd-network/sd-lldp.c4
-rw-r--r--src/systemd/src/libsystemd/sd-event/sd-event.c4
-rw-r--r--src/systemd/src/libsystemd/sd-id128/id128-util.c2
-rw-r--r--src/systemd/src/libsystemd/sd-id128/id128-util.h3
-rw-r--r--src/systemd/src/libsystemd/sd-id128/sd-id128.c2
-rw-r--r--src/systemd/src/shared/dns-domain.c4
-rw-r--r--src/systemd/src/shared/dns-domain.h3
-rw-r--r--src/systemd/src/systemd/_sd-common.h1
-rw-r--r--src/systemd/src/systemd/sd-dhcp-client.h7
-rw-r--r--src/systemd/src/systemd/sd-dhcp-lease.h2
-rw-r--r--src/systemd/src/systemd/sd-dhcp6-client.h3
-rw-r--r--src/systemd/src/systemd/sd-dhcp6-lease.h1
-rw-r--r--src/systemd/src/systemd/sd-event.h1
-rw-r--r--src/systemd/src/systemd/sd-id128.h1
-rw-r--r--src/systemd/src/systemd/sd-ipv4acd.h2
-rw-r--r--src/systemd/src/systemd/sd-lldp.h3
67 files changed, 1494 insertions, 330 deletions
diff --git a/src/systemd/src/basic/env-util.c b/src/systemd/src/basic/env-util.c
new file mode 100644
index 0000000000..a784a30e1d
--- /dev/null
+++ b/src/systemd/src/basic/env-util.c
@@ -0,0 +1,785 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "env-util.h"
+#include "escape.h"
+#include "extract-word.h"
+#include "macro.h"
+#include "parse-util.h"
+#include "string-util.h"
+#include "strv.h"
+#include "utf8.h"
+
+#define VALID_CHARS_ENV_NAME \
+ DIGITS LETTERS \
+ "_"
+
+#ifndef ARG_MAX
+#define ARG_MAX ((size_t) sysconf(_SC_ARG_MAX))
+#endif
+
+static bool env_name_is_valid_n(const char *e, size_t n) {
+ const char *p;
+
+ if (!e)
+ return false;
+
+ if (n <= 0)
+ return false;
+
+ if (e[0] >= '0' && e[0] <= '9')
+ return false;
+
+ /* POSIX says the overall size of the environment block cannot
+ * be > ARG_MAX, an individual assignment hence cannot be
+ * either. Discounting the equal sign and trailing NUL this
+ * hence leaves ARG_MAX-2 as longest possible variable
+ * name. */
+ if (n > ARG_MAX - 2)
+ return false;
+
+ for (p = e; p < e + n; p++)
+ if (!strchr(VALID_CHARS_ENV_NAME, *p))
+ return false;
+
+ return true;
+}
+
+bool env_name_is_valid(const char *e) {
+ if (!e)
+ return false;
+
+ return env_name_is_valid_n(e, strlen(e));
+}
+
+bool env_value_is_valid(const char *e) {
+ if (!e)
+ return false;
+
+ if (!utf8_is_valid(e))
+ return false;
+
+ /* bash allows tabs and newlines in environment variables, and so
+ * should we */
+ if (string_has_cc(e, "\t\n"))
+ return false;
+
+ /* POSIX says the overall size of the environment block cannot
+ * be > ARG_MAX, an individual assignment hence cannot be
+ * either. Discounting the shortest possible variable name of
+ * length 1, the equal sign and trailing NUL this hence leaves
+ * ARG_MAX-3 as longest possible variable value. */
+ if (strlen(e) > ARG_MAX - 3)
+ return false;
+
+ return true;
+}
+
+bool env_assignment_is_valid(const char *e) {
+ const char *eq;
+
+ eq = strchr(e, '=');
+ if (!eq)
+ return false;
+
+ if (!env_name_is_valid_n(e, eq - e))
+ return false;
+
+ if (!env_value_is_valid(eq + 1))
+ return false;
+
+ /* POSIX says the overall size of the environment block cannot
+ * be > ARG_MAX, hence the individual variable assignments
+ * cannot be either, but let's leave room for one trailing NUL
+ * byte. */
+ if (strlen(e) > ARG_MAX - 1)
+ return false;
+
+ return true;
+}
+
+bool strv_env_is_valid(char **e) {
+ char **p, **q;
+
+ STRV_FOREACH(p, e) {
+ size_t k;
+
+ if (!env_assignment_is_valid(*p))
+ return false;
+
+ /* Check if there are duplicate assginments */
+ k = strcspn(*p, "=");
+ STRV_FOREACH(q, p + 1)
+ if (strneq(*p, *q, k) && (*q)[k] == '=')
+ return false;
+ }
+
+ return true;
+}
+
+bool strv_env_name_is_valid(char **l) {
+ char **p, **q;
+
+ STRV_FOREACH(p, l) {
+ if (!env_name_is_valid(*p))
+ return false;
+
+ STRV_FOREACH(q, p + 1)
+ if (streq(*p, *q))
+ return false;
+ }
+
+ return true;
+}
+
+bool strv_env_name_or_assignment_is_valid(char **l) {
+ char **p, **q;
+
+ STRV_FOREACH(p, l) {
+ if (!env_assignment_is_valid(*p) && !env_name_is_valid(*p))
+ return false;
+
+ STRV_FOREACH(q, p + 1)
+ if (streq(*p, *q))
+ return false;
+ }
+
+ return true;
+}
+
+static int env_append(char **r, char ***k, char **a) {
+ assert(r);
+ assert(k);
+
+ if (!a)
+ return 0;
+
+ /* Add the entries of a to *k unless they already exist in *r
+ * in which case they are overridden instead. This assumes
+ * there is enough space in the r array. */
+
+ for (; *a; a++) {
+ char **j;
+ size_t n;
+
+ n = strcspn(*a, "=");
+
+ if ((*a)[n] == '=')
+ n++;
+
+ for (j = r; j < *k; j++)
+ if (strneq(*j, *a, n))
+ break;
+
+ if (j >= *k)
+ (*k)++;
+ else
+ free(*j);
+
+ *j = strdup(*a);
+ if (!*j)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+char **strv_env_merge(size_t n_lists, ...) {
+ size_t n = 0;
+ char **l, **k, **r;
+ va_list ap;
+ size_t i;
+
+ /* Merges an arbitrary number of environment sets */
+
+ va_start(ap, n_lists);
+ for (i = 0; i < n_lists; i++) {
+ l = va_arg(ap, char**);
+ n += strv_length(l);
+ }
+ va_end(ap);
+
+ r = new(char*, n+1);
+ if (!r)
+ return NULL;
+
+ k = r;
+
+ va_start(ap, n_lists);
+ for (i = 0; i < n_lists; i++) {
+ l = va_arg(ap, char**);
+ if (env_append(r, &k, l) < 0)
+ goto fail;
+ }
+ va_end(ap);
+
+ *k = NULL;
+
+ return r;
+
+fail:
+ va_end(ap);
+ strv_free(r);
+
+ return NULL;
+}
+
+static bool env_match(const char *t, const char *pattern) {
+ assert(t);
+ assert(pattern);
+
+ /* pattern a matches string a
+ * a matches a=
+ * a matches a=b
+ * a= matches a=
+ * a=b matches a=b
+ * a= does not match a
+ * a=b does not match a=
+ * a=b does not match a
+ * a=b does not match a=c */
+
+ if (streq(t, pattern))
+ return true;
+
+ if (!strchr(pattern, '=')) {
+ size_t l = strlen(pattern);
+
+ return strneq(t, pattern, l) && t[l] == '=';
+ }
+
+ return false;
+}
+
+static bool env_entry_has_name(const char *entry, const char *name) {
+ const char *t;
+
+ assert(entry);
+ assert(name);
+
+ t = startswith(entry, name);
+ if (!t)
+ return false;
+
+ return *t == '=';
+}
+
+char **strv_env_delete(char **x, size_t n_lists, ...) {
+ size_t n, i = 0;
+ char **k, **r;
+ va_list ap;
+
+ /* Deletes every entry from x that is mentioned in the other
+ * string lists */
+
+ n = strv_length(x);
+
+ r = new(char*, n+1);
+ if (!r)
+ return NULL;
+
+ STRV_FOREACH(k, x) {
+ size_t v;
+
+ va_start(ap, n_lists);
+ for (v = 0; v < n_lists; v++) {
+ char **l, **j;
+
+ l = va_arg(ap, char**);
+ STRV_FOREACH(j, l)
+ if (env_match(*k, *j))
+ goto skip;
+ }
+ va_end(ap);
+
+ r[i] = strdup(*k);
+ if (!r[i]) {
+ strv_free(r);
+ return NULL;
+ }
+
+ i++;
+ continue;
+
+ skip:
+ va_end(ap);
+ }
+
+ r[i] = NULL;
+
+ assert(i <= n);
+
+ return r;
+}
+
+char **strv_env_unset(char **l, const char *p) {
+
+ char **f, **t;
+
+ if (!l)
+ return NULL;
+
+ assert(p);
+
+ /* Drops every occurrence of the env var setting p in the
+ * string list. Edits in-place. */
+
+ for (f = t = l; *f; f++) {
+
+ if (env_match(*f, p)) {
+ free(*f);
+ continue;
+ }
+
+ *(t++) = *f;
+ }
+
+ *t = NULL;
+ return l;
+}
+
+char **strv_env_unset_many(char **l, ...) {
+
+ char **f, **t;
+
+ if (!l)
+ return NULL;
+
+ /* Like strv_env_unset() but applies many at once. Edits in-place. */
+
+ for (f = t = l; *f; f++) {
+ bool found = false;
+ const char *p;
+ va_list ap;
+
+ va_start(ap, l);
+
+ while ((p = va_arg(ap, const char*))) {
+ if (env_match(*f, p)) {
+ found = true;
+ break;
+ }
+ }
+
+ va_end(ap);
+
+ if (found) {
+ free(*f);
+ continue;
+ }
+
+ *(t++) = *f;
+ }
+
+ *t = NULL;
+ return l;
+}
+
+int strv_env_replace(char ***l, char *p) {
+ char **f;
+ const char *t, *name;
+
+ assert(p);
+
+ /* Replace first occurrence of the env var or add a new one in the
+ * string list. Drop other occurences. Edits in-place. Does not copy p.
+ * p must be a valid key=value assignment.
+ */
+
+ t = strchr(p, '=');
+ assert(t);
+
+ name = strndupa(p, t - p);
+
+ for (f = *l; f && *f; f++)
+ if (env_entry_has_name(*f, name)) {
+ free_and_replace(*f, p);
+ strv_env_unset(f + 1, *f);
+ return 0;
+ }
+
+ /* We didn't find a match, we need to append p or create a new strv */
+ if (strv_push(l, p) < 0)
+ return -ENOMEM;
+ return 1;
+}
+
+char **strv_env_set(char **x, const char *p) {
+
+ char **k;
+ _cleanup_strv_free_ char **r = NULL;
+ char* m[2] = { (char*) p, NULL };
+
+ /* Overrides the env var setting of p, returns a new copy */
+
+ r = new(char*, strv_length(x)+2);
+ if (!r)
+ return NULL;
+
+ k = r;
+ if (env_append(r, &k, x) < 0)
+ return NULL;
+
+ if (env_append(r, &k, m) < 0)
+ return NULL;
+
+ *k = NULL;
+
+ return TAKE_PTR(r);
+}
+
+char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) {
+ char **i;
+
+ assert(name);
+
+ if (k <= 0)
+ return NULL;
+
+ STRV_FOREACH_BACKWARDS(i, l)
+ if (strneq(*i, name, k) &&
+ (*i)[k] == '=')
+ return *i + k + 1;
+
+ if (flags & REPLACE_ENV_USE_ENVIRONMENT) {
+ const char *t;
+
+ t = strndupa(name, k);
+ return getenv(t);
+ };
+
+ return NULL;
+}
+
+char *strv_env_get(char **l, const char *name) {
+ assert(name);
+
+ return strv_env_get_n(l, name, strlen(name), 0);
+}
+
+char **strv_env_clean_with_callback(char **e, void (*invalid_callback)(const char *p, void *userdata), void *userdata) {
+ char **p, **q;
+ int k = 0;
+
+ STRV_FOREACH(p, e) {
+ size_t n;
+ bool duplicate = false;
+
+ if (!env_assignment_is_valid(*p)) {
+ if (invalid_callback)
+ invalid_callback(*p, userdata);
+ free(*p);
+ continue;
+ }
+
+ n = strcspn(*p, "=");
+ STRV_FOREACH(q, p + 1)
+ if (strneq(*p, *q, n) && (*q)[n] == '=') {
+ duplicate = true;
+ break;
+ }
+
+ if (duplicate) {
+ free(*p);
+ continue;
+ }
+
+ e[k++] = *p;
+ }
+
+ if (e)
+ e[k] = NULL;
+
+ return e;
+}
+
+char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
+ enum {
+ WORD,
+ CURLY,
+ VARIABLE,
+ VARIABLE_RAW,
+ TEST,
+ DEFAULT_VALUE,
+ ALTERNATE_VALUE,
+ } state = WORD;
+
+ const char *e, *word = format, *test_value;
+ char *k;
+ _cleanup_free_ char *r = NULL;
+ size_t i, len;
+ int nest = 0;
+
+ assert(format);
+
+ for (e = format, i = 0; *e && i < n; e ++, i ++)
+ switch (state) {
+
+ case WORD:
+ if (*e == '$')
+ state = CURLY;
+ break;
+
+ case CURLY:
+ if (*e == '{') {
+ k = strnappend(r, word, e-word-1);
+ if (!k)
+ return NULL;
+
+ free_and_replace(r, k);
+
+ word = e-1;
+ state = VARIABLE;
+ nest++;
+ } else if (*e == '$') {
+ k = strnappend(r, word, e-word);
+ if (!k)
+ return NULL;
+
+ free_and_replace(r, k);
+
+ word = e+1;
+ state = WORD;
+
+ } else if (flags & REPLACE_ENV_ALLOW_BRACELESS && strchr(VALID_CHARS_ENV_NAME, *e)) {
+ k = strnappend(r, word, e-word-1);
+ if (!k)
+ return NULL;
+
+ free_and_replace(r, k);
+
+ word = e-1;
+ state = VARIABLE_RAW;
+
+ } else
+ state = WORD;
+ break;
+
+ case VARIABLE:
+ if (*e == '}') {
+ const char *t;
+
+ t = strv_env_get_n(env, word+2, e-word-2, flags);
+
+ k = strappend(r, t);
+ if (!k)
+ return NULL;
+
+ free_and_replace(r, k);
+
+ word = e+1;
+ state = WORD;
+ } else if (*e == ':') {
+ if (!(flags & REPLACE_ENV_ALLOW_EXTENDED))
+ /* Treat this as unsupported syntax, i.e. do no replacement */
+ state = WORD;
+ else {
+ len = e-word-2;
+ state = TEST;
+ }
+ }
+ break;
+
+ case TEST:
+ if (*e == '-')
+ state = DEFAULT_VALUE;
+ else if (*e == '+')
+ state = ALTERNATE_VALUE;
+ else {
+ state = WORD;
+ break;
+ }
+
+ test_value = e+1;
+ break;
+
+ case DEFAULT_VALUE: /* fall through */
+ case ALTERNATE_VALUE:
+ assert(flags & REPLACE_ENV_ALLOW_EXTENDED);
+
+ if (*e == '{') {
+ nest++;
+ break;
+ }
+
+ if (*e != '}')
+ break;
+
+ nest--;
+ if (nest == 0) {
+ const char *t;
+ _cleanup_free_ char *v = NULL;
+
+ t = strv_env_get_n(env, word+2, len, flags);
+
+ if (t && state == ALTERNATE_VALUE)
+ t = v = replace_env_n(test_value, e-test_value, env, flags);
+ else if (!t && state == DEFAULT_VALUE)
+ t = v = replace_env_n(test_value, e-test_value, env, flags);
+
+ k = strappend(r, t);
+ if (!k)
+ return NULL;
+
+ free_and_replace(r, k);
+
+ word = e+1;
+ state = WORD;
+ }
+ break;
+
+ case VARIABLE_RAW:
+ assert(flags & REPLACE_ENV_ALLOW_BRACELESS);
+
+ if (!strchr(VALID_CHARS_ENV_NAME, *e)) {
+ const char *t;
+
+ t = strv_env_get_n(env, word+1, e-word-1, flags);
+
+ k = strappend(r, t);
+ if (!k)
+ return NULL;
+
+ free_and_replace(r, k);
+
+ word = e--;
+ i--;
+ state = WORD;
+ }
+ break;
+ }
+
+ if (state == VARIABLE_RAW) {
+ const char *t;
+
+ assert(flags & REPLACE_ENV_ALLOW_BRACELESS);
+
+ t = strv_env_get_n(env, word+1, e-word-1, flags);
+ return strappend(r, t);
+ } else
+ return strnappend(r, word, e-word);
+}
+
+char **replace_env_argv(char **argv, char **env) {
+ char **ret, **i;
+ size_t k = 0, l = 0;
+
+ l = strv_length(argv);
+
+ ret = new(char*, l+1);
+ if (!ret)
+ return NULL;
+
+ STRV_FOREACH(i, argv) {
+
+ /* If $FOO appears as single word, replace it by the split up variable */
+ if ((*i)[0] == '$' && !IN_SET((*i)[1], '{', '$')) {
+ char *e;
+ char **w, **m = NULL;
+ size_t q;
+
+ e = strv_env_get(env, *i+1);
+ if (e) {
+ int r;
+
+ r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_QUOTES);
+ if (r < 0) {
+ ret[k] = NULL;
+ strv_free(ret);
+ return NULL;
+ }
+ } else
+ m = NULL;
+
+ q = strv_length(m);
+ l = l + q - 1;
+
+ w = reallocarray(ret, l + 1, sizeof(char *));
+ if (!w) {
+ ret[k] = NULL;
+ strv_free(ret);
+ strv_free(m);
+ return NULL;
+ }
+
+ ret = w;
+ if (m) {
+ memcpy(ret + k, m, q * sizeof(char*));
+ free(m);
+ }
+
+ k += q;
+ continue;
+ }
+
+ /* If ${FOO} appears as part of a word, replace it by the variable as-is */
+ ret[k] = replace_env(*i, env, 0);
+ if (!ret[k]) {
+ strv_free(ret);
+ return NULL;
+ }
+ k++;
+ }
+
+ ret[k] = NULL;
+ return ret;
+}
+
+int getenv_bool(const char *p) {
+ const char *e;
+
+ e = getenv(p);
+ if (!e)
+ return -ENXIO;
+
+ return parse_boolean(e);
+}
+
+int getenv_bool_secure(const char *p) {
+ const char *e;
+
+ e = secure_getenv(p);
+ if (!e)
+ return -ENXIO;
+
+ return parse_boolean(e);
+}
+
+int serialize_environment(FILE *f, char **environment) {
+ char **e;
+
+ STRV_FOREACH(e, environment) {
+ _cleanup_free_ char *ce;
+
+ ce = cescape(*e);
+ if (!ce)
+ return -ENOMEM;
+
+ fprintf(f, "env=%s\n", ce);
+ }
+
+ /* caller should call ferror() */
+
+ return 0;
+}
+
+int deserialize_environment(char ***environment, const char *line) {
+ char *uce;
+ int r;
+
+ assert(line);
+ assert(environment);
+
+ assert(startswith(line, "env="));
+ r = cunescape(line + 4, 0, &uce);
+ if (r < 0)
+ return r;
+
+ return strv_env_replace(environment, uce);
+}
diff --git a/src/systemd/src/basic/env-util.h b/src/systemd/src/basic/env-util.h
new file mode 100644
index 0000000000..174433ea91
--- /dev/null
+++ b/src/systemd/src/basic/env-util.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include "macro.h"
+#include "string.h"
+
+bool env_name_is_valid(const char *e);
+bool env_value_is_valid(const char *e);
+bool env_assignment_is_valid(const char *e);
+
+enum {
+ REPLACE_ENV_USE_ENVIRONMENT = 1u,
+ REPLACE_ENV_ALLOW_BRACELESS = 2u,
+ REPLACE_ENV_ALLOW_EXTENDED = 4u,
+};
+
+char *replace_env_n(const char *format, size_t n, char **env, unsigned flags);
+char **replace_env_argv(char **argv, char **env);
+
+static inline char *replace_env(const char *format, char **env, unsigned flags) {
+ return replace_env_n(format, strlen(format), env, flags);
+}
+
+bool strv_env_is_valid(char **e);
+#define strv_env_clean(l) strv_env_clean_with_callback(l, NULL, NULL)
+char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const char *p, void *userdata), void *userdata);
+
+bool strv_env_name_is_valid(char **l);
+bool strv_env_name_or_assignment_is_valid(char **l);
+
+char **strv_env_merge(size_t n_lists, ...);
+char **strv_env_delete(char **x, size_t n_lists, ...); /* New copy */
+
+char **strv_env_set(char **x, const char *p); /* New copy ... */
+char **strv_env_unset(char **l, const char *p); /* In place ... */
+char **strv_env_unset_many(char **l, ...) _sentinel_;
+int strv_env_replace(char ***l, char *p); /* In place ... */
+
+char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) _pure_;
+char *strv_env_get(char **x, const char *n) _pure_;
+
+int getenv_bool(const char *p);
+int getenv_bool_secure(const char *p);
+
+int serialize_environment(FILE *f, char **environment);
+int deserialize_environment(char ***environment, const char *line);
diff --git a/src/systemd/src/basic/ether-addr-util.c b/src/systemd/src/basic/ether-addr-util.c
index a7f13ef06f..461ace73e2 100644
--- a/src/systemd/src/basic/ether-addr-util.c
+++ b/src/systemd/src/basic/ether-addr-util.c
@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2014 Tom Gundersen
-***/
#include <errno.h>
#include <net/ethernet.h>
diff --git a/src/systemd/src/basic/ether-addr-util.h b/src/systemd/src/basic/ether-addr-util.h
index f02cefead3..3be0370049 100644
--- a/src/systemd/src/basic/ether-addr-util.h
+++ b/src/systemd/src/basic/ether-addr-util.h
@@ -1,10 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- Copyright © 2014 Tom Gundersen
-***/
-
#include <net/ethernet.h>
#include <stdbool.h>
diff --git a/src/systemd/src/basic/fd-util.h b/src/systemd/src/basic/fd-util.h
index 8adc959da8..00303a7e45 100644
--- a/src/systemd/src/basic/fd-util.h
+++ b/src/systemd/src/basic/fd-util.h
@@ -78,8 +78,12 @@ int acquire_data_fd(const void *data, size_t size, unsigned flags);
int fd_duplicate_data_fd(int fd);
/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
-#define ERRNO_IS_DISCONNECT(r) \
- IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)
+/* The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases.
+ * See the icmp_err_convert[] in net/ipv4/icmp.c in the kernel sources */
+#define ERRNO_IS_DISCONNECT(r) \
+ IN_SET(r, \
+ ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, \
+ ENETUNREACH, EHOSTUNREACH, ENOPROTOOPT, EHOSTDOWN, ENONET)
/* Resource exhaustion, could be our fault or general system trouble */
#define ERRNO_IS_RESOURCE(r) \
diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c
index 6b0bad5b71..ea607f8cfb 100644
--- a/src/systemd/src/basic/fileio.c
+++ b/src/systemd/src/basic/fileio.c
@@ -1225,9 +1225,13 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
const char *fn;
char *t;
- assert(p);
assert(ret);
+ if (isempty(p))
+ return -EINVAL;
+ if (path_equal(p, "/"))
+ return -EINVAL;
+
/*
* Turns this:
* /foo/bar/waldo
@@ -1258,9 +1262,13 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
uint64_t u;
unsigned i;
- assert(p);
assert(ret);
+ if (isempty(p))
+ return -EINVAL;
+ if (path_equal(p, "/"))
+ return -EINVAL;
+
/*
* Turns this:
* /foo/bar/waldo
@@ -1319,7 +1327,10 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
if (!t)
return -ENOMEM;
- x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
+ if (isempty(p))
+ x = stpcpy(stpcpy(t, ".#"), extra);
+ else
+ x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
u = random_u64();
for (i = 0; i < 16; i++) {
@@ -1404,7 +1415,8 @@ int open_tmpfile_unlinkable(const char *directory, int flags) {
r = tmp_dir(&directory);
if (r < 0)
return r;
- }
+ } else if (isempty(directory))
+ return -EINVAL;
/* Returns an unlinked temporary file that cannot be linked into the file system anymore */
@@ -1439,22 +1451,14 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
* which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
* "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
- {
- _cleanup_free_ char *dn = NULL;
-
- dn = dirname_malloc(target);
- if (!dn)
- return -ENOMEM;
-
- fd = open(dn, O_TMPFILE|flags, 0640);
- if (fd >= 0) {
- *ret_path = NULL;
- return fd;
- }
-
- log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn);
+ fd = open_parent(target, O_TMPFILE|flags, 0640);
+ if (fd >= 0) {
+ *ret_path = NULL;
+ return fd;
}
+ log_debug_errno(fd, "Failed to use O_TMPFILE for %s: %m", target);
+
r = tempfn_random(target, NULL, &tmp);
if (r < 0)
return r;
diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c
index 3a8b32d881..09fcc32e0e 100644
--- a/src/systemd/src/basic/fs-util.c
+++ b/src/systemd/src/basic/fs-util.c
@@ -435,6 +435,31 @@ int mkfifo_atomic(const char *path, mode_t mode) {
return 0;
}
+int mkfifoat_atomic(int dirfd, const char *path, mode_t mode) {
+ _cleanup_free_ char *t = NULL;
+ int r;
+
+ assert(path);
+
+ if (path_is_absolute(path))
+ return mkfifo_atomic(path, mode);
+
+ /* We're only interested in the (random) filename. */
+ r = tempfn_random_child("", NULL, &t);
+ if (r < 0)
+ return r;
+
+ if (mkfifoat(dirfd, t, mode) < 0)
+ return -errno;
+
+ if (renameat(dirfd, t, dirfd, path) < 0) {
+ unlink_noerrno(t);
+ return -errno;
+ }
+
+ return 0;
+}
+
int get_files_in_directory(const char *path, char ***list) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
@@ -670,7 +695,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN|CHASE_STEP)) == CHASE_OPEN) {
/* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set
* and doesn't care about any of the other special features we provide either. */
- r = open(path, O_PATH|O_CLOEXEC);
+ r = open(path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0));
if (r < 0)
return -errno;
@@ -825,7 +850,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0)
return -EREMOTE;
- if (S_ISLNK(st.st_mode)) {
+ if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) {
char *joined;
_cleanup_free_ char *destination = NULL;
@@ -1156,7 +1181,7 @@ int unlinkat_deallocate(int fd, const char *name, int flags) {
}
int fsync_directory_of_file(int fd) {
- _cleanup_free_ char *path = NULL, *dn = NULL;
+ _cleanup_free_ char *path = NULL;
_cleanup_close_ int dfd = -1;
int r;
@@ -1182,16 +1207,40 @@ int fsync_directory_of_file(int fd) {
if (!path_is_absolute(path))
return -EINVAL;
- dn = dirname_malloc(path);
- if (!dn)
- return -ENOMEM;
-
- dfd = open(dn, O_RDONLY|O_CLOEXEC|O_DIRECTORY);
+ dfd = open_parent(path, O_CLOEXEC, 0);
if (dfd < 0)
- return -errno;
+ return dfd;
if (fsync(dfd) < 0)
return -errno;
return 0;
}
+
+int open_parent(const char *path, int flags, mode_t mode) {
+ _cleanup_free_ char *parent = NULL;
+ int fd;
+
+ if (isempty(path))
+ return -EINVAL;
+ if (path_equal(path, "/")) /* requesting the parent of the root dir is fishy, let's prohibit that */
+ return -EINVAL;
+
+ parent = dirname_malloc(path);
+ if (!parent)
+ return -ENOMEM;
+
+ /* Let's insist on O_DIRECTORY since the parent of a file or directory is a directory. Except if we open an
+ * O_TMPFILE file, because in that case we are actually create a regular file below the parent directory. */
+
+ if ((flags & O_PATH) == O_PATH)
+ flags |= O_DIRECTORY;
+ else if ((flags & O_TMPFILE) != O_TMPFILE)
+ flags |= O_DIRECTORY|O_RDONLY;
+
+ fd = open(parent, flags, mode);
+ if (fd < 0)
+ return -errno;
+
+ return fd;
+}
diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h
index 28566773c6..4b65625861 100644
--- a/src/systemd/src/basic/fs-util.h
+++ b/src/systemd/src/basic/fs-util.h
@@ -42,6 +42,7 @@ int symlink_idempotent(const char *from, const char *to);
int symlink_atomic(const char *from, const char *to);
int mknod_atomic(const char *path, mode_t mode, dev_t dev);
int mkfifo_atomic(const char *path, mode_t mode);
+int mkfifoat_atomic(int dir_fd, const char *path, mode_t mode);
int get_files_in_directory(const char *path, char ***list);
@@ -72,6 +73,7 @@ enum {
CHASE_OPEN = 1 << 4, /* If set, return an O_PATH object to the final component */
CHASE_TRAIL_SLASH = 1 << 5, /* If set, any trailing slash will be preserved */
CHASE_STEP = 1 << 6, /* If set, just execute a single step of the normalization */
+ CHASE_NOFOLLOW = 1 << 7, /* Only valid with CHASE_OPEN: when the path's right-most component refers to symlink return O_PATH fd of the symlink, rather than following it. */
};
/* How many iterations to execute before returning -ELOOP */
@@ -103,3 +105,5 @@ void unlink_tempfilep(char (*p)[]);
int unlinkat_deallocate(int fd, const char *name, int flags);
int fsync_directory_of_file(int fd);
+
+int open_parent(const char *path, int flags, mode_t mode);
diff --git a/src/systemd/src/basic/hash-funcs.c b/src/systemd/src/basic/hash-funcs.c
index 2892346886..6f6832d237 100644
--- a/src/systemd/src/basic/hash-funcs.c
+++ b/src/systemd/src/basic/hash-funcs.c
@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2014 Michal Schmidt
-***/
#include <string.h>
@@ -74,7 +71,7 @@ void trivial_hash_func(const void *p, struct siphash *state) {
}
int trivial_compare_func(const void *a, const void *b) {
- return a < b ? -1 : (a > b ? 1 : 0);
+ return CMP(a, b);
}
const struct hash_ops trivial_hash_ops = {
@@ -90,7 +87,7 @@ int uint64_compare_func(const void *_a, const void *_b) {
uint64_t a, b;
a = *(const uint64_t*) _a;
b = *(const uint64_t*) _b;
- return a < b ? -1 : (a > b ? 1 : 0);
+ return CMP(a, b);
}
const struct hash_ops uint64_hash_ops = {
@@ -107,7 +104,7 @@ int devt_compare_func(const void *_a, const void *_b) {
dev_t a, b;
a = *(const dev_t*) _a;
b = *(const dev_t*) _b;
- return a < b ? -1 : (a > b ? 1 : 0);
+ return CMP(a, b);
}
const struct hash_ops devt_hash_ops = {
diff --git a/src/systemd/src/basic/hash-funcs.h b/src/systemd/src/basic/hash-funcs.h
index 3715c56e07..fa45cfe256 100644
--- a/src/systemd/src/basic/hash-funcs.h
+++ b/src/systemd/src/basic/hash-funcs.h
@@ -1,10 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- Copyright © 2014 Michal Schmidt
-***/
-
#include "macro.h"
#include "siphash24.h"
diff --git a/src/systemd/src/basic/hashmap.c b/src/systemd/src/basic/hashmap.c
index df9660560a..44d718c83d 100644
--- a/src/systemd/src/basic/hashmap.c
+++ b/src/systemd/src/basic/hashmap.c
@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2014 Michal Schmidt
-***/
#include <errno.h>
#include <stdint.h>
@@ -9,8 +6,9 @@
#include <string.h>
#include "alloc-util.h"
-#include "hashmap.h"
+#include "env-util.h"
#include "fileio.h"
+#include "hashmap.h"
#include "macro.h"
#include "mempool.h"
#include "process-util.h"
@@ -769,20 +767,31 @@ static void reset_direct_storage(HashmapBase *h) {
memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
}
+static bool use_pool(void) {
+ static int b = -1;
+
+ if (!is_main_thread())
+ return false;
+
+ if (b < 0)
+ b = getenv_bool("SYSTEMD_MEMPOOL") != 0;
+
+ return b;
+}
+
static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
HashmapBase *h;
const struct hashmap_type_info *hi = &hashmap_type_info[type];
- bool use_pool;
+ bool up;
- use_pool = is_main_thread();
-
- h = use_pool ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size);
+ up = use_pool();
+ h = up ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size);
if (!h)
return NULL;
h->type = type;
- h->from_pool = use_pool;
+ h->from_pool = up;
h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops;
if (type == HASHMAP_TYPE_ORDERED) {
@@ -860,9 +869,11 @@ static void hashmap_free_no_clear(HashmapBase *h) {
assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0);
#endif
- if (h->from_pool)
+ if (h->from_pool) {
+ /* Ensure that the object didn't get migrated between threads. */
+ assert_se(is_main_thread());
mempool_free_tile(hashmap_type_info[h->type].mempool, h);
- else
+ } else
free(h);
}
diff --git a/src/systemd/src/basic/hashmap.h b/src/systemd/src/basic/hashmap.h
index d1d1b9c8a4..274afb395c 100644
--- a/src/systemd/src/basic/hashmap.h
+++ b/src/systemd/src/basic/hashmap.h
@@ -1,10 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- Copyright © 2014 Michal Schmidt
-***/
-
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
diff --git a/src/systemd/src/basic/in-addr-util.c b/src/systemd/src/basic/in-addr-util.c
index aed7601d50..d83658eaa7 100644
--- a/src/systemd/src/basic/in-addr-util.c
+++ b/src/systemd/src/basic/in-addr-util.c
@@ -571,3 +571,26 @@ int in_addr_prefix_from_string_auto(
return 0;
}
+
+void in_addr_data_hash_func(const void *p, struct siphash *state) {
+ const struct in_addr_data *a = p;
+
+ siphash24_compress(&a->family, sizeof(a->family), state);
+ siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state);
+}
+
+int in_addr_data_compare_func(const void *a, const void *b) {
+ const struct in_addr_data *x = a, *y = b;
+ int r;
+
+ r = CMP(x->family, y->family);
+ if (r != 0)
+ return r;
+
+ return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
+}
+
+const struct hash_ops in_addr_data_hash_ops = {
+ .hash = in_addr_data_hash_func,
+ .compare = in_addr_data_compare_func,
+};
diff --git a/src/systemd/src/basic/in-addr-util.h b/src/systemd/src/basic/in-addr-util.h
index 956c00a850..e4be30dc0d 100644
--- a/src/systemd/src/basic/in-addr-util.h
+++ b/src/systemd/src/basic/in-addr-util.h
@@ -5,6 +5,7 @@
#include <stddef.h>
#include <sys/socket.h>
+#include "hash-funcs.h"
#include "macro.h"
#include "util.h"
@@ -53,3 +54,7 @@ static inline size_t FAMILY_ADDRESS_SIZE(int family) {
}
#define IN_ADDR_NULL ((union in_addr_union) {})
+
+void in_addr_data_hash_func(const void *p, struct siphash *state);
+int in_addr_data_compare_func(const void *a, const void *b);
+extern const struct hash_ops in_addr_data_hash_ops;
diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h
index d1365f7058..24fcdc8400 100644
--- a/src/systemd/src/basic/macro.h
+++ b/src/systemd/src/basic/macro.h
@@ -7,7 +7,7 @@
#include <sys/sysmacros.h>
#include <sys/types.h>
-#define _printf_(a,b) __attribute__ ((format (printf, a, b)))
+#define _printf_(a, b) __attribute__ ((format (printf, a, b)))
#ifdef __clang__
# define _alloc_(...)
#else
@@ -22,8 +22,8 @@
#define _packed_ __attribute__ ((packed))
#define _malloc_ __attribute__ ((malloc))
#define _weak_ __attribute__ ((weak))
-#define _likely_(x) (__builtin_expect(!!(x),1))
-#define _unlikely_(x) (__builtin_expect(!!(x),0))
+#define _likely_(x) (__builtin_expect(!!(x), 1))
+#define _unlikely_(x) (__builtin_expect(!!(x), 0))
#define _public_ __attribute__ ((visibility("default")))
#define _hidden_ __attribute__ ((visibility("hidden")))
#define _weakref_(x) __attribute__((weakref(#x)))
@@ -146,10 +146,10 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
# define VOID_0 ((void*)0)
#endif
-#define ELEMENTSOF(x) \
- __extension__ (__builtin_choose_expr( \
+#define ELEMENTSOF(x) \
+ (__builtin_choose_expr( \
!__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
- sizeof(x)/sizeof((x)[0]), \
+ sizeof(x)/sizeof((x)[0]), \
VOID_0))
/*
@@ -167,23 +167,23 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
*/
#define container_of(ptr, type, member) __container_of(UNIQ, (ptr), type, member)
#define __container_of(uniq, ptr, type, member) \
- __extension__ ({ \
+ ({ \
const typeof( ((type*)0)->member ) *UNIQ_T(A, uniq) = (ptr); \
- (type*)( (char *)UNIQ_T(A, uniq) - offsetof(type,member) ); \
+ (type*)( (char *)UNIQ_T(A, uniq) - offsetof(type, member) ); \
})
#undef MAX
#define MAX(a, b) __MAX(UNIQ, (a), UNIQ, (b))
#define __MAX(aq, a, bq, b) \
- __extension__ ({ \
+ ({ \
const typeof(a) UNIQ_T(A, aq) = (a); \
const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A,aq) > UNIQ_T(B,bq) ? UNIQ_T(A,aq) : UNIQ_T(B,bq); \
+ UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \
})
/* evaluates to (void) if _A or _B are not constant or of different types */
#define CONST_MAX(_A, _B) \
- __extension__ (__builtin_choose_expr( \
+ (__builtin_choose_expr( \
__builtin_constant_p(_A) && \
__builtin_constant_p(_B) && \
__builtin_types_compatible_p(typeof(_A), typeof(_B)), \
@@ -193,47 +193,56 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
/* takes two types and returns the size of the larger one */
#define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; }))
-#define MAX3(x,y,z) \
- __extension__ ({ \
- const typeof(x) _c = MAX(x,y); \
- MAX(_c, z); \
- })
+#define MAX3(x, y, z) \
+ ({ \
+ const typeof(x) _c = MAX(x, y); \
+ MAX(_c, z); \
+ })
#undef MIN
#define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b))
#define __MIN(aq, a, bq, b) \
- __extension__ ({ \
+ ({ \
const typeof(a) UNIQ_T(A, aq) = (a); \
const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A,aq) < UNIQ_T(B,bq) ? UNIQ_T(A,aq) : UNIQ_T(B,bq); \
+ UNIQ_T(A, aq) < UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \
})
-#define MIN3(x,y,z) \
- __extension__ ({ \
- const typeof(x) _c = MIN(x,y); \
- MIN(_c, z); \
- })
+#define MIN3(x, y, z) \
+ ({ \
+ const typeof(x) _c = MIN(x, y); \
+ MIN(_c, z); \
+ })
#define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b))
#define __LESS_BY(aq, a, bq, b) \
- __extension__ ({ \
+ ({ \
+ const typeof(a) UNIQ_T(A, aq) = (a); \
+ const typeof(b) UNIQ_T(B, bq) = (b); \
+ UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) - UNIQ_T(B, bq) : 0; \
+ })
+
+#define CMP(a, b) __CMP(UNIQ, (a), UNIQ, (b))
+#define __CMP(aq, a, bq, b) \
+ ({ \
const typeof(a) UNIQ_T(A, aq) = (a); \
const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A,aq) > UNIQ_T(B,bq) ? UNIQ_T(A,aq) - UNIQ_T(B,bq) : 0; \
+ UNIQ_T(A, aq) < UNIQ_T(B, bq) ? -1 : \
+ UNIQ_T(A, aq) > UNIQ_T(B, bq) ? 1 : 0; \
})
#undef CLAMP
#define CLAMP(x, low, high) __CLAMP(UNIQ, (x), UNIQ, (low), UNIQ, (high))
#define __CLAMP(xq, x, lowq, low, highq, high) \
- __extension__ ({ \
- const typeof(x) UNIQ_T(X,xq) = (x); \
- const typeof(low) UNIQ_T(LOW,lowq) = (low); \
- const typeof(high) UNIQ_T(HIGH,highq) = (high); \
- UNIQ_T(X,xq) > UNIQ_T(HIGH,highq) ? \
- UNIQ_T(HIGH,highq) : \
- UNIQ_T(X,xq) < UNIQ_T(LOW,lowq) ? \
- UNIQ_T(LOW,lowq) : \
- UNIQ_T(X,xq); \
+ ({ \
+ const typeof(x) UNIQ_T(X, xq) = (x); \
+ const typeof(low) UNIQ_T(LOW, lowq) = (low); \
+ const typeof(high) UNIQ_T(HIGH, highq) = (high); \
+ UNIQ_T(X, xq) > UNIQ_T(HIGH, highq) ? \
+ UNIQ_T(HIGH, highq) : \
+ UNIQ_T(X, xq) < UNIQ_T(LOW, lowq) ? \
+ UNIQ_T(LOW, lowq) : \
+ UNIQ_T(X, xq); \
})
/* [(x + y - 1) / y] suffers from an integer overflow, even though the
@@ -241,18 +250,54 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
* [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the
* quotient and the remainder, so both should be equally fast. */
#define DIV_ROUND_UP(_x, _y) \
- __extension__ ({ \
+ ({ \
const typeof(_x) __x = (_x); \
const typeof(_y) __y = (_y); \
(__x / __y + !!(__x % __y)); \
})
+#ifdef __COVERITY__
+
+/* Use special definitions of assertion macros in order to prevent
+ * false positives of ASSERT_SIDE_EFFECT on Coverity static analyzer
+ * for uses of assert_se() and assert_return().
+ *
+ * These definitions make expression go through a (trivial) function
+ * call to ensure they are not discarded. Also use ! or !! to ensure
+ * the boolean expressions are seen as such.
+ *
+ * This technique has been described and recommended in:
+ * https://community.synopsys.com/s/question/0D534000046Yuzb/suppressing-assertsideeffect-for-functions-that-allow-for-sideeffects
+ */
+
+extern void __coverity_panic__(void);
+
+static inline int __coverity_check__(int condition) {
+ return condition;
+}
+
+#define assert_message_se(expr, message) \
+ do { \
+ if (__coverity_check__(!(expr))) \
+ __coverity_panic__(); \
+ } while (false)
+
+#define assert_log(expr, message) __coverity_check__(!!(expr))
+
+#else /* ! __COVERITY__ */
+
#define assert_message_se(expr, message) \
do { \
if (_unlikely_(!(expr))) \
log_assert_failed(message, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
} while (false)
+#define assert_log(expr, message) ((_likely_(expr)) \
+ ? (true) \
+ : (log_assert_failed_return(message, __FILE__, __LINE__, __PRETTY_FUNCTION__), false))
+
+#endif /* __COVERITY__ */
+
#define assert_se(expr) assert_message_se(expr, #expr)
/* We override the glibc assert() here. */
@@ -285,10 +330,6 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
REENABLE_WARNING
#endif
-#define assert_log(expr, message) ((_likely_(expr)) \
- ? (true) \
- : (log_assert_failed_return(message, __FILE__, __LINE__, __PRETTY_FUNCTION__), false))
-
#define assert_return(expr, r) \
do { \
if (!assert_log(expr, #expr)) \
diff --git a/src/systemd/src/basic/mempool.c b/src/systemd/src/basic/mempool.c
index 567f6b916e..a5ec8a1020 100644
--- a/src/systemd/src/basic/mempool.c
+++ b/src/systemd/src/basic/mempool.c
@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2014 Michal Schmidt
-***/
#include <stdint.h>
#include <stdlib.h>
diff --git a/src/systemd/src/basic/mempool.h b/src/systemd/src/basic/mempool.h
index 291415deb0..4098535c6f 100644
--- a/src/systemd/src/basic/mempool.h
+++ b/src/systemd/src/basic/mempool.h
@@ -1,10 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- Copyright © 2014 Michal Schmidt
-***/
-
#include <stddef.h>
struct pool;
diff --git a/src/systemd/src/basic/parse-util.c b/src/systemd/src/basic/parse-util.c
index 6becf85878..db38f91c83 100644
--- a/src/systemd/src/basic/parse-util.c
+++ b/src/systemd/src/basic/parse-util.c
@@ -637,6 +637,8 @@ int parse_permille_unbounded(const char *p) {
r = safe_atoi(n, &v);
if (r < 0)
return r;
+ if (v < 0)
+ return -ERANGE;
} else {
pc = endswith(p, "%");
if (!pc)
@@ -657,15 +659,14 @@ int parse_permille_unbounded(const char *p) {
r = safe_atoi(n, &v);
if (r < 0)
return r;
+ if (v < 0)
+ return -ERANGE;
if (v > (INT_MAX - q) / 10)
return -ERANGE;
v = v * 10 + q;
}
- if (v < 0)
- return -ERANGE;
-
return v;
}
diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c
index d214c72916..b62786f27e 100644
--- a/src/systemd/src/basic/path-util.c
+++ b/src/systemd/src/basic/path-util.c
@@ -110,10 +110,7 @@ int path_make_absolute_cwd(const char *p, char **ret) {
if (r < 0)
return r;
- if (endswith(cwd, "/"))
- c = strjoin(cwd, p);
- else
- c = strjoin(cwd, "/", p);
+ c = path_join(NULL, cwd, p);
}
if (!c)
return -ENOMEM;
diff --git a/src/systemd/src/basic/path-util.h b/src/systemd/src/basic/path-util.h
index 8277c6b916..49604eab80 100644
--- a/src/systemd/src/basic/path-util.h
+++ b/src/systemd/src/basic/path-util.h
@@ -58,10 +58,10 @@ static inline bool path_equal_ptr(const char *a, const char *b) {
/* Note: the search terminates on the first NULL item. */
#define PATH_IN_SET(p, ...) \
({ \
- char **s; \
+ char **_s; \
bool _found = false; \
- STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__)) \
- if (path_equal(p, *s)) { \
+ STRV_FOREACH(_s, STRV_MAKE(__VA_ARGS__)) \
+ if (path_equal(p, *_s)) { \
_found = true; \
break; \
} \
diff --git a/src/systemd/src/basic/process-util.c b/src/systemd/src/basic/process-util.c
index 0a4f917cbd..d6ee8b62b8 100644
--- a/src/systemd/src/basic/process-util.c
+++ b/src/systemd/src/basic/process-util.c
@@ -1108,12 +1108,7 @@ int pid_compare_func(const void *a, const void *b) {
const pid_t *p = a, *q = b;
/* Suitable for usage in qsort() */
-
- if (*p < *q)
- return -1;
- if (*p > *q)
- return 1;
- return 0;
+ return CMP(*p, *q);
}
int ioprio_parse_priority(const char *s, int *ret) {
@@ -1153,7 +1148,7 @@ void reset_cached_pid(void) {
/* We use glibc __register_atfork() + __dso_handle directly here, as they are not included in the glibc
* headers. __register_atfork() is mostly equivalent to pthread_atfork(), but doesn't require us to link against
* libpthread, as it is part of glibc anyway. */
-extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void (*child) (void), void * __dso_handle);
+extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void (*child) (void), void *dso_handle);
extern void* __dso_handle __attribute__ ((__weak__));
pid_t getpid_cached(void) {
diff --git a/src/systemd/src/basic/random-util.c b/src/systemd/src/basic/random-util.c
index 91481559db..aa04cc2318 100644
--- a/src/systemd/src/basic/random-util.c
+++ b/src/systemd/src/basic/random-util.c
@@ -1,5 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
+#ifdef __x86_64__
+#include <cpuid.h>
+#endif
+
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
@@ -26,6 +30,41 @@
#include "random-util.h"
#include "time-util.h"
+
+int rdrand64(uint64_t *ret) {
+
+#ifdef __x86_64__
+ static int have_rdrand = -1;
+ unsigned char err;
+
+ if (have_rdrand < 0) {
+ uint32_t eax, ebx, ecx, edx;
+
+ /* Check if RDRAND is supported by the CPU */
+ if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) == 0) {
+ have_rdrand = false;
+ return -EOPNOTSUPP;
+ }
+
+ have_rdrand = !!(ecx & (1U << 30));
+ }
+
+ if (have_rdrand == 0)
+ return -EOPNOTSUPP;
+
+ asm volatile("rdrand %0;"
+ "setc %1"
+ : "=r" (*ret),
+ "=qm" (err));
+ if (!err)
+ return -EAGAIN;
+
+ return 0;
+#else
+ return -EOPNOTSUPP;
+#endif
+}
+
int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
static int have_syscall = -1;
@@ -68,8 +107,26 @@ int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
* a best-effort basis. */
have_syscall = true;
- if (!high_quality_required)
- return -ENODATA;
+ if (!high_quality_required) {
+ uint64_t u;
+ size_t k;
+
+ /* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality
+ * randomness is not required, as we don't trust it (who does?). Note that we only do a
+ * single iteration of RDRAND here, even though the Intel docs suggest calling this in
+ * a tight loop of 10 invocatins or so. That's because we don't really care about the
+ * quality here. */
+
+ if (rdrand64(&u) < 0)
+ return -ENODATA;
+
+ k = MIN(n, sizeof(u));
+ memcpy(p, &u, k);
+
+ /* We only get 64bit out of RDRAND, the rest let's fill up with pseudo-random crap. */
+ pseudorandom_bytes((uint8_t*) p + k, n - k);
+ return 0;
+ }
} else
return -errno;
}
diff --git a/src/systemd/src/basic/random-util.h b/src/systemd/src/basic/random-util.h
index 9a103f0e94..affcc9ac1d 100644
--- a/src/systemd/src/basic/random-util.h
+++ b/src/systemd/src/basic/random-util.h
@@ -21,3 +21,5 @@ static inline uint32_t random_u32(void) {
random_bytes(&u, sizeof(u));
return u;
}
+
+int rdrand64(uint64_t *ret);
diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c
index 69f2c41e9d..986bc6e67f 100644
--- a/src/systemd/src/basic/socket-util.c
+++ b/src/systemd/src/basic/socket-util.c
@@ -50,7 +50,8 @@ static const char* const socket_address_type_table[] = {
DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int);
int socket_address_parse(SocketAddress *a, const char *s) {
- char *e, *n;
+ _cleanup_free_ char *n = NULL;
+ char *e;
int r;
assert(a);
@@ -68,7 +69,9 @@ int socket_address_parse(SocketAddress *a, const char *s) {
if (!e)
return -EINVAL;
- n = strndupa(s+1, e-s-1);
+ n = strndup(s+1, e-s-1);
+ if (!n)
+ return -ENOMEM;
errno = 0;
if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0)
@@ -125,7 +128,10 @@ int socket_address_parse(SocketAddress *a, const char *s) {
if (r < 0)
return r;
- n = strndupa(cid_start, e - cid_start);
+ n = strndup(cid_start, e - cid_start);
+ if (!n)
+ return -ENOMEM;
+
if (!isempty(n)) {
r = safe_atou(n, &a->sockaddr.vm.svm_cid);
if (r < 0)
@@ -146,7 +152,9 @@ int socket_address_parse(SocketAddress *a, const char *s) {
if (r < 0)
return r;
- n = strndupa(s, e-s);
+ n = strndup(s, e-s);
+ if (!n)
+ return -ENOMEM;
/* IPv4 in w.x.y.z:p notation? */
r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr);
@@ -1003,9 +1011,10 @@ int getpeergroups(int fd, gid_t **ret) {
return (int) n;
}
-int send_one_fd_sa(
+ssize_t send_one_fd_iov_sa(
int transport_fd,
int fd,
+ struct iovec *iov, size_t iovlen,
const struct sockaddr *sa, socklen_t len,
int flags) {
@@ -1016,28 +1025,58 @@ int send_one_fd_sa(
struct msghdr mh = {
.msg_name = (struct sockaddr*) sa,
.msg_namelen = len,
- .msg_control = &control,
- .msg_controllen = sizeof(control),
+ .msg_iov = iov,
+ .msg_iovlen = iovlen,
};
- struct cmsghdr *cmsg;
+ ssize_t k;
assert(transport_fd >= 0);
- assert(fd >= 0);
- cmsg = CMSG_FIRSTHDR(&mh);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(int));
- memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
+ /*
+ * We need either an FD or data to send.
+ * If there's nothing, return an error.
+ */
+ if (fd < 0 && !iov)
+ return -EINVAL;
- mh.msg_controllen = CMSG_SPACE(sizeof(int));
- if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0)
- return -errno;
+ if (fd >= 0) {
+ struct cmsghdr *cmsg;
- return 0;
+ mh.msg_control = &control;
+ mh.msg_controllen = sizeof(control);
+
+ cmsg = CMSG_FIRSTHDR(&mh);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
+
+ mh.msg_controllen = CMSG_SPACE(sizeof(int));
+ }
+ k = sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags);
+ if (k < 0)
+ return (ssize_t) -errno;
+
+ return k;
}
-int receive_one_fd(int transport_fd, int flags) {
+int send_one_fd_sa(
+ int transport_fd,
+ int fd,
+ const struct sockaddr *sa, socklen_t len,
+ int flags) {
+
+ assert(fd >= 0);
+
+ return (int) send_one_fd_iov_sa(transport_fd, fd, NULL, 0, sa, len, flags);
+}
+
+ssize_t receive_one_fd_iov(
+ int transport_fd,
+ struct iovec *iov, size_t iovlen,
+ int flags,
+ int *ret_fd) {
+
union {
struct cmsghdr cmsghdr;
uint8_t buf[CMSG_SPACE(sizeof(int))];
@@ -1045,10 +1084,14 @@ int receive_one_fd(int transport_fd, int flags) {
struct msghdr mh = {
.msg_control = &control,
.msg_controllen = sizeof(control),
+ .msg_iov = iov,
+ .msg_iovlen = iovlen,
};
struct cmsghdr *cmsg, *found = NULL;
+ ssize_t k;
assert(transport_fd >= 0);
+ assert(ret_fd);
/*
* Receive a single FD via @transport_fd. We don't care for
@@ -1058,8 +1101,9 @@ int receive_one_fd(int transport_fd, int flags) {
* combination with send_one_fd().
*/
- if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0)
- return -errno;
+ k = recvmsg(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags);
+ if (k < 0)
+ return (ssize_t) -errno;
CMSG_FOREACH(cmsg, &mh) {
if (cmsg->cmsg_level == SOL_SOCKET &&
@@ -1071,12 +1115,33 @@ int receive_one_fd(int transport_fd, int flags) {
}
}
- if (!found) {
+ if (!found)
cmsg_close_all(&mh);
+
+ /* If didn't receive an FD or any data, return an error. */
+ if (k == 0 && !found)
return -EIO;
- }
- return *(int*) CMSG_DATA(found);
+ if (found)
+ *ret_fd = *(int*) CMSG_DATA(found);
+ else
+ *ret_fd = -1;
+
+ return k;
+}
+
+int receive_one_fd(int transport_fd, int flags) {
+ int fd;
+ ssize_t k;
+
+ k = receive_one_fd_iov(transport_fd, NULL, 0, flags, &fd);
+ if (k == 0)
+ return fd;
+
+ /* k must be negative, since receive_one_fd_iov() only returns
+ * a positive value if data was received through the iov. */
+ assert(k < 0);
+ return (int) k;
}
ssize_t next_datagram_size_fd(int fd) {
diff --git a/src/systemd/src/basic/socket-util.h b/src/systemd/src/basic/socket-util.h
index 8e23cf2dbd..82781a0de1 100644
--- a/src/systemd/src/basic/socket-util.h
+++ b/src/systemd/src/basic/socket-util.h
@@ -130,11 +130,19 @@ int getpeercred(int fd, struct ucred *ucred);
int getpeersec(int fd, char **ret);
int getpeergroups(int fd, gid_t **ret);
+ssize_t send_one_fd_iov_sa(
+ int transport_fd,
+ int fd,
+ struct iovec *iov, size_t iovlen,
+ const struct sockaddr *sa, socklen_t len,
+ int flags);
int send_one_fd_sa(int transport_fd,
int fd,
const struct sockaddr *sa, socklen_t len,
int flags);
-#define send_one_fd(transport_fd, fd, flags) send_one_fd_sa(transport_fd, fd, NULL, 0, flags)
+#define send_one_fd_iov(transport_fd, fd, iov, iovlen, flags) send_one_fd_iov_sa(transport_fd, fd, iov, iovlen, NULL, 0, flags)
+#define send_one_fd(transport_fd, fd, flags) send_one_fd_iov_sa(transport_fd, fd, NULL, 0, NULL, 0, flags)
+ssize_t receive_one_fd_iov(int transport_fd, struct iovec *iov, size_t iovlen, int flags, int *ret_fd);
int receive_one_fd(int transport_fd, int flags);
ssize_t next_datagram_size_fd(int fd);
diff --git a/src/systemd/src/basic/stat-util.c b/src/systemd/src/basic/stat-util.c
index 07154e25bb..762777e94f 100644
--- a/src/systemd/src/basic/stat-util.c
+++ b/src/systemd/src/basic/stat-util.c
@@ -45,6 +45,17 @@ int is_dir(const char* path, bool follow) {
return !!S_ISDIR(st.st_mode);
}
+int is_dir_fd(int fd) {
+ struct stat st;
+ int r;
+
+ r = fstat(fd, &st);
+ if (r < 0)
+ return -errno;
+
+ return !!S_ISDIR(st.st_mode);
+}
+
int is_device_node(const char *path) {
struct stat info;
diff --git a/src/systemd/src/basic/stat-util.h b/src/systemd/src/basic/stat-util.h
index f8014ed30b..1a725f1da0 100644
--- a/src/systemd/src/basic/stat-util.h
+++ b/src/systemd/src/basic/stat-util.h
@@ -12,6 +12,7 @@
int is_symlink(const char *path);
int is_dir(const char *path, bool follow);
+int is_dir_fd(int fd);
int is_device_node(const char *path);
int dir_is_empty(const char *path);
diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c
index b3716233b5..abf3fc4c7b 100644
--- a/src/systemd/src/basic/strv.c
+++ b/src/systemd/src/basic/strv.c
@@ -253,6 +253,10 @@ char **strv_split(const char *s, const char *separator) {
assert(s);
+ s += strspn(s, separator);
+ if (isempty(s))
+ return new0(char*, 1);
+
n = 0;
FOREACH_WORD_SEPARATOR(word, l, s, separator, state)
n++;
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index fe201c398d..81d3f3f38f 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
@@ -996,10 +997,10 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
}
for (;;) {
+ usec_t multiplier = default_unit, k;
long long l, z = 0;
- char *e;
unsigned n = 0;
- usec_t multiplier = default_unit, k;
+ char *e;
p += strspn(p, WHITESPACE);
@@ -1010,6 +1011,9 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
break;
}
+ if (*p == '-') /* Don't allow "-0" */
+ return -ERANGE;
+
errno = 0;
l = strtoll(p, &e, 10);
if (errno > 0)
@@ -1020,14 +1024,16 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
if (*e == '.') {
char *b = e + 1;
+ /* Don't allow "0.-0", "3.+1" or "3. 1" */
+ if (*b == '-' || *b == '+' || isspace(*b))
+ return -EINVAL;
+
errno = 0;
z = strtoll(b, &e, 10);
if (errno > 0)
return -errno;
-
if (z < 0)
return -ERANGE;
-
if (e == b)
return -EINVAL;
@@ -1144,26 +1150,28 @@ int parse_nsec(const char *t, nsec_t *nsec) {
break;
}
+ if (*p == '-')
+ return -ERANGE;
+
errno = 0;
l = strtoll(p, &e, 10);
-
if (errno > 0)
return -errno;
-
if (l < 0)
return -ERANGE;
if (*e == '.') {
char *b = e + 1;
+ if (*b == '-' || *b == '+' || isspace(*b))
+ return -EINVAL;
+
errno = 0;
z = strtoll(b, &e, 10);
if (errno > 0)
return -errno;
-
if (z < 0)
return -ERANGE;
-
if (e == b)
return -EINVAL;
diff --git a/src/systemd/src/basic/utf8.c b/src/systemd/src/basic/utf8.c
index 531b518fad..a5ce1a2944 100644
--- a/src/systemd/src/basic/utf8.c
+++ b/src/systemd/src/basic/utf8.c
@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2008-2011 Kay Sievers
-***/
/* Parts of this file are based on the GLIB utf8 validation functions. The
* original license text follows. */
diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c
index 8f2d6061da..f951d641d7 100644
--- a/src/systemd/src/basic/util.c
+++ b/src/systemd/src/basic/util.c
@@ -77,31 +77,6 @@ bool display_is_local(const char *display) {
display[1] <= '9';
}
-int socket_from_display(const char *display, char **path) {
- size_t k;
- char *f, *c;
-
- assert(display);
- assert(path);
-
- if (!display_is_local(display))
- return -EINVAL;
-
- k = strspn(display+1, "0123456789");
-
- f = new(char, STRLEN("/tmp/.X11-unix/X") + k + 1);
- if (!f)
- return -ENOMEM;
-
- c = stpcpy(f, "/tmp/.X11-unix/X");
- memcpy(c, display+1, k);
- c[k] = 0;
-
- *path = f;
-
- return 0;
-}
-
bool kexec_loaded(void) {
_cleanup_free_ char *s = NULL;
@@ -255,6 +230,11 @@ int container_get_leader(const char *machine, pid_t *pid) {
assert(machine);
assert(pid);
+ if (streq(machine, ".host")) {
+ *pid = 1;
+ return 0;
+ }
+
if (!machine_name_is_valid(machine))
return -EINVAL;
diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h
index 9699d228f9..308933ac90 100644
--- a/src/systemd/src/basic/util.h
+++ b/src/systemd/src/basic/util.h
@@ -50,7 +50,6 @@ static inline const char* enable_disable(bool b) {
bool plymouth_running(void);
bool display_is_local(const char *display) _pure_;
-int socket_from_display(const char *display, char **path);
#define NULSTR_FOREACH(i, l) \
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
@@ -113,9 +112,7 @@ static inline void qsort_r_safe(void *base, size_t nmemb, size_t size, int (*com
qsort_r(base, nmemb, size, compar, userdata);
}
-/**
- * Normal memcpy requires src to be nonnull. We do nothing if n is 0.
- */
+/* Normal memcpy requires src to be nonnull. We do nothing if n is 0. */
static inline void memcpy_safe(void *dst, const void *src, size_t n) {
if (n == 0)
return;
@@ -123,6 +120,15 @@ static inline void memcpy_safe(void *dst, const void *src, size_t n) {
memcpy(dst, src, n);
}
+/* Normal memcmp requires s1 and s2 to be nonnull. We do nothing if n is 0. */
+static inline int memcmp_safe(const void *s1, const void *s2, size_t n) {
+ if (n == 0)
+ return 0;
+ assert(s1);
+ assert(s2);
+ return memcmp(s1, s2, n);
+}
+
int on_ac_power(void);
#define memzero(x,l) (memset((x), 0, (l)))
diff --git a/src/systemd/src/libsystemd-network/arp-util.c b/src/systemd/src/libsystemd-network/arp-util.c
index 0e0c234990..3a86f3f077 100644
--- a/src/systemd/src/libsystemd-network/arp-util.c
+++ b/src/systemd/src/libsystemd-network/arp-util.c
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Axis Communications AB. All rights reserved.
- Copyright © 2015 Tom Gundersen
***/
#include <linux/filter.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c
index ebbfe8bcd2..531cf6783b 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.c
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c
@@ -1,9 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2015 Tom Gundersen <teg@jklmen>
-***/
-#include "libudev.h"
+#include <linux/if_infiniband.h>
+#include <net/if_arp.h>
+
+#include "sd-device.h"
#include "sd-id128.h"
#include "dhcp-identifier.h"
@@ -11,11 +11,12 @@
#include "network-internal.h"
#include "siphash24.h"
#include "sparse-endian.h"
-#include "udev-util.h"
#include "virt.h"
-#define SYSTEMD_PEN 43793
-#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
+#define SYSTEMD_PEN 43793
+#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
+#define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03)
+#define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
struct duid d;
@@ -48,6 +49,56 @@ int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
return 0;
}
+int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) {
+ uint16_t time_from_2000y;
+
+ assert(duid);
+ assert(len);
+ assert(addr);
+
+ if (arp_type == ARPHRD_ETHER)
+ assert_return(addr_len == ETH_ALEN, -EINVAL);
+ else if (arp_type == ARPHRD_INFINIBAND)
+ assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
+ else
+ return -EINVAL;
+
+ if (t < USEC_2000)
+ time_from_2000y = 0;
+ else
+ time_from_2000y = (uint16_t) (((t - USEC_2000) / USEC_PER_SEC) & 0xffffffff);
+
+ unaligned_write_be16(&duid->type, DUID_TYPE_LLT);
+ unaligned_write_be16(&duid->llt.htype, arp_type);
+ unaligned_write_be32(&duid->llt.time, time_from_2000y);
+ memcpy(duid->llt.haddr, addr, addr_len);
+
+ *len = sizeof(duid->type) + sizeof(duid->llt.htype) + sizeof(duid->llt.time) + addr_len;
+
+ return 0;
+}
+
+int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) {
+ assert(duid);
+ assert(len);
+ assert(addr);
+
+ if (arp_type == ARPHRD_ETHER)
+ assert_return(addr_len == ETH_ALEN, -EINVAL);
+ else if (arp_type == ARPHRD_INFINIBAND)
+ assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
+ else
+ return -EINVAL;
+
+ unaligned_write_be16(&duid->type, DUID_TYPE_LL);
+ unaligned_write_be16(&duid->ll.htype, arp_type);
+ memcpy(duid->ll.haddr, addr, addr_len);
+
+ *len = sizeof(duid->type) + sizeof(duid->ll.htype) + addr_len;
+
+ return 0;
+}
+
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
sd_id128_t machine_id;
uint64_t hash;
@@ -66,33 +117,50 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
*len = sizeof(duid->type) + sizeof(duid->en);
/* a bit of snake-oil perhaps, but no need to expose the machine-id
- directly; duid->en.id might not be aligned, so we need to copy */
+ * directly; duid->en.id might not be aligned, so we need to copy */
hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes));
memcpy(duid->en.id, &hash, sizeof(duid->en.id));
return 0;
}
+int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len) {
+ sd_id128_t machine_id;
+ int r;
+
+ assert(duid);
+ assert(len);
+
+ r = sd_id128_get_machine_app_specific(APPLICATION_ID, &machine_id);
+ if (r < 0)
+ return r;
+
+ unaligned_write_be16(&duid->type, DUID_TYPE_UUID);
+ memcpy(&duid->raw.data, &machine_id, sizeof(machine_id));
+
+ *len = sizeof(duid->type) + sizeof(machine_id);
+
+ return 0;
+}
+
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
- /* name is a pointer to memory in the udev_device struct, so must
- have the same scope */
- _cleanup_(udev_device_unrefp) struct udev_device *device = NULL;
+ /* name is a pointer to memory in the sd_device struct, so must
+ * have the same scope */
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
const char *name = NULL;
uint64_t id;
if (detect_container() <= 0) {
/* not in a container, udev will be around */
- _cleanup_(udev_unrefp) struct udev *udev;
char ifindex_str[2 + DECIMAL_STR_MAX(int)];
-
- udev = udev_new();
- if (!udev)
- return -ENOMEM;
+ int initialized, r;
sprintf(ifindex_str, "n%d", ifindex);
- device = udev_device_new_from_device_id(udev, ifindex_str);
- if (device) {
- if (udev_device_get_is_initialized(device) <= 0)
+ if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) {
+ r = sd_device_get_is_initialized(device, &initialized);
+ if (r < 0)
+ return r;
+ if (!initialized)
/* not yet ready */
return -EBUSY;
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.h b/src/systemd/src/libsystemd-network/dhcp-identifier.h
index 42d4956d10..64315d3a3b 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.h
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.h
@@ -1,14 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- Copyright © 2015 Tom Gundersen <teg@jklmen>
-***/
-
#include "sd-id128.h"
#include "macro.h"
#include "sparse-endian.h"
+#include "time-util.h"
#include "unaligned.h"
typedef enum DUIDType {
@@ -31,18 +28,18 @@ struct duid {
union {
struct {
/* DUID_TYPE_LLT */
- uint16_t htype;
- uint32_t time;
+ be16_t htype;
+ be32_t time;
uint8_t haddr[0];
} _packed_ llt;
struct {
/* DUID_TYPE_EN */
- uint32_t pen;
+ be32_t pen;
uint8_t id[8];
} _packed_ en;
struct {
/* DUID_TYPE_LL */
- int16_t htype;
+ be16_t htype;
uint8_t haddr[0];
} _packed_ ll;
struct {
@@ -56,5 +53,8 @@ struct duid {
} _packed_;
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len);
+int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
+int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
+int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len);
int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);
diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h
index 257a3c2e2f..a0f9c2299f 100644
--- a/src/systemd/src/libsystemd-network/dhcp-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-internal.h
@@ -3,7 +3,6 @@
/***
Copyright © 2013 Intel Corporation. All rights reserved.
- Copyright © 2014 Tom Gundersen
***/
#include <linux/if_packet.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
index fabac183ef..9d245a9059 100644
--- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
@@ -3,7 +3,6 @@
/***
Copyright © 2013 Intel Corporation. All rights reserved.
- Copyright © 2014 Tom Gundersen
***/
#include <stdint.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp-packet.c b/src/systemd/src/libsystemd-network/dhcp-packet.c
index 79707933eb..d29cd06cb1 100644
--- a/src/systemd/src/libsystemd-network/dhcp-packet.c
+++ b/src/systemd/src/libsystemd-network/dhcp-packet.c
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2013 Intel Corporation. All rights reserved.
- Copyright © 2014 Tom Gundersen
***/
#include <errno.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
index dc85c437c9..ff0b0f00ce 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
@@ -2,7 +2,6 @@
#pragma once
/***
- Copyright © 2014 Tom Gundersen
Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
diff --git a/src/systemd/src/libsystemd-network/lldp-internal.h b/src/systemd/src/libsystemd-network/lldp-internal.h
index e56509884e..328d51f8ea 100644
--- a/src/systemd/src/libsystemd-network/lldp-internal.h
+++ b/src/systemd/src/libsystemd-network/lldp-internal.h
@@ -1,11 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- Copyright © 2014 Tom Gundersen
- Copyright © 2014 Susant Sahani
-***/
-
#include "sd-event.h"
#include "sd-lldp.h"
diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/systemd/src/libsystemd-network/lldp-neighbor.c
index 5dcb051373..8295d4d404 100644
--- a/src/systemd/src/libsystemd-network/lldp-neighbor.c
+++ b/src/systemd/src/libsystemd-network/lldp-neighbor.c
@@ -26,22 +26,15 @@ static int lldp_neighbor_id_compare_func(const void *a, const void *b) {
if (r != 0)
return r;
- if (x->chassis_id_size < y->chassis_id_size)
- return -1;
-
- if (x->chassis_id_size > y->chassis_id_size)
- return 1;
+ r = CMP(x->chassis_id_size, y->chassis_id_size);
+ if (r != 0)
+ return r;
r = memcmp(x->port_id, y->port_id, MIN(x->port_id_size, y->port_id_size));
if (r != 0)
return r;
- if (x->port_id_size < y->port_id_size)
- return -1;
- if (x->port_id_size > y->port_id_size)
- return 1;
-
- return 0;
+ return CMP(x->port_id_size, y->port_id_size);
}
const struct hash_ops lldp_neighbor_id_hash_ops = {
@@ -52,13 +45,7 @@ const struct hash_ops lldp_neighbor_id_hash_ops = {
int lldp_neighbor_prioq_compare_func(const void *a, const void *b) {
const sd_lldp_neighbor *x = a, *y = b;
- if (x->until < y->until)
- return -1;
-
- if (x->until > y->until)
- return 1;
-
- return 0;
+ return CMP(x->until, y->until);
}
_public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) {
diff --git a/src/systemd/src/libsystemd-network/lldp-network.c b/src/systemd/src/libsystemd-network/lldp-network.c
index 63ba718f46..a4020d1e19 100644
--- a/src/systemd/src/libsystemd-network/lldp-network.c
+++ b/src/systemd/src/libsystemd-network/lldp-network.c
@@ -1,8 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2014 Tom Gundersen
- Copyright © 2014 Susant Sahani
-***/
#include <linux/filter.h>
#include <netinet/if_ether.h>
diff --git a/src/systemd/src/libsystemd-network/lldp-network.h b/src/systemd/src/libsystemd-network/lldp-network.h
index 1d773acc2d..e4ed2898a5 100644
--- a/src/systemd/src/libsystemd-network/lldp-network.h
+++ b/src/systemd/src/libsystemd-network/lldp-network.h
@@ -1,11 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- Copyright © 2014 Tom Gundersen
- Copyright © 2014 Susant Sahani
-***/
-
#include "sd-event.h"
int lldp_network_bind_raw_socket(int ifindex);
diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c
index adb92d1c95..949798a1d3 100644
--- a/src/systemd/src/libsystemd-network/network-internal.c
+++ b/src/systemd/src/libsystemd-network/network-internal.c
@@ -1,7 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2013 Tom Gundersen <teg@jklm.no>
-***/
#include <arpa/inet.h>
#include <linux/if.h>
@@ -26,24 +23,22 @@
#include "utf8.h"
#include "util.h"
-const char *net_get_name(struct udev_device *device) {
+const char *net_get_name(sd_device *device) {
const char *name, *field;
assert(device);
/* fetch some persistent data unique (on this machine) to this device */
- FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
- name = udev_device_get_property_value(device, field);
- if (name)
+ FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC")
+ if (sd_device_get_property_value(device, field, &name) >= 0)
return name;
- }
return NULL;
}
#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
-int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result) {
+int net_get_unique_predictable_data(sd_device *device, uint64_t *result) {
size_t l, sz = 0;
const char *name = NULL;
int r;
@@ -127,7 +122,7 @@ bool net_match_config(Set *match_mac,
if (match_arch && condition_test(match_arch) <= 0)
return false;
- if (match_mac && dev_mac && !set_contains(match_mac, dev_mac))
+ if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac)))
return false;
if (!net_condition_test_strv(match_paths, dev_path))
diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h
index 51b69c3d15..45020c2bcf 100644
--- a/src/systemd/src/libsystemd-network/network-internal.h
+++ b/src/systemd/src/libsystemd-network/network-internal.h
@@ -1,18 +1,14 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- Copyright © 2013 Tom Gundersen <teg@jklm.no>
-***/
-
#include <stdbool.h>
+#include "sd-device.h"
#include "sd-dhcp-lease.h"
#include "condition.h"
#include "conf-parser.h"
#include "set.h"
-#include "udev.h"
#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
#define LINK_BRIDGE_PORT_PRIORITY_MAX 63
@@ -42,8 +38,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
-int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
-const char *net_get_name(struct udev_device *device);
+int net_get_unique_predictable_data(sd_device *device, uint64_t *result);
+const char *net_get_name(sd_device *device);
void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size);
int deserialize_in_addrs(struct in_addr **addresses, const char *string);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index ff434f8ce7..de86028a5d 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -341,13 +341,14 @@ int sd_dhcp_client_set_client_id(
* without further modification. Otherwise, if duid_type is supported, DUID
* is set based on that type. Otherwise, an error is returned.
*/
-static int dhcp_client_set_iaid_duid(
+static int dhcp_client_set_iaid_duid_internal(
sd_dhcp_client *client,
uint32_t iaid,
bool append_iaid,
uint16_t duid_type,
const void *duid,
- size_t duid_len) {
+ size_t duid_len,
+ usec_t llt_time) {
DHCP_CLIENT_DONT_DESTROY(client);
int r;
@@ -381,18 +382,43 @@ static int dhcp_client_set_iaid_duid(
client->client_id.ns.duid.type = htobe16(duid_type);
memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
len = sizeof(client->client_id.ns.duid.type) + duid_len;
- } else if (duid_type == DUID_TYPE_EN) {
- r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
- if (r < 0)
- return r;
} else
- return -EOPNOTSUPP;
+ switch (duid_type) {
+ case DUID_TYPE_LLT:
+ if (!client->mac_addr || client->mac_addr_len == 0)
+ return -EOPNOTSUPP;
+
+ r = dhcp_identifier_set_duid_llt(&client->client_id.ns.duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &len);
+ if (r < 0)
+ return r;
+ break;
+ case DUID_TYPE_EN:
+ r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
+ if (r < 0)
+ return r;
+ break;
+ case DUID_TYPE_LL:
+ if (!client->mac_addr || client->mac_addr_len == 0)
+ return -EOPNOTSUPP;
+
+ r = dhcp_identifier_set_duid_ll(&client->client_id.ns.duid, client->mac_addr, client->mac_addr_len, client->arp_type, &len);
+ if (r < 0)
+ return r;
+ break;
+ case DUID_TYPE_UUID:
+ r = dhcp_identifier_set_duid_uuid(&client->client_id.ns.duid, &len);
+ if (r < 0)
+ return r;
+ break;
+ default:
+ return -EINVAL;
+ }
client->client_id_len = sizeof(client->client_id.type) + len +
(append_iaid ? sizeof(client->client_id.ns.iaid) : 0);
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
- log_dhcp_client(client, "Configured IAID+DUID, restarting.");
+ log_dhcp_client(client, "Configured %sDUID, restarting.", append_iaid ? "IAID+" : "");
client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
sd_dhcp_client_start(client);
}
@@ -406,7 +432,14 @@ int sd_dhcp_client_set_iaid_duid(
uint16_t duid_type,
const void *duid,
size_t duid_len) {
- return dhcp_client_set_iaid_duid(client, iaid, true, duid_type, duid, duid_len);
+ return dhcp_client_set_iaid_duid_internal(client, iaid, true, duid_type, duid, duid_len, 0);
+}
+
+int sd_dhcp_client_set_iaid_duid_llt(
+ sd_dhcp_client *client,
+ uint32_t iaid,
+ usec_t llt_time) {
+ return dhcp_client_set_iaid_duid_internal(client, iaid, true, DUID_TYPE_LLT, NULL, 0, llt_time);
}
int sd_dhcp_client_set_duid(
@@ -414,7 +447,13 @@ int sd_dhcp_client_set_duid(
uint16_t duid_type,
const void *duid,
size_t duid_len) {
- return dhcp_client_set_iaid_duid(client, 0, false, duid_type, duid, duid_len);
+ return dhcp_client_set_iaid_duid_internal(client, 0, false, duid_type, duid, duid_len, 0);
+}
+
+int sd_dhcp_client_set_duid_llt(
+ sd_dhcp_client *client,
+ usec_t llt_time) {
+ return dhcp_client_set_iaid_duid_internal(client, 0, false, DUID_TYPE_LLT, NULL, 0, llt_time);
}
int sd_dhcp_client_set_hostname(
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
index 47cd439e26..8b6f5ad34f 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2013 Intel Corporation. All rights reserved.
- Copyright © 2014 Tom Gundersen
***/
#include <arpa/inet.h>
@@ -26,6 +25,7 @@
#include "parse-util.h"
#include "stdio-util.h"
#include "string-util.h"
+#include "strv.h"
#include "unaligned.h"
int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
index b3bc259280..84c58af346 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
@@ -182,13 +182,14 @@ static int client_ensure_duid(sd_dhcp6_client *client) {
* without further modification. Otherwise, if duid_type is supported, DUID
* is set based on that type. Otherwise, an error is returned.
*/
-int sd_dhcp6_client_set_duid(
+static int dhcp6_client_set_duid_internal(
sd_dhcp6_client *client,
uint16_t duid_type,
const void *duid,
- size_t duid_len) {
-
+ size_t duid_len,
+ usec_t llt_time) {
int r;
+
assert_return(client, -EINVAL);
assert_return(duid_len == 0 || duid != NULL, -EINVAL);
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
@@ -197,22 +198,59 @@ int sd_dhcp6_client_set_duid(
r = dhcp_validate_duid_len(duid_type, duid_len);
if (r < 0)
return r;
- }
- if (duid != NULL) {
client->duid.type = htobe16(duid_type);
memcpy(&client->duid.raw.data, duid, duid_len);
client->duid_len = sizeof(client->duid.type) + duid_len;
- } else if (duid_type == DUID_TYPE_EN) {
- r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
- if (r < 0)
- return r;
} else
- return -EOPNOTSUPP;
+ switch (duid_type) {
+ case DUID_TYPE_LLT:
+ if (!client->mac_addr || client->mac_addr_len == 0)
+ return -EOPNOTSUPP;
+
+ r = dhcp_identifier_set_duid_llt(&client->duid, 0, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len);
+ if (r < 0)
+ return r;
+ break;
+ case DUID_TYPE_EN:
+ r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
+ if (r < 0)
+ return r;
+ break;
+ case DUID_TYPE_LL:
+ if (!client->mac_addr || client->mac_addr_len == 0)
+ return -EOPNOTSUPP;
+
+ r = dhcp_identifier_set_duid_ll(&client->duid, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len);
+ if (r < 0)
+ return r;
+ break;
+ case DUID_TYPE_UUID:
+ r = dhcp_identifier_set_duid_uuid(&client->duid, &client->duid_len);
+ if (r < 0)
+ return r;
+ break;
+ default:
+ return -EINVAL;
+ }
return 0;
}
+int sd_dhcp6_client_set_duid(
+ sd_dhcp6_client *client,
+ uint16_t duid_type,
+ const void *duid,
+ size_t duid_len) {
+ return dhcp6_client_set_duid_internal(client, duid_type, duid, duid_len, 0);
+}
+
+int sd_dhcp6_client_set_duid_llt(
+ sd_dhcp6_client *client,
+ usec_t llt_time) {
+ return dhcp6_client_set_duid_internal(client, DUID_TYPE_LLT, NULL, 0, llt_time);
+}
+
int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) {
assert_return(client, -EINVAL);
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
@@ -1144,9 +1182,8 @@ static int client_receive_message(
return 0;
}
- if (r >= 0)
- log_dhcp6_client(client, "Recv %s",
- dhcp6_message_type_to_string(message->type));
+ log_dhcp6_client(client, "Recv %s",
+ dhcp6_message_type_to_string(message->type));
return 0;
}
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
index 4a4e37a100..779ad54b4a 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- Copyright © 2014 Tom Gundersen
Copyright © 2014-2015 Intel Corporation. All rights reserved.
***/
diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c
index 8cd685b04d..a40d40db90 100644
--- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c
+++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Axis Communications AB. All rights reserved.
- Copyright © 2015 Tom Gundersen
***/
#include <arpa/inet.h>
diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c
index 001b322610..7307e1668f 100644
--- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Axis Communications AB. All rights reserved.
- Copyright © 2015 Tom Gundersen
***/
#include <arpa/inet.h>
diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/systemd/src/libsystemd-network/sd-lldp.c
index 15a7f291e4..c75d6079e1 100644
--- a/src/systemd/src/libsystemd-network/sd-lldp.c
+++ b/src/systemd/src/libsystemd-network/sd-lldp.c
@@ -1,8 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- Copyright © 2014 Tom Gundersen
- Copyright © 2014 Susant Sahani
-***/
#include <arpa/inet.h>
#include <linux/sockios.h>
diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c
index d53b9a7026..6e50fcc4c6 100644
--- a/src/systemd/src/libsystemd/sd-event/sd-event.c
+++ b/src/systemd/src/libsystemd/sd-event/sd-event.c
@@ -1,6 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
-***/
#include <sys/epoll.h>
#include <sys/timerfd.h>
@@ -92,7 +90,7 @@ struct sd_event_source {
char *description;
EventSourceType type:5;
- int enabled:3;
+ signed int enabled:3;
bool pending:1;
bool dispatching:1;
bool floating:1;
diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.c b/src/systemd/src/libsystemd/sd-id128/id128-util.c
index edee985e44..95c9e1138c 100644
--- a/src/systemd/src/libsystemd/sd-id128/id128-util.c
+++ b/src/systemd/src/libsystemd/sd-id128/id128-util.c
@@ -1,6 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.h b/src/systemd/src/libsystemd/sd-id128/id128-util.h
index f0b4eca581..44f159c0b6 100644
--- a/src/systemd/src/libsystemd/sd-id128/id128-util.h
+++ b/src/systemd/src/libsystemd/sd-id128/id128-util.h
@@ -1,9 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
-***/
-
#include <stdbool.h>
#include "sd-id128.h"
diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
index b7123280f3..9d93732d7e 100644
--- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
@@ -1,6 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
-***/
#include <errno.h>
#include <fcntl.h>
diff --git a/src/systemd/src/shared/dns-domain.c b/src/systemd/src/shared/dns-domain.c
index de2fcca8b2..1ecfb77de2 100644
--- a/src/systemd/src/shared/dns-domain.c
+++ b/src/systemd/src/shared/dns-domain.c
@@ -1,6 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- ***/
#if HAVE_LIBIDN2
# include <idn2.h>
@@ -505,7 +503,7 @@ int dns_name_compare_func(const void *a, const void *b) {
r = dns_label_unescape_suffix(a, &x, la, sizeof(la));
q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb));
if (r < 0 || q < 0)
- return r - q;
+ return CMP(r, q);
r = ascii_strcasecmp_nn(la, r, lb, q);
if (r != 0)
diff --git a/src/systemd/src/shared/dns-domain.h b/src/systemd/src/shared/dns-domain.h
index 0fd72cb029..1e9b57059b 100644
--- a/src/systemd/src/shared/dns-domain.h
+++ b/src/systemd/src/shared/dns-domain.h
@@ -1,9 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-/***
- ***/
-
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
diff --git a/src/systemd/src/systemd/_sd-common.h b/src/systemd/src/systemd/_sd-common.h
index 7b54d179eb..4742b2e742 100644
--- a/src/systemd/src/systemd/_sd-common.h
+++ b/src/systemd/src/systemd/_sd-common.h
@@ -3,7 +3,6 @@
#define foosdcommonhfoo
/***
-
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
diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h
index 931b0e890b..e388552064 100644
--- a/src/systemd/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/src/systemd/sd-dhcp-client.h
@@ -131,11 +131,18 @@ int sd_dhcp_client_set_iaid_duid(
uint16_t duid_type,
const void *duid,
size_t duid_len);
+int sd_dhcp_client_set_iaid_duid_llt(
+ sd_dhcp_client *client,
+ uint32_t iaid,
+ uint64_t llt_time);
int sd_dhcp_client_set_duid(
sd_dhcp_client *client,
uint16_t duid_type,
const void *duid,
size_t duid_len);
+int sd_dhcp_client_set_duid_llt(
+ sd_dhcp_client *client,
+ uint64_t llt_time);
int sd_dhcp_client_get_client_id(
sd_dhcp_client *client,
uint8_t *type,
diff --git a/src/systemd/src/systemd/sd-dhcp-lease.h b/src/systemd/src/systemd/sd-dhcp-lease.h
index 16c05661ec..2a60145f5b 100644
--- a/src/systemd/src/systemd/sd-dhcp-lease.h
+++ b/src/systemd/src/systemd/sd-dhcp-lease.h
@@ -4,8 +4,6 @@
/***
Copyright © 2013 Intel Corporation. All rights reserved.
- Copyright © 2014 Tom Gundersen
-
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
diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h
index 4f3b2d9e2e..fa36dca909 100644
--- a/src/systemd/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/src/systemd/sd-dhcp6-client.h
@@ -102,6 +102,9 @@ int sd_dhcp6_client_set_duid(
uint16_t duid_type,
const void *duid,
size_t duid_len);
+int sd_dhcp6_client_set_duid_llt(
+ sd_dhcp6_client *client,
+ uint64_t llt_time);
int sd_dhcp6_client_set_iaid(
sd_dhcp6_client *client,
uint32_t iaid);
diff --git a/src/systemd/src/systemd/sd-dhcp6-lease.h b/src/systemd/src/systemd/sd-dhcp6-lease.h
index a673de5edd..33a32a6dc5 100644
--- a/src/systemd/src/systemd/sd-dhcp6-lease.h
+++ b/src/systemd/src/systemd/sd-dhcp6-lease.h
@@ -3,7 +3,6 @@
#define foosddhcp6leasehfoo
/***
- Copyright © 2014 Tom Gundersen
Copyright © 2014-2015 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h
index 7fcae4ac49..eb35b83431 100644
--- a/src/systemd/src/systemd/sd-event.h
+++ b/src/systemd/src/systemd/sd-event.h
@@ -3,7 +3,6 @@
#define foosdeventhfoo
/***
-
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
diff --git a/src/systemd/src/systemd/sd-id128.h b/src/systemd/src/systemd/sd-id128.h
index b24fd06f01..143a0ffb5e 100644
--- a/src/systemd/src/systemd/sd-id128.h
+++ b/src/systemd/src/systemd/sd-id128.h
@@ -3,7 +3,6 @@
#define foosdid128hfoo
/***
-
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
diff --git a/src/systemd/src/systemd/sd-ipv4acd.h b/src/systemd/src/systemd/sd-ipv4acd.h
index 259db26330..039ed3c7f2 100644
--- a/src/systemd/src/systemd/sd-ipv4acd.h
+++ b/src/systemd/src/systemd/sd-ipv4acd.h
@@ -4,8 +4,6 @@
/***
Copyright © 2014 Axis Communications AB. All rights reserved.
- Copyright © 2015 Tom Gundersen
-
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
diff --git a/src/systemd/src/systemd/sd-lldp.h b/src/systemd/src/systemd/sd-lldp.h
index 11a2119ab6..d650794cc0 100644
--- a/src/systemd/src/systemd/sd-lldp.h
+++ b/src/systemd/src/systemd/sd-lldp.h
@@ -3,9 +3,6 @@
#define foosdlldphfoo
/***
- Copyright © 2014 Tom Gundersen
- Copyright © 2014 Susant Sahani
-
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