summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-10-04 00:19:48 +0200
committerThomas Haller <thaller@redhat.com>2018-10-05 00:20:48 +0200
commit56cc16cdf7013468e6ee2371712d3c34e6e52dcd (patch)
treef3956e86397cf9d498d7afd31db3b55fde554e1c
parentf699fc644d8aa7f8f05cb7253e1e519f76cacf53 (diff)
systemd: update code from upstream (2018-10-04)
This is a direct dump from systemd git. ====== SYSTEMD_DIR=../systemd COMMIT=b62f9008668a5330c61b4de7e0d48147bcd1edf7 ( 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"
-rw-r--r--src/systemd/src/basic/env-util.c4
-rw-r--r--src/systemd/src/basic/fd-util.c2
-rw-r--r--src/systemd/src/basic/fileio.c6
-rw-r--r--src/systemd/src/basic/fs-util.c70
-rw-r--r--src/systemd/src/basic/fs-util.h2
-rw-r--r--src/systemd/src/basic/hashmap.h2
-rw-r--r--src/systemd/src/basic/hexdecoct.c10
-rw-r--r--src/systemd/src/basic/macro.h49
-rw-r--r--src/systemd/src/basic/parse-util.c2
-rw-r--r--src/systemd/src/basic/path-util.c2
-rw-r--r--src/systemd/src/basic/process-util.c8
-rw-r--r--src/systemd/src/basic/process-util.h2
-rw-r--r--src/systemd/src/basic/refcnt.h38
-rw-r--r--src/systemd/src/basic/socket-util.c8
-rw-r--r--src/systemd/src/basic/sparse-endian.h5
-rw-r--r--src/systemd/src/basic/string-table.h2
-rw-r--r--src/systemd/src/basic/string-util.c28
-rw-r--r--src/systemd/src/basic/string-util.h23
-rw-r--r--src/systemd/src/basic/strv.c16
-rw-r--r--src/systemd/src/basic/strv.h5
-rw-r--r--src/systemd/src/basic/time-util.c2
-rw-r--r--src/systemd/src/basic/utf8.c123
-rw-r--r--src/systemd/src/basic/utf8.h15
-rw-r--r--src/systemd/src/basic/util.c2
-rw-r--r--src/systemd/src/basic/util.h29
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.c7
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-network.c2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-internal.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-lease-internal.h2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-option.c13
-rw-r--r--src/systemd/src/libsystemd-network/lldp-neighbor.c5
-rw-r--r--src/systemd/src/libsystemd-network/lldp-neighbor.h1
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c31
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-lease.c30
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-client.c211
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-lease.c45
-rw-r--r--src/systemd/src/libsystemd-network/sd-ipv4acd.c23
-rw-r--r--src/systemd/src/libsystemd-network/sd-ipv4ll.c23
-rw-r--r--src/systemd/src/libsystemd-network/sd-lldp.c35
-rw-r--r--src/systemd/src/libsystemd/sd-event/sd-event.c167
-rw-r--r--src/systemd/src/libsystemd/sd-id128/sd-id128.c38
-rw-r--r--src/systemd/src/shared/dns-domain.c2
-rw-r--r--src/systemd/src/systemd/sd-dhcp6-client.h10
-rw-r--r--src/systemd/src/systemd/sd-id128.h1
44 files changed, 645 insertions, 460 deletions
diff --git a/src/systemd/src/basic/env-util.c b/src/systemd/src/basic/env-util.c
index a784a30e1..3b8130b03 100644
--- a/src/systemd/src/basic/env-util.c
+++ b/src/systemd/src/basic/env-util.c
@@ -114,7 +114,7 @@ bool strv_env_is_valid(char **e) {
if (!env_assignment_is_valid(*p))
return false;
- /* Check if there are duplicate assginments */
+ /* Check if there are duplicate assignments */
k = strcspn(*p, "=");
STRV_FOREACH(q, p + 1)
if (strneq(*p, *q, k) && (*q)[k] == '=')
@@ -388,7 +388,7 @@ int strv_env_replace(char ***l, char *p) {
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.
+ * string list. Drop other occurrences. Edits in-place. Does not copy p.
* p must be a valid key=value assignment.
*/
diff --git a/src/systemd/src/basic/fd-util.c b/src/systemd/src/basic/fd-util.c
index e085dc23b..b97bd191a 100644
--- a/src/systemd/src/basic/fd-util.c
+++ b/src/systemd/src/basic/fd-util.c
@@ -277,7 +277,7 @@ int same_fd(int a, int b) {
return true;
if (r > 0)
return false;
- if (errno != ENOSYS)
+ if (!IN_SET(errno, ENOSYS, EACCES, EPERM))
return -errno;
/* We don't have kcmp(), use fstat() instead. */
diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c
index ea607f8cf..d2fd4c47b 100644
--- a/src/systemd/src/basic/fileio.c
+++ b/src/systemd/src/basic/fileio.c
@@ -1492,6 +1492,7 @@ int open_serialization_fd(const char *ident) {
}
int link_tmpfile(int fd, const char *path, const char *target) {
+ int r;
assert(fd >= 0);
assert(target);
@@ -1504,8 +1505,9 @@ int link_tmpfile(int fd, const char *path, const char *target) {
* operation currently (renameat2() does), and there is no nice way to emulate this. */
if (path) {
- if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0)
- return -errno;
+ r = rename_noreplace(AT_FDCWD, path, AT_FDCWD, target);
+ if (r < 0)
+ return r;
} else {
char proc_fd_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c
index 09fcc32e0..3d83fc9b1 100644
--- a/src/systemd/src/basic/fs-util.c
+++ b/src/systemd/src/basic/fs-util.c
@@ -89,41 +89,44 @@ int rmdir_parents(const char *path, const char *stop) {
}
int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
- struct stat buf;
- int ret;
+ int r;
- ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
- if (ret >= 0)
+ /* Try the ideal approach first */
+ if (renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE) >= 0)
return 0;
- /* renameat2() exists since Linux 3.15, btrfs added support for it later.
- * If it is not implemented, fallback to another method. */
- if (!IN_SET(errno, EINVAL, ENOSYS))
+ /* renameat2() exists since Linux 3.15, btrfs and FAT added support for it later. If it is not implemented,
+ * fall back to a different method. */
+ if (!IN_SET(errno, EINVAL, ENOSYS, ENOTTY))
return -errno;
- /* The link()/unlink() fallback does not work on directories. But
- * renameat() without RENAME_NOREPLACE gives the same semantics on
- * directories, except when newpath is an *empty* directory. This is
- * good enough. */
- ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
- if (ret >= 0 && S_ISDIR(buf.st_mode)) {
- ret = renameat(olddirfd, oldpath, newdirfd, newpath);
- return ret >= 0 ? 0 : -errno;
+ /* Let's try to use linkat()+unlinkat() as fallback. This doesn't work on directories and on some file systems
+ * that do not support hard links (such as FAT, most prominently), but for files it's pretty close to what we
+ * want — though not atomic (i.e. for a short period both the new and the old filename will exist). */
+ if (linkat(olddirfd, oldpath, newdirfd, newpath, 0) >= 0) {
+
+ if (unlinkat(olddirfd, oldpath, 0) < 0) {
+ r = -errno; /* Backup errno before the following unlinkat() alters it */
+ (void) unlinkat(newdirfd, newpath, 0);
+ return r;
+ }
+
+ return 0;
}
- /* If it is not a directory, use the link()/unlink() fallback. */
- ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
- if (ret < 0)
+ if (!IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM)) /* FAT returns EPERM on link()… */
return -errno;
- ret = unlinkat(olddirfd, oldpath, 0);
- if (ret < 0) {
- /* backup errno before the following unlinkat() alters it */
- ret = errno;
- (void) unlinkat(newdirfd, newpath, 0);
- errno = ret;
+ /* OK, neither RENAME_NOREPLACE nor linkat()+unlinkat() worked. Let's then fallback to the racy TOCTOU
+ * vulnerable accessat(F_OK) check followed by classic, replacing renameat(), we have nothing better. */
+
+ if (faccessat(newdirfd, newpath, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ return -EEXIST;
+ if (errno != ENOENT)
+ return -errno;
+
+ if (renameat(olddirfd, oldpath, newdirfd, newpath) < 0)
return -errno;
- }
return 0;
}
@@ -346,12 +349,27 @@ int touch(const char *path) {
return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
}
-int symlink_idempotent(const char *from, const char *to) {
+int symlink_idempotent(const char *from, const char *to, bool make_relative) {
+ _cleanup_free_ char *relpath = NULL;
int r;
assert(from);
assert(to);
+ if (make_relative) {
+ _cleanup_free_ char *parent = NULL;
+
+ parent = dirname_malloc(to);
+ if (!parent)
+ return -ENOMEM;
+
+ r = path_make_relative(parent, from, &relpath);
+ if (r < 0)
+ return r;
+
+ from = relpath;
+ }
+
if (symlink(from, to) < 0) {
_cleanup_free_ char *p = NULL;
diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h
index 4b6562586..bc753d592 100644
--- a/src/systemd/src/basic/fs-util.h
+++ b/src/systemd/src/basic/fs-util.h
@@ -37,7 +37,7 @@ int fd_warn_permissions(const char *path, int fd);
int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode);
int touch(const char *path);
-int symlink_idempotent(const char *from, const char *to);
+int symlink_idempotent(const char *from, const char *to, bool make_relative);
int symlink_atomic(const char *from, const char *to);
int mknod_atomic(const char *path, mode_t mode, dev_t dev);
diff --git a/src/systemd/src/basic/hashmap.h b/src/systemd/src/basic/hashmap.h
index 274afb395..b771ceccd 100644
--- a/src/systemd/src/basic/hashmap.h
+++ b/src/systemd/src/basic/hashmap.h
@@ -15,7 +15,7 @@
* necessary to instantiate an object for each Hashmap use.
*
* If ENABLE_DEBUG_HASHMAP is defined (by configuring with --enable-debug=hashmap),
- * the implemention will:
+ * the implementation will:
* - store extra data for debugging and statistics (see tools/gdb-sd_dump_hashmaps.py)
* - perform extra checks for invalid use of iterators
*/
diff --git a/src/systemd/src/basic/hexdecoct.c b/src/systemd/src/basic/hexdecoct.c
index 7748e8352..c0f96409f 100644
--- a/src/systemd/src/basic/hexdecoct.c
+++ b/src/systemd/src/basic/hexdecoct.c
@@ -79,7 +79,7 @@ static int unhex_next(const char **p, size_t *l) {
assert(l);
/* Find the next non-whitespace character, and decode it. We
- * greedily skip all preceeding and all following whitespace. */
+ * greedily skip all preceding and all following whitespace. */
for (;;) {
if (*l == 0)
@@ -592,8 +592,7 @@ static int base64_append_width(
_cleanup_free_ char *x = NULL;
char *t, *s;
- ssize_t slen, len, avail;
- int line, lines;
+ ssize_t len, slen, avail, line, lines;
len = base64mem(p, l, &x);
if (len <= 0)
@@ -602,6 +601,9 @@ static int base64_append_width(
lines = DIV_ROUND_UP(len, width);
slen = strlen_ptr(sep);
+ if (lines > (SSIZE_MAX - plen - 1 - slen) / (indent + width + 1))
+ return -ENOMEM;
+
t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
if (!t)
return -ENOMEM;
@@ -647,7 +649,7 @@ static int unbase64_next(const char **p, size_t *l) {
assert(l);
/* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We
- * greedily skip all preceeding and all following whitespace. */
+ * greedily skip all preceding and all following whitespace. */
for (;;) {
if (*l == 0)
diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h
index 24fcdc840..9972b6f99 100644
--- a/src/systemd/src/basic/macro.h
+++ b/src/systemd/src/basic/macro.h
@@ -464,4 +464,53 @@ static inline int __coverity_check__(int condition) {
func(*p); \
}
+#define _DEFINE_TRIVIAL_REF_FUNC(type, name, scope) \
+ scope type *name##_ref(type *p) { \
+ if (!p) \
+ return NULL; \
+ \
+ assert(p->n_ref > 0); \
+ p->n_ref++; \
+ return p; \
+ }
+
+#define _DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func, scope) \
+ scope type *name##_unref(type *p) { \
+ if (!p) \
+ return NULL; \
+ \
+ assert(p->n_ref > 0); \
+ p->n_ref--; \
+ if (p->n_ref > 0) \
+ return NULL; \
+ \
+ return free_func(p); \
+ }
+
+#define DEFINE_TRIVIAL_REF_FUNC(type, name) \
+ _DEFINE_TRIVIAL_REF_FUNC(type, name,)
+#define DEFINE_PRIVATE_TRIVIAL_REF_FUNC(type, name) \
+ _DEFINE_TRIVIAL_REF_FUNC(type, name, static)
+#define DEFINE_PUBLIC_TRIVIAL_REF_FUNC(type, name) \
+ _DEFINE_TRIVIAL_REF_FUNC(type, name, _public_)
+
+#define DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func) \
+ _DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func,)
+#define DEFINE_PRIVATE_TRIVIAL_UNREF_FUNC(type, name, free_func) \
+ _DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func, static)
+#define DEFINE_PUBLIC_TRIVIAL_UNREF_FUNC(type, name, free_func) \
+ _DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func, _public_)
+
+#define DEFINE_TRIVIAL_REF_UNREF_FUNC(type, name, free_func) \
+ DEFINE_TRIVIAL_REF_FUNC(type, name); \
+ DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func);
+
+#define DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(type, name, free_func) \
+ DEFINE_PRIVATE_TRIVIAL_REF_FUNC(type, name); \
+ DEFINE_PRIVATE_TRIVIAL_UNREF_FUNC(type, name, free_func);
+
+#define DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(type, name, free_func) \
+ DEFINE_PUBLIC_TRIVIAL_REF_FUNC(type, name); \
+ DEFINE_PUBLIC_TRIVIAL_UNREF_FUNC(type, name, free_func);
+
#include "log.h"
diff --git a/src/systemd/src/basic/parse-util.c b/src/systemd/src/basic/parse-util.c
index db38f91c8..a9085348b 100644
--- a/src/systemd/src/basic/parse-util.c
+++ b/src/systemd/src/basic/parse-util.c
@@ -570,7 +570,7 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
s = *p;
- /* accept any number of digits, strtoull is limted to 19 */
+ /* accept any number of digits, strtoull is limited to 19 */
for (i=0; i < digits; i++,s++) {
if (*s < '0' || *s > '9') {
if (i == 0)
diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c
index b62786f27..f3c6c16aa 100644
--- a/src/systemd/src/basic/path-util.c
+++ b/src/systemd/src/basic/path-util.c
@@ -425,7 +425,7 @@ int path_compare(const char *a, const char *b) {
assert(a);
assert(b);
- /* A relative path and an abolute path must not compare as equal.
+ /* A relative path and an absolute path must not compare as equal.
* Which one is sorted before the other does not really matter.
* Here a relative path is ordered before an absolute path. */
d = (a[0] == '/') - (b[0] == '/');
diff --git a/src/systemd/src/basic/process-util.c b/src/systemd/src/basic/process-util.c
index d6ee8b62b..1098cf453 100644
--- a/src/systemd/src/basic/process-util.c
+++ b/src/systemd/src/basic/process-util.c
@@ -425,7 +425,7 @@ int is_kernel_thread(pid_t pid) {
q += l;
}
- /* Skip preceeding whitespace */
+ /* Skip preceding whitespace */
l = strspn(q, WHITESPACE);
if (l < 1)
return -EINVAL;
@@ -1104,11 +1104,9 @@ void valgrind_summary_hack(void) {
#endif
}
-int pid_compare_func(const void *a, const void *b) {
- const pid_t *p = a, *q = b;
-
+int pid_compare_func(const pid_t *a, const pid_t *b) {
/* Suitable for usage in qsort() */
- return CMP(*p, *q);
+ return CMP(*a, *b);
}
int ioprio_parse_priority(const char *s, int *ret) {
diff --git a/src/systemd/src/basic/process-util.h b/src/systemd/src/basic/process-util.h
index a5bb072b2..7ef45dc92 100644
--- a/src/systemd/src/basic/process-util.h
+++ b/src/systemd/src/basic/process-util.h
@@ -108,7 +108,7 @@ static inline void* PID_TO_PTR(pid_t pid) {
void valgrind_summary_hack(void);
-int pid_compare_func(const void *a, const void *b);
+int pid_compare_func(const pid_t *a, const pid_t *b);
static inline bool nice_is_valid(int n) {
return n >= PRIO_MIN && n < PRIO_MAX;
diff --git a/src/systemd/src/basic/refcnt.h b/src/systemd/src/basic/refcnt.h
index d2be6086d..40f9a84a2 100644
--- a/src/systemd/src/basic/refcnt.h
+++ b/src/systemd/src/basic/refcnt.h
@@ -14,3 +14,41 @@ typedef struct {
#define REFCNT_DEC(r) (__sync_sub_and_fetch(&(r)._value, 1))
#define REFCNT_INIT ((RefCount) { ._value = 1 })
+
+#define _DEFINE_ATOMIC_REF_FUNC(type, name, scope) \
+ scope type *name##_ref(type *p) { \
+ if (!p) \
+ return NULL; \
+ \
+ assert_se(REFCNT_INC(p->n_ref) >= 2); \
+ return p; \
+ }
+
+#define _DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func, scope) \
+ scope type *name##_unref(type *p) { \
+ if (!p) \
+ return NULL; \
+ \
+ if (REFCNT_DEC(p->n_ref) > 0) \
+ return NULL; \
+ \
+ return free_func(p); \
+ }
+
+#define DEFINE_ATOMIC_REF_FUNC(type, name) \
+ _DEFINE_ATOMIC_REF_FUNC(type, name,)
+#define DEFINE_PUBLIC_ATOMIC_REF_FUNC(type, name) \
+ _DEFINE_ATOMIC_REF_FUNC(type, name, _public_)
+
+#define DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func) \
+ _DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func,)
+#define DEFINE_PUBLIC_ATOMIC_UNREF_FUNC(type, name, free_func) \
+ _DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func, _public_)
+
+#define DEFINE_ATOMIC_REF_UNREF_FUNC(type, name, free_func) \
+ DEFINE_ATOMIC_REF_FUNC(type, name); \
+ DEFINE_ATOMIC_UNREF_FUNC(type, name, free_func);
+
+#define DEFINE_PUBLIC_ATOMIC_REF_UNREF_FUNC(type, name, free_func) \
+ DEFINE_PUBLIC_ATOMIC_REF_FUNC(type, name); \
+ DEFINE_PUBLIC_ATOMIC_UNREF_FUNC(type, name, free_func);
diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c
index 986bc6e67..4e8b2baf8 100644
--- a/src/systemd/src/basic/socket-util.c
+++ b/src/systemd/src/basic/socket-util.c
@@ -835,8 +835,8 @@ int fd_inc_sndbuf(int fd, size_t n) {
/* If we have the privileges we will ignore the kernel limit. */
value = (int) n;
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
return -errno;
return 1;
@@ -853,8 +853,8 @@ int fd_inc_rcvbuf(int fd, size_t n) {
/* If we have the privileges we will ignore the kernel limit. */
value = (int) n;
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
return -errno;
return 1;
}
diff --git a/src/systemd/src/basic/sparse-endian.h b/src/systemd/src/basic/sparse-endian.h
index 5e59de543..8540ccd0b 100644
--- a/src/systemd/src/basic/sparse-endian.h
+++ b/src/systemd/src/basic/sparse-endian.h
@@ -20,8 +20,7 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
-#ifndef SPARSE_ENDIAN_H
-#define SPARSE_ENDIAN_H
+#pragma once
#include <byteswap.h>
#include <endian.h>
@@ -89,5 +88,3 @@ static inline uint64_t be64toh(be64_t value) { return bswap_64_on_le((uint64_t _
#undef __sd_bitwise
#undef __sd_force
-
-#endif /* SPARSE_ENDIAN_H */
diff --git a/src/systemd/src/basic/string-table.h b/src/systemd/src/basic/string-table.h
index 9bd787935..228c12ad0 100644
--- a/src/systemd/src/basic/string-table.h
+++ b/src/systemd/src/basic/string-table.h
@@ -58,7 +58,7 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
}
#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,scope) \
- type name##_from_string(const char *s) { \
+ scope type name##_from_string(const char *s) { \
type i; \
unsigned u = 0; \
if (!s) \
diff --git a/src/systemd/src/basic/string-util.c b/src/systemd/src/basic/string-util.c
index 0a4068349..dfa739996 100644
--- a/src/systemd/src/basic/string-util.c
+++ b/src/systemd/src/basic/string-util.c
@@ -1004,7 +1004,7 @@ int free_and_strdup(char **p, const char *s) {
assert(p);
- /* Replaces a string pointer with an strdup()ed new string,
+ /* Replaces a string pointer with a strdup()ed new string,
* possibly freeing the old one. */
if (streq_ptr(*p, s))
@@ -1023,6 +1023,32 @@ int free_and_strdup(char **p, const char *s) {
return 1;
}
+int free_and_strndup(char **p, const char *s, size_t l) {
+ char *t;
+
+ assert(p);
+ assert(s || l == 0);
+
+ /* Replaces a string pointer with a strndup()ed new string,
+ * freeing the old one. */
+
+ if (!*p && !s)
+ return 0;
+
+ if (*p && s && strneq(*p, s, l) && (l > strlen(*p) || (*p)[l] == '\0'))
+ return 0;
+
+ if (s) {
+ t = strndup(s, l);
+ if (!t)
+ return -ENOMEM;
+ } else
+ t = NULL;
+
+ free_and_replace(*p, t);
+ return 1;
+}
+
#if !HAVE_EXPLICIT_BZERO
/*
* Pointer to memset is volatile so that compiler must de-reference
diff --git a/src/systemd/src/basic/string-util.h b/src/systemd/src/basic/string-util.h
index c0cc4e78d..72c075aa3 100644
--- a/src/systemd/src/basic/string-util.h
+++ b/src/systemd/src/basic/string-util.h
@@ -176,6 +176,7 @@ char *strrep(const char *s, unsigned n);
int split_pair(const char *s, const char *sep, char **l, char **r);
int free_and_strdup(char **p, const char *s);
+int free_and_strndup(char **p, const char *s, size_t l);
/* Normal memmem() requires haystack to be nonnull, which is annoying for zero-length buffers */
static inline void *memmem_safe(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) {
@@ -228,3 +229,25 @@ static inline void *memory_startswith(const void *p, size_t sz, const char *toke
return (uint8_t*) p + n;
}
+
+/* Like startswith_no_case(), but operates on arbitrary memory blocks.
+ * It works only for ASCII strings.
+ */
+static inline void *memory_startswith_no_case(const void *p, size_t sz, const char *token) {
+ size_t n, i;
+
+ assert(token);
+
+ n = strlen(token);
+ if (sz < n)
+ return NULL;
+
+ assert(p);
+
+ for (i = 0; i < n; i++) {
+ if (ascii_tolower(((char *)p)[i]) != ascii_tolower(token[i]))
+ return NULL;
+ }
+
+ return (uint8_t*) p + n;
+}
diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c
index abf3fc4c7..dc72f036a 100644
--- a/src/systemd/src/basic/strv.c
+++ b/src/systemd/src/basic/strv.c
@@ -339,21 +339,22 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
return (int) n;
}
-char *strv_join(char **l, const char *separator) {
+char *strv_join_prefix(char **l, const char *separator, const char *prefix) {
char *r, *e;
char **s;
- size_t n, k;
+ size_t n, k, m;
if (!separator)
separator = " ";
k = strlen(separator);
+ m = strlen_ptr(prefix);
n = 0;
STRV_FOREACH(s, l) {
if (s != l)
n += k;
- n += strlen(*s);
+ n += m + strlen(*s);
}
r = new(char, n+1);
@@ -365,6 +366,9 @@ char *strv_join(char **l, const char *separator) {
if (s != l)
e = stpcpy(e, separator);
+ if (prefix)
+ e = stpcpy(e, prefix);
+
e = stpcpy(e, *s);
}
@@ -711,14 +715,12 @@ bool strv_overlap(char **a, char **b) {
return false;
}
-static int str_compare(const void *_a, const void *_b) {
- const char **a = (const char**) _a, **b = (const char**) _b;
-
+static int str_compare(char * const *a, char * const *b) {
return strcmp(*a, *b);
}
char **strv_sort(char **l) {
- qsort_safe(l, strv_length(l), sizeof(char*), str_compare);
+ typesafe_qsort(l, strv_length(l), str_compare);
return l;
}
diff --git a/src/systemd/src/basic/strv.h b/src/systemd/src/basic/strv.h
index 51d03db94..34a660cb9 100644
--- a/src/systemd/src/basic/strv.h
+++ b/src/systemd/src/basic/strv.h
@@ -71,7 +71,10 @@ char **strv_split_newlines(const char *s);
int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
-char *strv_join(char **l, const char *separator);
+char *strv_join_prefix(char **l, const char *separator, const char *prefix);
+static inline char *strv_join(char **l, const char *separator) {
+ return strv_join_prefix(l, separator, NULL);
+}
char **strv_parse_nulstr(const char *s, size_t l);
char **strv_split_nulstr(const char *s);
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index 81d3f3f38..9ac739b42 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -905,7 +905,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
* Otherwise just cut it off. */
with_tz = !STR_IN_SET(tz, tzname[0], tzname[1]);
- /* Cut off the timezone if we dont need it. */
+ /* Cut off the timezone if we don't need it. */
if (with_tz)
t = strndupa(t, last_space - t);
diff --git a/src/systemd/src/basic/utf8.c b/src/systemd/src/basic/utf8.c
index a5ce1a294..e0d1949dc 100644
--- a/src/systemd/src/basic/utf8.c
+++ b/src/systemd/src/basic/utf8.c
@@ -61,12 +61,12 @@ static bool unichar_is_control(char32_t ch) {
}
/* count of characters used to encode one unicode char */
-static int utf8_encoded_expected_len(const char *str) {
- unsigned char c;
+static size_t utf8_encoded_expected_len(const char *str) {
+ uint8_t c;
assert(str);
- c = (unsigned char) str[0];
+ c = (uint8_t) str[0];
if (c < 0x80)
return 1;
if ((c & 0xe0) == 0xc0)
@@ -86,7 +86,7 @@ static int utf8_encoded_expected_len(const char *str) {
/* decode one unicode char */
int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) {
char32_t unichar;
- int len, i;
+ size_t len, i;
assert(str);
@@ -118,6 +118,7 @@ int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) {
for (i = 1; i < len; i++) {
if (((char32_t)str[i] & 0xc0) != 0x80)
return -EINVAL;
+
unichar <<= 6;
unichar |= (char32_t)str[i] & 0x3f;
}
@@ -154,22 +155,23 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
return true;
}
-const char *utf8_is_valid(const char *str) {
- const uint8_t *p;
+char *utf8_is_valid(const char *str) {
+ const char *p;
assert(str);
- for (p = (const uint8_t*) str; *p; ) {
+ p = str;
+ while (*p) {
int len;
- len = utf8_encoded_valid_unichar((const char *)p);
+ len = utf8_encoded_valid_unichar(p);
if (len < 0)
return NULL;
p += len;
}
- return str;
+ return (char*) str;
}
char *utf8_escape_invalid(const char *str) {
@@ -312,18 +314,25 @@ size_t utf8_encode_unichar(char *out_utf8, char32_t g) {
return 0;
}
-char *utf16_to_utf8(const void *s, size_t length) {
+char *utf16_to_utf8(const char16_t *s, size_t length /* bytes! */) {
const uint8_t *f;
char *r, *t;
- r = new(char, (length * 4 + 1) / 2 + 1);
+ assert(s);
+
+ /* Input length is in bytes, i.e. the shortest possible character takes 2 bytes. Each unicode character may
+ * take up to 4 bytes in UTF-8. Let's also account for a trailing NUL byte. */
+ if (length * 2 < length)
+ return NULL; /* overflow */
+
+ r = new(char, length * 2 + 1);
if (!r)
return NULL;
- f = s;
+ f = (const uint8_t*) s;
t = r;
- while (f < (const uint8_t*) s + length) {
+ while (f + 1 < (const uint8_t*) s + length) {
char16_t w1, w2;
/* see RFC 2781 section 2.2 */
@@ -333,13 +342,13 @@ char *utf16_to_utf8(const void *s, size_t length) {
if (!utf16_is_surrogate(w1)) {
t += utf8_encode_unichar(t, w1);
-
continue;
}
if (utf16_is_trailing_surrogate(w1))
- continue;
- else if (f >= (const uint8_t*) s + length)
+ continue; /* spurious trailing surrogate, ignore */
+
+ if (f + 1 >= (const uint8_t*) s + length)
break;
w2 = f[1] << 8 | f[0];
@@ -347,7 +356,7 @@ char *utf16_to_utf8(const void *s, size_t length) {
if (!utf16_is_trailing_surrogate(w2)) {
f -= 2;
- continue;
+ continue; /* surrogate missing its trailing surrogate, ignore */
}
t += utf8_encode_unichar(t, utf16_surrogate_pair_to_unichar(w1, w2));
@@ -357,6 +366,79 @@ char *utf16_to_utf8(const void *s, size_t length) {
return r;
}
+size_t utf16_encode_unichar(char16_t *out, char32_t c) {
+
+ /* Note that this encodes as little-endian. */
+
+ switch (c) {
+
+ case 0 ... 0xd7ffU:
+ case 0xe000U ... 0xffffU:
+ out[0] = htole16(c);
+ return 1;
+
+ case 0x10000U ... 0x10ffffU:
+ c -= 0x10000U;
+ out[0] = htole16((c >> 10) + 0xd800U);
+ out[1] = htole16((c & 0x3ffU) + 0xdc00U);
+ return 2;
+
+ default: /* A surrogate (invalid) */
+ return 0;
+ }
+}
+
+char16_t *utf8_to_utf16(const char *s, size_t length) {
+ char16_t *n, *p;
+ size_t i;
+ int r;
+
+ assert(s);
+
+ n = new(char16_t, length + 1);
+ if (!n)
+ return NULL;
+
+ p = n;
+
+ for (i = 0; i < length;) {
+ char32_t unichar;
+ size_t e;
+
+ e = utf8_encoded_expected_len(s + i);
+ if (e <= 1) /* Invalid and single byte characters are copied as they are */
+ goto copy;
+
+ if (i + e > length) /* sequence longer than input buffer, then copy as-is */
+ goto copy;
+
+ r = utf8_encoded_to_unichar(s + i, &unichar);
+ if (r < 0) /* sequence invalid, then copy as-is */
+ goto copy;
+
+ p += utf16_encode_unichar(p, unichar);
+ i += e;
+ continue;
+
+ copy:
+ *(p++) = htole16(s[i++]);
+ }
+
+ *p = 0;
+ return n;
+}
+
+size_t char16_strlen(const char16_t *s) {
+ size_t n = 0;
+
+ assert(s);
+
+ while (*s != 0)
+ n++, s++;
+
+ return n;
+}
+
/* expected size used to encode one unicode char */
static int utf8_unichar_to_encoded_len(char32_t unichar) {
@@ -376,8 +458,9 @@ static int utf8_unichar_to_encoded_len(char32_t unichar) {
/* validate one encoded unicode char and return its length */
int utf8_encoded_valid_unichar(const char *str) {
- int len, i, r;
char32_t unichar;
+ size_t len, i;
+ int r;
assert(str);
@@ -399,14 +482,14 @@ int utf8_encoded_valid_unichar(const char *str) {
return r;
/* check if encoded length matches encoded value */
- if (utf8_unichar_to_encoded_len(unichar) != len)
+ if (utf8_unichar_to_encoded_len(unichar) != (int) len)
return -EINVAL;
/* check if value has valid range */
if (!unichar_is_valid(unichar))
return -EINVAL;
- return len;
+ return (int) len;
}
size_t utf8_n_codepoints(const char *str) {
diff --git a/src/systemd/src/basic/utf8.h b/src/systemd/src/basic/utf8.h
index e8af7a576..3de798050 100644
--- a/src/systemd/src/basic/utf8.h
+++ b/src/systemd/src/basic/utf8.h
@@ -14,7 +14,7 @@
bool unichar_is_valid(char32_t c);
-const char *utf8_is_valid(const char *s) _pure_;
+char *utf8_is_valid(const char *s) _pure_;
char *ascii_is_valid(const char *s) _pure_;
char *ascii_is_valid_n(const char *str, size_t len);
@@ -25,21 +25,26 @@ char *utf8_escape_invalid(const char *s);
char *utf8_escape_non_printable(const char *str);
size_t utf8_encode_unichar(char *out_utf8, char32_t g);
-char *utf16_to_utf8(const void *s, size_t length);
+size_t utf16_encode_unichar(char16_t *out, char32_t c);
+
+char *utf16_to_utf8(const char16_t *s, size_t length /* bytes! */);
+char16_t *utf8_to_utf16(const char *s, size_t length);
+
+size_t char16_strlen(const char16_t *s); /* returns the number of 16bit words in the string (not bytes!) */
int utf8_encoded_valid_unichar(const char *str);
int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar);
static inline bool utf16_is_surrogate(char16_t c) {
- return (0xd800 <= c && c <= 0xdfff);
+ return c >= 0xd800U && c <= 0xdfffU;
}
static inline bool utf16_is_trailing_surrogate(char16_t c) {
- return (0xdc00 <= c && c <= 0xdfff);
+ return c >= 0xdc00U && c <= 0xdfffU;
}
static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t trail) {
- return ((lead - 0xd800) << 10) + (trail - 0xdc00) + 0x10000;
+ return ((((char32_t) lead - 0xd800U) << 10) + ((char32_t) trail - 0xdc00U) + 0x10000U);
}
size_t utf8_n_codepoints(const char *str);
diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c
index f951d641d..081c63c89 100644
--- a/src/systemd/src/basic/util.c
+++ b/src/systemd/src/basic/util.c
@@ -133,7 +133,7 @@ void in_initrd_force(bool value) {
/* hey glibc, APIs with callbacks without a user pointer are so useless */
void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
- int (*compar) (const void *, const void *, void *), void *arg) {
+ __compar_d_fn_t compar, void *arg) {
size_t l, u, idx;
const void *p;
int comparison;
diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h
index 308933ac9..5f3f98219 100644
--- a/src/systemd/src/basic/util.h
+++ b/src/systemd/src/basic/util.h
@@ -68,15 +68,21 @@ bool in_initrd(void);
void in_initrd_force(bool value);
void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
- int (*compar) (const void *, const void *, void *),
- void *arg);
+ __compar_d_fn_t compar, void *arg);
+
+#define typesafe_bsearch_r(k, b, n, func, userdata) \
+ ({ \
+ const typeof(b[0]) *_k = k; \
+ int (*_func_)(const typeof(b[0])*, const typeof(b[0])*, typeof(userdata)) = func; \
+ xbsearch_r((const void*) _k, (b), (n), sizeof((b)[0]), (__compar_d_fn_t) _func_, userdata); \
+ })
/**
* Normal bsearch requires base to be nonnull. Here were require
* that only if nmemb > 0.
*/
static inline void* bsearch_safe(const void *key, const void *base,
- size_t nmemb, size_t size, comparison_fn_t compar) {
+ size_t nmemb, size_t size, __compar_fn_t compar) {
if (nmemb <= 0)
return NULL;
@@ -84,11 +90,18 @@ static inline void* bsearch_safe(const void *key, const void *base,
return bsearch(key, base, nmemb, size, compar);
}
+#define typesafe_bsearch(k, b, n, func) \
+ ({ \
+ const typeof(b[0]) *_k = k; \
+ int (*_func_)(const typeof(b[0])*, const typeof(b[0])*) = func; \
+ bsearch_safe((const void*) _k, (b), (n), sizeof((b)[0]), (__compar_fn_t) _func_); \
+ })
+
/**
* Normal qsort requires base to be nonnull. Here were require
* that only if nmemb > 0.
*/
-static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_fn_t compar) {
+static inline void qsort_safe(void *base, size_t nmemb, size_t size, __compar_fn_t compar) {
if (nmemb <= 1)
return;
@@ -104,7 +117,7 @@ static inline void qsort_safe(void *base, size_t nmemb, size_t size, comparison_
qsort_safe((p), (n), sizeof((p)[0]), (__compar_fn_t) _func_); \
})
-static inline void qsort_r_safe(void *base, size_t nmemb, size_t size, int (*compar)(const void*, const void*, void*), void *userdata) {
+static inline void qsort_r_safe(void *base, size_t nmemb, size_t size, __compar_d_fn_t compar, void *userdata) {
if (nmemb <= 1)
return;
@@ -112,6 +125,12 @@ static inline void qsort_r_safe(void *base, size_t nmemb, size_t size, int (*com
qsort_r(base, nmemb, size, compar, userdata);
}
+#define typesafe_qsort_r(p, n, func, userdata) \
+ ({ \
+ int (*_func_)(const typeof(p[0])*, const typeof(p[0])*, typeof(userdata)) = func; \
+ qsort_r_safe((p), (n), sizeof((p)[0]), (__compar_d_fn_t) _func_, userdata); \
+ })
+
/* 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)
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c
index 531cf6783..77c584ee6 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.c
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c
@@ -108,8 +108,13 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
assert(len);
r = sd_id128_get_machine(&machine_id);
- if (r < 0)
+ if (r < 0) {
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ machine_id = SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10);
+#else
return r;
+#endif
+ }
unaligned_write_be16(&duid->type, DUID_TYPE_EN);
unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
diff --git a/src/systemd/src/libsystemd-network/dhcp-network.c b/src/systemd/src/libsystemd-network/dhcp-network.c
index 77638338f..cf59f1495 100644
--- a/src/systemd/src/libsystemd-network/dhcp-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp-network.c
@@ -126,8 +126,6 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
const uint8_t *bcast_addr = NULL;
uint8_t dhcp_hlen = 0;
- assert_return(mac_addr_len > 0, -EINVAL);
-
if (arp_type == ARPHRD_ETHER) {
assert_return(mac_addr_len == ETH_ALEN, -EINVAL);
memcpy(&eth_mac, mac_addr, ETH_ALEN);
diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h
index f1cbd6a4f..63d8fe35f 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h
@@ -73,8 +73,6 @@ struct DHCP6IA {
struct ia_pd ia_pd;
struct ia_ta ia_ta;
};
- sd_event_source *timeout_t1;
- sd_event_source *timeout_t2;
LIST_HEAD(DHCP6Address, addresses);
};
@@ -91,7 +89,7 @@ int dhcp6_option_append_pd(uint8_t *buf, size_t len, DHCP6IA *pd);
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn);
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
size_t *optlen, uint8_t **optvalue);
-int dhcp6_option_parse_status(DHCP6Option *option);
+int dhcp6_option_parse_status(DHCP6Option *option, size_t len);
int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia);
int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
struct in6_addr **addrs, size_t count,
diff --git a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
index ff0b0f00c..e004f48b4 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
@@ -37,7 +37,6 @@ struct sd_dhcp6_lease {
size_t ntp_fqdn_count;
};
-int dhcp6_lease_clear_timers(DHCP6IA *ia);
int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire);
DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia);
@@ -50,6 +49,7 @@ int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease);
int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit);
int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
+int dhcp6_lease_get_pd_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c
index 18196b125..cf19d366d 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-option.c
@@ -247,10 +247,11 @@ int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
return 0;
}
-int dhcp6_option_parse_status(DHCP6Option *option) {
+int dhcp6_option_parse_status(DHCP6Option *option, size_t len) {
DHCP6StatusOption *statusopt = (DHCP6StatusOption *)option;
- if (be16toh(option->len) + sizeof(DHCP6Option) < sizeof(*statusopt))
+ if (len < sizeof(DHCP6StatusOption) ||
+ be16toh(option->len) + sizeof(DHCP6Option) < sizeof(DHCP6StatusOption))
return -ENOBUFS;
return be16toh(statusopt->status);
@@ -277,7 +278,7 @@ static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia,
}
if (be16toh(option->len) + sizeof(DHCP6Option) > sizeof(*addr_option)) {
- r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options);
+ r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options, be16toh(option->len) + sizeof(DHCP6Option) - sizeof(*addr_option));
if (r != 0)
return r < 0 ? r: 0;
}
@@ -317,7 +318,7 @@ static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia,
}
if (be16toh(option->len) + sizeof(DHCP6Option) > sizeof(*pdprefix_option)) {
- r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options);
+ r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options, be16toh(option->len) + sizeof(DHCP6Option) - sizeof(*pdprefix_option));
if (r != 0)
return r < 0 ? r: 0;
}
@@ -462,7 +463,7 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
case SD_DHCP6_OPTION_STATUS_CODE:
- status = dhcp6_option_parse_status(option);
+ status = dhcp6_option_parse_status(option, optlen);
if (status) {
log_dhcp6_client(client, "IA status %d",
status);
@@ -563,7 +564,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
/* Literal label */
label = (const char *)&optval[pos];
pos += c;
- if (pos > optlen)
+ if (pos >= optlen)
return -EMSGSIZE;
if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) {
diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/systemd/src/libsystemd-network/lldp-neighbor.c
index 8295d4d40..f3c4e0ac8 100644
--- a/src/systemd/src/libsystemd-network/lldp-neighbor.c
+++ b/src/systemd/src/libsystemd-network/lldp-neighbor.c
@@ -18,8 +18,7 @@ static void lldp_neighbor_id_hash_func(const void *p, struct siphash *state) {
siphash24_compress(&id->port_id_size, sizeof(id->port_id_size), state);
}
-static int lldp_neighbor_id_compare_func(const void *a, const void *b) {
- const LLDPNeighborID *x = a, *y = b;
+int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y) {
int r;
r = memcmp(x->chassis_id, y->chassis_id, MIN(x->chassis_id_size, y->chassis_id_size));
@@ -39,7 +38,7 @@ static int lldp_neighbor_id_compare_func(const void *a, const void *b) {
const struct hash_ops lldp_neighbor_id_hash_ops = {
.hash = lldp_neighbor_id_hash_func,
- .compare = lldp_neighbor_id_compare_func
+ .compare = (__compar_fn_t) lldp_neighbor_id_compare_func,
};
int lldp_neighbor_prioq_compare_func(const void *a, const void *b) {
diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.h b/src/systemd/src/libsystemd-network/lldp-neighbor.h
index 494bc5176..2241c3bd9 100644
--- a/src/systemd/src/libsystemd-network/lldp-neighbor.h
+++ b/src/systemd/src/libsystemd-network/lldp-neighbor.h
@@ -81,6 +81,7 @@ static inline void* LLDP_NEIGHBOR_TLV_DATA(const sd_lldp_neighbor *n) {
}
extern const struct hash_ops lldp_neighbor_id_hash_ops;
+int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y);
int lldp_neighbor_prioq_compare_func(const void *a, const void *b);
sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index de86028a5..3e8d985aa 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -385,7 +385,7 @@ static int dhcp_client_set_iaid_duid_internal(
} else
switch (duid_type) {
case DUID_TYPE_LLT:
- if (!client->mac_addr || client->mac_addr_len == 0)
+ if (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);
@@ -398,7 +398,7 @@ static int dhcp_client_set_iaid_duid_internal(
return r;
break;
case DUID_TYPE_LL:
- if (!client->mac_addr || client->mac_addr_len == 0)
+ if (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);
@@ -698,7 +698,7 @@ static int client_message_init(
let the server know how large the server may make its DHCP messages.
Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
- than the defined default size unless the Maximum Messge Size option
+ than the defined default size unless the Maximum Message Size option
is explicitly set
RFC3442 "Requirements to Avoid Sizing Constraints":
@@ -1951,27 +1951,8 @@ sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
return client->event;
}
-sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
-
- if (!client)
- return NULL;
-
- assert(client->n_ref >= 1);
- client->n_ref++;
-
- return client;
-}
-
-sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
-
- if (!client)
- return NULL;
-
- assert(client->n_ref >= 1);
- client->n_ref--;
-
- if (client->n_ref > 0)
- return NULL;
+static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) {
+ assert(client);
log_dhcp_client(client, "FREE");
@@ -1990,6 +1971,8 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
return mfree(client);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free);
+
int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
_cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL;
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
index 8b6f5ad34..863818d6d 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
@@ -246,27 +246,8 @@ int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, s
return 0;
}
-sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) {
-
- if (!lease)
- return NULL;
-
- assert(lease->n_ref >= 1);
- lease->n_ref++;
-
- return lease;
-}
-
-sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
-
- if (!lease)
- return NULL;
-
- assert(lease->n_ref >= 1);
- lease->n_ref--;
-
- if (lease->n_ref > 0)
- return NULL;
+static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) {
+ assert(lease);
while (lease->private_options) {
struct sd_dhcp_raw_option *option = lease->private_options;
@@ -277,6 +258,8 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
free(option);
}
+ free(lease->root_path);
+ free(lease->timezone);
free(lease->hostname);
free(lease->domainname);
free(lease->dns);
@@ -288,6 +271,8 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
return mfree(lease);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_lease, sd_dhcp_lease, dhcp_lease_free);
+
static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {
assert(option);
assert(ret);
@@ -347,8 +332,7 @@ static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
if (!string)
return -ENOMEM;
- free(*ret);
- *ret = string;
+ free_and_replace(*ret, string);
}
return 0;
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
index 84c58af34..c07d831f7 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
@@ -27,6 +27,13 @@
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
+/* what to request from the server, addresses (IA_NA) and/or prefixes (IA_PD) */
+enum {
+ DHCP6_REQUEST_IA_NA = 1,
+ DHCP6_REQUEST_IA_TA = 2, /* currently not used */
+ DHCP6_REQUEST_IA_PD = 4,
+};
+
struct sd_dhcp6_client {
unsigned n_ref;
@@ -40,7 +47,9 @@ struct sd_dhcp6_client {
uint16_t arp_type;
DHCP6IA ia_na;
DHCP6IA ia_pd;
- bool prefix_delegation;
+ sd_event_source *timeout_t1;
+ sd_event_source *timeout_t2;
+ unsigned request;
be32_t transaction_id;
usec_t transaction_start;
struct sd_dhcp6_lease *lease;
@@ -205,10 +214,10 @@ static int dhcp6_client_set_duid_internal(
} else
switch (duid_type) {
case DUID_TYPE_LLT:
- if (!client->mac_addr || client->mac_addr_len == 0)
+ if (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);
+ r = dhcp_identifier_set_duid_llt(&client->duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len);
if (r < 0)
return r;
break;
@@ -218,7 +227,7 @@ static int dhcp6_client_set_duid_internal(
return r;
break;
case DUID_TYPE_LL:
- if (!client->mac_addr || client->mac_addr_len == 0)
+ if (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);
@@ -325,10 +334,44 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
return 0;
}
-int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, bool delegation) {
+int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) {
+ assert_return(client, -EINVAL);
+ assert_return(delegation, -EINVAL);
+
+ *delegation = FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD);
+
+ return 0;
+}
+
+int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, int delegation) {
+ assert_return(client, -EINVAL);
+
+ SET_FLAG(client->request, DHCP6_REQUEST_IA_PD, delegation);
+
+ return 0;
+}
+
+int sd_dhcp6_client_get_address_request(sd_dhcp6_client *client, int *request) {
+ assert_return(client, -EINVAL);
+ assert_return(request, -EINVAL);
+
+ *request = FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA);
+
+ return 0;
+}
+
+int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client, int request) {
assert_return(client, -EINVAL);
- client->prefix_delegation = delegation;
+ SET_FLAG(client->request, DHCP6_REQUEST_IA_NA, request);
+
+ return 0;
+}
+
+int sd_dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transaction_id) {
+ assert_return(client, -EINVAL);
+
+ client->transaction_id = transaction_id;
return 0;
}
@@ -352,21 +395,10 @@ static void client_notify(sd_dhcp6_client *client, int event) {
client->callback(client, event, client->userdata);
}
-static void client_set_lease(sd_dhcp6_client *client, sd_dhcp6_lease *lease) {
- assert(client);
-
- if (client->lease) {
- dhcp6_lease_clear_timers(&client->lease->ia);
- sd_dhcp6_lease_unref(client->lease);
- }
-
- client->lease = lease;
-}
-
static int client_reset(sd_dhcp6_client *client) {
assert(client);
- client_set_lease(client, NULL);
+ client->lease = sd_dhcp6_lease_unref(client->lease);
client->receive_message =
sd_event_source_unref(client->receive_message);
@@ -374,17 +406,15 @@ static int client_reset(sd_dhcp6_client *client) {
client->transaction_id = 0;
client->transaction_start = 0;
- client->ia_na.timeout_t1 =
- sd_event_source_unref(client->ia_na.timeout_t1);
- client->ia_na.timeout_t2 =
- sd_event_source_unref(client->ia_na.timeout_t2);
-
client->retransmit_time = 0;
client->retransmit_count = 0;
client->timeout_resend = sd_event_source_unref(client->timeout_resend);
client->timeout_resend_expire =
sd_event_source_unref(client->timeout_resend_expire);
+ client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
+ client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
+
client->state = DHCP6_STATE_STOPPED;
return 0;
@@ -436,9 +466,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
if (r < 0)
return r;
- r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na);
- if (r < 0)
- return r;
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) {
+ r = dhcp6_option_append_ia(&opt, &optlen,
+ &client->ia_na);
+ if (r < 0)
+ return r;
+ }
if (client->fqdn) {
r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn);
@@ -446,7 +479,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
- if (client->prefix_delegation) {
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd);
if (r < 0)
return r;
@@ -471,9 +504,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
if (r < 0)
return r;
- r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
- if (r < 0)
- return r;
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) {
+ r = dhcp6_option_append_ia(&opt, &optlen,
+ &client->lease->ia);
+ if (r < 0)
+ return r;
+ }
if (client->fqdn) {
r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn);
@@ -481,7 +517,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
- if (client->prefix_delegation) {
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd);
if (r < 0)
return r;
@@ -495,9 +531,11 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
case DHCP6_STATE_REBIND:
message->type = DHCP6_REBIND;
- r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
- if (r < 0)
- return r;
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) {
+ r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
+ if (r < 0)
+ return r;
+ }
if (client->fqdn) {
r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn);
@@ -505,7 +543,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
- if (client->prefix_delegation) {
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd);
if (r < 0)
return r;
@@ -562,8 +600,8 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
assert(client);
assert(client->lease);
- client->lease->ia.timeout_t2 =
- sd_event_source_unref(client->lease->ia.timeout_t2);
+ client->timeout_t2 =
+ sd_event_source_unref(client->timeout_t2);
log_dhcp6_client(client, "Timeout T2");
@@ -579,8 +617,8 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata)
assert(client);
assert(client->lease);
- client->lease->ia.timeout_t1 =
- sd_event_source_unref(client->lease->ia.timeout_t1);
+ client->timeout_t1 =
+ sd_event_source_unref(client->timeout_t1);
log_dhcp6_client(client, "Timeout T1");
@@ -810,8 +848,8 @@ static int client_parse_message(
uint8_t *optval;
be32_t iaid_lease;
- if (len < offsetof(DHCP6Option, data) ||
- len < offsetof(DHCP6Option, data) + be16toh(option->len))
+ if (len < pos + offsetof(DHCP6Option, data) ||
+ len < pos + offsetof(DHCP6Option, data) + be16toh(option->len))
return -ENOBUFS;
optcode = be16toh(option->code);
@@ -862,7 +900,7 @@ static int client_parse_message(
break;
case SD_DHCP6_OPTION_STATUS_CODE:
- status = dhcp6_option_parse_status(option);
+ status = dhcp6_option_parse_status(option, optlen);
if (status) {
log_dhcp6_client(client, "%s Status %s",
dhcp6_message_type_to_string(message->type),
@@ -914,7 +952,7 @@ static int client_parse_message(
if (r < 0 && r != -ENOMSG)
return r;
- r = dhcp6_lease_get_iaid(lease, &iaid_lease);
+ r = dhcp6_lease_get_pd_iaid(lease, &iaid_lease);
if (r < 0)
return r;
@@ -967,7 +1005,7 @@ static int client_parse_message(
break;
}
- pos += sizeof(*option) + optlen;
+ pos += offsetof(DHCP6Option, data) + optlen;
}
if (!clientid) {
@@ -1027,8 +1065,8 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, si
return 0;
}
- client_set_lease(client, lease);
- lease = NULL;
+ sd_dhcp6_lease_unref(client->lease);
+ client->lease = TAKE_PTR(lease);
return DHCP6_STATE_BOUND;
}
@@ -1056,8 +1094,8 @@ static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *adver
r = dhcp6_lease_get_preference(client->lease, &pref_lease);
if (r < 0 || pref_advertise > pref_lease) {
- client_set_lease(client, lease);
- lease = NULL;
+ sd_dhcp6_lease_unref(client->lease);
+ client->lease = TAKE_PTR(lease);
r = 0;
}
@@ -1188,10 +1226,33 @@ static int client_receive_message(
return 0;
}
+static int client_get_lifetime(sd_dhcp6_client *client, uint32_t *lifetime_t1,
+ uint32_t *lifetime_t2) {
+ assert_return(client, -EINVAL);
+ assert_return(client->lease, -EINVAL);
+
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA) && client->lease->ia.addresses) {
+ *lifetime_t1 = be32toh(client->lease->ia.ia_na.lifetime_t1);
+ *lifetime_t2 = be32toh(client->lease->ia.ia_na.lifetime_t2);
+
+ return 0;
+ }
+
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD) && client->lease->pd.addresses) {
+ *lifetime_t1 = be32toh(client->lease->pd.ia_pd.lifetime_t1);
+ *lifetime_t2 = be32toh(client->lease->pd.ia_pd.lifetime_t2);
+
+ return 0;
+ }
+
+ return -ENOMSG;
+}
+
static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
int r;
usec_t timeout, time_now;
char time_string[FORMAT_TIMESPAN_MAX];
+ uint32_t lifetime_t1, lifetime_t2;
assert_return(client, -EINVAL);
assert_return(client->event, -EINVAL);
@@ -1251,57 +1312,58 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
case DHCP6_STATE_BOUND:
- if (client->lease->ia.ia_na.lifetime_t1 == 0xffffffff ||
- client->lease->ia.ia_na.lifetime_t2 == 0xffffffff) {
+ r = client_get_lifetime(client, &lifetime_t1, &lifetime_t2);
+ if (r < 0)
+ goto error;
+ if (lifetime_t1 == 0xffffffff || lifetime_t2 == 0xffffffff) {
log_dhcp6_client(client, "Infinite T1 0x%08x or T2 0x%08x",
- be32toh(client->lease->ia.ia_na.lifetime_t1),
- be32toh(client->lease->ia.ia_na.lifetime_t2));
+ lifetime_t1, lifetime_t2);
return 0;
}
- timeout = client_timeout_compute_random(be32toh(client->lease->ia.ia_na.lifetime_t1) * USEC_PER_SEC);
+ timeout = client_timeout_compute_random(lifetime_t1 * USEC_PER_SEC);
log_dhcp6_client(client, "T1 expires in %s",
format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
r = sd_event_add_time(client->event,
- &client->lease->ia.timeout_t1,
+ &client->timeout_t1,
clock_boottime_or_monotonic(), time_now + timeout,
10 * USEC_PER_SEC, client_timeout_t1,
client);
if (r < 0)
goto error;
- r = sd_event_source_set_priority(client->lease->ia.timeout_t1,
+ r = sd_event_source_set_priority(client->timeout_t1,
client->event_priority);
if (r < 0)
goto error;
- r = sd_event_source_set_description(client->lease->ia.timeout_t1, "dhcp6-t1-timeout");
+ r = sd_event_source_set_description(client->timeout_t1, "dhcp6-t1-timeout");
if (r < 0)
goto error;
- timeout = client_timeout_compute_random(be32toh(client->lease->ia.ia_na.lifetime_t2) * USEC_PER_SEC);
+ timeout = client_timeout_compute_random(lifetime_t2 * USEC_PER_SEC);
log_dhcp6_client(client, "T2 expires in %s",
format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
r = sd_event_add_time(client->event,
- &client->lease->ia.timeout_t2,
+ &client->timeout_t2,
clock_boottime_or_monotonic(), time_now + timeout,
10 * USEC_PER_SEC, client_timeout_t2,
client);
if (r < 0)
goto error;
- r = sd_event_source_set_priority(client->lease->ia.timeout_t2,
+ r = sd_event_source_set_priority(client->timeout_t2,
client->event_priority);
if (r < 0)
goto error;
- r = sd_event_source_set_description(client->lease->ia.timeout_t2, "dhcp6-t2-timeout");
+ r = sd_event_source_set_description(client->timeout_t2, "dhcp6-t2-timeout");
if (r < 0)
goto error;
@@ -1363,6 +1425,9 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
if (!IN_SET(client->state, DHCP6_STATE_STOPPED))
return -EBUSY;
+ if (!client->information_request && !client->request)
+ return -EINVAL;
+
r = client_reset(client);
if (r < 0)
return r;
@@ -1431,27 +1496,8 @@ sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) {
return client->event;
}
-sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client) {
-
- if (!client)
- return NULL;
-
- assert(client->n_ref >= 1);
- client->n_ref++;
-
- return client;
-}
-
-sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
-
- if (!client)
- return NULL;
-
- assert(client->n_ref >= 1);
- client->n_ref--;
-
- if (client->n_ref > 0)
- return NULL;
+static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
+ assert(client);
client_reset(client);
@@ -1464,6 +1510,8 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
return mfree(client);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_client, sd_dhcp6_client, dhcp6_client_free);
+
int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
size_t t;
@@ -1478,6 +1526,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
client->ia_na.type = SD_DHCP6_OPTION_IA_NA;
client->ia_pd.type = SD_DHCP6_OPTION_IA_PD;
client->ifindex = -1;
+ client->request = DHCP6_REQUEST_IA_NA;
client->fd = -1;
client->req_opts_len = ELEMENTSOF(default_req_opts);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
index 779ad54b4..15fec2d85 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
@@ -11,15 +11,6 @@
#include "strv.h"
#include "util.h"
-int dhcp6_lease_clear_timers(DHCP6IA *ia) {
- assert_return(ia, -EINVAL);
-
- ia->timeout_t1 = sd_event_source_unref(ia->timeout_t1);
- ia->timeout_t2 = sd_event_source_unref(ia->timeout_t2);
-
- return 0;
-}
-
int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) {
DHCP6Address *addr;
uint32_t valid = 0, t;
@@ -48,8 +39,6 @@ DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) {
if (!ia)
return NULL;
- dhcp6_lease_clear_timers(ia);
-
while (ia->addresses) {
address = ia->addresses;
@@ -136,6 +125,15 @@ int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
return 0;
}
+int dhcp6_lease_get_pd_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
+ assert_return(lease, -EINVAL);
+ assert_return(iaid, -EINVAL);
+
+ *iaid = lease->pd.ia_pd.id;
+
+ return 0;
+}
+
int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr,
uint32_t *lifetime_preferred,
uint32_t *lifetime_valid) {
@@ -374,27 +372,8 @@ int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) {
return -ENOENT;
}
-sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) {
-
- if (!lease)
- return NULL;
-
- assert(lease->n_ref >= 1);
- lease->n_ref++;
-
- return lease;
-}
-
-sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) {
-
- if (!lease)
- return NULL;
-
- assert(lease->n_ref >= 1);
- lease->n_ref--;
-
- if (lease->n_ref > 0)
- return NULL;
+static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) {
+ assert(lease);
free(lease->serverid);
dhcp6_lease_free_ia(&lease->ia);
@@ -410,6 +389,8 @@ sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) {
return mfree(lease);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_lease, sd_dhcp6_lease, dhcp6_lease_free);
+
int dhcp6_lease_new(sd_dhcp6_lease **ret) {
sd_dhcp6_lease *lease;
diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c
index a40d40db9..6c12b5144 100644
--- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c
+++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c
@@ -97,25 +97,8 @@ static void ipv4acd_reset(sd_ipv4acd *acd) {
ipv4acd_set_state(acd, IPV4ACD_STATE_INIT, true);
}
-sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *acd) {
- if (!acd)
- return NULL;
-
- assert_se(acd->n_ref >= 1);
- acd->n_ref++;
-
- return acd;
-}
-
-sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd) {
- if (!acd)
- return NULL;
-
- assert_se(acd->n_ref >= 1);
- acd->n_ref--;
-
- if (acd->n_ref > 0)
- return NULL;
+static sd_ipv4acd *ipv4acd_free(sd_ipv4acd *acd) {
+ assert(acd);
ipv4acd_reset(acd);
sd_ipv4acd_detach_event(acd);
@@ -123,6 +106,8 @@ sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd) {
return mfree(acd);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_ipv4acd, sd_ipv4acd, ipv4acd_free);
+
int sd_ipv4acd_new(sd_ipv4acd **ret) {
_cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *acd = NULL;
diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c
index 7307e1668..e451dff74 100644
--- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c
@@ -55,30 +55,15 @@ struct sd_ipv4ll {
static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata);
-sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll) {
- if (!ll)
- return NULL;
-
- assert(ll->n_ref >= 1);
- ll->n_ref++;
-
- return ll;
-}
-
-sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) {
- if (!ll)
- return NULL;
-
- assert(ll->n_ref >= 1);
- ll->n_ref--;
-
- if (ll->n_ref > 0)
- return NULL;
+static sd_ipv4ll *ipv4ll_free(sd_ipv4ll *ll) {
+ assert(ll);
sd_ipv4acd_unref(ll->acd);
return mfree(ll);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_ipv4ll, sd_ipv4ll, ipv4ll_free);
+
int sd_ipv4ll_new(sd_ipv4ll **ret) {
_cleanup_(sd_ipv4ll_unrefp) sd_ipv4ll *ll = NULL;
int r;
diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/systemd/src/libsystemd-network/sd-lldp.c
index c75d6079e..f72ef204b 100644
--- a/src/systemd/src/libsystemd-network/sd-lldp.c
+++ b/src/systemd/src/libsystemd-network/sd-lldp.c
@@ -119,7 +119,7 @@ static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
}
if (lldp_neighbor_equal(n, old)) {
- /* Is this equal, then restart the TTL counter, but don't do anyting else. */
+ /* Is this equal, then restart the TTL counter, but don't do anything else. */
old->timestamp = n->timestamp;
lldp_start_timer(lldp, old);
lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old);
@@ -329,27 +329,8 @@ _public_ int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex) {
return 0;
}
-_public_ sd_lldp* sd_lldp_ref(sd_lldp *lldp) {
-
- if (!lldp)
- return NULL;
-
- assert(lldp->n_ref > 0);
- lldp->n_ref++;
-
- return lldp;
-}
-
-_public_ sd_lldp* sd_lldp_unref(sd_lldp *lldp) {
-
- if (!lldp)
- return NULL;
-
- assert(lldp->n_ref > 0);
- lldp->n_ref --;
-
- if (lldp->n_ref > 0)
- return NULL;
+static sd_lldp* lldp_free(sd_lldp *lldp) {
+ assert(lldp);
lldp_reset(lldp);
sd_lldp_detach_event(lldp);
@@ -360,6 +341,8 @@ _public_ sd_lldp* sd_lldp_unref(sd_lldp *lldp) {
return mfree(lldp);
}
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_lldp, sd_lldp, lldp_free);
+
_public_ int sd_lldp_new(sd_lldp **ret) {
_cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL;
int r;
@@ -388,10 +371,8 @@ _public_ int sd_lldp_new(sd_lldp **ret) {
return 0;
}
-static int neighbor_compare_func(const void *a, const void *b) {
- const sd_lldp_neighbor * const*x = a, * const *y = b;
-
- return lldp_neighbor_id_hash_ops.compare(&(*x)->id, &(*y)->id);
+static int neighbor_compare_func(sd_lldp_neighbor * const *a, sd_lldp_neighbor * const *b) {
+ return lldp_neighbor_id_compare_func(&(*a)->id, &(*b)->id);
}
static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
@@ -479,7 +460,7 @@ _public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) {
assert((size_t) k == hashmap_size(lldp->neighbor_by_id));
/* Return things in a stable order */
- qsort(l, k, sizeof(sd_lldp_neighbor*), neighbor_compare_func);
+ typesafe_qsort(l, k, neighbor_compare_func);
*ret = l;
return k;
diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c
index 6e50fcc4c..880e12768 100644
--- a/src/systemd/src/libsystemd/sd-event/sd-event.c
+++ b/src/systemd/src/libsystemd/sd-event/sd-event.c
@@ -456,7 +456,7 @@ static void free_clock_data(struct clock_data *d) {
prioq_free(d->latest);
}
-static void event_free(sd_event *e) {
+static sd_event *event_free(sd_event *e) {
sd_event_source *s;
assert(e);
@@ -492,7 +492,8 @@ static void event_free(sd_event *e) {
hashmap_free(e->child_sources);
set_free(e->post_sources);
- free(e);
+
+ return mfree(e);
}
_public_ int sd_event_new(sd_event** ret) {
@@ -553,30 +554,7 @@ fail:
return r;
}
-_public_ sd_event* sd_event_ref(sd_event *e) {
-
- if (!e)
- return NULL;
-
- assert(e->n_ref >= 1);
- e->n_ref++;
-
- return e;
-}
-
-_public_ sd_event* sd_event_unref(sd_event *e) {
-
- if (!e)
- return NULL;
-
- assert(e->n_ref >= 1);
- e->n_ref--;
-
- if (e->n_ref <= 0)
- event_free(e);
-
- return NULL;
-}
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
static bool event_pid_changed(sd_event *e) {
assert(e);
@@ -972,7 +950,7 @@ static void source_disconnect(sd_event_source *s) {
* continued to being watched. That's because inotify doesn't really have an API for that: we
* can only change watch masks with access to the original inode either by fd or by path. But
* paths aren't stable, and keeping an O_PATH fd open all the time would mean wasting an fd
- * continously and keeping the mount busy which we can't really do. We could reconstruct the
+ * continuously and keeping the mount busy which we can't really do. We could reconstruct the
* original inode from /proc/self/fdinfo/$INOTIFY_FD (as all watch descriptors are listed
* there), but given the need for open_by_handle_at() which is privileged and not universally
* available this would be quite an incomplete solution. Hence we go the other way, leave the
@@ -1021,6 +999,7 @@ static void source_free(sd_event_source *s) {
free(s->description);
free(s);
}
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_event_source*, source_free);
static int source_set_pending(sd_event_source *s, bool b) {
int r;
@@ -1114,7 +1093,7 @@ _public_ int sd_event_add_io(
sd_event_io_handler_t callback,
void *userdata) {
- sd_event_source *s;
+ _cleanup_(source_freep) sd_event_source *s = NULL;
int r;
assert_return(e, -EINVAL);
@@ -1137,13 +1116,12 @@ _public_ int sd_event_add_io(
s->enabled = SD_EVENT_ON;
r = source_io_register(s, s->enabled, events);
- if (r < 0) {
- source_free(s);
+ if (r < 0)
return r;
- }
if (ret)
*ret = s;
+ TAKE_PTR(s);
return 0;
}
@@ -1152,7 +1130,7 @@ static void initialize_perturb(sd_event *e) {
sd_id128_t bootid = {};
/* When we sleep for longer, we try to realign the wakeup to
- the same time wihtin each minute/second/250ms, so that
+ the same time within each minute/second/250ms, so that
events all across the system can be coalesced into a single
CPU wakeup. However, let's take some system-specific
randomness for this value, so that in a network of systems
@@ -1218,7 +1196,7 @@ _public_ int sd_event_add_time(
void *userdata) {
EventSourceType type;
- sd_event_source *s;
+ _cleanup_(source_freep) sd_event_source *s = NULL;
struct clock_data *d;
int r;
@@ -1270,20 +1248,17 @@ _public_ int sd_event_add_time(
r = prioq_put(d->earliest, s, &s->time.earliest_index);
if (r < 0)
- goto fail;
+ return r;
r = prioq_put(d->latest, s, &s->time.latest_index);
if (r < 0)
- goto fail;
+ return r;
if (ret)
*ret = s;
+ TAKE_PTR(s);
return 0;
-
-fail:
- source_free(s);
- return r;
}
static int signal_exit_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
@@ -1299,7 +1274,7 @@ _public_ int sd_event_add_signal(
sd_event_signal_handler_t callback,
void *userdata) {
- sd_event_source *s;
+ _cleanup_(source_freep) sd_event_source *s = NULL;
struct signal_data *d;
sigset_t ss;
int r;
@@ -1339,16 +1314,15 @@ _public_ int sd_event_add_signal(
e->signal_sources[sig] = s;
r = event_make_signal_data(e, sig, &d);
- if (r < 0) {
- source_free(s);
+ if (r < 0)
return r;
- }
/* Use the signal name as description for the event source by default */
(void) sd_event_source_set_description(s, signal_to_string(sig));
if (ret)
*ret = s;
+ TAKE_PTR(s);
return 0;
}
@@ -1361,7 +1335,7 @@ _public_ int sd_event_add_child(
sd_event_child_handler_t callback,
void *userdata) {
- sd_event_source *s;
+ _cleanup_(source_freep) sd_event_source *s = NULL;
int r;
assert_return(e, -EINVAL);
@@ -1391,17 +1365,14 @@ _public_ int sd_event_add_child(
s->enabled = SD_EVENT_ONESHOT;
r = hashmap_put(e->child_sources, PID_TO_PTR(pid), s);
- if (r < 0) {
- source_free(s);
+ if (r < 0)
return r;
- }
e->n_enabled_child_sources++;
r = event_make_signal_data(e, SIGCHLD, NULL);
if (r < 0) {
e->n_enabled_child_sources--;
- source_free(s);
return r;
}
@@ -1409,6 +1380,7 @@ _public_ int sd_event_add_child(
if (ret)
*ret = s;
+ TAKE_PTR(s);
return 0;
}
@@ -1419,7 +1391,7 @@ _public_ int sd_event_add_defer(
sd_event_handler_t callback,
void *userdata) {
- sd_event_source *s;
+ _cleanup_(source_freep) sd_event_source *s = NULL;
int r;
assert_return(e, -EINVAL);
@@ -1437,13 +1409,12 @@ _public_ int sd_event_add_defer(
s->enabled = SD_EVENT_ONESHOT;
r = source_set_pending(s, true);
- if (r < 0) {
- source_free(s);
+ if (r < 0)
return r;
- }
if (ret)
*ret = s;
+ TAKE_PTR(s);
return 0;
}
@@ -1454,7 +1425,7 @@ _public_ int sd_event_add_post(
sd_event_handler_t callback,
void *userdata) {
- sd_event_source *s;
+ _cleanup_(source_freep) sd_event_source *s = NULL;
int r;
assert_return(e, -EINVAL);
@@ -1476,13 +1447,12 @@ _public_ int sd_event_add_post(
s->enabled = SD_EVENT_ON;
r = set_put(e->post_sources, s);
- if (r < 0) {
- source_free(s);
+ if (r < 0)
return r;
- }
if (ret)
*ret = s;
+ TAKE_PTR(s);
return 0;
}
@@ -1493,7 +1463,7 @@ _public_ int sd_event_add_exit(
sd_event_handler_t callback,
void *userdata) {
- sd_event_source *s;
+ _cleanup_(source_freep) sd_event_source *s = NULL;
int r;
assert_return(e, -EINVAL);
@@ -1516,13 +1486,12 @@ _public_ int sd_event_add_exit(
s->enabled = SD_EVENT_ONESHOT;
r = prioq_put(s->event->exit, s, &s->exit.prioq_index);
- if (r < 0) {
- source_free(s);
+ if (r < 0)
return r;
- }
if (ret)
*ret = s;
+ TAKE_PTR(s);
return 0;
}
@@ -1777,7 +1746,7 @@ static uint32_t inode_data_determine_mask(struct inode_data *d) {
*
* Note that we add all sources to the mask here, regardless whether enabled, disabled or oneshot. That's
* because we cannot change the mask anymore after the event source was created once, since the kernel has no
- * API for that. Hence we need to subscribe to the maximum mask we ever might be interested in, and supress
+ * API for that. Hence we need to subscribe to the maximum mask we ever might be interested in, and suppress
* events we don't care for client-side. */
LIST_FOREACH(inotify.by_inode_data, s, d->event_sources) {
@@ -1839,11 +1808,10 @@ _public_ int sd_event_add_inotify(
sd_event_inotify_handler_t callback,
void *userdata) {
- bool rm_inotify = false, rm_inode = false;
struct inotify_data *inotify_data = NULL;
struct inode_data *inode_data = NULL;
_cleanup_close_ int fd = -1;
- sd_event_source *s;
+ _cleanup_(source_freep) sd_event_source *s = NULL;
struct stat st;
int r;
@@ -1881,13 +1849,13 @@ _public_ int sd_event_add_inotify(
/* Allocate an inotify object for this priority, and an inode object within it */
r = event_make_inotify_data(e, SD_EVENT_PRIORITY_NORMAL, &inotify_data);
if (r < 0)
- goto fail;
- rm_inotify = r > 0;
+ return r;
r = event_make_inode_data(e, inotify_data, st.st_dev, st.st_ino, &inode_data);
- if (r < 0)
- goto fail;
- rm_inode = r > 0;
+ if (r < 0) {
+ event_free_inotify_data(e, inotify_data);
+ return r;
+ }
/* Keep the O_PATH fd around until the first iteration of the loop, so that we can still change the priority of
* the event source, until then, for which we need the original inode. */
@@ -1900,72 +1868,45 @@ _public_ int sd_event_add_inotify(
LIST_PREPEND(inotify.by_inode_data, inode_data->event_sources, s);
s->inotify.inode_data = inode_data;
- rm_inode = rm_inotify = false;
-
/* Actually realize the watch now */
r = inode_data_realize_watch(e, inode_data);
if (r < 0)
- goto fail;
+ return r;
(void) sd_event_source_set_description(s, path);
if (ret)
*ret = s;
+ TAKE_PTR(s);
return 0;
-
-fail:
- source_free(s);
-
- if (rm_inode)
- event_free_inode_data(e, inode_data);
-
- if (rm_inotify)
- event_free_inotify_data(e, inotify_data);
-
- return r;
}
-_public_ sd_event_source* sd_event_source_ref(sd_event_source *s) {
-
+static sd_event_source* event_source_free(sd_event_source *s) {
if (!s)
return NULL;
- assert(s->n_ref >= 1);
- s->n_ref++;
-
- return s;
-}
-
-_public_ sd_event_source* sd_event_source_unref(sd_event_source *s) {
+ /* Here's a special hack: when we are called from a
+ * dispatch handler we won't free the event source
+ * immediately, but we will detach the fd from the
+ * epoll. This way it is safe for the caller to unref
+ * the event source and immediately close the fd, but
+ * we still retain a valid event source object after
+ * the callback. */
- if (!s)
- return NULL;
-
- assert(s->n_ref >= 1);
- s->n_ref--;
-
- if (s->n_ref <= 0) {
- /* Here's a special hack: when we are called from a
- * dispatch handler we won't free the event source
- * immediately, but we will detach the fd from the
- * epoll. This way it is safe for the caller to unref
- * the event source and immediately close the fd, but
- * we still retain a valid event source object after
- * the callback. */
-
- if (s->dispatching) {
- if (s->type == SOURCE_IO)
- source_io_unregister(s);
+ if (s->dispatching) {
+ if (s->type == SOURCE_IO)
+ source_io_unregister(s);
- source_disconnect(s);
- } else
- source_free(s);
- }
+ source_disconnect(s);
+ } else
+ source_free(s);
return NULL;
}
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event_source, sd_event_source, event_source_free);
+
_public_ int sd_event_source_set_description(sd_event_source *s, const char *description) {
assert_return(s, -EINVAL);
assert_return(!event_pid_changed(s->event), -ECHILD);
diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
index 9d93732d7..b7cca832d 100644
--- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
@@ -284,19 +284,15 @@ _public_ int sd_id128_randomize(sd_id128_t *ret) {
return 0;
}
-_public_ int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret) {
+static int get_app_specific(sd_id128_t base, sd_id128_t app_id, sd_id128_t *ret) {
_cleanup_(khash_unrefp) khash *h = NULL;
- sd_id128_t m, result;
+ sd_id128_t result;
const void *p;
int r;
- assert_return(ret, -EINVAL);
-
- r = sd_id128_get_machine(&m);
- if (r < 0)
- return r;
+ assert(ret);
- r = khash_new_with_key(&h, "hmac(sha256)", &m, sizeof(m));
+ r = khash_new_with_key(&h, "hmac(sha256)", &base, sizeof(base));
if (r < 0)
return r;
@@ -314,3 +310,29 @@ _public_ int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *re
*ret = make_v4_uuid(result);
return 0;
}
+
+_public_ int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret) {
+ sd_id128_t id;
+ int r;
+
+ assert_return(ret, -EINVAL);
+
+ r = sd_id128_get_machine(&id);
+ if (r < 0)
+ return r;
+
+ return get_app_specific(id, app_id, ret);
+}
+
+_public_ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret) {
+ sd_id128_t id;
+ int r;
+
+ assert_return(ret, -EINVAL);
+
+ r = sd_id128_get_boot(&id);
+ if (r < 0)
+ return r;
+
+ return get_app_specific(id, app_id, ret);
+}
diff --git a/src/systemd/src/shared/dns-domain.c b/src/systemd/src/shared/dns-domain.c
index 1ecfb77de..f24edf579 100644
--- a/src/systemd/src/shared/dns-domain.c
+++ b/src/systemd/src/shared/dns-domain.c
@@ -1284,7 +1284,7 @@ int dns_name_apply_idna(const char *name, char **ret) {
log_debug("idn2_lookup_u8(\"%s\") failed: %d/%s", name, r, idn2_strerror(r));
if (r == IDN2_2HYPHEN)
- /* The name has two hypens — forbidden by IDNA2008 in some cases */
+ /* The name has two hyphens — forbidden by IDNA2008 in some cases */
return 0;
if (IN_SET(r, IDN2_TOO_BIG_DOMAIN, IDN2_TOO_BIG_LABEL))
return -ENOSPC;
diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h
index fa36dca90..43d38f5c7 100644
--- a/src/systemd/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/src/systemd/sd-dhcp6-client.h
@@ -21,7 +21,6 @@
#include <inttypes.h>
#include <net/ethernet.h>
-#include <stdbool.h>
#include <sys/types.h>
#include "sd-dhcp6-lease.h"
@@ -120,8 +119,15 @@ int sd_dhcp6_client_get_information_request(
int sd_dhcp6_client_set_request_option(
sd_dhcp6_client *client,
uint16_t option);
+int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client,
+ int *delegation);
int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client,
- bool delegation);
+ int delegation);
+int sd_dhcp6_client_get_address_request(sd_dhcp6_client *client,
+ int *request);
+int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client,
+ int request);
+int sd_dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transaction_id);
int sd_dhcp6_client_get_lease(
sd_dhcp6_client *client,
diff --git a/src/systemd/src/systemd/sd-id128.h b/src/systemd/src/systemd/sd-id128.h
index 143a0ffb5..78cf9462b 100644
--- a/src/systemd/src/systemd/sd-id128.h
+++ b/src/systemd/src/systemd/sd-id128.h
@@ -42,6 +42,7 @@ int sd_id128_randomize(sd_id128_t *ret);
int sd_id128_get_machine(sd_id128_t *ret);
int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret);
+int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret);
int sd_id128_get_boot(sd_id128_t *ret);
int sd_id128_get_invocation(sd_id128_t *ret);