summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2020-08-04 17:12:42 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2020-08-04 17:20:21 +0200
commitdee5ce0a52b9e443afc56a95941ca18a4de23a02 (patch)
tree62ca735f888a2a88b77cf1ce30a66cb67070974b
parent0024cef23850e6141a15cb02d92551adef3cf4dd (diff)
parent5747fb11a8db9a177800ca58318a772fc13500a9 (diff)
downloadNetworkManager-dee5ce0a52b9e443afc56a95941ca18a4de23a02.tar.gz
systemd: merge branch systemd into master
-rw-r--r--shared/systemd/src/basic/fileio.c84
-rw-r--r--shared/systemd/src/basic/fileio.h8
-rw-r--r--shared/systemd/src/basic/fs-util.c4
-rw-r--r--shared/systemd/src/basic/hashmap.c64
-rw-r--r--shared/systemd/src/basic/hashmap.h13
-rw-r--r--shared/systemd/src/basic/in-addr-util.c62
-rw-r--r--shared/systemd/src/basic/in-addr-util.h1
-rw-r--r--shared/systemd/src/basic/list.h15
-rw-r--r--shared/systemd/src/basic/log.h4
-rw-r--r--shared/systemd/src/basic/macro.h15
-rw-r--r--shared/systemd/src/basic/memory-util.h1
-rw-r--r--shared/systemd/src/basic/path-util.c6
-rw-r--r--shared/systemd/src/basic/process-util.h12
-rw-r--r--shared/systemd/src/basic/random-util.c35
-rw-r--r--shared/systemd/src/basic/random-util.h2
-rw-r--r--shared/systemd/src/basic/set.h18
-rw-r--r--shared/systemd/src/basic/siphash24.h14
-rw-r--r--shared/systemd/src/basic/socket-util.c10
-rw-r--r--shared/systemd/src/basic/string-table.c4
-rw-r--r--shared/systemd/src/basic/time-util.c82
-rw-r--r--shared/systemd/src/basic/time-util.h6
-rw-r--r--shared/systemd/src/basic/tmpfile-util.c2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-lease-internal.h3
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-internal.h7
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-lease-internal.h2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-network.c6
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-option.c120
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.h4
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c8
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-lease.c2
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-client.c9
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-lease.c39
-rw-r--r--src/systemd/src/libsystemd/sd-event/sd-event.c49
-rw-r--r--src/systemd/src/systemd/sd-dhcp6-lease.h1
-rw-r--r--src/systemd/src/systemd/sd-event.h2
35 files changed, 555 insertions, 159 deletions
diff --git a/shared/systemd/src/basic/fileio.c b/shared/systemd/src/basic/fileio.c
index 309032638c..24a6c8afd1 100644
--- a/shared/systemd/src/basic/fileio.c
+++ b/shared/systemd/src/basic/fileio.c
@@ -24,6 +24,7 @@
#include "mkdir.h"
#include "parse-util.h"
#include "path-util.h"
+#include "socket-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "tmpfile-util.h"
@@ -486,13 +487,12 @@ int read_full_stream_full(
assert(f);
assert(ret_contents);
assert(!FLAGS_SET(flags, READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX));
- assert(!(flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) || ret_size);
n_next = LINE_MAX; /* Start size */
fd = fileno(f);
- if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see fmemopen(), let's
- * optimize our buffering) */
+ if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see fmemopen()), let's
+ * optimize our buffering */
if (fstat(fd, &st) < 0)
return -errno;
@@ -509,7 +509,7 @@ int read_full_stream_full(
if (st.st_size > 0)
n_next = st.st_size + 1;
- if (flags & READ_FULL_FILE_SECURE)
+ if (flags & READ_FULL_FILE_WARN_WORLD_READABLE)
(void) warn_file_is_world_accessible(filename, &st, NULL, 0);
}
}
@@ -539,21 +539,18 @@ int read_full_stream_full(
errno = 0;
k = fread(buf + l, 1, n - l, f);
- if (k > 0)
- l += k;
+
+ assert(k <= n - l);
+ l += k;
if (ferror(f)) {
r = errno_or_else(EIO);
goto finalize;
}
-
if (feof(f))
break;
- /* We aren't expecting fread() to return a short read outside
- * of (error && eof), assert buffer is full and enlarge buffer.
- */
- assert(l == n);
+ assert(k > 0); /* we can't have read zero bytes because that would have been EOF */
/* Safety check */
if (n >= READ_FULL_BYTES_MAX) {
@@ -565,12 +562,21 @@ int read_full_stream_full(
}
if (flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) {
+ _cleanup_free_ void *decoded = NULL;
+ size_t decoded_size;
+
buf[l++] = 0;
if (flags & READ_FULL_FILE_UNBASE64)
- r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size);
+ r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, &decoded, &decoded_size);
else
- r = unhexmem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size);
- goto finalize;
+ r = unhexmem_full(buf, l, flags & READ_FULL_FILE_SECURE, &decoded, &decoded_size);
+ if (r < 0)
+ goto finalize;
+
+ if (flags & READ_FULL_FILE_SECURE)
+ explicit_bzero_safe(buf, n);
+ free_and_replace(buf, decoded);
+ n = l = decoded_size;
}
if (!ret_size) {
@@ -607,8 +613,54 @@ int read_full_file_full(int dir_fd, const char *filename, ReadFullFileFlags flag
assert(contents);
r = xfopenat(dir_fd, filename, "re", 0, &f);
- if (r < 0)
- return r;
+ if (r < 0) {
+ _cleanup_close_ int dfd = -1, sk = -1;
+ union sockaddr_union sa;
+
+ /* ENXIO is what Linux returns if we open a node that is an AF_UNIX socket */
+ if (r != -ENXIO)
+ return r;
+
+ /* If this is enabled, let's try to connect to it */
+ if (!FLAGS_SET(flags, READ_FULL_FILE_CONNECT_SOCKET))
+ return -ENXIO;
+
+ if (dir_fd == AT_FDCWD)
+ r = sockaddr_un_set_path(&sa.un, filename);
+ else {
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+
+ /* If we shall operate relative to some directory, then let's use O_PATH first to
+ * open the socket inode, and then connect to it via /proc/self/fd/. We have to do
+ * this since there's not connectat() that takes a directory fd as first arg. */
+
+ dfd = openat(dir_fd, filename, O_PATH|O_CLOEXEC);
+ if (dfd < 0)
+ return -errno;
+
+ xsprintf(procfs_path, "/proc/self/fd/%i", dfd);
+ r = sockaddr_un_set_path(&sa.un, procfs_path);
+ }
+ if (r < 0)
+ return r;
+
+ sk = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
+ if (sk < 0)
+ return -errno;
+
+ if (connect(sk, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
+ return errno == ENOTSOCK ? -ENXIO : -errno; /* propagate original error if this is
+ * not a socket after all */
+
+ if (shutdown(sk, SHUT_WR) < 0)
+ return -errno;
+
+ f = fdopen(sk, "r");
+ if (!f)
+ return -errno;
+
+ TAKE_FD(sk);
+ }
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
diff --git a/shared/systemd/src/basic/fileio.h b/shared/systemd/src/basic/fileio.h
index e2830b7963..7d58fa7cfc 100644
--- a/shared/systemd/src/basic/fileio.h
+++ b/shared/systemd/src/basic/fileio.h
@@ -32,9 +32,11 @@ typedef enum {
} WriteStringFileFlags;
typedef enum {
- READ_FULL_FILE_SECURE = 1 << 0,
- READ_FULL_FILE_UNBASE64 = 1 << 1,
- READ_FULL_FILE_UNHEX = 1 << 2,
+ READ_FULL_FILE_SECURE = 1 << 0, /* erase any buffers we employ internally, after use */
+ READ_FULL_FILE_UNBASE64 = 1 << 1, /* base64 decode what we read */
+ READ_FULL_FILE_UNHEX = 1 << 2, /* hex decode what we read */
+ READ_FULL_FILE_WARN_WORLD_READABLE = 1 << 3, /* if regular file, log at LOG_WARNING level if access mode above 0700 */
+ READ_FULL_FILE_CONNECT_SOCKET = 1 << 4, /* if socket inode, connect to it and read off it */
} ReadFullFileFlags;
int fopen_unlocked(const char *path, const char *options, FILE **ret);
diff --git a/shared/systemd/src/basic/fs-util.c b/shared/systemd/src/basic/fs-util.c
index 75df913acf..a1f6380f3b 100644
--- a/shared/systemd/src/basic/fs-util.c
+++ b/shared/systemd/src/basic/fs-util.c
@@ -1587,7 +1587,7 @@ static int blockdev_is_encrypted(const char *sysfs_path, unsigned depth_left) {
d = opendir(p);
if (!d) {
- if (errno == ENOENT) /* Doesn't have slaves */
+ if (errno == ENOENT) /* Doesn't have underlying devices */
return false;
return -errno;
@@ -1603,7 +1603,7 @@ static int blockdev_is_encrypted(const char *sysfs_path, unsigned depth_left) {
if (errno != 0)
return -errno;
- break; /* No more slaves */
+ break; /* No more underlying devices */
}
q = path_join(p, de->d_name);
diff --git a/shared/systemd/src/basic/hashmap.c b/shared/systemd/src/basic/hashmap.c
index c0296bde36..db62ec790f 100644
--- a/shared/systemd/src/basic/hashmap.c
+++ b/shared/systemd/src/basic/hashmap.c
@@ -770,7 +770,7 @@ static void reset_direct_storage(HashmapBase *h) {
memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
}
-static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
+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 up;
@@ -810,19 +810,19 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu
}
Hashmap *_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return (Hashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
+ return (Hashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
}
OrderedHashmap *_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return (OrderedHashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
+ return (OrderedHashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
}
Set *_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return (Set*) hashmap_base_new(hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
+ return (Set*) hashmap_base_new(hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
}
static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops *hash_ops,
- enum HashmapType type HASHMAP_DEBUG_PARAMS) {
+ enum HashmapType type HASHMAP_DEBUG_PARAMS) {
HashmapBase *q;
assert(h);
@@ -830,7 +830,7 @@ static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops
if (*h)
return 0;
- q = hashmap_base_new(hash_ops, type HASHMAP_DEBUG_PASS_ARGS);
+ q = hashmap_base_new(hash_ops, type HASHMAP_DEBUG_PASS_ARGS);
if (!q)
return -ENOMEM;
@@ -839,15 +839,15 @@ static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops
}
int _hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
+ return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS);
}
int _ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
+ return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS);
}
int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) {
- return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
+ return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS);
}
static void hashmap_free_no_clear(HashmapBase *h) {
@@ -1249,6 +1249,30 @@ int set_put(Set *s, const void *key) {
return hashmap_put_boldly(s, hash, &swap, true);
}
+int _set_ensure_put(Set **s, const struct hash_ops *hash_ops, const void *key HASHMAP_DEBUG_PARAMS) {
+ int r;
+
+ r = _set_ensure_allocated(s, hash_ops HASHMAP_DEBUG_PASS_ARGS);
+ if (r < 0)
+ return r;
+
+ return set_put(*s, key);
+}
+
+int _set_ensure_consume(Set **s, const struct hash_ops *hash_ops, void *key HASHMAP_DEBUG_PARAMS) {
+ int r;
+
+ r = _set_ensure_put(s, hash_ops, key HASHMAP_DEBUG_PASS_ARGS);
+ if (r <= 0) {
+ if (hash_ops && hash_ops->free_key)
+ hash_ops->free_key(key);
+ else
+ free(key);
+ }
+
+ return r;
+}
+
int hashmap_replace(Hashmap *h, const void *key, void *value) {
struct swap_entries swap;
struct plain_hashmap_entry *e;
@@ -1689,13 +1713,13 @@ int _hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) {
return 0;
}
-HashmapBase *_hashmap_copy(HashmapBase *h) {
+HashmapBase *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS) {
HashmapBase *copy;
int r;
assert(h);
- copy = hashmap_base_new(h->hash_ops, h->type HASHMAP_DEBUG_SRC_ARGS);
+ copy = hashmap_base_new(h->hash_ops, h->type HASHMAP_DEBUG_PASS_ARGS);
if (!copy)
return NULL;
@@ -1711,10 +1735,8 @@ HashmapBase *_hashmap_copy(HashmapBase *h) {
assert_not_reached("Unknown hashmap type");
}
- if (r < 0) {
- _hashmap_free(copy, false, false);
- return NULL;
- }
+ if (r < 0)
+ return _hashmap_free(copy, false, false);
return copy;
}
@@ -1768,10 +1790,10 @@ int set_consume(Set *s, void *value) {
}
#if 0 /* NM_IGNORED */
-int hashmap_put_strdup(Hashmap **h, const char *k, const char *v) {
+int _hashmap_put_strdup(Hashmap **h, const char *k, const char *v HASHMAP_DEBUG_PARAMS) {
int r;
- r = hashmap_ensure_allocated(h, &string_hash_ops_free_free);
+ r = _hashmap_ensure_allocated(h, &string_hash_ops_free_free HASHMAP_DEBUG_PASS_ARGS);
if (r < 0)
return r;
@@ -1803,14 +1825,14 @@ int hashmap_put_strdup(Hashmap **h, const char *k, const char *v) {
}
#endif /* NM_IGNORED */
-int set_put_strdup(Set **s, const char *p) {
+int _set_put_strdup(Set **s, const char *p HASHMAP_DEBUG_PARAMS) {
char *c;
int r;
assert(s);
assert(p);
- r = set_ensure_allocated(s, &string_hash_ops_free);
+ r = _set_ensure_allocated(s, &string_hash_ops_free HASHMAP_DEBUG_PASS_ARGS);
if (r < 0)
return r;
@@ -1824,14 +1846,14 @@ int set_put_strdup(Set **s, const char *p) {
return set_consume(*s, c);
}
-int set_put_strdupv(Set **s, char **l) {
+int _set_put_strdupv(Set **s, char **l HASHMAP_DEBUG_PARAMS) {
int n = 0, r;
char **i;
assert(s);
STRV_FOREACH(i, l) {
- r = set_put_strdup(s, *i);
+ r = _set_put_strdup(s, *i HASHMAP_DEBUG_PASS_ARGS);
if (r < 0)
return r;
diff --git a/shared/systemd/src/basic/hashmap.h b/shared/systemd/src/basic/hashmap.h
index 230d322213..6009441621 100644
--- a/shared/systemd/src/basic/hashmap.h
+++ b/shared/systemd/src/basic/hashmap.h
@@ -128,13 +128,9 @@ static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h)
IteratedCache *iterated_cache_free(IteratedCache *cache);
int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries);
-HashmapBase *_hashmap_copy(HashmapBase *h);
-static inline Hashmap *hashmap_copy(Hashmap *h) {
- return (Hashmap*) _hashmap_copy(HASHMAP_BASE(h));
-}
-static inline OrderedHashmap *ordered_hashmap_copy(OrderedHashmap *h) {
- return (OrderedHashmap*) _hashmap_copy(HASHMAP_BASE(h));
-}
+HashmapBase *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS);
+#define hashmap_copy(h) ((Hashmap*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS))
+#define ordered_hashmap_copy(h) ((OrderedHashmap*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS))
int _hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
int _ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
@@ -154,7 +150,8 @@ static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *
return hashmap_put(PLAIN_HASHMAP(h), key, value);
}
-int hashmap_put_strdup(Hashmap **h, const char *k, const char *v);
+int _hashmap_put_strdup(Hashmap **h, const char *k, const char *v HASHMAP_DEBUG_PARAMS);
+#define hashmap_put_strdup(h, k, v) _hashmap_put_strdup(h, k, v HASHMAP_DEBUG_SRC_ARGS)
int hashmap_update(Hashmap *h, const void *key, void *value);
static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) {
diff --git a/shared/systemd/src/basic/in-addr-util.c b/shared/systemd/src/basic/in-addr-util.c
index cddc269f4a..98ccbdfe24 100644
--- a/shared/systemd/src/basic/in-addr-util.c
+++ b/shared/systemd/src/basic/in-addr-util.c
@@ -16,6 +16,7 @@
#include "macro.h"
#include "parse-util.h"
#include "random-util.h"
+#include "string-util.h"
#include "strxcpyx.h"
#include "util.h"
@@ -109,11 +110,7 @@ int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_
return in4_addr_equal(&a->in, &b->in);
if (family == AF_INET6)
- return
- a->in6.s6_addr32[0] == b->in6.s6_addr32[0] &&
- a->in6.s6_addr32[1] == b->in6.s6_addr32[1] &&
- a->in6.s6_addr32[2] == b->in6.s6_addr32[2] &&
- a->in6.s6_addr32[3] == b->in6.s6_addr32[3];
+ return IN6_ARE_ADDR_EQUAL(&a->in6, &b->in6);
return -EAFNOSUPPORT;
}
@@ -451,6 +448,61 @@ fallback:
return in_addr_to_string(family, u, ret);
}
+int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret) {
+ _cleanup_free_ char *ip_str = NULL, *x = NULL;
+ int r;
+
+ assert(IN_SET(family, AF_INET, AF_INET6));
+ assert(u);
+ assert(ret);
+
+ /* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly
+ * handle IPv6 link-local addresses. */
+
+ r = in_addr_to_string(family, u, &ip_str);
+ if (r < 0)
+ return r;
+
+ if (family == AF_INET6) {
+ r = in_addr_is_link_local(family, u);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ ifindex = 0;
+ } else
+ ifindex = 0; /* For IPv4 address, ifindex is always ignored. */
+
+ if (port == 0 && ifindex == 0 && isempty(server_name)) {
+ *ret = TAKE_PTR(ip_str);
+ return 0;
+ }
+
+ const char *separator = isempty(server_name) ? "" : "#";
+ server_name = strempty(server_name);
+
+ if (port > 0) {
+ if (family == AF_INET6) {
+ if (ifindex > 0)
+ r = asprintf(&x, "[%s]:%"PRIu16"%%%i%s%s", ip_str, port, ifindex, separator, server_name);
+ else
+ r = asprintf(&x, "[%s]:%"PRIu16"%s%s", ip_str, port, separator, server_name);
+ } else
+ r = asprintf(&x, "%s:%"PRIu16"%s%s", ip_str, port, separator, server_name);
+ } else {
+ if (ifindex > 0)
+ r = asprintf(&x, "%s%%%i%s%s", ip_str, ifindex, separator, server_name);
+ else {
+ x = strjoin(ip_str, separator, server_name);
+ r = x ? 0 : -ENOMEM;
+ }
+ }
+ if (r < 0)
+ return -ENOMEM;
+
+ *ret = TAKE_PTR(x);
+ return 0;
+}
+
int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
union in_addr_union buffer;
assert(s);
diff --git a/shared/systemd/src/basic/in-addr-util.h b/shared/systemd/src/basic/in-addr-util.h
index 90d79a5ef5..dc3f575bc9 100644
--- a/shared/systemd/src/basic/in-addr-util.h
+++ b/shared/systemd/src/basic/in-addr-util.h
@@ -41,6 +41,7 @@ int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen
int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret);
int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret);
+int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret);
int in_addr_from_string(int family, const char *s, union in_addr_union *ret);
int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret);
diff --git a/shared/systemd/src/basic/list.h b/shared/systemd/src/basic/list.h
index f7f97000e0..b62c374985 100644
--- a/shared/systemd/src/basic/list.h
+++ b/shared/systemd/src/basic/list.h
@@ -169,3 +169,18 @@
#define LIST_IS_EMPTY(head) \
(!(head))
+
+/* Join two lists tail to head: a->b, c->d to a->b->c->d and de-initialise second list */
+#define LIST_JOIN(name,a,b) \
+ do { \
+ assert(b); \
+ if (!(a)) \
+ (a) = (b); \
+ else { \
+ typeof(*(a)) *_head = (b), *_tail; \
+ LIST_FIND_TAIL(name, (a), _tail); \
+ _tail->name##_next = _head; \
+ _head->name##_prev = _tail; \
+ } \
+ (b) = NULL; \
+ } while (false)
diff --git a/shared/systemd/src/basic/log.h b/shared/systemd/src/basic/log.h
index 3725b08f80..9bc875af66 100644
--- a/shared/systemd/src/basic/log.h
+++ b/shared/systemd/src/basic/log.h
@@ -89,8 +89,11 @@ void log_close(void);
void log_forget_fds(void);
void log_parse_environment_realm(LogRealm realm);
+void log_parse_environment_cli_realm(LogRealm realm);
#define log_parse_environment() \
log_parse_environment_realm(LOG_REALM)
+#define log_parse_environment_cli() \
+ log_parse_environment_cli_realm(LOG_REALM)
#if 0 /* NM_IGNORED */
int log_dispatch_internal(
@@ -359,3 +362,4 @@ int log_syntax_invalid_utf8_internal(
#define DEBUG_LOGGING _unlikely_(log_get_max_level() >= LOG_DEBUG)
void log_setup_service(void);
+void log_setup_cli(void);
diff --git a/shared/systemd/src/basic/macro.h b/shared/systemd/src/basic/macro.h
index 0c2eb894c0..4c05389113 100644
--- a/shared/systemd/src/basic/macro.h
+++ b/shared/systemd/src/basic/macro.h
@@ -295,6 +295,15 @@ static inline size_t GREEDY_ALLOC_ROUND_UP(size_t l) {
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_MIN(_A, _B) \
+ (__builtin_choose_expr( \
+ __builtin_constant_p(_A) && \
+ __builtin_constant_p(_B) && \
+ __builtin_types_compatible_p(typeof(_A), typeof(_B)), \
+ ((_A) < (_B)) ? (_A) : (_B), \
+ VOID_0))
+
#define MIN3(x, y, z) \
({ \
const typeof(x) _c = MIN(x, y); \
@@ -538,6 +547,12 @@ static inline int __coverity_check_and_return__(int condition) {
(y) = (_t); \
} while (false)
+/* Iterates through a specified list of pointers. Accepts NULL pointers, but uses (void*) -1 as internal marker for EOL. */
+#define FOREACH_POINTER(p, x, ...) \
+ for (typeof(p) *_l = (typeof(p)[]) { ({ p = x; }), ##__VA_ARGS__, (void*) -1 }; \
+ p != (typeof(p)) (void*) -1; \
+ p = *(++_l))
+
/* Define C11 thread_local attribute even on older gcc compiler
* version */
#ifndef thread_local
diff --git a/shared/systemd/src/basic/memory-util.h b/shared/systemd/src/basic/memory-util.h
index a6a2ccdbc2..4f596cffb7 100644
--- a/shared/systemd/src/basic/memory-util.h
+++ b/shared/systemd/src/basic/memory-util.h
@@ -13,6 +13,7 @@
size_t page_size(void) _pure_;
#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
#define PAGE_ALIGN_DOWN(l) ((l) & ~(page_size() - 1))
+#define PAGE_OFFSET(l) ((l) & (page_size() - 1))
/* 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) {
diff --git a/shared/systemd/src/basic/path-util.c b/shared/systemd/src/basic/path-util.c
index 45477bc245..8f988fb231 100644
--- a/shared/systemd/src/basic/path-util.c
+++ b/shared/systemd/src/basic/path-util.c
@@ -649,10 +649,8 @@ int find_binary(const char *name, char **ret) {
if (access(j, X_OK) >= 0) {
/* Found it! */
- if (ret) {
- *ret = path_simplify(j, false);
- j = NULL;
- }
+ if (ret)
+ *ret = path_simplify(TAKE_PTR(j), false);
return 0;
}
diff --git a/shared/systemd/src/basic/process-util.h b/shared/systemd/src/basic/process-util.h
index 0501237790..314a8de17e 100644
--- a/shared/systemd/src/basic/process-util.h
+++ b/shared/systemd/src/basic/process-util.h
@@ -20,14 +20,16 @@
#define procfs_file_alloca(pid, field) \
({ \
pid_t _pid_ = (pid); \
- const char *_r_; \
+ const char *_field_ = (field); \
+ char *_r_; \
if (_pid_ == 0) { \
- _r_ = ("/proc/self/" field); \
+ _r_ = newa(char, STRLEN("/proc/self/") + strlen(_field_) + 1); \
+ strcpy(stpcpy(_r_, "/proc/self/"), _field_); \
} else { \
- _r_ = newa(char, STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
- sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \
+ _r_ = newa(char, STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + strlen(_field_) + 1); \
+ sprintf(_r_, "/proc/" PID_FMT "/%s", _pid_, _field_); \
} \
- _r_; \
+ (const char*) _r_; \
})
typedef enum ProcessCmdlineFlags {
diff --git a/shared/systemd/src/basic/random-util.c b/shared/systemd/src/basic/random-util.c
index e68262359d..463d2430d7 100644
--- a/shared/systemd/src/basic/random-util.c
+++ b/shared/systemd/src/basic/random-util.c
@@ -9,11 +9,13 @@
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
+#include <linux/random.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/ioctl.h>
#include <sys/time.h>
#if HAVE_SYS_AUXV_H
@@ -448,4 +450,37 @@ size_t random_pool_size(void) {
/* Use the minimum as default, if we can't retrieve the correct value */
return RANDOM_POOL_SIZE_MIN;
}
+
+int random_write_entropy(int fd, const void *seed, size_t size, bool credit) {
+ int r;
+
+ assert(fd >= 0);
+ assert(seed && size > 0);
+
+ if (credit) {
+ _cleanup_free_ struct rand_pool_info *info = NULL;
+
+ /* The kernel API only accepts "int" as entropy count (which is in bits), let's avoid any
+ * chance for confusion here. */
+ if (size > INT_MAX / 8)
+ return -EOVERFLOW;
+
+ info = malloc(offsetof(struct rand_pool_info, buf) + size);
+ if (!info)
+ return -ENOMEM;
+
+ info->entropy_count = size * 8;
+ info->buf_size = size;
+ memcpy(info->buf, seed, size);
+
+ if (ioctl(fd, RNDADDENTROPY, info) < 0)
+ return -errno;
+ } else {
+ r = loop_write(fd, seed, size, false);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
#endif /* NM_IGNORED */
diff --git a/shared/systemd/src/basic/random-util.h b/shared/systemd/src/basic/random-util.h
index d8e067d96e..7824ffaceb 100644
--- a/shared/systemd/src/basic/random-util.h
+++ b/shared/systemd/src/basic/random-util.h
@@ -38,3 +38,5 @@ int rdrand(unsigned long *ret);
#define RANDOM_POOL_SIZE_MAX (10U*1024U*1024U)
size_t random_pool_size(void);
+
+int random_write_entropy(int fd, const void *seed, size_t size, bool credit);
diff --git a/shared/systemd/src/basic/set.h b/shared/systemd/src/basic/set.h
index 621e83bf27..e4fc1e3c4a 100644
--- a/shared/systemd/src/basic/set.h
+++ b/shared/systemd/src/basic/set.h
@@ -26,9 +26,7 @@ static inline Set *set_free_free(Set *s) {
/* no set_free_free_free */
-static inline Set *set_copy(Set *s) {
- return (Set*) _hashmap_copy(HASHMAP_BASE(s));
-}
+#define set_copy(s) ((Set*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS))
int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
#define set_ensure_allocated(h, ops) _set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
@@ -120,9 +118,19 @@ static inline char **set_get_strv(Set *s) {
return _hashmap_get_strv(HASHMAP_BASE(s));
}
+int _set_ensure_put(Set **s, const struct hash_ops *hash_ops, const void *key HASHMAP_DEBUG_PARAMS);
+#define set_ensure_put(s, hash_ops, key) _set_ensure_put(s, hash_ops, key HASHMAP_DEBUG_SRC_ARGS)
+
+int _set_ensure_consume(Set **s, const struct hash_ops *hash_ops, void *key HASHMAP_DEBUG_PARAMS);
+#define set_ensure_consume(s, hash_ops, key) _set_ensure_consume(s, hash_ops, key HASHMAP_DEBUG_SRC_ARGS)
+
int set_consume(Set *s, void *value);
-int set_put_strdup(Set **s, const char *p);
-int set_put_strdupv(Set **s, char **l);
+
+int _set_put_strdup(Set **s, const char *p HASHMAP_DEBUG_PARAMS);
+#define set_put_strdup(s, p) _set_put_strdup(s, p HASHMAP_DEBUG_SRC_ARGS)
+int _set_put_strdupv(Set **s, char **l HASHMAP_DEBUG_PARAMS);
+#define set_put_strdupv(s, l) _set_put_strdupv(s, l HASHMAP_DEBUG_SRC_ARGS)
+
int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags);
#define SET_FOREACH(e, s, i) \
diff --git a/shared/systemd/src/basic/siphash24.h b/shared/systemd/src/basic/siphash24.h
index c4e919dfbc..b56c41a65d 100644
--- a/shared/systemd/src/basic/siphash24.h
+++ b/shared/systemd/src/basic/siphash24.h
@@ -47,9 +47,21 @@ siphash24 (const void *in, size_t inlen, const uint8_t k[16])
void siphash24_init(struct siphash *state, const uint8_t k[static 16]);
void siphash24_compress(const void *in, size_t inlen, struct siphash *state);
-void siphash24_compress_boolean(bool in, struct siphash *state);
#define siphash24_compress_byte(byte, state) siphash24_compress((const uint8_t[]) { (byte) }, 1, (state))
+static inline void siphash24_compress_boolean(bool in, struct siphash *state) {
+ uint8_t i = in;
+
+ siphash24_compress(&i, sizeof i, state);
+}
+
+static inline void siphash24_compress_string(const char *in, struct siphash *state) {
+ if (!in)
+ return;
+
+ siphash24_compress(in, strlen(in), state);
+}
+
uint64_t siphash24_finalize(struct siphash *state);
uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[static 16]);
diff --git a/shared/systemd/src/basic/socket-util.c b/shared/systemd/src/basic/socket-util.c
index cc592da870..755cdeb214 100644
--- a/shared/systemd/src/basic/socket-util.c
+++ b/shared/systemd/src/basic/socket-util.c
@@ -1081,6 +1081,7 @@ int sockaddr_un_unlink(const struct sockaddr_un *sa) {
return 1;
}
+#endif /* NM_IGNORED */
int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) {
size_t l;
@@ -1125,7 +1126,6 @@ int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) {
return (int) (offsetof(struct sockaddr_un, sun_path) + l + 1); /* include trailing NUL in size */
}
}
-#endif /* NM_IGNORED */
int socket_bind_to_ifname(int fd, const char *ifname) {
assert(fd >= 0);
@@ -1140,6 +1140,7 @@ int socket_bind_to_ifname(int fd, const char *ifname) {
int socket_bind_to_ifindex(int fd, int ifindex) {
char ifname[IF_NAMESIZE + 1];
+ int r;
assert(fd >= 0);
@@ -1151,10 +1152,9 @@ int socket_bind_to_ifindex(int fd, int ifindex) {
return 0;
}
- if (setsockopt(fd, SOL_SOCKET, SO_BINDTOIFINDEX, &ifindex, sizeof(ifindex)) >= 0)
- return 0;
- if (errno != ENOPROTOOPT)
- return -errno;
+ r = setsockopt_int(fd, SOL_SOCKET, SO_BINDTOIFINDEX, ifindex);
+ if (r != -ENOPROTOOPT)
+ return r;
/* Fall back to SO_BINDTODEVICE on kernels < 5.0 which didn't have SO_BINDTOIFINDEX */
if (!format_ifname(ifindex, ifname))
diff --git a/shared/systemd/src/basic/string-table.c b/shared/systemd/src/basic/string-table.c
index 14ae630804..46014b180c 100644
--- a/shared/systemd/src/basic/string-table.c
+++ b/shared/systemd/src/basic/string-table.c
@@ -6,12 +6,10 @@
#include "string-util.h"
ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) {
- size_t i;
-
if (!key)
return -1;
- for (i = 0; i < len; ++i)
+ for (size_t i = 0; i < len; ++i)
if (streq_ptr(table[i], key))
return (ssize_t) i;
diff --git a/shared/systemd/src/basic/time-util.c b/shared/systemd/src/basic/time-util.c
index 71af4f21f0..3979dd7cc3 100644
--- a/shared/systemd/src/basic/time-util.c
+++ b/shared/systemd/src/basic/time-util.c
@@ -84,43 +84,82 @@ triple_timestamp* triple_timestamp_get(triple_timestamp *ts) {
return ts;
}
+static usec_t map_clock_usec_internal(usec_t from, usec_t from_base, usec_t to_base) {
+
+ /* Maps the time 'from' between two clocks, based on a common reference point where the first clock
+ * is at 'from_base' and the second clock at 'to_base'. Basically calculates:
+ *
+ * from - from_base + to_base
+ *
+ * But takes care of overflows/underflows and avoids signed operations. */
+
+ if (from >= from_base) { /* In the future */
+ usec_t delta = from - from_base;
+
+ if (to_base >= USEC_INFINITY - delta) /* overflow? */
+ return USEC_INFINITY;
+
+ return to_base + delta;
+
+ } else { /* In the past */
+ usec_t delta = from_base - from;
+
+ if (to_base <= delta) /* underflow? */
+ return 0;
+
+ return to_base - delta;
+ }
+}
+
+usec_t map_clock_usec(usec_t from, clockid_t from_clock, clockid_t to_clock) {
+
+ /* Try to avoid any inaccuracy needlessly added in case we convert from effectively the same clock
+ * onto itself */
+ if (map_clock_id(from_clock) == map_clock_id(to_clock))
+ return from;
+
+ /* Keep infinity as is */
+ if (from == USEC_INFINITY)
+ return from;
+
+ return map_clock_usec_internal(from, now(from_clock), now(to_clock));
+}
+
dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
- int64_t delta;
assert(ts);
- if (u == USEC_INFINITY || u <= 0) {
+ if (u == USEC_INFINITY || u == 0) {
ts->realtime = ts->monotonic = u;
return ts;
}
ts->realtime = u;
-
- delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
- ts->monotonic = usec_sub_signed(now(CLOCK_MONOTONIC), delta);
-
+ ts->monotonic = map_clock_usec(u, CLOCK_REALTIME, CLOCK_MONOTONIC);
return ts;
}
triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u) {
- int64_t delta;
+ usec_t nowr;
assert(ts);
- if (u == USEC_INFINITY || u <= 0) {
+ if (u == USEC_INFINITY || u == 0) {
ts->realtime = ts->monotonic = ts->boottime = u;
return ts;
}
+ nowr = now(CLOCK_REALTIME);
+
ts->realtime = u;
- delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
- ts->monotonic = usec_sub_signed(now(CLOCK_MONOTONIC), delta);
- ts->boottime = clock_boottime_supported() ? usec_sub_signed(now(CLOCK_BOOTTIME), delta) : USEC_INFINITY;
+ ts->monotonic = map_clock_usec_internal(u, nowr, now(CLOCK_MONOTONIC));
+ ts->boottime = clock_boottime_supported() ?
+ map_clock_usec_internal(u, nowr, now(CLOCK_BOOTTIME)) :
+ USEC_INFINITY;
return ts;
}
dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) {
- int64_t delta;
assert(ts);
if (u == USEC_INFINITY) {
@@ -129,25 +168,28 @@ dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) {
}
ts->monotonic = u;
- delta = (int64_t) now(CLOCK_MONOTONIC) - (int64_t) u;
- ts->realtime = usec_sub_signed(now(CLOCK_REALTIME), delta);
-
+ ts->realtime = map_clock_usec(u, CLOCK_MONOTONIC, CLOCK_REALTIME);
return ts;
}
dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u) {
- int64_t delta;
+ clockid_t cid;
+ usec_t nowm;
if (u == USEC_INFINITY) {
ts->realtime = ts->monotonic = USEC_INFINITY;
return ts;
}
- dual_timestamp_get(ts);
- delta = (int64_t) now(clock_boottime_or_monotonic()) - (int64_t) u;
- ts->realtime = usec_sub_signed(ts->realtime, delta);
- ts->monotonic = usec_sub_signed(ts->monotonic, delta);
+ cid = clock_boottime_or_monotonic();
+ nowm = now(cid);
+
+ if (cid == CLOCK_MONOTONIC)
+ ts->monotonic = u;
+ else
+ ts->monotonic = map_clock_usec_internal(u, nowm, now(CLOCK_MONOTONIC));
+ ts->realtime = map_clock_usec_internal(u, nowm, now(CLOCK_REALTIME));
return ts;
}
diff --git a/shared/systemd/src/basic/time-util.h b/shared/systemd/src/basic/time-util.h
index 4c371257e3..9bbe986306 100644
--- a/shared/systemd/src/basic/time-util.h
+++ b/shared/systemd/src/basic/time-util.h
@@ -29,8 +29,8 @@ typedef struct triple_timestamp {
usec_t boottime;
} triple_timestamp;
-#define USEC_INFINITY ((usec_t) -1)
-#define NSEC_INFINITY ((nsec_t) -1)
+#define USEC_INFINITY ((usec_t) UINT64_MAX)
+#define NSEC_INFINITY ((nsec_t) UINT64_MAX)
#define MSEC_PER_SEC 1000ULL
#define USEC_PER_SEC ((usec_t) 1000000ULL)
@@ -67,6 +67,8 @@ typedef struct triple_timestamp {
usec_t now(clockid_t clock);
nsec_t now_nsec(clockid_t clock);
+usec_t map_clock_usec(usec_t from, clockid_t from_clock, clockid_t to_clock);
+
dual_timestamp* dual_timestamp_get(dual_timestamp *ts);
dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u);
dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u);
diff --git a/shared/systemd/src/basic/tmpfile-util.c b/shared/systemd/src/basic/tmpfile-util.c
index 8bbd12b015..9b3621bad9 100644
--- a/shared/systemd/src/basic/tmpfile-util.c
+++ b/shared/systemd/src/basic/tmpfile-util.c
@@ -262,7 +262,7 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
assert((flags & O_EXCL) == 0);
/* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in
- * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
+ * which case "ret_path" will be returned as NULL. If not possible the temporary path name used is returned in
* "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
fd = open_parent(target, O_TMPFILE|flags, 0640);
diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
index aed30d6118..66222eaddb 100644
--- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
@@ -82,6 +82,3 @@ int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const vo
int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease);
int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len);
-
-int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
-int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h
index b0d1216eed..9ce6dcd02c 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h
@@ -109,10 +109,11 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat
int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
struct in6_addr **addrs, size_t count,
size_t *allocated);
-int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen,
- char ***str_arr);
+int dhcp6_option_parse_domainname_list(const uint8_t *optval, uint16_t optlen,
+ char ***str_arr);
+int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char **str);
-int dhcp6_network_bind_udp_socket(int index, struct in6_addr *address);
+int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *address);
int dhcp6_network_send_udp_socket(int s, struct in6_addr *address,
const void *packet, size_t len);
diff --git a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
index e004f48b4e..df6c95e0b3 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
@@ -35,6 +35,7 @@ struct sd_dhcp6_lease {
size_t ntp_allocated;
char **ntp_fqdn;
size_t ntp_fqdn_count;
+ char *fqdn;
};
int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire);
@@ -57,5 +58,6 @@ int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval,
size_t optlen) ;
+int dhcp6_lease_set_fqdn(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen);
int dhcp6_lease_new(sd_dhcp6_lease **ret);
diff --git a/src/systemd/src/libsystemd-network/dhcp6-network.c b/src/systemd/src/libsystemd-network/dhcp6-network.c
index d43680a561..449ff6c4b0 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-network.c
@@ -19,16 +19,16 @@
#include "fd-util.h"
#include "socket-util.h"
-int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
+int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *local_address) {
union sockaddr_union src = {
.in6.sin6_family = AF_INET6,
.in6.sin6_port = htobe16(DHCP6_PORT_CLIENT),
- .in6.sin6_scope_id = index,
+ .in6.sin6_scope_id = ifindex,
};
_cleanup_close_ int s = -1;
int r;
- assert(index > 0);
+ assert(ifindex > 0);
assert(local_address);
src.in6.sin6_addr = *local_address;
diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c
index d596752b3b..a6dad93406 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-option.c
@@ -644,59 +644,103 @@ int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
return count;
}
-int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char ***str_arr) {
- size_t pos = 0, idx = 0;
- _cleanup_strv_free_ char **names = NULL;
+static int parse_domain(const uint8_t **data, uint16_t *len, char **out_domain) {
+ _cleanup_free_ char *ret = NULL;
+ size_t n = 0, allocated = 0;
+ const uint8_t *optval = *data;
+ uint16_t optlen = *len;
+ bool first = true;
int r;
- assert_return(optlen > 1, -ENODATA);
- assert_return(optval[optlen - 1] == '\0', -EINVAL);
-
- while (pos < optlen) {
- _cleanup_free_ char *ret = NULL;
- size_t n = 0, allocated = 0;
- bool first = true;
+ if (optlen <= 1)
+ return -ENODATA;
- for (;;) {
- const char *label;
- uint8_t c;
+ for (;;) {
+ const char *label;
+ uint8_t c;
- c = optval[pos++];
+ if (optlen == 0)
+ break;
- if (c == 0)
- /* End of name */
- break;
- if (c > 63)
- return -EBADMSG;
+ c = *optval;
+ optval++;
+ optlen--;
- /* Literal label */
- label = (const char *)&optval[pos];
- pos += c;
- if (pos >= optlen)
- return -EMSGSIZE;
+ if (c == 0)
+ /* End label */
+ break;
+ if (c > 63)
+ return -EBADMSG;
+ if (c > optlen)
+ return -EMSGSIZE;
- if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
- return -ENOMEM;
+ /* Literal label */
+ label = (const char *)optval;
+ optval += c;
+ optlen -= c;
- if (first)
- first = false;
- else
- ret[n++] = '.';
+ if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
+ return -ENOMEM;
- r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
- if (r < 0)
- return r;
+ if (first)
+ first = false;
+ else
+ ret[n++] = '.';
- n += r;
- }
+ r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
+ if (r < 0)
+ return r;
- if (n == 0)
- continue;
+ n += r;
+ }
+ if (n) {
if (!GREEDY_REALLOC(ret, allocated, n + 1))
return -ENOMEM;
-
ret[n] = 0;
+ }
+
+ *out_domain = TAKE_PTR(ret);
+ *data = optval;
+ *len = optlen;
+
+ return n;
+}
+
+int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char **str) {
+ _cleanup_free_ char *domain = NULL;
+ int r;
+
+ r = parse_domain(&optval, &optlen, &domain);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ENODATA;
+ if (optlen != 0)
+ return -EINVAL;
+
+ *str = TAKE_PTR(domain);
+ return 0;
+}
+
+int dhcp6_option_parse_domainname_list(const uint8_t *optval, uint16_t optlen, char ***str_arr) {
+ size_t idx = 0;
+ _cleanup_strv_free_ char **names = NULL;
+ int r;
+
+ if (optlen <= 1)
+ return -ENODATA;
+ if (optval[optlen - 1] != '\0')
+ return -EINVAL;
+
+ while (optlen > 0) {
+ _cleanup_free_ char *ret = NULL;
+
+ r = parse_domain(&optval, &optlen, &ret);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ continue;
r = strv_extend(&names, ret);
if (r < 0)
diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h
index 8e6377e0b0..1959474ee2 100644
--- a/src/systemd/src/libsystemd-network/network-internal.h
+++ b/src/systemd/src/libsystemd-network/network-internal.h
@@ -62,9 +62,13 @@ int deserialize_in6_addrs(struct in6_addr **addresses, const char *string);
/* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */
struct sd_dhcp_route;
+struct sd_dhcp_lease;
void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size);
int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string);
/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */
int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
+
+int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
+int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index 334cd6565b..806b83ae4f 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -1446,7 +1446,10 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata)
sd_dhcp_client *client = userdata;
DHCP_CLIENT_DONT_DESTROY(client);
- client->state = DHCP_STATE_RENEWING;
+ if (client->lease)
+ client->state = DHCP_STATE_RENEWING;
+ else if (client->state != DHCP_STATE_INIT)
+ client->state = DHCP_STATE_INIT_REBOOT;
client->attempt = 0;
return client_initialize_time_events(client);
@@ -2017,6 +2020,9 @@ int sd_dhcp_client_send_renew(sd_dhcp_client *client) {
assert_return(client, -EINVAL);
assert_return(client->fd >= 0, -EINVAL);
+ if (!client->lease)
+ return 0;
+
client->start_delay = 0;
client->attempt = 1;
client->state = DHCP_STATE_RENEWING;
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
index ae581f910c..d566f5eff0 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
@@ -1078,7 +1078,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
"ADDRESS", &address,
"ROUTER", &router,
"NETMASK", &netmask,
- "SERVER_IDENTIFIER", &server_address,
+ "SERVER_ADDRESS", &server_address,
"NEXT_SERVER", &next_server,
"BROADCAST", &broadcast,
"DNS", &dns,
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
index a68089261c..3e50422654 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
@@ -161,7 +161,7 @@ int sd_dhcp6_client_set_callback(
int sd_dhcp6_client_set_ifindex(sd_dhcp6_client *client, int ifindex) {
assert_return(client, -EINVAL);
- assert_return(ifindex >= -1, -EINVAL);
+ assert_return(ifindex > 0, -EINVAL);
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
client->ifindex = ifindex;
@@ -1288,6 +1288,13 @@ static int client_parse_message(
break;
+ case SD_DHCP6_OPTION_FQDN:
+ r = dhcp6_lease_set_fqdn(lease, optval, optlen);
+ if (r < 0)
+ return r;
+
+ break;
+
case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
if (optlen != 4)
return -EINVAL;
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
index b6dc027915..5f5a7fe616 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
@@ -238,7 +238,7 @@ int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
if (!optlen)
return 0;
- r = dhcp6_option_parse_domainname(optval, optlen, &domains);
+ r = dhcp6_option_parse_domainname_list(optval, optlen, &domains);
if (r < 0)
return 0;
@@ -296,8 +296,8 @@ int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
break;
case DHCP6_NTP_SUBOPTION_SRV_FQDN:
- r = dhcp6_option_parse_domainname(subval, sublen,
- &servers);
+ r = dhcp6_option_parse_domainname_list(subval, sublen,
+ &servers);
if (r < 0)
return 0;
@@ -367,6 +367,38 @@ int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) {
return -ENOENT;
}
+int dhcp6_lease_set_fqdn(sd_dhcp6_lease *lease, const uint8_t *optval,
+ size_t optlen) {
+ int r;
+ char *fqdn;
+
+ assert_return(lease, -EINVAL);
+ assert_return(optval, -EINVAL);
+
+ if (optlen < 2)
+ return -ENODATA;
+
+ /* Ignore the flags field, it doesn't carry any useful
+ information for clients. */
+ r = dhcp6_option_parse_domainname(optval + 1, optlen - 1, &fqdn);
+ if (r < 0)
+ return r;
+
+ return free_and_replace(lease->fqdn, fqdn);
+}
+
+int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease *lease, const char **fqdn) {
+ assert_return(lease, -EINVAL);
+ assert_return(fqdn, -EINVAL);
+
+ if (lease->fqdn) {
+ *fqdn = lease->fqdn;
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) {
assert(lease);
@@ -375,6 +407,7 @@ static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) {
dhcp6_lease_free_ia(&lease->pd);
free(lease->dns);
+ free(lease->fqdn);
lease->domains = strv_free(lease->domains);
diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c
index 3e56e80780..8b7691d0a6 100644
--- a/src/systemd/src/libsystemd/sd-event/sd-event.c
+++ b/src/systemd/src/libsystemd/sd-event/sd-event.c
@@ -1149,6 +1149,31 @@ _public_ int sd_event_add_time(
}
#if 0 /* NM_IGNORED */
+_public_ int sd_event_add_time_relative(
+ sd_event *e,
+ sd_event_source **ret,
+ clockid_t clock,
+ uint64_t usec,
+ uint64_t accuracy,
+ sd_event_time_handler_t callback,
+ void *userdata) {
+
+ usec_t t;
+ int r;
+
+ /* Same as sd_event_add_time() but operates relative to the event loop's current point in time, and
+ * checks for overflow. */
+
+ r = sd_event_now(e, clock, &t);
+ if (r < 0)
+ return r;
+
+ if (usec >= USEC_INFINITY - t)
+ return -EOVERFLOW;
+
+ return sd_event_add_time(e, ret, clock, t + usec, accuracy, callback, userdata);
+}
+
static int signal_exit_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
assert(s);
@@ -1454,10 +1479,6 @@ _public_ int sd_event_add_post(
assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
assert_return(!event_pid_changed(e), -ECHILD);
- r = set_ensure_allocated(&e->post_sources, NULL);
- if (r < 0)
- return r;
-
s = source_new(e, !ret, SOURCE_POST);
if (!s)
return -ENOMEM;
@@ -1466,9 +1487,10 @@ _public_ int sd_event_add_post(
s->userdata = userdata;
s->enabled = SD_EVENT_ON;
- r = set_put(e->post_sources, s);
+ r = set_ensure_put(&e->post_sources, NULL, s);
if (r < 0)
return r;
+ assert(r > 0);
if (ret)
*ret = s;
@@ -2409,6 +2431,23 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) {
return 0;
}
+_public_ int sd_event_source_set_time_relative(sd_event_source *s, uint64_t usec) {
+ usec_t t;
+ int r;
+
+ assert_return(s, -EINVAL);
+ assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM);
+
+ r = sd_event_now(s->event, event_source_type_to_clock(s->type), &t);
+ if (r < 0)
+ return r;
+
+ if (usec >= USEC_INFINITY - t)
+ return -EOVERFLOW;
+
+ return sd_event_source_set_time(s, t + usec);
+}
+
_public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) {
assert_return(s, -EINVAL);
assert_return(usec, -EINVAL);
diff --git a/src/systemd/src/systemd/sd-dhcp6-lease.h b/src/systemd/src/systemd/sd-dhcp6-lease.h
index 4301c6db87..240df74af8 100644
--- a/src/systemd/src/systemd/sd-dhcp6-lease.h
+++ b/src/systemd/src/systemd/sd-dhcp6-lease.h
@@ -43,6 +43,7 @@ int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, const struct in6_addr **addrs)
int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains);
int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, const struct in6_addr **addrs);
int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn);
+int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease *lease, const char **fqdn);
sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease);
sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease);
diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h
index 2ec726a897..dc96bfa681 100644
--- a/src/systemd/src/systemd/sd-event.h
+++ b/src/systemd/src/systemd/sd-event.h
@@ -88,6 +88,7 @@ sd_event* sd_event_unref(sd_event *e);
int sd_event_add_io(sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata);
int sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata);
+int sd_event_add_time_relative(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata);
int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata);
int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata);
int sd_event_add_child_pidfd(sd_event *e, sd_event_source **s, int pidfd, int options, sd_event_child_handler_t callback, void *userdata);
@@ -138,6 +139,7 @@ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events);
int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents);
int sd_event_source_get_time(sd_event_source *s, uint64_t *usec);
int sd_event_source_set_time(sd_event_source *s, uint64_t usec);
+int sd_event_source_set_time_relative(sd_event_source *s, uint64_t usec);
int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec);
int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec);
int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock);