about summary refs log tree commit diff
path: root/src/systemd
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemd')
-rw-r--r--src/systemd/nm-sd.c7
-rw-r--r--src/systemd/nm-sd.h11
-rw-r--r--src/systemd/sd-adapt/build.h3
-rw-r--r--src/systemd/sd-adapt/cgroup-util.h3
-rw-r--r--src/systemd/sd-adapt/condition.h5
-rw-r--r--src/systemd/sd-adapt/conf-parser.h3
-rw-r--r--src/systemd/sd-adapt/def.h3
-rw-r--r--src/systemd/sd-adapt/dirent-util.h3
-rw-r--r--src/systemd/sd-adapt/formats-util.h3
-rw-r--r--src/systemd/sd-adapt/gunicode.h3
-rw-r--r--src/systemd/sd-adapt/libudev.h5
-rw-r--r--src/systemd/sd-adapt/missing.h3
-rw-r--r--src/systemd/sd-adapt/mkdir.h3
-rw-r--r--src/systemd/sd-adapt/nm-sd-adapt.c (renamed from src/systemd/nm-sd-adapt.c)0
-rw-r--r--src/systemd/sd-adapt/nm-sd-adapt.h (renamed from src/systemd/nm-sd-adapt.h)6
-rw-r--r--src/systemd/sd-adapt/process-util.h3
-rw-r--r--src/systemd/sd-adapt/sd-daemon.h3
-rw-r--r--src/systemd/sd-adapt/stat-util.h3
-rw-r--r--src/systemd/sd-adapt/udev-util.h3
-rw-r--r--src/systemd/sd-adapt/udev.h5
-rw-r--r--src/systemd/sd-adapt/user-util.h3
-rw-r--r--src/systemd/sd-adapt/virt.h3
-rw-r--r--src/systemd/src/basic/escape.h2
-rw-r--r--src/systemd/src/basic/ether-addr-util.c69
-rw-r--r--src/systemd/src/basic/ether-addr-util.h2
-rw-r--r--src/systemd/src/basic/extract-word.c302
-rw-r--r--src/systemd/src/basic/extract-word.h35
-rw-r--r--src/systemd/src/basic/fd-util.c26
-rw-r--r--src/systemd/src/basic/fd-util.h3
-rw-r--r--src/systemd/src/basic/fileio.c210
-rw-r--r--src/systemd/src/basic/fileio.h8
-rw-r--r--src/systemd/src/basic/fs-util.c112
-rw-r--r--src/systemd/src/basic/fs-util.h5
-rw-r--r--src/systemd/src/basic/hashmap.c37
-rw-r--r--src/systemd/src/basic/hostname-util.c10
-rw-r--r--src/systemd/src/basic/in-addr-util.c105
-rw-r--r--src/systemd/src/basic/in-addr-util.h5
-rw-r--r--src/systemd/src/basic/io-util.c5
-rw-r--r--src/systemd/src/basic/macro.h9
-rw-r--r--src/systemd/src/basic/parse-util.c46
-rw-r--r--src/systemd/src/basic/parse-util.h17
-rw-r--r--src/systemd/src/basic/path-util.c79
-rw-r--r--src/systemd/src/basic/path-util.h20
-rw-r--r--src/systemd/src/basic/random-util.c4
-rw-r--r--src/systemd/src/basic/set.h10
-rw-r--r--src/systemd/src/basic/signal-util.h56
-rw-r--r--src/systemd/src/basic/siphash24.c2
-rw-r--r--src/systemd/src/basic/socket-util.c122
-rw-r--r--src/systemd/src/basic/socket-util.h17
-rw-r--r--src/systemd/src/basic/string-table.h56
-rw-r--r--src/systemd/src/basic/string-util.c47
-rw-r--r--src/systemd/src/basic/string-util.h8
-rw-r--r--src/systemd/src/basic/strv.c90
-rw-r--r--src/systemd/src/basic/strv.h9
-rw-r--r--src/systemd/src/basic/time-util.c258
-rw-r--r--src/systemd/src/basic/time-util.h32
-rw-r--r--src/systemd/src/basic/unaligned.h18
-rw-r--r--src/systemd/src/basic/utf8.h2
-rw-r--r--src/systemd/src/basic/util.c229
-rw-r--r--src/systemd/src/basic/util.h17
-rw-r--r--src/systemd/src/libsystemd-network/arp-util.c10
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.c36
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.h40
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-internal.h3
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-network.c4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-protocol.h2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-internal.h3
-rw-r--r--src/systemd/src/libsystemd-network/lldp-internal.h2
-rw-r--r--src/systemd/src/libsystemd-network/lldp-neighbor.c51
-rw-r--r--src/systemd/src/libsystemd-network/lldp-neighbor.h8
-rw-r--r--src/systemd/src/libsystemd-network/lldp-network.c3
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.c186
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.h6
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c270
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-client.c171
-rw-r--r--src/systemd/src/libsystemd-network/sd-ipv4acd.c505
-rw-r--r--src/systemd/src/libsystemd-network/sd-ipv4ll.c180
-rw-r--r--src/systemd/src/libsystemd-network/sd-lldp.c105
-rw-r--r--src/systemd/src/libsystemd/sd-event/sd-event.c87
-rw-r--r--src/systemd/src/libsystemd/sd-id128/id128-util.c200
-rw-r--r--src/systemd/src/libsystemd/sd-id128/id128-util.h45
-rw-r--r--src/systemd/src/libsystemd/sd-id128/sd-id128.c122
-rw-r--r--src/systemd/src/systemd/sd-dhcp-client.h78
-rw-r--r--src/systemd/src/systemd/sd-dhcp6-client.h61
-rw-r--r--src/systemd/src/systemd/sd-event.h1
-rw-r--r--src/systemd/src/systemd/sd-ipv4acd.h28
-rw-r--r--src/systemd/src/systemd/sd-ipv4ll.h6
-rw-r--r--src/systemd/src/systemd/sd-lldp.h90
-rw-r--r--src/systemd/src/systemd/sd-ndisc.h114
89 files changed, 3248 insertions, 1337 deletions
diff --git a/src/systemd/nm-sd.c b/src/systemd/nm-sd.c
index 4d596020..43ae0a8b 100644
--- a/src/systemd/nm-sd.c
+++ b/src/systemd/nm-sd.c
@@ -134,3 +134,10 @@ nm_sd_event_attach_default (void)
 
 /*****************************************************************************/
 
+/* ensure that defines in nm-sd.h correspond to the internal defines. */
+
+#include "nm-sd-adapt.h"
+#include "dhcp-lease-internal.h"
+
+/*****************************************************************************/
+
diff --git a/src/systemd/nm-sd.h b/src/systemd/nm-sd.h
index 888d44ab..f07a7082 100644
--- a/src/systemd/nm-sd.h
+++ b/src/systemd/nm-sd.h
@@ -21,5 +21,16 @@
 
 guint nm_sd_event_attach_default (void);
 
+/*****************************************************************************
+ * expose internal systemd API
+ *
+ * FIXME: don't use any internal systemd API.
+ *****************************************************************************/
+
+struct sd_dhcp_lease;
+
+int dhcp_lease_save(struct sd_dhcp_lease *lease, const char *lease_file);
+int dhcp_lease_load(struct sd_dhcp_lease **ret, const char *lease_file);
+
 #endif /* __NM_SD_H__ */
 
diff --git a/src/systemd/sd-adapt/build.h b/src/systemd/sd-adapt/build.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/build.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/cgroup-util.h b/src/systemd/sd-adapt/cgroup-util.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/cgroup-util.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/condition.h b/src/systemd/sd-adapt/condition.h
new file mode 100644
index 00000000..d3a6812a
--- /dev/null
+++ b/src/systemd/sd-adapt/condition.h
@@ -0,0 +1,5 @@
+#pragma once
+
+/* dummy header */
+
+typedef struct _sd_adapt_Condition Condition;
diff --git a/src/systemd/sd-adapt/conf-parser.h b/src/systemd/sd-adapt/conf-parser.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/conf-parser.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/def.h b/src/systemd/sd-adapt/def.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/def.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/dirent-util.h b/src/systemd/sd-adapt/dirent-util.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/dirent-util.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/formats-util.h b/src/systemd/sd-adapt/formats-util.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/formats-util.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/gunicode.h b/src/systemd/sd-adapt/gunicode.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/gunicode.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/libudev.h b/src/systemd/sd-adapt/libudev.h
new file mode 100644
index 00000000..8c49f075
--- /dev/null
+++ b/src/systemd/sd-adapt/libudev.h
@@ -0,0 +1,5 @@
+#pragma once
+
+/* dummy header */
+
+struct udev_device;
diff --git a/src/systemd/sd-adapt/missing.h b/src/systemd/sd-adapt/missing.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/missing.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/mkdir.h b/src/systemd/sd-adapt/mkdir.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/mkdir.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/nm-sd-adapt.c b/src/systemd/sd-adapt/nm-sd-adapt.c
index 4e308276..4e308276 100644
--- a/src/systemd/nm-sd-adapt.c
+++ b/src/systemd/sd-adapt/nm-sd-adapt.c
diff --git a/src/systemd/nm-sd-adapt.h b/src/systemd/sd-adapt/nm-sd-adapt.h
index 010c8a80..cf27c1af 100644
--- a/src/systemd/nm-sd-adapt.h
+++ b/src/systemd/sd-adapt/nm-sd-adapt.h
@@ -140,8 +140,12 @@ sd_notify (int unset_environment, const char *state)
 }
 
 /* Can't include both net/if.h and linux/if.h; so have to define this here */
+#ifndef IF_NAMESIZE
+#define IF_NAMESIZE 16
+#endif
+
 #ifndef IFNAMSIZ
-#define IFNAMSIZ 16
+#define IFNAMSIZ IF_NAMESIZE
 #endif
 
 #ifndef MAX_HANDLE_SZ
diff --git a/src/systemd/sd-adapt/process-util.h b/src/systemd/sd-adapt/process-util.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/process-util.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/sd-daemon.h b/src/systemd/sd-adapt/sd-daemon.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/sd-daemon.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/stat-util.h b/src/systemd/sd-adapt/stat-util.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/stat-util.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/udev-util.h b/src/systemd/sd-adapt/udev-util.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/udev-util.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/udev.h b/src/systemd/sd-adapt/udev.h
new file mode 100644
index 00000000..00f60f92
--- /dev/null
+++ b/src/systemd/sd-adapt/udev.h
@@ -0,0 +1,5 @@
+#pragma once
+
+/* dummy header */
+
+#include "libudev.h"
diff --git a/src/systemd/sd-adapt/user-util.h b/src/systemd/sd-adapt/user-util.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/user-util.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/sd-adapt/virt.h b/src/systemd/sd-adapt/virt.h
new file mode 100644
index 00000000..637892c2
--- /dev/null
+++ b/src/systemd/sd-adapt/virt.h
@@ -0,0 +1,3 @@
+#pragma once
+
+/* dummy header */
diff --git a/src/systemd/src/basic/escape.h b/src/systemd/src/basic/escape.h
index b8ec96ad..24729dc1 100644
--- a/src/systemd/src/basic/escape.h
+++ b/src/systemd/src/basic/escape.h
@@ -28,9 +28,7 @@
 #endif /* NM_IGNORED */
 
 #include "string-util.h"
-#if 0 /* NM_IGNORED */
 #include "missing.h"
-#endif /* NM_IGNORED */
 
 /* What characters are special in the shell? */
 /* must be escaped outside and inside double-quotes */
diff --git a/src/systemd/src/basic/ether-addr-util.c b/src/systemd/src/basic/ether-addr-util.c
index 0219300d..a793219c 100644
--- a/src/systemd/src/basic/ether-addr-util.c
+++ b/src/systemd/src/basic/ether-addr-util.c
@@ -25,6 +25,7 @@
 
 #include "ether-addr-util.h"
 #include "macro.h"
+#include "string-util.h"
 
 char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {
         assert(addr);
@@ -56,3 +57,71 @@ bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
                 a->ether_addr_octet[4] == b->ether_addr_octet[4] &&
                 a->ether_addr_octet[5] == b->ether_addr_octet[5];
 }
+
+int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset) {
+        size_t pos = 0, n, field;
+        char sep = '\0';
+        const char *hex = HEXDIGITS, *hexoff;
+        size_t x;
+        bool touched;
+
+#define parse_fields(v)                                         \
+        for (field = 0; field < ELEMENTSOF(v); field++) {       \
+                touched = false;                                \
+                for (n = 0; n < (2 * sizeof(v[0])); n++) {      \
+                        if (s[pos] == '\0')                     \
+                                break;                          \
+                        hexoff = strchr(hex, s[pos]);           \
+                        if (hexoff == NULL)                     \
+                                break;                          \
+                        assert(hexoff >= hex);                  \
+                        x = hexoff - hex;                       \
+                        if (x >= 16)                            \
+                                x -= 6; /* A-F */               \
+                        assert(x < 16);                         \
+                        touched = true;                         \
+                        v[field] <<= 4;                         \
+                        v[field] += x;                          \
+                        pos++;                                  \
+                }                                               \
+                if (!touched)                                   \
+                        return -EINVAL;                         \
+                if (field < (ELEMENTSOF(v)-1)) {                \
+                        if (s[pos] != sep)                      \
+                                return -EINVAL;                 \
+                        else                                    \
+                                pos++;                          \
+                }                                               \
+        }
+
+        assert(s);
+        assert(ret);
+
+        sep = s[strspn(s, hex)];
+        if (sep == '\n')
+                return -EINVAL;
+        if (strchr(":.-", sep) == NULL)
+                return -EINVAL;
+
+        if (sep == '.') {
+                uint16_t shorts[3] = { 0 };
+
+                parse_fields(shorts);
+
+                for (n = 0; n < ELEMENTSOF(shorts); n++) {
+                        ret->ether_addr_octet[2*n] = ((shorts[n] & (uint16_t)0xff00) >> 8);
+                        ret->ether_addr_octet[2*n + 1] = (shorts[n] & (uint16_t)0x00ff);
+                }
+        } else {
+                struct ether_addr out = { .ether_addr_octet = { 0 } };
+
+                parse_fields(out.ether_addr_octet);
+
+                for (n = 0; n < ELEMENTSOF(out.ether_addr_octet); n++)
+                        ret->ether_addr_octet[n] = out.ether_addr_octet[n];
+        }
+
+        if (offset)
+                *offset = pos;
+        return 0;
+}
diff --git a/src/systemd/src/basic/ether-addr-util.h b/src/systemd/src/basic/ether-addr-util.h
index 07436379..74e125a9 100644
--- a/src/systemd/src/basic/ether-addr-util.h
+++ b/src/systemd/src/basic/ether-addr-util.h
@@ -35,3 +35,5 @@ bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b);
 static inline bool ether_addr_is_null(const struct ether_addr *addr) {
         return ether_addr_equal(addr, &ETHER_ADDR_NULL);
 }
+
+int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset);
diff --git a/src/systemd/src/basic/extract-word.c b/src/systemd/src/basic/extract-word.c
new file mode 100644
index 00000000..eb54daa3
--- /dev/null
+++ b/src/systemd/src/basic/extract-word.c
@@ -0,0 +1,302 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "nm-sd-adapt.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "alloc-util.h"
+#include "escape.h"
+#include "extract-word.h"
+#include "log.h"
+#include "macro.h"
+#include "string-util.h"
+#include "utf8.h"
+
+int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
+        _cleanup_free_ char *s = NULL;
+        size_t allocated = 0, sz = 0;
+        char c;
+        int r;
+
+        char quote = 0;                 /* 0 or ' or " */
+        bool backslash = false;         /* whether we've just seen a backslash */
+
+        assert(p);
+        assert(ret);
+
+        /* Bail early if called after last value or with no input */
+        if (!*p)
+                goto finish_force_terminate;
+        c = **p;
+
+        if (!separators)
+                separators = WHITESPACE;
+
+        /* Parses the first word of a string, and returns it in
+         * *ret. Removes all quotes in the process. When parsing fails
+         * (because of an uneven number of quotes or similar), leaves
+         * the pointer *p at the first invalid character. */
+
+        if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
+                if (!GREEDY_REALLOC(s, allocated, sz+1))
+                        return -ENOMEM;
+
+        for (;; (*p)++, c = **p) {
+                if (c == 0)
+                        goto finish_force_terminate;
+                else if (strchr(separators, c)) {
+                        if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
+                                (*p)++;
+                                goto finish_force_next;
+                        }
+                } else {
+                        /* We found a non-blank character, so we will always
+                         * want to return a string (even if it is empty),
+                         * allocate it here. */
+                        if (!GREEDY_REALLOC(s, allocated, sz+1))
+                                return -ENOMEM;
+                        break;
+                }
+        }
+
+        for (;; (*p)++, c = **p) {
+                if (backslash) {
+                        if (!GREEDY_REALLOC(s, allocated, sz+7))
+                                return -ENOMEM;
+
+                        if (c == 0) {
+                                if ((flags & EXTRACT_CUNESCAPE_RELAX) &&
+                                    (!quote || flags & EXTRACT_RELAX)) {
+                                        /* If we find an unquoted trailing backslash and we're in
+                                         * EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the
+                                         * output.
+                                         *
+                                         * Unbalanced quotes will only be allowed in EXTRACT_RELAX
+                                         * mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them.
+                                         */
+                                        s[sz++] = '\\';
+                                        goto finish_force_terminate;
+                                }
+                                if (flags & EXTRACT_RELAX)
+                                        goto finish_force_terminate;
+                                return -EINVAL;
+                        }
+
+                        if (flags & EXTRACT_CUNESCAPE) {
+                                bool eight_bit = false;
+                                char32_t u;
+
+                                r = cunescape_one(*p, (size_t) -1, &u, &eight_bit);
+                                if (r < 0) {
+                                        if (flags & EXTRACT_CUNESCAPE_RELAX) {
+                                                s[sz++] = '\\';
+                                                s[sz++] = c;
+                                        } else
+                                                return -EINVAL;
+                                } else {
+                                        (*p) += r - 1;
+
+                                        if (eight_bit)
+                                                s[sz++] = u;
+                                        else
+                                                sz += utf8_encode_unichar(s + sz, u);
+                                }
+                        } else
+                                s[sz++] = c;
+
+                        backslash = false;
+
+                } else if (quote) {     /* inside either single or double quotes */
+                        for (;; (*p)++, c = **p) {
+                                if (c == 0) {
+                                        if (flags & EXTRACT_RELAX)
+                                                goto finish_force_terminate;
+                                        return -EINVAL;
+                                } else if (c == quote) {        /* found the end quote */
+                                        quote = 0;
+                                        break;
+                                } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
+                                        backslash = true;
+                                        break;
+                                } else {
+                                        if (!GREEDY_REALLOC(s, allocated, sz+2))
+                                                return -ENOMEM;
+
+                                        s[sz++] = c;
+                                }
+                        }
+
+                } else {
+                        for (;; (*p)++, c = **p) {
+                                if (c == 0)
+                                        goto finish_force_terminate;
+                                else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
+                                        quote = c;
+                                        break;
+                                } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
+                                        backslash = true;
+                                        break;
+                                } else if (strchr(separators, c)) {
+                                        if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
+                                                (*p)++;
+                                                goto finish_force_next;
+                                        }
+                                        /* Skip additional coalesced separators. */
+                                        for (;; (*p)++, c = **p) {
+                                                if (c == 0)
+                                                        goto finish_force_terminate;
+                                                if (!strchr(separators, c))
+                                                        break;
+                                        }
+                                        goto finish;
+
+                                } else {
+                                        if (!GREEDY_REALLOC(s, allocated, sz+2))
+                                                return -ENOMEM;
+
+                                        s[sz++] = c;
+                                }
+                        }
+                }
+        }
+
+finish_force_terminate:
+        *p = NULL;
+finish:
+        if (!s) {
+                *p = NULL;
+                *ret = NULL;
+                return 0;
+        }
+
+finish_force_next:
+        s[sz] = 0;
+        *ret = s;
+        s = NULL;
+
+        return 1;
+}
+
+#if 0 /* NM_IGNORED */
+int extract_first_word_and_warn(
+                const char **p,
+                char **ret,
+                const char *separators,
+                ExtractFlags flags,
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *rvalue) {
+
+        /* Try to unquote it, if it fails, warn about it and try again
+         * but this time using EXTRACT_CUNESCAPE_RELAX to keep the
+         * backslashes verbatim in invalid escape sequences. */
+
+        const char *save;
+        int r;
+
+        save = *p;
+        r = extract_first_word(p, ret, separators, flags);
+        if (r >= 0)
+                return r;
+
+        if (r == -EINVAL && !(flags & EXTRACT_CUNESCAPE_RELAX)) {
+
+                /* Retry it with EXTRACT_CUNESCAPE_RELAX. */
+                *p = save;
+                r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX);
+                if (r >= 0) {
+                        /* It worked this time, hence it must have been an invalid escape sequence we could correct. */
+                        log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Invalid escape sequences in line, correcting: \"%s\"", rvalue);
+                        return r;
+                }
+
+                /* If it's still EINVAL; then it must be unbalanced quoting, report this. */
+                if (r == -EINVAL)
+                        return log_syntax(unit, LOG_ERR, filename, line, r, "Unbalanced quoting, ignoring: \"%s\"", rvalue);
+        }
+
+        /* Can be any error, report it */
+        return log_syntax(unit, LOG_ERR, filename, line, r, "Unable to decode word \"%s\", ignoring: %m", rvalue);
+}
+
+int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) {
+        va_list ap;
+        char **l;
+        int n = 0, i, c, r;
+
+        /* Parses a number of words from a string, stripping any
+         * quotes if necessary. */
+
+        assert(p);
+
+        /* Count how many words are expected */
+        va_start(ap, flags);
+        for (;;) {
+                if (!va_arg(ap, char **))
+                        break;
+                n++;
+        }
+        va_end(ap);
+
+        if (n <= 0)
+                return 0;
+
+        /* Read all words into a temporary array */
+        l = newa0(char*, n);
+        for (c = 0; c < n; c++) {
+
+                r = extract_first_word(p, &l[c], separators, flags);
+                if (r < 0) {
+                        int j;
+
+                        for (j = 0; j < c; j++)
+                                free(l[j]);
+
+                        return r;
+                }
+
+                if (r == 0)
+                        break;
+        }
+
+        /* If we managed to parse all words, return them in the passed
+         * in parameters */
+        va_start(ap, flags);
+        for (i = 0; i < n; i++) {
+                char **v;
+
+                v = va_arg(ap, char **);
+                assert(v);
+
+                *v = l[i];
+        }
+        va_end(ap);
+
+        return c;
+}
+#endif /* NM_IGNORED */
diff --git a/src/systemd/src/basic/extract-word.h b/src/systemd/src/basic/extract-word.h
new file mode 100644
index 00000000..21db5ef3
--- /dev/null
+++ b/src/systemd/src/basic/extract-word.h
@@ -0,0 +1,35 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "macro.h"
+
+typedef enum ExtractFlags {
+        EXTRACT_RELAX                    = 1,
+        EXTRACT_CUNESCAPE                = 2,
+        EXTRACT_CUNESCAPE_RELAX          = 4,
+        EXTRACT_QUOTES                   = 8,
+        EXTRACT_DONT_COALESCE_SEPARATORS = 16,
+        EXTRACT_RETAIN_ESCAPE            = 32,
+} ExtractFlags;
+
+int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
+int extract_first_word_and_warn(const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue);
+int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) _sentinel_;
diff --git a/src/systemd/src/basic/fd-util.c b/src/systemd/src/basic/fd-util.c
index e92b3740..c518f757 100644
--- a/src/systemd/src/basic/fd-util.c
+++ b/src/systemd/src/basic/fd-util.c
@@ -27,13 +27,13 @@
 #include <unistd.h>
 
 #include "fd-util.h"
+#include "fs-util.h"
 #include "macro.h"
-#if 0 /* NM_IGNORED */
 #include "missing.h"
-#endif /* NM_IGNORED */
 #include "parse-util.h"
 #include "path-util.h"
 #include "socket-util.h"
+#include "stdio-util.h"
 #include "util.h"
 
 int close_nointr(int fd) {
@@ -189,6 +189,12 @@ int fd_cloexec(int fd, bool cloexec) {
 }
 
 #if 0 /* NM_IGNORED */
+void stdio_unset_cloexec(void) {
+        fd_cloexec(STDIN_FILENO, false);
+        fd_cloexec(STDOUT_FILENO, false);
+        fd_cloexec(STDERR_FILENO, false);
+}
+
 _pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
         unsigned i;
 
@@ -234,7 +240,7 @@ int close_all_fds(const int except[], unsigned n_except) {
         while ((de = readdir(d))) {
                 int fd = -1;
 
-                if (hidden_file(de->d_name))
+                if (hidden_or_backup_file(de->d_name))
                         continue;
 
                 if (safe_atoi(de->d_name, &fd) < 0)
@@ -362,3 +368,17 @@ bool fdname_is_valid(const char *s) {
 
         return p - s < 256;
 }
+
+int fd_get_path(int fd, char **ret) {
+        char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+        int r;
+
+        xsprintf(procfs_path, "/proc/self/fd/%i", fd);
+
+        r = readlink_malloc(procfs_path, ret);
+
+        if (r == -ENOENT) /* If the file doesn't exist the fd is invalid */
+                return -EBADF;
+
+        return r;
+}
diff --git a/src/systemd/src/basic/fd-util.h b/src/systemd/src/basic/fd-util.h
index 44528c6e..34b98d4a 100644
--- a/src/systemd/src/basic/fd-util.h
+++ b/src/systemd/src/basic/fd-util.h
@@ -63,6 +63,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
 
 int fd_nonblock(int fd, bool nonblock);
 int fd_cloexec(int fd, bool cloexec);
+void stdio_unset_cloexec(void);
 
 int close_all_fds(const int except[], unsigned n_except);
 
@@ -72,6 +73,8 @@ void cmsg_close_all(struct msghdr *mh);
 
 bool fdname_is_valid(const char *s);
 
+int fd_get_path(int fd, char **ret);
+
 /* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
 #define ERRNO_IS_DISCONNECT(r) \
         IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)
diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c
index e940e10e..b2fe15ca 100644
--- a/src/systemd/src/basic/fileio.c
+++ b/src/systemd/src/basic/fileio.c
@@ -49,6 +49,8 @@
 #include "umask-util.h"
 #include "utf8.h"
 
+#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
+
 int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
 
         assert(f);
@@ -232,7 +234,7 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
         if (S_ISREG(st.st_mode)) {
 
                 /* Safety check */
-                if (st.st_size > 4*1024*1024)
+                if (st.st_size > READ_FULL_BYTES_MAX)
                         return -E2BIG;
 
                 /* Start with the right file size, but be prepared for
@@ -247,26 +249,31 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
                 char *t;
                 size_t k;
 
-                t = realloc(buf, n+1);
+                t = realloc(buf, n + 1);
                 if (!t)
                         return -ENOMEM;
 
                 buf = t;
                 k = fread(buf + l, 1, n - l, f);
+                if (k > 0)
+                        l += k;
 
-                if (k <= 0) {
-                        if (ferror(f))
-                                return -errno;
+                if (ferror(f))
+                        return -errno;
 
+                if (feof(f))
                         break;
-                }
 
-                l += k;
-                n *= 2;
+                /* We aren't expecting fread() to return a short read outside
+                 * of (error && eof), assert buffer is full and enlarge buffer.
+                 */
+                assert(l == n);
 
                 /* Safety check */
-                if (n > 4*1024*1024)
+                if (n >= READ_FULL_BYTES_MAX)
                         return -E2BIG;
+
+                n = MIN(n * 2, READ_FULL_BYTES_MAX);
         }
 
         buf[l] = 0;
@@ -1071,7 +1078,7 @@ int fflush_and_check(FILE *f) {
         return 0;
 }
 
-/* This is much like like mkostemp() but is subject to umask(). */
+/* This is much like mkostemp() but is subject to umask(). */
 int mkostemp_safe(char *pattern, int flags) {
         _cleanup_umask_ mode_t u = 0;
         int fd;
@@ -1087,30 +1094,6 @@ int mkostemp_safe(char *pattern, int flags) {
         return fd;
 }
 
-int open_tmpfile(const char *path, int flags) {
-        char *p;
-        int fd;
-
-        assert(path);
-
-#ifdef O_TMPFILE
-        /* Try O_TMPFILE first, if it is supported */
-        fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
-        if (fd >= 0)
-                return fd;
-#endif
-
-        /* Fall back to unguessable name + unlinking */
-        p = strjoina(path, "/systemd-tmp-XXXXXX");
-
-        fd = mkostemp_safe(p, flags);
-        if (fd < 0)
-                return fd;
-
-        unlink(p);
-        return fd;
-}
-
 int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
         const char *fn;
         char *t;
@@ -1185,12 +1168,13 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
         return 0;
 }
 
+#if 0 /* NM_IGNORED */
 int tempfn_random_child(const char *p, const char *extra, char **ret) {
         char *t, *x;
         uint64_t u;
         unsigned i;
+        int r;
 
-        assert(p);
         assert(ret);
 
         /* Turns this:
@@ -1199,6 +1183,12 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
          *         /foo/bar/waldo/.#<extra>3c2b6219aa75d7d0
          */
 
+        if (!p) {
+                r = tmp_dir(&p);
+                if (r < 0)
+                        return r;
+        }
+
         if (!extra)
                 extra = "";
 
@@ -1220,7 +1210,6 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
         return 0;
 }
 
-#if 0 /* NM_IGNORED */
 int write_timestamp_file_atomic(const char *fn, usec_t n) {
         char ln[DECIMAL_STR_MAX(n)+2];
 
@@ -1234,7 +1223,6 @@ int write_timestamp_file_atomic(const char *fn, usec_t n) {
 
         return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
 }
-#endif /* NM_IGNORED */
 
 int read_timestamp_file(const char *fn, usec_t *ret) {
         _cleanup_free_ char *ln = NULL;
@@ -1255,6 +1243,7 @@ int read_timestamp_file(const char *fn, usec_t *ret) {
         *ret = (usec_t) t;
         return 0;
 }
+#endif /* NM_IGNORED */
 
 int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) {
         int r;
@@ -1284,3 +1273,150 @@ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space)
 
         return fputs(s, f);
 }
+
+#if 0 /* NM_IGNORED */
+int open_tmpfile_unlinkable(const char *directory, int flags) {
+        char *p;
+        int fd, r;
+
+        if (!directory) {
+                r = tmp_dir(&directory);
+                if (r < 0)
+                        return r;
+        }
+
+        /* Returns an unlinked temporary file that cannot be linked into the file system anymore */
+
+#ifdef O_TMPFILE
+        /* Try O_TMPFILE first, if it is supported */
+        fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
+        if (fd >= 0)
+                return fd;
+#endif
+
+        /* Fall back to unguessable name + unlinking */
+        p = strjoina(directory, "/systemd-tmp-XXXXXX");
+
+        fd = mkostemp_safe(p, flags);
+        if (fd < 0)
+                return fd;
+
+        (void) unlink(p);
+
+        return fd;
+}
+
+int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
+        _cleanup_free_ char *tmp = NULL;
+        int r, fd;
+
+        assert(target);
+        assert(ret_path);
+
+        /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */
+        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
+         * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
+
+#ifdef O_TMPFILE
+        {
+                _cleanup_free_ char *dn = NULL;
+
+                dn = dirname_malloc(target);
+                if (!dn)
+                        return -ENOMEM;
+
+                fd = open(dn, O_TMPFILE|flags, 0640);
+                if (fd >= 0) {
+                        *ret_path = NULL;
+                        return fd;
+                }
+
+                log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn);
+        }
+#endif
+
+        r = tempfn_random(target, NULL, &tmp);
+        if (r < 0)
+                return r;
+
+        fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640);
+        if (fd < 0)
+                return -errno;
+
+        *ret_path = tmp;
+        tmp = NULL;
+
+        return fd;
+}
+
+int link_tmpfile(int fd, const char *path, const char *target) {
+
+        assert(fd >= 0);
+        assert(target);
+
+        /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd
+         * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported
+         * on the directory, and renameat2() is used instead.
+         *
+         * Note that in both cases we will not replace existing files. This is because linkat() does not support this
+         * 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;
+        } else {
+                char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1];
+
+                xsprintf(proc_fd_path, "/proc/self/fd/%i", fd);
+
+                if (linkat(AT_FDCWD, proc_fd_path, AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0)
+                        return -errno;
+        }
+
+        return 0;
+}
+
+int read_nul_string(FILE *f, char **ret) {
+        _cleanup_free_ char *x = NULL;
+        size_t allocated = 0, n = 0;
+
+        assert(f);
+        assert(ret);
+
+        /* Reads a NUL-terminated string from the specified file. */
+
+        for (;;) {
+                int c;
+
+                if (!GREEDY_REALLOC(x, allocated, n+2))
+                        return -ENOMEM;
+
+                c = fgetc(f);
+                if (c == 0) /* Terminate at NUL byte */
+                        break;
+                if (c == EOF) {
+                        if (ferror(f))
+                                return -errno;
+                        break; /* Terminate at EOF */
+                }
+
+                x[n++] = (char) c;
+        }
+
+        if (x)
+                x[n] = 0;
+        else {
+                x = new0(char, 1);
+                if (!x)
+                        return -ENOMEM;
+        }
+
+        *ret = x;
+        x = NULL;
+
+        return 0;
+}
+#endif /* NM_IGNORED */
diff --git a/src/systemd/src/basic/fileio.h b/src/systemd/src/basic/fileio.h
index 8084895f..9ac497d9 100644
--- a/src/systemd/src/basic/fileio.h
+++ b/src/systemd/src/basic/fileio.h
@@ -72,7 +72,6 @@ int fflush_and_check(FILE *f);
 
 int fopen_temporary(const char *path, FILE **_f, char **_temp_path);
 int mkostemp_safe(char *pattern, int flags);
-int open_tmpfile(const char *path, int flags);
 
 int tempfn_xxxxxx(const char *p, const char *extra, char **ret);
 int tempfn_random(const char *p, const char *extra, char **ret);
@@ -82,3 +81,10 @@ int write_timestamp_file_atomic(const char *fn, usec_t n);
 int read_timestamp_file(const char *fn, usec_t *ret);
 
 int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space);
+
+int open_tmpfile_unlinkable(const char *directory, int flags);
+int open_tmpfile_linkable(const char *target, int flags, char **ret_path);
+
+int link_tmpfile(int fd, const char *path, const char *target);
+
+int read_nul_string(FILE *f, char **ret);
diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c
index 9a843644..de0cd8fb 100644
--- a/src/systemd/src/basic/fs-util.c
+++ b/src/systemd/src/basic/fs-util.c
@@ -30,26 +30,22 @@
 #include <unistd.h>
 
 #include "alloc-util.h"
-#if 0 /* NM_IGNORED */
 #include "dirent-util.h"
-#endif /* NM_IGNORED */
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
 #include "log.h"
 #include "macro.h"
-#if 0 /* NM_IGNORED */
 #include "missing.h"
 #include "mkdir.h"
-#endif /* NM_IGNORED */
 #include "parse-util.h"
 #include "path-util.h"
+#include "stat-util.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "time-util.h"
-#if 0 /* NM_IGNORED */
 #include "user-util.h"
-#endif /* NM_IGNORED */
 #include "util.h"
 
 int unlink_noerrno(const char *path) {
@@ -151,6 +147,7 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
 
         return 0;
 }
+#endif /* NM_IGNORED */
 
 int readlinkat_malloc(int fd, const char *p, char **ret) {
         size_t l = 100;
@@ -189,6 +186,7 @@ int readlink_malloc(const char *p, char **ret) {
         return readlinkat_malloc(AT_FDCWD, p, ret);
 }
 
+#if 0 /* NM_IGNORED */
 int readlink_value(const char *p, char **ret) {
         _cleanup_free_ char *link = NULL;
         char *value;
@@ -504,4 +502,106 @@ int get_files_in_directory(const char *path, char ***list) {
 
         return n;
 }
+
+static int getenv_tmp_dir(const char **ret_path) {
+        const char *n;
+        int r, ret = 0;
+
+        assert(ret_path);
+
+        /* We use the same order of environment variables python uses in tempfile.gettempdir():
+         * https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */
+        FOREACH_STRING(n, "TMPDIR", "TEMP", "TMP") {
+                const char *e;
+
+                e = secure_getenv(n);
+                if (!e)
+                        continue;
+                if (!path_is_absolute(e)) {
+                        r = -ENOTDIR;
+                        goto next;
+                }
+                if (!path_is_safe(e)) {
+                        r = -EPERM;
+                        goto next;
+                }
+
+                r = is_dir(e, true);
+                if (r < 0)
+                        goto next;
+                if (r == 0) {
+                        r = -ENOTDIR;
+                        goto next;
+                }
+
+                *ret_path = e;
+                return 1;
+
+        next:
+                /* Remember first error, to make this more debuggable */
+                if (ret >= 0)
+                        ret = r;
+        }
+
+        if (ret < 0)
+                return ret;
+
+        *ret_path = NULL;
+        return ret;
+}
+
+static int tmp_dir_internal(const char *def, const char **ret) {
+        const char *e;
+        int r, k;
+
+        assert(def);
+        assert(ret);
+
+        r = getenv_tmp_dir(&e);
+        if (r > 0) {
+                *ret = e;
+                return 0;
+        }
+
+        k = is_dir(def, true);
+        if (k == 0)
+                k = -ENOTDIR;
+        if (k < 0)
+                return r < 0 ? r : k;
+
+        *ret = def;
+        return 0;
+}
+
+int var_tmp_dir(const char **ret) {
+
+        /* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus
+         * even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is
+         * returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR,
+         * making it a variable that overrides all temporary file storage locations. */
+
+        return tmp_dir_internal("/var/tmp", ret);
+}
+
+int tmp_dir(const char **ret) {
+
+        /* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually
+         * backed by an in-memory file system: /tmp. */
+
+        return tmp_dir_internal("/tmp", ret);
+}
+
+int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
+        char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
+        int r;
+
+        /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
+        xsprintf(path, "/proc/self/fd/%i", what);
+
+        r = inotify_add_watch(fd, path, mask);
+        if (r < 0)
+                return -errno;
+
+        return r;
+}
 #endif /* NM_IGNORED */
diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h
index 0d23f863..2c3b9a1c 100644
--- a/src/systemd/src/basic/fs-util.h
+++ b/src/systemd/src/basic/fs-util.h
@@ -61,6 +61,9 @@ int mkfifo_atomic(const char *path, mode_t mode);
 
 int get_files_in_directory(const char *path, char ***list);
 
+int tmp_dir(const char **ret);
+int var_tmp_dir(const char **ret);
+
 #define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
 
 #define FOREACH_INOTIFY_EVENT(e, buffer, sz) \
@@ -72,3 +75,5 @@ union inotify_event_buffer {
         struct inotify_event ev;
         uint8_t raw[INOTIFY_EVENT_MAX];
 };
+
+int inotify_add_watch_fd(int fd, int what, uint32_t mask);
diff --git a/src/systemd/src/basic/hashmap.c b/src/systemd/src/basic/hashmap.c
index 4df3ae73..dc6bcab0 100644
--- a/src/systemd/src/basic/hashmap.c
+++ b/src/systemd/src/basic/hashmap.c
@@ -29,9 +29,7 @@
 #include "hashmap.h"
 #include "macro.h"
 #include "mempool.h"
-#if 0 /* NM_IGNORED */
 #include "process-util.h"
-#endif /* NM_IGNORED */
 #include "random-util.h"
 #include "set.h"
 #include "siphash24.h"
@@ -1768,6 +1766,9 @@ void *ordered_hashmap_next(OrderedHashmap *h, const void *key) {
 int set_consume(Set *s, void *value) {
         int r;
 
+        assert(s);
+        assert(value);
+
         r = set_put(s, value);
         if (r <= 0)
                 free(value);
@@ -1777,26 +1778,26 @@ int set_consume(Set *s, void *value) {
 
 int set_put_strdup(Set *s, const char *p) {
         char *c;
-        int r;
 
         assert(s);
         assert(p);
 
+        if (set_contains(s, (char*) p))
+                return 0;
+
         c = strdup(p);
         if (!c)
                 return -ENOMEM;
 
-        r = set_consume(s, c);
-        if (r == -EEXIST)
-                return 0;
-
-        return r;
+        return set_consume(s, c);
 }
 
 int set_put_strdupv(Set *s, char **l) {
         int n = 0, r;
         char **i;
 
+        assert(s);
+
         STRV_FOREACH(i, l) {
                 r = set_put_strdup(s, *i);
                 if (r < 0)
@@ -1807,3 +1808,23 @@ int set_put_strdupv(Set *s, char **l) {
 
         return n;
 }
+
+int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags) {
+        const char *p = v;
+        int r;
+
+        assert(s);
+        assert(v);
+
+        for (;;) {
+                char *word;
+
+                r = extract_first_word(&p, &word, separators, flags);
+                if (r <= 0)
+                        return r;
+
+                r = set_consume(s, word);
+                if (r < 0)
+                        return r;
+        }
+}
diff --git a/src/systemd/src/basic/hostname-util.c b/src/systemd/src/basic/hostname-util.c
index ee48b86d..480f9d9d 100644
--- a/src/systemd/src/basic/hostname-util.c
+++ b/src/systemd/src/basic/hostname-util.c
@@ -180,16 +180,16 @@ bool is_localhost(const char *hostname) {
         assert(hostname);
 
         /* This tries to identify local host and domain names
-         * described in RFC6761 plus the redhatism of .localdomain */
+         * described in RFC6761 plus the redhatism of localdomain */
 
         return strcaseeq(hostname, "localhost") ||
                strcaseeq(hostname, "localhost.") ||
-               strcaseeq(hostname, "localdomain.") ||
-               strcaseeq(hostname, "localdomain") ||
+               strcaseeq(hostname, "localhost.localdomain") ||
+               strcaseeq(hostname, "localhost.localdomain.") ||
                endswith_no_case(hostname, ".localhost") ||
                endswith_no_case(hostname, ".localhost.") ||
-               endswith_no_case(hostname, ".localdomain") ||
-               endswith_no_case(hostname, ".localdomain.");
+               endswith_no_case(hostname, ".localhost.localdomain") ||
+               endswith_no_case(hostname, ".localhost.localdomain.");
 }
 
 #if 0 /* NM_IGNORED */
diff --git a/src/systemd/src/basic/in-addr-util.c b/src/systemd/src/basic/in-addr-util.c
index 10898dae..95230e7d 100644
--- a/src/systemd/src/basic/in-addr-util.c
+++ b/src/systemd/src/basic/in-addr-util.c
@@ -22,26 +22,36 @@
 #include <arpa/inet.h>
 #include <endian.h>
 #include <errno.h>
+#include <net/if.h>
 #include <stdint.h>
 #include <stdlib.h>
 
 #include "alloc-util.h"
 #include "in-addr-util.h"
 #include "macro.h"
+#include "parse-util.h"
 #include "util.h"
 
+bool in4_addr_is_null(const struct in_addr *a) {
+        return a->s_addr == 0;
+}
+
+bool in6_addr_is_null(const struct in6_addr *a) {
+        return
+                a->s6_addr32[0] == 0 &&
+                a->s6_addr32[1] == 0 &&
+                a->s6_addr32[2] == 0 &&
+                a->s6_addr32[3] == 0;
+}
+
 int in_addr_is_null(int family, const union in_addr_union *u) {
         assert(u);
 
         if (family == AF_INET)
-                return u->in.s_addr == 0;
+                return in4_addr_is_null(&u->in);
 
         if (family == AF_INET6)
-                return
-                        u->in6.s6_addr32[0] == 0 &&
-                        u->in6.s6_addr32[1] == 0 &&
-                        u->in6.s6_addr32[2] == 0 &&
-                        u->in6.s6_addr32[3] == 0;
+                return in6_addr_is_null(&u->in6);
 
         return -EAFNOSUPPORT;
 }
@@ -226,6 +236,48 @@ int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
         return 0;
 }
 
+int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) {
+        size_t l;
+        char *x;
+        int r;
+
+        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. */
+
+        if (family != AF_INET6)
+                goto fallback;
+        if (ifindex <= 0)
+                goto fallback;
+
+        r = in_addr_is_link_local(family, u);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                goto fallback;
+
+        l = INET6_ADDRSTRLEN + 1 + DECIMAL_STR_MAX(ifindex) + 1;
+        x = new(char, l);
+        if (!x)
+                return -ENOMEM;
+
+        errno = 0;
+        if (!inet_ntop(family, u, x, l)) {
+                free(x);
+                return errno > 0 ? -errno : -EINVAL;
+        }
+
+        sprintf(strchr(x, 0), "%%%i", ifindex);
+        *ret = x;
+
+        return 0;
+
+fallback:
+        return in_addr_to_string(family, u, ret);
+}
+
 int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
 
         assert(s);
@@ -263,6 +315,47 @@ int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *re
         return -EINVAL;
 }
 
+int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex) {
+        const char *suffix;
+        int r, ifi = 0;
+
+        assert(s);
+        assert(family);
+        assert(ret);
+
+        /* Similar to in_addr_from_string_auto() but also parses an optionally appended IPv6 zone suffix ("scope id")
+         * if one is found. */
+
+        suffix = strchr(s, '%');
+        if (suffix) {
+
+                if (ifindex) {
+                        /* If we shall return the interface index, try to parse it */
+                        r = parse_ifindex(suffix + 1, &ifi);
+                        if (r < 0) {
+                                unsigned u;
+
+                                u = if_nametoindex(suffix + 1);
+                                if (u <= 0)
+                                        return -errno;
+
+                                ifi = (int) u;
+                        }
+                }
+
+                s = strndupa(s, suffix - s);
+        }
+
+        r = in_addr_from_string_auto(s, family, ret);
+        if (r < 0)
+                return r;
+
+        if (ifindex)
+                *ifindex = ifi;
+
+        return r;
+}
+
 unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr) {
         assert(addr);
 
diff --git a/src/systemd/src/basic/in-addr-util.h b/src/systemd/src/basic/in-addr-util.h
index 17798ce8..d60064ae 100644
--- a/src/systemd/src/basic/in-addr-util.h
+++ b/src/systemd/src/basic/in-addr-util.h
@@ -36,6 +36,9 @@ struct in_addr_data {
         union in_addr_union address;
 };
 
+bool in4_addr_is_null(const struct in_addr *a);
+bool in6_addr_is_null(const struct in6_addr *a);
+
 int in_addr_is_null(int family, const union in_addr_union *u);
 int in_addr_is_link_local(int family, const union in_addr_union *u);
 int in_addr_is_localhost(int family, const union in_addr_union *u);
@@ -43,8 +46,10 @@ int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_
 int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
 int in_addr_prefix_next(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_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, 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 *family, union in_addr_union *ret);
+int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex);
 unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr);
 struct in_addr* in_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen);
 int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen);
diff --git a/src/systemd/src/basic/io-util.c b/src/systemd/src/basic/io-util.c
index aaf414f4..61b667f0 100644
--- a/src/systemd/src/basic/io-util.c
+++ b/src/systemd/src/basic/io-util.c
@@ -35,6 +35,11 @@ int flush_fd(int fd) {
                 .events = POLLIN,
         };
 
+        /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
+         * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
+         * (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used
+         * was set to non-blocking too. */
+
         for (;;) {
                 char buf[LINE_MAX];
                 ssize_t l;
diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h
index d6a877ea..7db87b49 100644
--- a/src/systemd/src/basic/macro.h
+++ b/src/systemd/src/basic/macro.h
@@ -98,6 +98,15 @@
 #define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
 #define UNIQ __COUNTER__
 
+/* builtins */
+#if __SIZEOF_INT__ == 4
+#define BUILTIN_FFS_U32(x) __builtin_ffs(x);
+#elif __SIZEOF_LONG__ == 4
+#define BUILTIN_FFS_U32(x) __builtin_ffsl(x);
+#else
+#error "neither int nor long are four bytes long?!?"
+#endif
+
 /* Rounds up */
 
 #define ALIGN4(l) (((l) + 3) & ~3)
diff --git a/src/systemd/src/basic/parse-util.c b/src/systemd/src/basic/parse-util.c
index eb53c42d..27386631 100644
--- a/src/systemd/src/basic/parse-util.c
+++ b/src/systemd/src/basic/parse-util.c
@@ -28,11 +28,10 @@
 #include <xlocale.h>
 
 #include "alloc-util.h"
-#if 0 /* NM_IGNORED */
 #include "extract-word.h"
-#endif /* NM_IGNORED */
 #include "macro.h"
 #include "parse-util.h"
+#include "process-util.h"
 #include "string-util.h"
 
 int parse_boolean(const char *v) {
@@ -538,3 +537,46 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) {
 
         return 0;
 }
+
+int parse_percent_unbounded(const char *p) {
+        const char *pc, *n;
+        unsigned v;
+        int r;
+
+        pc = endswith(p, "%");
+        if (!pc)
+                return -EINVAL;
+
+        n = strndupa(p, pc - p);
+        r = safe_atou(n, &v);
+        if (r < 0)
+                return r;
+
+        return (int) v;
+}
+
+int parse_percent(const char *p) {
+        int v;
+
+        v = parse_percent_unbounded(p);
+        if (v > 100)
+                return -ERANGE;
+
+        return v;
+}
+
+#if 0 /* NM_IGNORED */
+int parse_nice(const char *p, int *ret) {
+        int n, r;
+
+        r = safe_atoi(p, &n);
+        if (r < 0)
+                return r;
+
+        if (!nice_is_valid(n))
+                return -ERANGE;
+
+        *ret = n;
+        return 0;
+}
+#endif /* NM_IGNORED */
diff --git a/src/systemd/src/basic/parse-util.h b/src/systemd/src/basic/parse-util.h
index d8dc26a3..461e1cd4 100644
--- a/src/systemd/src/basic/parse-util.h
+++ b/src/systemd/src/basic/parse-util.h
@@ -90,6 +90,23 @@ static inline int safe_atoli(const char *s, long int *ret_u) {
 }
 #endif
 
+#if SIZE_MAX == UINT_MAX
+static inline int safe_atozu(const char *s, size_t *ret_u) {
+        assert_cc(sizeof(size_t) == sizeof(unsigned));
+        return safe_atou(s, (unsigned *) ret_u);
+}
+#else
+static inline int safe_atozu(const char *s, size_t *ret_u) {
+        assert_cc(sizeof(size_t) == sizeof(long unsigned));
+        return safe_atolu(s, ret_u);
+}
+#endif
+
 int safe_atod(const char *s, double *ret_d);
 
 int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
+
+int parse_percent_unbounded(const char *p);
+int parse_percent(const char *p);
+
+int parse_nice(const char *p, int *ret);
diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c
index c3b7d187..86d35bbe 100644
--- a/src/systemd/src/basic/path-util.c
+++ b/src/systemd/src/basic/path-util.c
@@ -34,19 +34,13 @@
 #undef basename
 
 #include "alloc-util.h"
-#if 0 /* NM_IGNORED */
 #include "extract-word.h"
-#endif /* NM_IGNORED */
 #include "fs-util.h"
 #include "log.h"
 #include "macro.h"
-#if 0 /* NM_IGNORED */
 #include "missing.h"
-#endif /* NM_IGNORED */
 #include "path-util.h"
-#if 0 /* NM_IGNORED */
 #include "stat-util.h"
-#endif /* NM_IGNORED */
 #include "string-util.h"
 #include "strv.h"
 #include "time-util.h"
@@ -580,10 +574,10 @@ static int binary_is_good(const char *binary) {
         if (r < 0)
                 return r;
 
-        return !path_equal(d, "true") &&
-               !path_equal(d, "/bin/true") &&
-               !path_equal(d, "/usr/bin/true") &&
-               !path_equal(d, "/dev/null");
+        return !PATH_IN_SET(d, "true"
+                               "/bin/true",
+                               "/usr/bin/true",
+                               "/dev/null");
 }
 
 int fsck_exists(const char *fstype) {
@@ -769,34 +763,53 @@ char *file_in_same_dir(const char *path, const char *filename) {
         return ret;
 }
 
-bool hidden_file_allow_backup(const char *filename) {
-        assert(filename);
-
-        return
-                filename[0] == '.' ||
-                streq(filename, "lost+found") ||
-                streq(filename, "aquota.user") ||
-                streq(filename, "aquota.group") ||
-                endswith(filename, ".rpmnew") ||
-                endswith(filename, ".rpmsave") ||
-                endswith(filename, ".rpmorig") ||
-                endswith(filename, ".dpkg-old") ||
-                endswith(filename, ".dpkg-new") ||
-                endswith(filename, ".dpkg-tmp") ||
-                endswith(filename, ".dpkg-dist") ||
-                endswith(filename, ".dpkg-bak") ||
-                endswith(filename, ".dpkg-backup") ||
-                endswith(filename, ".dpkg-remove") ||
-                endswith(filename, ".swp");
-}
+bool hidden_or_backup_file(const char *filename) {
+        const char *p;
 
-bool hidden_file(const char *filename) {
         assert(filename);
 
-        if (endswith(filename, "~"))
+        if (filename[0] == '.' ||
+            streq(filename, "lost+found") ||
+            streq(filename, "aquota.user") ||
+            streq(filename, "aquota.group") ||
+            endswith(filename, "~"))
                 return true;
 
-        return hidden_file_allow_backup(filename);
+        p = strrchr(filename, '.');
+        if (!p)
+                return false;
+
+        /* Please, let's not add more entries to the list below. If external projects think it's a good idea to come up
+         * with always new suffixes and that everybody else should just adjust to that, then it really should be on
+         * them. Hence, in future, let's not add any more entries. Instead, let's ask those packages to instead adopt
+         * one of the generic suffixes/prefixes for hidden files or backups, possibly augmented with an additional
+         * string. Specifically: there's now:
+         *
+         *    The generic suffixes "~" and ".bak" for backup files
+         *    The generic prefix "." for hidden files
+         *
+         * Thus, if a new package manager "foopkg" wants its own set of ".foopkg-new", ".foopkg-old", ".foopkg-dist"
+         * or so registered, let's refuse that and ask them to use ".foopkg.new", ".foopkg.old" or ".foopkg~" instead.
+         */
+
+        return STR_IN_SET(p + 1,
+                          "rpmnew",
+                          "rpmsave",
+                          "rpmorig",
+                          "dpkg-old",
+                          "dpkg-new",
+                          "dpkg-tmp",
+                          "dpkg-dist",
+                          "dpkg-bak",
+                          "dpkg-backup",
+                          "dpkg-remove",
+                          "ucf-new",
+                          "ucf-old",
+                          "ucf-dist",
+                          "swp",
+                          "bak",
+                          "old",
+                          "new");
 }
 
 bool is_device_path(const char *path) {
diff --git a/src/systemd/src/basic/path-util.h b/src/systemd/src/basic/path-util.h
index 2c2f87a9..a27c13fc 100644
--- a/src/systemd/src/basic/path-util.h
+++ b/src/systemd/src/basic/path-util.h
@@ -48,6 +48,23 @@ bool path_equal(const char *a, const char *b) _pure_;
 bool path_equal_or_files_same(const char *a, const char *b);
 char* path_join(const char *root, const char *path, const char *rest);
 
+static inline bool path_equal_ptr(const char *a, const char *b) {
+        return !!a == !!b && (!a || path_equal(a, b));
+}
+
+/* Note: the search terminates on the first NULL item. */
+#define PATH_IN_SET(p, ...)                                     \
+        ({                                                      \
+                char **s;                                       \
+                bool _found = false;                            \
+                STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__))         \
+                        if (path_equal(p, *s)) {                \
+                               _found = true;                   \
+                               break;                           \
+                        }                                       \
+                _found;                                         \
+        })
+
 int path_strv_make_absolute_cwd(char **l);
 char** path_strv_resolve(char **l, const char *prefix);
 char** path_strv_resolve_uniq(char **l, const char *prefix);
@@ -105,7 +122,6 @@ bool path_is_safe(const char *p) _pure_;
 
 char *file_in_same_dir(const char *path, const char *filename);
 
-bool hidden_file_allow_backup(const char *filename);
-bool hidden_file(const char *filename) _pure_;
+bool hidden_or_backup_file(const char *filename) _pure_;
 
 bool is_device_path(const char *path);
diff --git a/src/systemd/src/basic/random-util.c b/src/systemd/src/basic/random-util.c
index 5500fd28..1d8ca882 100644
--- a/src/systemd/src/basic/random-util.c
+++ b/src/systemd/src/basic/random-util.c
@@ -34,9 +34,7 @@
 
 #include "fd-util.h"
 #include "io-util.h"
-#if 0 /* NM_IGNORED */
 #include "missing.h"
-#endif
 #include "random-util.h"
 #include "time-util.h"
 
@@ -51,7 +49,7 @@ int dev_urandom(void *p, size_t n) {
          * never block, and will always return some data from the
          * kernel, regardless if the random pool is fully initialized
          * or not. It thus makes no guarantee for the quality of the
-         * returned entropy, but is good enough for or usual usecases
+         * returned entropy, but is good enough for our usual usecases
          * of seeding the hash functions for hashtable */
 
         /* Use the getrandom() syscall unless we know we don't have
diff --git a/src/systemd/src/basic/set.h b/src/systemd/src/basic/set.h
index e0d9dd00..a5f8beb0 100644
--- a/src/systemd/src/basic/set.h
+++ b/src/systemd/src/basic/set.h
@@ -19,11 +19,12 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include "extract-word.h"
 #include "hashmap.h"
 #include "macro.h"
 
-Set *internal_set_new(const struct hash_ops *hash_ops  HASHMAP_DEBUG_PARAMS);
-#define set_new(ops) internal_set_new(ops  HASHMAP_DEBUG_SRC_ARGS)
+Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
+#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
 
 static inline Set *set_free(Set *s) {
         internal_hashmap_free(HASHMAP_BASE(s));
@@ -41,8 +42,8 @@ static inline Set *set_copy(Set *s) {
         return (Set*) internal_hashmap_copy(HASHMAP_BASE(s));
 }
 
-int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops  HASHMAP_DEBUG_PARAMS);
-#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops  HASHMAP_DEBUG_SRC_ARGS)
+int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
+#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
 
 int set_put(Set *s, const void *key);
 /* no set_update */
@@ -122,6 +123,7 @@ static inline char **set_get_strv(Set *s) {
 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_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags);
 
 #define SET_FOREACH(e, s, i) \
         for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); )
diff --git a/src/systemd/src/basic/signal-util.h b/src/systemd/src/basic/signal-util.h
new file mode 100644
index 00000000..dfd6eb56
--- /dev/null
+++ b/src/systemd/src/basic/signal-util.h
@@ -0,0 +1,56 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010-2015 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <signal.h>
+
+#include "macro.h"
+
+int reset_all_signal_handlers(void);
+int reset_signal_mask(void);
+
+int ignore_signals(int sig, ...);
+int default_signals(int sig, ...);
+int sigaction_many(const struct sigaction *sa, ...);
+
+int sigset_add_many(sigset_t *ss, ...);
+int sigprocmask_many(int how, sigset_t *old, ...);
+
+const char *signal_to_string(int i) _const_;
+int signal_from_string(const char *s) _pure_;
+
+int signal_from_string_try_harder(const char *s);
+
+void nop_signal_handler(int sig);
+
+static inline void block_signals_reset(sigset_t *ss) {
+        assert_se(sigprocmask(SIG_SETMASK, ss, NULL) >= 0);
+}
+
+#define BLOCK_SIGNALS(...)                                                        \
+        _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({       \
+                sigset_t t;                                                       \
+                assert_se(sigprocmask_many(SIG_BLOCK, &t, __VA_ARGS__, -1) >= 0); \
+                t;                                                                \
+        })
+
+static inline bool SIGNAL_VALID(int signo) {
+        return signo > 0 && signo < _NSIG;
+}
diff --git a/src/systemd/src/basic/siphash24.c b/src/systemd/src/basic/siphash24.c
index 145f64b2..4db444f5 100644
--- a/src/systemd/src/basic/siphash24.c
+++ b/src/systemd/src/basic/siphash24.c
@@ -19,6 +19,8 @@
 
 #include "nm-sd-adapt.h"
 
+#include <stdio.h>
+
 #include "macro.h"
 #include "siphash24.h"
 #include "unaligned.h"
diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c
index c68db7c3..be57d829 100644
--- a/src/systemd/src/basic/socket-util.c
+++ b/src/systemd/src/basic/socket-util.c
@@ -25,6 +25,7 @@
 #include <net/if.h>
 #include <netdb.h>
 #include <netinet/ip.h>
+#include <poll.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -35,22 +36,18 @@
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "fileio.h"
-#if 0 /* NM_IGNORED */
 #include "formats-util.h"
-#endif /* NM_IGNORED */
 #include "log.h"
 #include "macro.h"
-#if 0 /* NM_IGNORED */
 #include "missing.h"
-#endif /* NM_IGNORED */
 #include "parse-util.h"
 #include "path-util.h"
 #include "socket-util.h"
 #include "string-table.h"
 #include "string-util.h"
-#if 0 /* NM_IGNORED */
+#include "strv.h"
 #include "user-util.h"
-#endif /* NM_IGNORED */
+#include "utf8.h"
 #include "util.h"
 
 #if 0 /* NM_IGNORED */
@@ -91,7 +88,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                         return -EINVAL;
 
                 a->sockaddr.in6.sin6_family = AF_INET6;
-                a->sockaddr.in6.sin6_port = htons((uint16_t) u);
+                a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
                 a->size = sizeof(struct sockaddr_in6);
 
         } else if (*s == '/') {
@@ -139,7 +136,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                         if (r > 0) {
                                 /* Gotcha, it's a traditional IPv4 address */
                                 a->sockaddr.in.sin_family = AF_INET;
-                                a->sockaddr.in.sin_port = htons((uint16_t) u);
+                                a->sockaddr.in.sin_port = htobe16((uint16_t)u);
                                 a->size = sizeof(struct sockaddr_in);
                         } else {
                                 unsigned idx;
@@ -153,7 +150,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
                                         return -EINVAL;
 
                                 a->sockaddr.in6.sin6_family = AF_INET6;
-                                a->sockaddr.in6.sin6_port = htons((uint16_t) u);
+                                a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
                                 a->sockaddr.in6.sin6_scope_id = idx;
                                 a->sockaddr.in6.sin6_addr = in6addr_any;
                                 a->size = sizeof(struct sockaddr_in6);
@@ -170,12 +167,12 @@ int socket_address_parse(SocketAddress *a, const char *s) {
 
                         if (socket_ipv6_is_supported()) {
                                 a->sockaddr.in6.sin6_family = AF_INET6;
-                                a->sockaddr.in6.sin6_port = htons((uint16_t) u);
+                                a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
                                 a->sockaddr.in6.sin6_addr = in6addr_any;
                                 a->size = sizeof(struct sockaddr_in6);
                         } else {
                                 a->sockaddr.in.sin_family = AF_INET;
-                                a->sockaddr.in.sin_port = htons((uint16_t) u);
+                                a->sockaddr.in.sin_port = htobe16((uint16_t)u);
                                 a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
                                 a->size = sizeof(struct sockaddr_in);
                         }
@@ -494,9 +491,7 @@ int sockaddr_port(const struct sockaddr *_sa) {
         if (!IN_SET(sa->sa.sa_family, AF_INET, AF_INET6))
                 return -EAFNOSUPPORT;
 
-        return ntohs(sa->sa.sa_family == AF_INET6 ?
-                       sa->in6.sin6_port :
-                       sa->in.sin_port);
+        return be16toh(sa->sa.sa_family == AF_INET6 ? sa->in6.sin6_port : sa->in.sin_port);
 }
 
 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) {
@@ -512,13 +507,13 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
         case AF_INET: {
                 uint32_t a;
 
-                a = ntohl(sa->in.sin_addr.s_addr);
+                a = be32toh(sa->in.sin_addr.s_addr);
 
                 if (include_port)
                         r = asprintf(&p,
                                      "%u.%u.%u.%u:%u",
                                      a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
-                                     ntohs(sa->in.sin_port));
+                                     be16toh(sa->in.sin_port));
                 else
                         r = asprintf(&p,
                                      "%u.%u.%u.%u",
@@ -540,7 +535,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
                                 r = asprintf(&p,
                                              "%u.%u.%u.%u:%u",
                                              a[0], a[1], a[2], a[3],
-                                             ntohs(sa->in6.sin6_port));
+                                             be16toh(sa->in6.sin6_port));
                         else
                                 r = asprintf(&p,
                                              "%u.%u.%u.%u",
@@ -556,7 +551,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
                                 r = asprintf(&p,
                                              "[%s]:%u",
                                              a,
-                                             ntohs(sa->in6.sin6_port));
+                                             be16toh(sa->in6.sin6_port));
                                 if (r < 0)
                                         return -ENOMEM;
                         } else {
@@ -803,6 +798,42 @@ static const char* const ip_tos_table[] = {
 
 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
 
+bool ifname_valid(const char *p) {
+        bool numeric = true;
+
+        /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
+         * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
+         * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
+
+        if (isempty(p))
+                return false;
+
+        if (strlen(p) >= IFNAMSIZ)
+                return false;
+
+        if (STR_IN_SET(p, ".", ".."))
+                return false;
+
+        while (*p) {
+                if ((unsigned char) *p >= 127U)
+                        return false;
+
+                if ((unsigned char) *p <= 32U)
+                        return false;
+
+                if (*p == ':' || *p == '/')
+                        return false;
+
+                numeric = numeric && (*p >= '0' && *p <= '9');
+                p++;
+        }
+
+        if (numeric)
+                return false;
+
+        return true;
+}
+
 int getpeercred(int fd, struct ucred *ucred) {
         socklen_t n = sizeof(struct ucred);
         struct ucred u;
@@ -959,7 +990,7 @@ ssize_t next_datagram_size_fd(int fd) {
 
         l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
         if (l < 0) {
-                if (errno == EOPNOTSUPP)
+                if (errno == EOPNOTSUPP || errno == EFAULT)
                         goto fallback;
 
                 return -errno;
@@ -980,3 +1011,56 @@ fallback:
 
         return (ssize_t) k;
 }
+
+int flush_accept(int fd) {
+
+        struct pollfd pollfd = {
+                .fd = fd,
+                .events = POLLIN,
+        };
+        int r;
+
+
+        /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
+
+        for (;;) {
+                int cfd;
+
+                r = poll(&pollfd, 1, 0);
+                if (r < 0) {
+                        if (errno == EINTR)
+                                continue;
+
+                        return -errno;
+
+                } else if (r == 0)
+                        return 0;
+
+                cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
+                if (cfd < 0) {
+                        if (errno == EINTR)
+                                continue;
+
+                        if (errno == EAGAIN)
+                                return 0;
+
+                        return -errno;
+                }
+
+                close(cfd);
+        }
+}
+
+struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length) {
+        struct cmsghdr *cmsg;
+
+        assert(mh);
+
+        CMSG_FOREACH(cmsg, mh)
+                if (cmsg->cmsg_level == level &&
+                    cmsg->cmsg_type == type &&
+                    (length == (socklen_t) -1 || length == cmsg->cmsg_len))
+                        return cmsg;
+
+        return NULL;
+}
diff --git a/src/systemd/src/basic/socket-util.h b/src/systemd/src/basic/socket-util.h
index d17a2f35..2536b085 100644
--- a/src/systemd/src/basic/socket-util.h
+++ b/src/systemd/src/basic/socket-util.h
@@ -123,6 +123,8 @@ int fd_inc_rcvbuf(int fd, size_t n);
 int ip_tos_to_string_alloc(int i, char **s);
 int ip_tos_from_string(const char *s);
 
+bool ifname_valid(const char *p);
+
 int getpeercred(int fd, struct ucred *ucred);
 int getpeersec(int fd, char **ret);
 
@@ -135,5 +137,20 @@ int receive_one_fd(int transport_fd, int flags);
 
 ssize_t next_datagram_size_fd(int fd);
 
+int flush_accept(int fd);
+
 #define CMSG_FOREACH(cmsg, mh)                                          \
         for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
+
+struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length);
+
+/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
+#define SOCKADDR_UN_LEN(sa)                                             \
+        ({                                                              \
+                const struct sockaddr_un *_sa = &(sa);                  \
+                assert(_sa->sun_family == AF_UNIX);                     \
+                offsetof(struct sockaddr_un, sun_path) +                \
+                        (_sa->sun_path[0] == 0 ?                        \
+                         1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \
+                         strnlen(_sa->sun_path, sizeof(_sa->sun_path))); \
+        })
diff --git a/src/systemd/src/basic/string-table.h b/src/systemd/src/basic/string-table.h
index b180488f..369610ef 100644
--- a/src/systemd/src/basic/string-table.h
+++ b/src/systemd/src/basic/string-table.h
@@ -48,6 +48,8 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
 #define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
         scope type name##_from_string(const char *s) {                  \
                 int b;                                                  \
+                if (!s)                                                 \
+                        return -1;                                      \
                 b = parse_boolean(s);                                   \
                 if (b == 0)                                             \
                         return (type) 0;                                \
@@ -56,26 +58,8 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
                 return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
         }
 
-#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope)                    \
-        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
-        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)        \
-        struct __useless_struct_to_allow_trailing_semicolon__
-
-#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope)   \
-        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
-        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
-        struct __useless_struct_to_allow_trailing_semicolon__
-
-#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
-#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
-
-#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,)
-
-/* For string conversions where numbers are also acceptable */
-#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max)         \
-        int name##_to_string_alloc(type i, char **str) {                \
+#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,scope) \
+        scope int name##_to_string_alloc(type i, char **str) {          \
                 char *s;                                                \
                 if (i < 0 || i > max)                                   \
                         return -ERANGE;                                 \
@@ -89,7 +73,9 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
                 }                                                       \
                 *str = s;                                               \
                 return 0;                                               \
-        }                                                               \
+        }
+
+#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,scope) \
         type name##_from_string(const char *s) {                        \
                 type i;                                                 \
                 unsigned u = 0;                                         \
@@ -102,4 +88,32 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
                         return (type) u;                                \
                 return (type) -1;                                       \
         }                                                               \
+
+
+#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope)                    \
+        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
+        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)        \
+        struct __useless_struct_to_allow_trailing_semicolon__
+
+#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope)   \
+        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope)          \
+        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
+        struct __useless_struct_to_allow_trailing_semicolon__
+
+#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
+
+#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,)
+
+/* For string conversions where numbers are also acceptable */
+#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max)         \
+        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,)  \
+        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,) \
         struct __useless_struct_to_allow_trailing_semicolon__
+
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max) \
+        _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \
+        _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static)
diff --git a/src/systemd/src/basic/string-util.c b/src/systemd/src/basic/string-util.c
index 68de772e..b4e774cc 100644
--- a/src/systemd/src/basic/string-util.c
+++ b/src/systemd/src/basic/string-util.c
@@ -24,11 +24,10 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "alloc-util.h"
-#if 0 /* NM_IGNORED */
 #include "gunicode.h"
-#endif /* NM_IGNORED */
 #include "macro.h"
 #include "string-util.h"
 #include "utf8.h"
@@ -327,6 +326,14 @@ char ascii_tolower(char x) {
         return x;
 }
 
+char ascii_toupper(char x) {
+
+        if (x >= 'a' && x <= 'z')
+                return x - 'a' + 'A';
+
+        return x;
+}
+
 char *ascii_strlower(char *t) {
         char *p;
 
@@ -338,6 +345,17 @@ char *ascii_strlower(char *t) {
         return t;
 }
 
+char *ascii_strupper(char *t) {
+        char *p;
+
+        assert(t);
+
+        for (p = t; *p; p++)
+                *p = ascii_toupper(*p);
+
+        return t;
+}
+
 char *ascii_strlower_n(char *t, size_t n) {
         size_t i;
 
@@ -809,25 +827,20 @@ int free_and_strdup(char **p, const char *s) {
         return 1;
 }
 
-#pragma GCC push_options
-#pragma GCC optimize("O0")
+/*
+ * Pointer to memset is volatile so that compiler must de-reference
+ * the pointer and can't assume that it points to any function in
+ * particular (such as memset, which it then might further "optimize")
+ * This approach is inspired by openssl's crypto/mem_clr.c.
+ */
+typedef void *(*memset_t)(void *,int,size_t);
 
-void* memory_erase(void *p, size_t l) {
-        volatile uint8_t* x = (volatile uint8_t*) p;
-
-        /* This basically does what memset() does, but hopefully isn't
-         * optimized away by the compiler. One of those days, when
-         * glibc learns memset_s() we should replace this call by
-         * memset_s(), but until then this has to do. */
-
-        for (; l > 0; l--)
-                *(x++) = 'x';
+static volatile memset_t memset_func = memset;
 
-        return p;
+void* memory_erase(void *p, size_t l) {
+        return memset_func(p, 'x', l);
 }
 
-#pragma GCC pop_options
-
 char* string_erase(char *x) {
 
         if (!x)
diff --git a/src/systemd/src/basic/string-util.h b/src/systemd/src/basic/string-util.h
index ad0c8137..b75aba63 100644
--- a/src/systemd/src/basic/string-util.h
+++ b/src/systemd/src/basic/string-util.h
@@ -37,6 +37,7 @@
 #define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 #define LETTERS           LOWERCASE_LETTERS UPPERCASE_LETTERS
 #define ALPHANUMERICAL    LETTERS DIGITS
+#define HEXDIGITS         DIGITS "abcdefABCDEF"
 
 #define streq(a,b) (strcmp((a),(b)) == 0)
 #define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
@@ -65,6 +66,10 @@ static inline bool isempty(const char *p) {
         return !p || !p[0];
 }
 
+static inline const char *empty_to_null(const char *p) {
+        return isempty(p) ? NULL : p;
+}
+
 static inline char *startswith(const char *s, const char *prefix) {
         size_t l;
 
@@ -132,6 +137,9 @@ char ascii_tolower(char x);
 char *ascii_strlower(char *s);
 char *ascii_strlower_n(char *s, size_t n);
 
+char ascii_toupper(char x);
+char *ascii_strupper(char *s);
+
 int ascii_strcasecmp_n(const char *a, const char *b, size_t n);
 int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m);
 
diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c
index e885c598..eeb8c1e0 100644
--- a/src/systemd/src/basic/strv.c
+++ b/src/systemd/src/basic/strv.c
@@ -28,9 +28,7 @@
 
 #include "alloc-util.h"
 #include "escape.h"
-#if 0 /* NM_IGNORED */
 #include "extract-word.h"
-#endif /* NM_IGNORED */
 #include "fileio.h"
 #include "string-util.h"
 #include "strv.h"
@@ -143,16 +141,16 @@ char **strv_new_ap(const char *x, va_list ap) {
         va_list aq;
 
         /* As a special trick we ignore all listed strings that equal
-         * (const char*) -1. This is supposed to be used with the
+         * STRV_IGNORE. This is supposed to be used with the
          * STRV_IFNOTNULL() macro to include possibly NULL strings in
          * the string list. */
 
         if (x) {
-                n = x == (const char*) -1 ? 0 : 1;
+                n = x == STRV_IGNORE ? 0 : 1;
 
                 va_copy(aq, ap);
                 while ((s = va_arg(aq, const char*))) {
-                        if (s == (const char*) -1)
+                        if (s == STRV_IGNORE)
                                 continue;
 
                         n++;
@@ -166,7 +164,7 @@ char **strv_new_ap(const char *x, va_list ap) {
                 return NULL;
 
         if (x) {
-                if (x != (const char*) -1) {
+                if (x != STRV_IGNORE) {
                         a[i] = strdup(x);
                         if (!a[i])
                                 goto fail;
@@ -175,7 +173,7 @@ char **strv_new_ap(const char *x, va_list ap) {
 
                 while ((s = va_arg(ap, const char*))) {
 
-                        if (s == (const char*) -1)
+                        if (s == STRV_IGNORE)
                                 continue;
 
                         a[i] = strdup(s);
@@ -564,6 +562,42 @@ int strv_extend(char ***l, const char *value) {
         return strv_consume(l, v);
 }
 
+int strv_extend_front(char ***l, const char *value) {
+        size_t n, m;
+        char *v, **c;
+
+        assert(l);
+
+        /* Like strv_extend(), but prepends rather than appends the new entry */
+
+        if (!value)
+                return 0;
+
+        n = strv_length(*l);
+
+        /* Increase and overflow check. */
+        m = n + 2;
+        if (m < n)
+                return -ENOMEM;
+
+        v = strdup(value);
+        if (!v)
+                return -ENOMEM;
+
+        c = realloc_multiply(*l, sizeof(char*), m);
+        if (!c) {
+                free(v);
+                return -ENOMEM;
+        }
+
+        memmove(c+1, c, n * sizeof(char*));
+        c[0] = v;
+        c[n+1] = NULL;
+
+        *l = c;
+        return 0;
+}
+
 char **strv_uniq(char **l) {
         char **i;
 
@@ -608,6 +642,17 @@ char **strv_remove(char **l, const char *s) {
 }
 
 char **strv_parse_nulstr(const char *s, size_t l) {
+        /* l is the length of the input data, which will be split at NULs into
+         * elements of the resulting strv. Hence, the number of items in the resulting strv
+         * will be equal to one plus the number of NUL bytes in the l bytes starting at s,
+         * unless s[l-1] is NUL, in which case the final empty string is not stored in
+         * the resulting strv, and length is equal to the number of NUL bytes.
+         *
+         * Note that contrary to a normal nulstr which cannot contain empty strings, because
+         * the input data is terminated by any two consequent NUL bytes, this parser accepts
+         * empty strings in s.
+         */
+
         const char *p;
         unsigned c = 0, i = 0;
         char **v;
@@ -670,6 +715,13 @@ char **strv_split_nulstr(const char *s) {
 }
 
 int strv_make_nulstr(char **l, char **p, size_t *q) {
+        /* A valid nulstr with two NULs at the end will be created, but
+         * q will be the length without the two trailing NULs. Thus the output
+         * string is a valid nulstr and can be iterated over using NULSTR_FOREACH,
+         * and can also be parsed by strv_parse_nulstr as long as the length
+         * is provided separately.
+         */
+
         size_t n_allocated = 0, n = 0;
         _cleanup_free_ char *m = NULL;
         char **i;
@@ -682,7 +734,7 @@ int strv_make_nulstr(char **l, char **p, size_t *q) {
 
                 z = strlen(*i);
 
-                if (!GREEDY_REALLOC(m, n_allocated, n + z + 1))
+                if (!GREEDY_REALLOC(m, n_allocated, n + z + 2))
                         return -ENOMEM;
 
                 memcpy(m + n, *i, z + 1);
@@ -693,11 +745,14 @@ int strv_make_nulstr(char **l, char **p, size_t *q) {
                 m = new0(char, 1);
                 if (!m)
                         return -ENOMEM;
-                n = 0;
-        }
+                n = 1;
+        } else
+                /* make sure there is a second extra NUL at the end of resulting nulstr */
+                m[n] = '\0';
 
+        assert(n > 0);
         *p = m;
-        *q = n;
+        *q = n - 1;
 
         m = NULL;
 
@@ -773,13 +828,8 @@ char **strv_reverse(char **l) {
         if (n <= 1)
                 return l;
 
-        for (i = 0; i < n / 2; i++) {
-                char *t;
-
-                t = l[i];
-                l[i] = l[n-1-i];
-                l[n-1-i] = t;
-        }
+        for (i = 0; i < n / 2; i++)
+                SWAP_TWO(l[i], l[n-1-i]);
 
         return l;
 }
@@ -808,7 +858,7 @@ bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
         char* const* p;
 
         STRV_FOREACH(p, patterns)
-                if (fnmatch(*p, s, 0) == 0)
+                if (fnmatch(*p, s, flags) == 0)
                         return true;
 
         return false;
@@ -850,7 +900,7 @@ int strv_extend_n(char ***l, const char *value, size_t n) {
         if (n == 0)
                 return 0;
 
-        /* Adds the value value n times to l */
+        /* Adds the value n times to l */
 
         k = strv_length(*l);
 
diff --git a/src/systemd/src/basic/strv.h b/src/systemd/src/basic/strv.h
index 4a93818a..683ce83a 100644
--- a/src/systemd/src/basic/strv.h
+++ b/src/systemd/src/basic/strv.h
@@ -25,9 +25,7 @@
 #include <stddef.h>
 
 #include "alloc-util.h"
-#if 0 /* NM_IGNORED */
 #include "extract-word.h"
-#endif /* NM_IGNORED */
 #include "macro.h"
 #include "util.h"
 
@@ -52,6 +50,7 @@ int strv_extend_strv(char ***a, char **b, bool filter_duplicates);
 int strv_extend_strv_concat(char ***a, char **b, const char *suffix);
 int strv_extend(char ***l, const char *value);
 int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
+int strv_extend_front(char ***l, const char *value);
 int strv_push(char ***l, char *value);
 int strv_push_pair(char ***l, char *a, char *b);
 int strv_push_prepend(char ***l, char *value);
@@ -70,8 +69,10 @@ bool strv_equal(char **a, char **b);
 char **strv_new(const char *x, ...) _sentinel_;
 char **strv_new_ap(const char *x, va_list ap);
 
+#define STRV_IGNORE ((const char *) -1)
+
 static inline const char* STRV_IFNOTNULL(const char *x) {
-        return x ? x : (const char *) -1;
+        return x ? x : STRV_IGNORE;
 }
 
 static inline bool strv_isempty(char * const *l) {
@@ -81,9 +82,7 @@ static inline bool strv_isempty(char * const *l) {
 char **strv_split(const char *s, const char *separator);
 char **strv_split_newlines(const char *s);
 
-#if 0 /* NM_IGNORED */
 int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
-#endif /* NM_IGNORED */
 
 char *strv_join(char **l, const char *separator);
 char *strv_join_quoted(char **l);
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index 5b2b2180..212c8f4e 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -49,15 +49,12 @@ static clockid_t map_clock_id(clockid_t c) {
         /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will
          * fail for them. Since they are essentially the same as their non-ALARM pendants (their only difference is
          * when timers are set on them), let's just map them accordingly. This way, we can get the correct time even on
-         * those archs.
-         *
-         * Also, older kernels don't support CLOCK_BOOTTIME: fall back to CLOCK_MONOTONIC. */
+         * those archs. */
 
         switch (c) {
 
-        case CLOCK_BOOTTIME:
         case CLOCK_BOOTTIME_ALARM:
-                return clock_boottime_or_monotonic ();
+                return CLOCK_BOOTTIME;
 
         case CLOCK_REALTIME_ALARM:
                 return CLOCK_REALTIME;
@@ -92,6 +89,16 @@ dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
         return ts;
 }
 
+triple_timestamp* triple_timestamp_get(triple_timestamp *ts) {
+        assert(ts);
+
+        ts->realtime = now(CLOCK_REALTIME);
+        ts->monotonic = now(CLOCK_MONOTONIC);
+        ts->boottime = clock_boottime_supported() ? now(CLOCK_BOOTTIME) : USEC_INFINITY;
+
+        return ts;
+}
+
 dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
         int64_t delta;
         assert(ts);
@@ -109,6 +116,24 @@ dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
         return ts;
 }
 
+triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u) {
+        int64_t delta;
+
+        assert(ts);
+
+        if (u == USEC_INFINITY || u <= 0) {
+                ts->realtime = ts->monotonic = ts->boottime = u;
+                return ts;
+        }
+
+        ts->realtime = u;
+        delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
+        ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta);
+        ts->boottime = clock_boottime_supported() ? usec_sub(now(CLOCK_BOOTTIME), delta) : USEC_INFINITY;
+
+        return ts;
+}
+
 dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) {
         int64_t delta;
         assert(ts);
@@ -141,6 +166,26 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us
         return ts;
 }
 
+usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock) {
+
+        switch (clock) {
+
+        case CLOCK_REALTIME:
+        case CLOCK_REALTIME_ALARM:
+                return ts->realtime;
+
+        case CLOCK_MONOTONIC:
+                return ts->monotonic;
+
+        case CLOCK_BOOTTIME:
+        case CLOCK_BOOTTIME_ALARM:
+                return ts->boottime;
+
+        default:
+                return USEC_INFINITY;
+        }
+}
+
 usec_t timespec_load(const struct timespec *ts) {
         assert(ts);
 
@@ -212,32 +257,95 @@ struct timeval *timeval_store(struct timeval *tv, usec_t u) {
         return tv;
 }
 
-static char *format_timestamp_internal(char *buf, size_t l, usec_t t,
-                                       bool utc, bool us) {
+static char *format_timestamp_internal(
+                char *buf,
+                size_t l,
+                usec_t t,
+                bool utc,
+                bool us) {
+
+        /* The weekdays in non-localized (English) form. We use this instead of the localized form, so that our
+         * generated timestamps may be parsed with parse_timestamp(), and always read the same. */
+        static const char * const weekdays[] = {
+                [0] = "Sun",
+                [1] = "Mon",
+                [2] = "Tue",
+                [3] = "Wed",
+                [4] = "Thu",
+                [5] = "Fri",
+                [6] = "Sat",
+        };
+
         struct tm tm;
         time_t sec;
-        int k;
+        size_t n;
 
         assert(buf);
-        assert(l > 0);
 
+        if (l <
+            3 +                  /* week day */
+            1 + 10 +             /* space and date */
+            1 + 8 +              /* space and time */
+            (us ? 1 + 6 : 0) +   /* "." and microsecond part */
+            1 + 1 +              /* space and shortest possible zone */
+            1)
+                return NULL; /* Not enough space even for the shortest form. */
         if (t <= 0 || t == USEC_INFINITY)
+                return NULL; /* Timestamp is unset */
+
+        sec = (time_t) (t / USEC_PER_SEC); /* Round down */
+        if ((usec_t) sec != (t / USEC_PER_SEC))
+                return NULL; /* overflow? */
+
+        if (!localtime_or_gmtime_r(&sec, &tm, utc))
                 return NULL;
 
-        sec = (time_t) (t / USEC_PER_SEC);
-        localtime_or_gmtime_r(&sec, &tm, utc);
+        /* Start with the week day */
+        assert((size_t) tm.tm_wday < ELEMENTSOF(weekdays));
+        memcpy(buf, weekdays[tm.tm_wday], 4);
 
-        if (us)
-                k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm);
-        else
-                k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", &tm);
+        /* Add the main components */
+        if (strftime(buf + 3, l - 3, " %Y-%m-%d %H:%M:%S", &tm) <= 0)
+                return NULL; /* Doesn't fit */
 
-        if (k <= 0)
-                return NULL;
+        /* Append the microseconds part, if that's requested */
         if (us) {
-                snprintf(buf + strlen(buf), l - strlen(buf), ".%06llu", (unsigned long long) (t % USEC_PER_SEC));
-                if (strftime(buf + strlen(buf), l - strlen(buf), " %Z", &tm) <= 0)
-                        return NULL;
+                n = strlen(buf);
+                if (n + 8 > l)
+                        return NULL; /* Microseconds part doesn't fit. */
+
+                sprintf(buf + n, ".%06llu", (unsigned long long) (t % USEC_PER_SEC));
+        }
+
+        /* Append the timezone */
+        n = strlen(buf);
+        if (utc) {
+                /* If this is UTC then let's explicitly use the "UTC" string here, because gmtime_r() normally uses the
+                 * obsolete "GMT" instead. */
+                if (n + 5 > l)
+                        return NULL; /* "UTC" doesn't fit. */
+
+                strcpy(buf + n, " UTC");
+
+        } else if (!isempty(tm.tm_zone)) {
+                size_t tn;
+
+                /* An explicit timezone is specified, let's use it, if it fits */
+                tn = strlen(tm.tm_zone);
+                if (n + 1 + tn + 1 > l) {
+                        /* The full time zone does not fit in. Yuck. */
+
+                        if (n + 1 + _POSIX_TZNAME_MAX + 1 > l)
+                                return NULL; /* Not even enough space for the POSIX minimum (of 6)? In that case, complain that it doesn't fit */
+
+                        /* So the time zone doesn't fit in fully, but the caller passed enough space for the POSIX
+                         * minimum time zone length. In this case suppress the timezone entirely, in order not to dump
+                         * an overly long, hard to read string on the user. This should be safe, because the user will
+                         * assume the local timezone anyway if none is shown. And so does parse_timestamp(). */
+                } else {
+                        buf[n++] = ' ';
+                        strcpy(buf + n, tm.tm_zone);
+                }
         }
 
         return buf;
@@ -499,12 +607,11 @@ int parse_timestamp(const char *t, usec_t *usec) {
                 { "Sat",       6 },
         };
 
-        const char *k;
-        const char *utc;
+        const char *k, *utc, *tzn = NULL;
         struct tm tm, copy;
         time_t x;
         usec_t x_usec, plus = 0, minus = 0, ret;
-        int r, weekday = -1;
+        int r, weekday = -1, dst = -1;
         unsigned i;
 
         /*
@@ -569,15 +676,55 @@ int parse_timestamp(const char *t, usec_t *usec) {
                 goto finish;
         }
 
+        /* See if the timestamp is suffixed with UTC */
         utc = endswith_no_case(t, " UTC");
         if (utc)
                 t = strndupa(t, utc - t);
+        else {
+                const char *e = NULL;
+                int j;
+
+                tzset();
+
+                /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
+                 * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
+                 * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
+                 * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
+                 * support arbitrary timezone specifications.  */
 
-        x = ret / USEC_PER_SEC;
+                for (j = 0; j <= 1; j++) {
+
+                        if (isempty(tzname[j]))
+                                continue;
+
+                        e = endswith_no_case(t, tzname[j]);
+                        if (!e)
+                                continue;
+                        if (e == t)
+                                continue;
+                        if (e[-1] != ' ')
+                                continue;
+
+                        break;
+                }
+
+                if (IN_SET(j, 0, 1)) {
+                        /* Found one of the two timezones specified. */
+                        t = strndupa(t, e - t - 1);
+                        dst = j;
+                        tzn = tzname[j];
+                }
+        }
+
+        x = (time_t) (ret / USEC_PER_SEC);
         x_usec = 0;
 
-        assert_se(localtime_or_gmtime_r(&x, &tm, utc));
-        tm.tm_isdst = -1;
+        if (!localtime_or_gmtime_r(&x, &tm, utc))
+                return -EINVAL;
+
+        tm.tm_isdst = dst;
+        if (tzn)
+                tm.tm_zone = tzn;
 
         if (streq(t, "today")) {
                 tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
@@ -594,7 +741,6 @@ int parse_timestamp(const char *t, usec_t *usec) {
                 goto from_tm;
         }
 
-
         for (i = 0; i < ELEMENTSOF(day_nr); i++) {
                 size_t skip;
 
@@ -687,7 +833,6 @@ parse_usec:
                         return -EINVAL;
 
                 x_usec = add;
-
         }
 
 from_tm:
@@ -1089,22 +1234,55 @@ bool timezone_is_valid(const char *name) {
         return true;
 }
 
-clockid_t clock_boottime_or_monotonic(void) {
-        static clockid_t clock = -1;
-        int fd;
+bool clock_boottime_supported(void) {
+        static int supported = -1;
 
-        if (clock != -1)
-                return clock;
+        /* Note that this checks whether CLOCK_BOOTTIME is available in general as well as available for timerfds()! */
 
-        fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
-        if (fd < 0)
-                clock = CLOCK_MONOTONIC;
-        else {
-                safe_close(fd);
-                clock = CLOCK_BOOTTIME;
+        if (supported < 0) {
+                int fd;
+
+                fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC);
+                if (fd < 0)
+                        supported = false;
+                else {
+                        safe_close(fd);
+                        supported = true;
+                }
         }
 
-        return clock;
+        return supported;
+}
+
+clockid_t clock_boottime_or_monotonic(void) {
+        if (clock_boottime_supported())
+                return CLOCK_BOOTTIME;
+        else
+                return CLOCK_MONOTONIC;
+}
+
+bool clock_supported(clockid_t clock) {
+        struct timespec ts;
+
+        switch (clock) {
+
+        case CLOCK_MONOTONIC:
+        case CLOCK_REALTIME:
+                return true;
+
+        case CLOCK_BOOTTIME:
+                return clock_boottime_supported();
+
+        case CLOCK_BOOTTIME_ALARM:
+                if (!clock_boottime_supported())
+                        return false;
+
+                /* fall through, after checking the cached value for CLOCK_BOOTTIME. */
+
+        default:
+                /* For everything else, check properly */
+                return clock_gettime(clock, &ts) >= 0;
+        }
 }
 
 #if 0 /* NM_IGNORED */
diff --git a/src/systemd/src/basic/time-util.h b/src/systemd/src/basic/time-util.h
index 77e3cd08..99be5ce6 100644
--- a/src/systemd/src/basic/time-util.h
+++ b/src/systemd/src/basic/time-util.h
@@ -39,6 +39,12 @@ typedef struct dual_timestamp {
         usec_t monotonic;
 } dual_timestamp;
 
+typedef struct triple_timestamp {
+        usec_t realtime;
+        usec_t monotonic;
+        usec_t boottime;
+} triple_timestamp;
+
 #define USEC_INFINITY ((usec_t) -1)
 #define NSEC_INFINITY ((nsec_t) -1)
 
@@ -62,14 +68,17 @@ typedef struct dual_timestamp {
 #define USEC_PER_YEAR ((usec_t) (31557600ULL*USEC_PER_SEC))
 #define NSEC_PER_YEAR ((nsec_t) (31557600ULL*NSEC_PER_SEC))
 
-#define FORMAT_TIMESTAMP_MAX ((4*4+1)+11+9+4+1) /* weekdays can be unicode */
+/* We assume a maximum timezone length of 6. TZNAME_MAX is not defined on Linux, but glibc internally initializes this
+ * to 6. Let's rely on that. */
+#define FORMAT_TIMESTAMP_MAX (3+1+10+1+8+1+6+1+6+1)
 #define FORMAT_TIMESTAMP_WIDTH 28 /* when outputting, assume this width */
 #define FORMAT_TIMESTAMP_RELATIVE_MAX 256
 #define FORMAT_TIMESPAN_MAX 64
 
 #define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1)
 
-#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) { 0ULL, 0ULL })
+#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) {})
+#define TRIPLE_TIMESTAMP_NULL ((struct triple_timestamp) {})
 
 usec_t now(clockid_t clock);
 nsec_t now_nsec(clockid_t clock);
@@ -79,11 +88,28 @@ dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u);
 dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u);
 dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u);
 
+triple_timestamp* triple_timestamp_get(triple_timestamp *ts);
+triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u);
+
+#define DUAL_TIMESTAMP_HAS_CLOCK(clock)                               \
+        IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC)
+
+#define TRIPLE_TIMESTAMP_HAS_CLOCK(clock)                               \
+        IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM)
+
 static inline bool dual_timestamp_is_set(dual_timestamp *ts) {
         return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
                 (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY));
 }
 
+static inline bool triple_timestamp_is_set(triple_timestamp *ts) {
+        return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
+                (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY) ||
+                (ts->boottime > 0 && ts->boottime != USEC_INFINITY));
+}
+
+usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock);
+
 usec_t timespec_load(const struct timespec *ts) _pure_;
 struct timespec *timespec_store(struct timespec *ts, usec_t u);
 
@@ -112,6 +138,8 @@ bool ntp_synced(void);
 int get_timezones(char ***l);
 bool timezone_is_valid(const char *name);
 
+bool clock_boottime_supported(void);
+bool clock_supported(clockid_t clock);
 clockid_t clock_boottime_or_monotonic(void);
 
 #define xstrftime(buf, fmt, tm) \
diff --git a/src/systemd/src/basic/unaligned.h b/src/systemd/src/basic/unaligned.h
index 79be645b..7c847a3c 100644
--- a/src/systemd/src/basic/unaligned.h
+++ b/src/systemd/src/basic/unaligned.h
@@ -109,3 +109,21 @@ static inline void unaligned_write_le64(void *_u, uint64_t a) {
         unaligned_write_le32(u, (uint32_t) a);
         unaligned_write_le32(u + 4, (uint32_t) (a >> 32));
 }
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define unaligned_read_ne16 unaligned_read_be16
+#define unaligned_read_ne32 unaligned_read_be32
+#define unaligned_read_ne64 unaligned_read_be64
+
+#define unaligned_write_ne16 unaligned_write_be16
+#define unaligned_write_ne32 unaligned_write_be32
+#define unaligned_write_ne64 unaligned_write_be64
+#else
+#define unaligned_read_ne16 unaligned_read_le16
+#define unaligned_read_ne32 unaligned_read_le32
+#define unaligned_read_ne64 unaligned_read_le64
+
+#define unaligned_write_ne16 unaligned_write_le16
+#define unaligned_write_ne32 unaligned_write_le32
+#define unaligned_write_ne64 unaligned_write_le64
+#endif
diff --git a/src/systemd/src/basic/utf8.h b/src/systemd/src/basic/utf8.h
index 1bc23dc1..322dac20 100644
--- a/src/systemd/src/basic/utf8.h
+++ b/src/systemd/src/basic/utf8.h
@@ -27,9 +27,7 @@
 #endif /* NM_IGNORED */
 
 #include "macro.h"
-#if 0 /* NM_IGNORED */
 #include "missing.h"
-#endif /* NM_IGNORED */
 
 #define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
 #define UTF8_BYTE_ORDER_MARK "\xef\xbb\xbf"
diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c
index 6d641a4a..79c7aa46 100644
--- a/src/systemd/src/basic/util.c
+++ b/src/systemd/src/basic/util.c
@@ -37,39 +37,29 @@
 #include <unistd.h>
 
 #include "alloc-util.h"
-#if 0 /* NM_IGNORED */
 #include "build.h"
+#include "cgroup-util.h"
 #include "def.h"
 #include "dirent-util.h"
-#endif /* NM_IGNORED */
 #include "fd-util.h"
 #include "fileio.h"
-#if 0 /* NM_IGNORED */
 #include "formats-util.h"
-#endif /* NM_IGNORED */
 #include "hashmap.h"
 #include "hostname-util.h"
 #include "log.h"
 #include "macro.h"
-#if 0 /* NM_IGNORED */
 #include "missing.h"
-#endif /* NM_IGNORED */
 #include "parse-util.h"
 #include "path-util.h"
-#if 0 /* NM_IGNORED */
 #include "process-util.h"
-#endif /* NM_IGNORED */
 #include "set.h"
-#if 0 /* NM_IGNORED */
 #include "signal-util.h"
 #include "stat-util.h"
-#endif /* NM_IGNORED */
 #include "string-util.h"
 #include "strv.h"
 #include "time-util.h"
-#if 0 /* NM_IGNORED */
+#include "umask-util.h"
 #include "user-util.h"
-#endif /* NM_IGNORED */
 #include "util.h"
 
 /* Put this test here for a lack of better place */
@@ -78,6 +68,7 @@ assert_cc(EAGAIN == EWOULDBLOCK);
 #if 0 /* NM_IGNORED */
 int saved_argc = 0;
 char **saved_argv = NULL;
+static int saved_in_initrd = -1;
 #endif /* NM_IGNORED */
 
 size_t page_size(void) {
@@ -436,13 +427,17 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
                         _exit(EXIT_FAILURE);
                 }
 
-                if (!stdout_is_tty)
-                        dup2(fd, STDOUT_FILENO);
+                if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) {
+                        log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
+                        _exit(EXIT_FAILURE);
+                }
 
-                if (!stderr_is_tty)
-                        dup2(fd, STDERR_FILENO);
+                if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) {
+                        log_error_errno(errno, "Failed to dup2 /dev/tty: %m");
+                        _exit(EXIT_FAILURE);
+                }
 
-                if (fd > 2)
+                if (fd > STDERR_FILENO)
                         close(fd);
         }
 
@@ -466,11 +461,10 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
 }
 
 bool in_initrd(void) {
-        static int saved = -1;
         struct statfs s;
 
-        if (saved >= 0)
-                return saved;
+        if (saved_in_initrd >= 0)
+                return saved_in_initrd;
 
         /* We make two checks here:
          *
@@ -482,11 +476,15 @@ bool in_initrd(void) {
          * emptying when transititioning to the main systemd.
          */
 
-        saved = access("/etc/initrd-release", F_OK) >= 0 &&
-                statfs("/", &s) >= 0 &&
-                is_temporary_fs(&s);
+        saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
+                          statfs("/", &s) >= 0 &&
+                          is_temporary_fs(&s);
+
+        return saved_in_initrd;
+}
 
-        return saved;
+void in_initrd_force(bool value) {
+        saved_in_initrd = value;
 }
 
 /* hey glibc, APIs with callbacks without a user pointer are so useless */
@@ -534,7 +532,7 @@ int on_ac_power(void) {
                 if (!de)
                         break;
 
-                if (hidden_file(de->d_name))
+                if (hidden_or_backup_file(de->d_name))
                         continue;
 
                 device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
@@ -588,47 +586,6 @@ int on_ac_power(void) {
         return found_online || !found_offline;
 }
 
-bool id128_is_valid(const char *s) {
-        size_t i, l;
-
-        l = strlen(s);
-        if (l == 32) {
-
-                /* Simple formatted 128bit hex string */
-
-                for (i = 0; i < l; i++) {
-                        char c = s[i];
-
-                        if (!(c >= '0' && c <= '9') &&
-                            !(c >= 'a' && c <= 'z') &&
-                            !(c >= 'A' && c <= 'Z'))
-                                return false;
-                }
-
-        } else if (l == 36) {
-
-                /* Formatted UUID */
-
-                for (i = 0; i < l; i++) {
-                        char c = s[i];
-
-                        if ((i == 8 || i == 13 || i == 18 || i == 23)) {
-                                if (c != '-')
-                                        return false;
-                        } else {
-                                if (!(c >= '0' && c <= '9') &&
-                                    !(c >= 'a' && c <= 'z') &&
-                                    !(c >= 'A' && c <= 'Z'))
-                                        return false;
-                        }
-                }
-
-        } else
-                return false;
-
-        return true;
-}
-
 int container_get_leader(const char *machine, pid_t *pid) {
         _cleanup_free_ char *s = NULL, *class = NULL;
         const char *p;
@@ -779,26 +736,140 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
 }
 
 uint64_t physical_memory(void) {
-        long mem;
+        _cleanup_free_ char *root = NULL, *value = NULL;
+        uint64_t mem, lim;
+        size_t ps;
+        long sc;
+
+        /* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
+         * memory.
+         *
+         * In order to support containers nicely that have a configured memory limit we'll take the minimum of the
+         * physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
+
+        sc = sysconf(_SC_PHYS_PAGES);
+        assert(sc > 0);
+
+        ps = page_size();
+        mem = (uint64_t) sc * (uint64_t) ps;
+
+        if (cg_get_root_path(&root) < 0)
+                return mem;
+
+        if (cg_get_attribute("memory", root, "memory.limit_in_bytes", &value))
+                return mem;
 
-        /* We return this as uint64_t in case we are running as 32bit
-         * process on a 64bit kernel with huge amounts of memory */
+        if (safe_atou64(value, &lim) < 0)
+                return mem;
 
-        mem = sysconf(_SC_PHYS_PAGES);
-        assert(mem > 0);
+        /* Make sure the limit is a multiple of our own page size */
+        lim /= ps;
+        lim *= ps;
 
-        return (uint64_t) mem * (uint64_t) page_size();
+        return MIN(mem, lim);
 }
 
-int update_reboot_param_file(const char *param) {
-        int r = 0;
+uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
+        uint64_t p, m, ps, r;
 
-        if (param) {
-                r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
+        assert(max > 0);
+
+        /* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
+         * the result is a multiple of the page size (rounds down). */
+
+        ps = page_size();
+        assert(ps > 0);
+
+        p = physical_memory() / ps;
+        assert(p > 0);
+
+        m = p * v;
+        if (m / p != v)
+                return UINT64_MAX;
+
+        m /= max;
+
+        r = m * ps;
+        if (r / ps != m)
+                return UINT64_MAX;
+
+        return r;
+}
+
+uint64_t system_tasks_max(void) {
+
+#if SIZEOF_PID_T == 4
+#define TASKS_MAX ((uint64_t) (INT32_MAX-1))
+#elif SIZEOF_PID_T == 2
+#define TASKS_MAX ((uint64_t) (INT16_MAX-1))
+#else
+#error "Unknown pid_t size"
+#endif
+
+        _cleanup_free_ char *value = NULL, *root = NULL;
+        uint64_t a = TASKS_MAX, b = TASKS_MAX;
+
+        /* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
+         * limit:
+         *
+         * a) the maximum value for the pid_t type
+         * b) the cgroups pids_max attribute for the system
+         * c) the kernel's configure maximum PID value
+         *
+         * And then pick the smallest of the three */
+
+        if (read_one_line_file("/proc/sys/kernel/pid_max", &value) >= 0)
+                (void) safe_atou64(value, &a);
+
+        if (cg_get_root_path(&root) >= 0) {
+                value = mfree(value);
+
+                if (cg_get_attribute("pids", root, "pids.max", &value) >= 0)
+                        (void) safe_atou64(value, &b);
+        }
+
+        return MIN3(TASKS_MAX,
+                    a <= 0 ? TASKS_MAX : a,
+                    b <= 0 ? TASKS_MAX : b);
+}
+
+uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
+        uint64_t t, m;
+
+        assert(max > 0);
+
+        /* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
+         * relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
+
+        t = system_tasks_max();
+        assert(t > 0);
+
+        m = t * v;
+        if (m / t != v) /* overflow? */
+                return UINT64_MAX;
+
+        return m / max;
+}
+
+int update_reboot_parameter_and_warn(const char *param) {
+        int r;
+
+        if (isempty(param)) {
+                if (unlink("/run/systemd/reboot-param") < 0) {
+                        if (errno == ENOENT)
+                                return 0;
+
+                        return log_warning_errno(errno, "Failed to unlink reboot parameter file: %m");
+                }
+
+                return 0;
+        }
+
+        RUN_WITH_UMASK(0022) {
+                r = write_string_file("/run/systemd/reboot-param", param, WRITE_STRING_FILE_CREATE);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m");
-        } else
-                (void) unlink(REBOOT_PARAM_FILE);
+                        return log_warning_errno(r, "Failed to write reboot parameter file: %m");
+        }
 
         return 0;
 }
diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h
index 3225269a..bb2fc318 100644
--- a/src/systemd/src/basic/util.h
+++ b/src/systemd/src/basic/util.h
@@ -41,13 +41,9 @@
 #include <time.h>
 #include <unistd.h>
 
-#if 0 /* NM_IGNORED */
 #include "formats-util.h"
-#endif /* NM_IGNORED */
 #include "macro.h"
-#if 0 /* NM_IGNORED */
 #include "missing.h"
-#endif /* NM_IGNORED */
 #include "time-util.h"
 
 size_t page_size(void) _pure_;
@@ -65,6 +61,10 @@ static inline const char* one_zero(bool b) {
         return b ? "1" : "0";
 }
 
+static inline const char* enable_disable(bool b) {
+        return b ? "enable" : "disable";
+}
+
 void execute_directories(const char* const* directories, usec_t timeout, char *argv[]);
 
 bool plymouth_running(void);
@@ -90,6 +90,7 @@ int prot_from_flags(int flags) _const_;
 int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
 
 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 *),
@@ -179,15 +180,17 @@ static inline unsigned log2u_round_up(unsigned x) {
         return log2u(x - 1) + 1;
 }
 
-bool id128_is_valid(const char *s) _pure_;
-
 int container_get_leader(const char *machine, pid_t *pid);
 
 int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
 int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
 
 uint64_t physical_memory(void);
+uint64_t physical_memory_scale(uint64_t v, uint64_t max);
+
+uint64_t system_tasks_max(void);
+uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
 
-int update_reboot_param_file(const char *param);
+int update_reboot_parameter_and_warn(const char *param);
 
 int version(void);
diff --git a/src/systemd/src/libsystemd-network/arp-util.c b/src/systemd/src/libsystemd-network/arp-util.c
index 0c898145..8c678626 100644
--- a/src/systemd/src/libsystemd-network/arp-util.c
+++ b/src/systemd/src/libsystemd-network/arp-util.c
@@ -81,7 +81,7 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_
         };
         union sockaddr_union link = {
                 .ll.sll_family = AF_PACKET,
-                .ll.sll_protocol = htons(ETH_P_ARP),
+                .ll.sll_protocol = htobe16(ETH_P_ARP),
                 .ll.sll_ifindex = ifindex,
                 .ll.sll_halen = ETH_ALEN,
                 .ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
@@ -114,17 +114,17 @@ static int arp_send_packet(int fd, int ifindex,
                            bool announce) {
         union sockaddr_union link = {
                 .ll.sll_family = AF_PACKET,
-                .ll.sll_protocol = htons(ETH_P_ARP),
+                .ll.sll_protocol = htobe16(ETH_P_ARP),
                 .ll.sll_ifindex = ifindex,
                 .ll.sll_halen = ETH_ALEN,
                 .ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
         };
         struct ether_arp arp = {
-                .ea_hdr.ar_hrd = htons(ARPHRD_ETHER), /* HTYPE */
-                .ea_hdr.ar_pro = htons(ETHERTYPE_IP), /* PTYPE */
+                .ea_hdr.ar_hrd = htobe16(ARPHRD_ETHER), /* HTYPE */
+                .ea_hdr.ar_pro = htobe16(ETHERTYPE_IP), /* PTYPE */
                 .ea_hdr.ar_hln = ETH_ALEN, /* HLEN */
                 .ea_hdr.ar_pln = sizeof(be32_t), /* PLEN */
-                .ea_hdr.ar_op = htons(ARPOP_REQUEST), /* REQUEST */
+                .ea_hdr.ar_op = htobe16(ARPOP_REQUEST), /* REQUEST */
         };
         int r;
 
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c
index c7a3eac5..c1fa8763 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.c
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c
@@ -19,9 +19,7 @@
 
 #include "nm-sd-adapt.h"
 
-#if 0 /* NM_IGNORED */
 #include "libudev.h"
-#endif /* NM_IGNORED */
 #include "sd-id128.h"
 
 #include "dhcp-identifier.h"
@@ -29,9 +27,10 @@
 #include "network-internal.h"
 #include "siphash24.h"
 #include "sparse-endian.h"
-#if 0 /* NM_IGNORED */
 #include "udev-util.h"
 #include "virt.h"
+
+#if 0 /* NM_IGNORED */
 #else /* NM_IGNORED */
 #include <net/if.h>
 #endif /* NM_IGNORED */
@@ -39,6 +38,37 @@
 #define SYSTEMD_PEN 43793
 #define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
 
+int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
+        struct duid d;
+
+        assert_cc(sizeof(d.raw) >= MAX_DUID_LEN);
+        if (duid_len > MAX_DUID_LEN)
+                return -EINVAL;
+
+        switch (duid_type) {
+        case DUID_TYPE_LLT:
+                if (duid_len <= sizeof(d.llt))
+                        return -EINVAL;
+                break;
+        case DUID_TYPE_EN:
+                if (duid_len != sizeof(d.en))
+                        return -EINVAL;
+                break;
+        case DUID_TYPE_LL:
+                if (duid_len <= sizeof(d.ll))
+                        return -EINVAL;
+                break;
+        case DUID_TYPE_UUID:
+                if (duid_len != sizeof(d.uuid))
+                        return -EINVAL;
+                break;
+        default:
+                /* accept unknown type in order to be forward compatible */
+                break;
+        }
+        return 0;
+}
+
 int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
         sd_id128_t machine_id;
         uint64_t hash;
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.h b/src/systemd/src/libsystemd-network/dhcp-identifier.h
index babae15c..1cc0f9fb 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.h
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.h
@@ -26,7 +26,6 @@
 #include "unaligned.h"
 
 typedef enum DUIDType {
-        DUID_TYPE_RAW       = 0,
         DUID_TYPE_LLT       = 1,
         DUID_TYPE_EN        = 2,
         DUID_TYPE_LL        = 3,
@@ -40,27 +39,28 @@ typedef enum DUIDType {
  */
 #define MAX_DUID_LEN 128
 
+/* https://tools.ietf.org/html/rfc3315#section-9.1 */
 struct duid {
         be16_t type;
         union {
                 struct {
-                        /* DHCP6_DUID_LLT */
+                        /* DUID_TYPE_LLT */
                         uint16_t htype;
                         uint32_t time;
                         uint8_t haddr[0];
                 } _packed_ llt;
                 struct {
-                        /* DHCP6_DUID_EN */
+                        /* DUID_TYPE_EN */
                         uint32_t pen;
                         uint8_t id[8];
                 } _packed_ en;
                 struct {
-                        /* DHCP6_DUID_LL */
+                        /* DUID_TYPE_LL */
                         int16_t htype;
                         uint8_t haddr[0];
                 } _packed_ ll;
                 struct {
-                        /* DHCP6_DUID_UUID */
+                        /* DUID_TYPE_UUID */
                         sd_id128_t uuid;
                 } _packed_ uuid;
                 struct {
@@ -69,34 +69,6 @@ struct duid {
         };
 } _packed_;
 
+int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len);
 int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
 int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);
-
-static inline int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
-        struct duid d;
-
-        assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
-
-        switch (duid_type) {
-        case DUID_TYPE_LLT:
-                if (duid_len <= sizeof(d.llt))
-                        return -EINVAL;
-                break;
-        case DUID_TYPE_EN:
-                if (duid_len != sizeof(d.en))
-                        return -EINVAL;
-                break;
-        case DUID_TYPE_LL:
-                if (duid_len <= sizeof(d.ll))
-                        return -EINVAL;
-                break;
-        case DUID_TYPE_UUID:
-                if (duid_len != sizeof(d.uuid))
-                        return -EINVAL;
-                break;
-        default:
-                /* accept unknown type in order to be forward compatible */
-                break;
-        }
-        return 0;
-}
diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h
index 4662b0d8..99f69089 100644
--- a/src/systemd/src/libsystemd-network/dhcp-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-internal.h
@@ -65,4 +65,5 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum);
 #define DHCP_CLIENT_DONT_DESTROY(client) \
         _cleanup_(sd_dhcp_client_unrefp) _unused_ sd_dhcp_client *_dont_destroy_##client = sd_dhcp_client_ref(client)
 
-#define log_dhcp_client(client, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCP CLIENT (0x%x): " fmt, client->xid, ##__VA_ARGS__)
+#define log_dhcp_client_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "DHCP CLIENT (0x%x): " fmt, client->xid, ##__VA_ARGS__)
+#define log_dhcp_client(client, fmt, ...) log_dhcp_client_errno(client, 0, fmt, ##__VA_ARGS__)
diff --git a/src/systemd/src/libsystemd-network/dhcp-network.c b/src/systemd/src/libsystemd-network/dhcp-network.c
index 15a0bb7b..f1856d0a 100644
--- a/src/systemd/src/libsystemd-network/dhcp-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp-network.c
@@ -109,9 +109,9 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
                 return -errno;
 
         link->ll.sll_family = AF_PACKET;
-        link->ll.sll_protocol = htons(ETH_P_IP);
+        link->ll.sll_protocol = htobe16(ETH_P_IP);
         link->ll.sll_ifindex = ifindex;
-        link->ll.sll_hatype = htons(arp_type);
+        link->ll.sll_hatype = htobe16(arp_type);
         link->ll.sll_halen = mac_addr_len;
         memcpy(link->ll.sll_addr, bcast_addr, mac_addr_len);
 
diff --git a/src/systemd/src/libsystemd-network/dhcp-protocol.h b/src/systemd/src/libsystemd-network/dhcp-protocol.h
index 3e32484c..5cf7abbf 100644
--- a/src/systemd/src/libsystemd-network/dhcp-protocol.h
+++ b/src/systemd/src/libsystemd-network/dhcp-protocol.h
@@ -59,7 +59,7 @@ typedef struct DHCPPacket DHCPPacket;
 #define DHCP_IP_UDP_SIZE        (int32_t)(sizeof(struct udphdr) + DHCP_IP_SIZE)
 #define DHCP_MESSAGE_SIZE       (int32_t)(sizeof(DHCPMessage))
 #define DHCP_DEFAULT_MIN_SIZE   576 /* the minimum internet hosts must be able to receive */
-#define DHCP_MIN_OPTIONS_SIZE   DHCP_DEFAULT_MIN_SIZE - DHCP_IP_UDP_SIZE - DHCP_MESSAGE_SIZE
+#define DHCP_MIN_OPTIONS_SIZE   (DHCP_DEFAULT_MIN_SIZE - DHCP_IP_UDP_SIZE - DHCP_MESSAGE_SIZE)
 #define DHCP_MAGIC_COOKIE       (uint32_t)(0x63825363)
 
 enum {
diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h
index 749086d3..945c3b97 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h
@@ -55,7 +55,8 @@ struct DHCP6IA {
 
 typedef struct DHCP6IA DHCP6IA;
 
-#define log_dhcp6_client(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__)
+#define log_dhcp6_client_errno(p, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__)
+#define log_dhcp6_client(p, fmt, ...) log_dhcp6_client_errno(p, 0, fmt, ##__VA_ARGS__)
 
 int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
                         size_t optlen, const void *optval);
diff --git a/src/systemd/src/libsystemd-network/lldp-internal.h b/src/systemd/src/libsystemd-network/lldp-internal.h
index 7592bc43..becc162f 100644
--- a/src/systemd/src/libsystemd-network/lldp-internal.h
+++ b/src/systemd/src/libsystemd-network/lldp-internal.h
@@ -28,6 +28,8 @@
 #include "prioq.h"
 
 struct sd_lldp {
+        unsigned n_ref;
+
         int ifindex;
         int fd;
 
diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/systemd/src/libsystemd-network/lldp-neighbor.c
index ce1d89b6..afede1e7 100644
--- a/src/systemd/src/libsystemd-network/lldp-neighbor.c
+++ b/src/systemd/src/libsystemd-network/lldp-neighbor.c
@@ -199,7 +199,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
         assert(n);
 
         if (n->raw_size < sizeof(struct ether_header)) {
-                log_lldp("Recieved truncated packet, ignoring.");
+                log_lldp("Received truncated packet, ignoring.");
                 return -EBADMSG;
         }
 
@@ -362,9 +362,16 @@ end_marker:
 void lldp_neighbor_start_ttl(sd_lldp_neighbor *n) {
         assert(n);
 
-        if (n->ttl > 0)
-                n->until = usec_add(now(clock_boottime_or_monotonic()), n->ttl * USEC_PER_SEC);
-        else
+        if (n->ttl > 0) {
+                usec_t base;
+
+                /* Use the packet's timestamp if there is one known */
+                base = triple_timestamp_by_clock(&n->timestamp, clock_boottime_or_monotonic());
+                if (base <= 0 || base == USEC_INFINITY)
+                        base = now(clock_boottime_or_monotonic()); /* Otherwise, take the current time */
+
+                n->until = usec_add(base, n->ttl * USEC_PER_SEC);
+        } else
                 n->until = 0;
 
         if (n->lldp)
@@ -590,11 +597,11 @@ done:
         return 0;
 }
 
-_public_ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret) {
+_public_ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec) {
         assert_return(n, -EINVAL);
-        assert_return(ret, -EINVAL);
+        assert_return(ret_sec, -EINVAL);
 
-        *ret = n->ttl;
+        *ret_sec = n->ttl;
         return 0;
 }
 
@@ -653,7 +660,7 @@ _public_ int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint
         return 0;
 }
 
-int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) {
+_public_ int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) {
         _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
         int r;
 
@@ -670,7 +677,7 @@ int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t ra
                 return r;
 
         *ret = n;
-        n = 0;
+        n = NULL;
 
         return r;
 }
@@ -681,7 +688,7 @@ _public_ int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n) {
         assert(n->raw_size >= sizeof(struct ether_header));
         n->rindex = sizeof(struct ether_header);
 
-        return 0;
+        return n->rindex < n->raw_size;
 }
 
 _public_ int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) {
@@ -695,7 +702,7 @@ _public_ int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) {
         if (n->rindex + 2 > n->raw_size) /* Truncated message */
                 return -EBADMSG;
 
-        length = LLDP_NEIGHBOR_LENGTH(n);
+        length = LLDP_NEIGHBOR_TLV_LENGTH(n);
         if (n->rindex + 2 + length > n->raw_size)
                 return -EBADMSG;
 
@@ -713,7 +720,7 @@ _public_ int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type) {
         if (n->rindex + 2 > n->raw_size)
                 return -EBADMSG;
 
-        *type = LLDP_NEIGHBOR_TYPE(n);
+        *type = LLDP_NEIGHBOR_TLV_TYPE(n);
         return 0;
 }
 
@@ -745,14 +752,14 @@ _public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[3], u
         if (r == 0)
                 return -ENXIO;
 
-        length = LLDP_NEIGHBOR_LENGTH(n);
+        length = LLDP_NEIGHBOR_TLV_LENGTH(n);
         if (length < 4)
                 return -EBADMSG;
 
         if (n->rindex + 2 + length > n->raw_size)
                 return -EBADMSG;
 
-        d = LLDP_NEIGHBOR_DATA(n);
+        d = LLDP_NEIGHBOR_TLV_DATA(n);
         memcpy(oui, d, 3);
         *subtype = d[3];
 
@@ -784,8 +791,7 @@ _public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret,
         if (n->rindex + 2 > n->raw_size)
                 return -EBADMSG;
 
-        length = LLDP_NEIGHBOR_LENGTH(n);
-
+        length = LLDP_NEIGHBOR_TLV_LENGTH(n);
         if (n->rindex + 2 + length > n->raw_size)
                 return -EBADMSG;
 
@@ -794,3 +800,16 @@ _public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret,
 
         return 0;
 }
+
+_public_ int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret) {
+        assert_return(n, -EINVAL);
+        assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP);
+        assert_return(clock_supported(clock), -EOPNOTSUPP);
+        assert_return(ret, -EINVAL);
+
+        if (!triple_timestamp_is_set(&n->timestamp))
+                return -ENODATA;
+
+        *ret = triple_timestamp_by_clock(&n->timestamp, clock);
+        return 0;
+}
diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.h b/src/systemd/src/libsystemd-network/lldp-neighbor.h
index f203bfa6..c1a7606d 100644
--- a/src/systemd/src/libsystemd-network/lldp-neighbor.h
+++ b/src/systemd/src/libsystemd-network/lldp-neighbor.h
@@ -43,6 +43,8 @@ struct sd_lldp_neighbor {
         sd_lldp *lldp;
         unsigned n_ref;
 
+        triple_timestamp timestamp;
+
         usec_t until;
         unsigned prioq_idx;
 
@@ -81,18 +83,18 @@ static inline void *LLDP_NEIGHBOR_RAW(const sd_lldp_neighbor *n) {
         return (uint8_t*) n + ALIGN(sizeof(sd_lldp_neighbor));
 }
 
-static inline uint8_t LLDP_NEIGHBOR_TYPE(const sd_lldp_neighbor *n) {
+static inline uint8_t LLDP_NEIGHBOR_TLV_TYPE(const sd_lldp_neighbor *n) {
         return ((uint8_t*) LLDP_NEIGHBOR_RAW(n))[n->rindex] >> 1;
 }
 
-static inline size_t LLDP_NEIGHBOR_LENGTH(const sd_lldp_neighbor *n) {
+static inline size_t LLDP_NEIGHBOR_TLV_LENGTH(const sd_lldp_neighbor *n) {
         uint8_t *p;
 
         p = (uint8_t*) LLDP_NEIGHBOR_RAW(n) + n->rindex;
         return p[1] + (((size_t) (p[0] & 1)) << 8);
 }
 
-static inline void* LLDP_NEIGHBOR_DATA(const sd_lldp_neighbor *n) {
+static inline void* LLDP_NEIGHBOR_TLV_DATA(const sd_lldp_neighbor *n) {
         return ((uint8_t*) LLDP_NEIGHBOR_RAW(n)) + n->rindex + 2;
 }
 
diff --git a/src/systemd/src/libsystemd-network/lldp-network.c b/src/systemd/src/libsystemd-network/lldp-network.c
index 658448f6..bba3a752 100644
--- a/src/systemd/src/libsystemd-network/lldp-network.c
+++ b/src/systemd/src/libsystemd-network/lldp-network.c
@@ -59,7 +59,8 @@ int lldp_network_bind_raw_socket(int ifindex) {
 
         assert(ifindex > 0);
 
-        fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, htons(ETHERTYPE_LLDP));
+        fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK,
+                    htobe16(ETHERTYPE_LLDP));
         if (fd < 0)
                 return -errno;
 
diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c
index 55fcc1da..46bddfeb 100644
--- a/src/systemd/src/libsystemd-network/network-internal.c
+++ b/src/systemd/src/libsystemd-network/network-internal.c
@@ -26,16 +26,16 @@
 #include "sd-ndisc.h"
 
 #include "alloc-util.h"
-#if 0 /* NM_IGNORED */
 #include "condition.h"
 #include "conf-parser.h"
-#endif /* NM_IGNORED */
 #include "dhcp-lease-internal.h"
+#include "ether-addr-util.h"
 #include "hexdecoct.h"
 #include "log.h"
 #include "network-internal.h"
 #include "parse-util.h"
 #include "siphash24.h"
+#include "socket-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "utf8.h"
@@ -105,16 +105,16 @@ bool net_match_config(const struct ether_addr *match_mac,
                       const char *dev_type,
                       const char *dev_name) {
 
-        if (match_host && !condition_test(match_host))
+        if (match_host && condition_test(match_host) <= 0)
                 return false;
 
-        if (match_virt && !condition_test(match_virt))
+        if (match_virt && condition_test(match_virt) <= 0)
                 return false;
 
-        if (match_kernel && !condition_test(match_kernel))
+        if (match_kernel && condition_test(match_kernel) <= 0)
                 return false;
 
-        if (match_arch && !condition_test(match_arch))
+        if (match_arch && condition_test(match_arch) <= 0)
                 return false;
 
         if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
@@ -180,58 +180,19 @@ int config_parse_net_condition(const char *unit,
         return 0;
 }
 
-int config_parse_ifname(const char *unit,
-                        const char *filename,
-                        unsigned line,
-                        const char *section,
-                        unsigned section_line,
-                        const char *lvalue,
-                        int ltype,
-                        const char *rvalue,
-                        void *data,
-                        void *userdata) {
-
-        char **s = data;
-        _cleanup_free_ char *n = NULL;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        n = strdup(rvalue);
-        if (!n)
-                return log_oom();
-
-        if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
-                log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
-                return 0;
-        }
-
-        free(*s);
-        if (*n) {
-                *s = n;
-                n = NULL;
-        } else
-                *s = NULL;
-
-        return 0;
-}
-
-int config_parse_ifnames(const char *unit,
-                        const char *filename,
-                        unsigned line,
-                        const char *section,
-                        unsigned section_line,
-                        const char *lvalue,
-                        int ltype,
-                        const char *rvalue,
-                        void *data,
-                        void *userdata) {
+int config_parse_ifnames(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
 
         char ***sv = data;
-        const char *word, *state;
-        size_t l;
         int r;
 
         assert(filename);
@@ -239,22 +200,27 @@ int config_parse_ifnames(const char *unit,
         assert(rvalue);
         assert(data);
 
-        FOREACH_WORD(word, l, rvalue, state) {
-                char *n;
+        for (;;) {
+                _cleanup_free_ char *word = NULL;
 
-                n = strndup(word, l);
-                if (!n)
-                        return log_oom();
+                r = extract_first_word(&rvalue, &word, NULL, 0);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse interface name list: %s", rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        break;
 
-                if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
-                        free(n);
+                if (!ifname_valid(word)) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not valid or too long, ignoring assignment: %s", rvalue);
                         return 0;
                 }
 
-                r = strv_consume(sv, n);
+                r = strv_push(sv, word);
                 if (r < 0)
                         return log_oom();
+
+                word = NULL;
         }
 
         return 0;
@@ -310,6 +276,8 @@ int config_parse_hwaddr(const char *unit,
                         void *userdata) {
         struct ether_addr **hwaddr = data;
         struct ether_addr *n;
+        const char *start;
+        size_t offset;
         int r;
 
         assert(filename);
@@ -321,14 +289,10 @@ int config_parse_hwaddr(const char *unit,
         if (!n)
                 return log_oom();
 
-        r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
-                   &n->ether_addr_octet[0],
-                   &n->ether_addr_octet[1],
-                   &n->ether_addr_octet[2],
-                   &n->ether_addr_octet[3],
-                   &n->ether_addr_octet[4],
-                   &n->ether_addr_octet[5]);
-        if (r != 6) {
+        start = rvalue + strspn(rvalue, WHITESPACE);
+        r = ether_addr_from_string(start, n, &offset);
+
+        if (r || (start[offset + strspn(start + offset, WHITESPACE)] != '\0')) {
                 log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
                 free(n);
                 return 0;
@@ -360,8 +324,9 @@ int config_parse_iaid(const char *unit,
 
         r = safe_atou32(rvalue, &iaid);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, 0, "Unable to read IAID: %s", rvalue);
-                return r;
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Unable to read IAID, ignoring assignment: %s", rvalue);
+                return 0;
         }
 
         *((uint32_t *)data) = iaid;
@@ -385,28 +350,28 @@ void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
 int deserialize_in_addrs(struct in_addr **ret, const char *string) {
         _cleanup_free_ struct in_addr *addresses = NULL;
         int size = 0;
-        const char *word, *state;
-        size_t len;
 
         assert(ret);
         assert(string);
 
-        FOREACH_WORD(word, len, string, state) {
-                _cleanup_free_ char *addr_str = NULL;
+        for (;;) {
+                _cleanup_free_ char *word = NULL;
                 struct in_addr *new_addresses;
                 int r;
 
+                r = extract_first_word(&string, &word, NULL, 0);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
                 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
                 if (!new_addresses)
                         return -ENOMEM;
                 else
                         addresses = new_addresses;
 
-                addr_str = strndup(word, len);
-                if (!addr_str)
-                        return -ENOMEM;
-
-                r = inet_pton(AF_INET, addr_str, &(addresses[size]));
+                r = inet_pton(AF_INET, word, &(addresses[size]));
                 if (r <= 0)
                         continue;
 
@@ -419,45 +384,48 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) {
         return size;
 }
 
-void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
-                         size_t size) {
+void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, size_t size) {
         unsigned i;
 
         assert(f);
         assert(addresses);
         assert(size);
 
-        for (i = 0; i < size; i++)
-                fprintf(f, SD_NDISC_ADDRESS_FORMAT_STR"%s",
-                        SD_NDISC_ADDRESS_FORMAT_VAL(addresses[i]),
-                        (i < (size - 1)) ? " ": "");
+        for (i = 0; i < size; i++) {
+                char buffer[INET6_ADDRSTRLEN];
+
+                fputs(inet_ntop(AF_INET6, addresses+i, buffer, sizeof(buffer)), f);
+
+                if (i < size - 1)
+                        fputc(' ', f);
+        }
 }
 
 int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
         _cleanup_free_ struct in6_addr *addresses = NULL;
         int size = 0;
-        const char *word, *state;
-        size_t len;
 
         assert(ret);
         assert(string);
 
-        FOREACH_WORD(word, len, string, state) {
-                _cleanup_free_ char *addr_str = NULL;
+        for (;;) {
+                _cleanup_free_ char *word = NULL;
                 struct in6_addr *new_addresses;
                 int r;
 
+                r = extract_first_word(&string, &word, NULL, 0);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
                 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
                 if (!new_addresses)
                         return -ENOMEM;
                 else
                         addresses = new_addresses;
 
-                addr_str = strndup(word, len);
-                if (!addr_str)
-                        return -ENOMEM;
-
-                r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
+                r = inet_pton(AF_INET6, word, &(addresses[size]));
                 if (r <= 0)
                         continue;
 
@@ -498,29 +466,29 @@ void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, siz
 int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
         _cleanup_free_ struct sd_dhcp_route *routes = NULL;
         size_t size = 0, allocated = 0;
-        const char *word, *state;
-        size_t len;
 
         assert(ret);
         assert(ret_size);
         assert(ret_allocated);
         assert(string);
 
-        FOREACH_WORD(word, len, string, state) {
-                /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
-                _cleanup_free_ char* entry = NULL;
+         /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
+        for (;;) {
+                _cleanup_free_ char *word = NULL;
                 char *tok, *tok_end;
                 unsigned n;
                 int r;
 
-                if (!GREEDY_REALLOC(routes, allocated, size + 1))
-                        return -ENOMEM;
+                r = extract_first_word(&string, &word, NULL, 0);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
 
-                entry = strndup(word, len);
-                if (!entry)
+                if (!GREEDY_REALLOC(routes, allocated, size + 1))
                         return -ENOMEM;
 
-                tok = entry;
+                tok = word;
 
                 /* get the subnet */
                 tok_end = strchr(tok, '/');
diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h
index 955cc898..5bcd5771 100644
--- a/src/systemd/src/libsystemd-network/network-internal.h
+++ b/src/systemd/src/libsystemd-network/network-internal.h
@@ -23,7 +23,6 @@
 
 #include "sd-dhcp-lease.h"
 
-#if 0 /* NM_IGNORED */
 #include "condition.h"
 #include "udev.h"
 
@@ -51,10 +50,6 @@ int config_parse_hwaddr(const char *unit, const char *filename, unsigned line,
                         const char *section, unsigned section_line, const char *lvalue,
                         int ltype, const char *rvalue, void *data, void *userdata);
 
-int config_parse_ifname(const char *unit, const char *filename, unsigned line,
-                        const char *section, unsigned section_line, const char *lvalue,
-                        int ltype, const char *rvalue, void *data, void *userdata);
-
 int config_parse_ifnames(const char *unit, const char *filename, unsigned line,
                          const char *section, unsigned section_line, const char *lvalue,
                          int ltype, const char *rvalue, void *data, void *userdata);
@@ -69,7 +64,6 @@ int config_parse_iaid(const char *unit, const char *filename, unsigned line,
 
 int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
 const char *net_get_name(struct udev_device *device);
-#endif /* NM_IGNORED */
 
 void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size);
 int deserialize_in_addrs(struct in_addr **addresses, const char *string);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index 758dba4b..f740075a 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -55,7 +55,7 @@ struct sd_dhcp_client {
         sd_event *event;
         int event_priority;
         sd_event_source *timeout_resend;
-        int index;
+        int ifindex;
         int fd;
         union sockaddr_union link;
         sd_event_source *receive_message;
@@ -103,7 +103,7 @@ struct sd_dhcp_client {
         sd_event_source *timeout_t1;
         sd_event_source *timeout_t2;
         sd_event_source *timeout_expire;
-        sd_dhcp_client_callback_t cb;
+        sd_dhcp_client_callback_t callback;
         void *userdata;
         sd_dhcp_lease *lease;
         usec_t start_delay;
@@ -117,17 +117,26 @@ static const uint8_t default_req_opts[] = {
         SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
 };
 
-static int client_receive_message_raw(sd_event_source *s, int fd,
-                                      uint32_t revents, void *userdata);
-static int client_receive_message_udp(sd_event_source *s, int fd,
-                                      uint32_t revents, void *userdata);
+static int client_receive_message_raw(
+                sd_event_source *s,
+                int fd,
+                uint32_t revents,
+                void *userdata);
+static int client_receive_message_udp(
+                sd_event_source *s,
+                int fd,
+                uint32_t revents,
+                void *userdata);
 static void client_stop(sd_dhcp_client *client, int error);
 
-int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb,
-                                void *userdata) {
+int sd_dhcp_client_set_callback(
+                sd_dhcp_client *client,
+                sd_dhcp_client_callback_t cb,
+                void *userdata) {
+
         assert_return(client, -EINVAL);
 
-        client->cb = cb;
+        client->callback = cb;
         client->userdata = userdata;
 
         return 0;
@@ -145,10 +154,10 @@ int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
         size_t i;
 
         assert_return(client, -EINVAL);
-        assert_return (IN_SET(client->state, DHCP_STATE_INIT,
-                              DHCP_STATE_STOPPED), -EBUSY);
+        assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY);
 
         switch(option) {
+
         case SD_DHCP_OPTION_PAD:
         case SD_DHCP_OPTION_OVERLOAD:
         case SD_DHCP_OPTION_MESSAGE_TYPE:
@@ -173,11 +182,12 @@ int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
         return 0;
 }
 
-int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
-                                       const struct in_addr *last_addr) {
+int sd_dhcp_client_set_request_address(
+                sd_dhcp_client *client,
+                const struct in_addr *last_addr) {
+
         assert_return(client, -EINVAL);
-        assert_return (IN_SET(client->state, DHCP_STATE_INIT,
-                              DHCP_STATE_STOPPED), -EBUSY);
+        assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY);
 
         if (last_addr)
                 client->last_addr = last_addr->s_addr;
@@ -187,19 +197,22 @@ int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
         return 0;
 }
 
-int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
-        assert_return(client, -EINVAL);
-        assert_return (IN_SET(client->state, DHCP_STATE_INIT,
-                              DHCP_STATE_STOPPED), -EBUSY);
-        assert_return(interface_index > 0, -EINVAL);
+int sd_dhcp_client_set_ifindex(sd_dhcp_client *client, int ifindex) {
 
-        client->index = interface_index;
+        assert_return(client, -EINVAL);
+        assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY);
+        assert_return(ifindex > 0, -EINVAL);
 
+        client->ifindex = ifindex;
         return 0;
 }
 
-int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
-                           size_t addr_len, uint16_t arp_type) {
+int sd_dhcp_client_set_mac(
+                sd_dhcp_client *client,
+                const uint8_t *addr,
+                size_t addr_len,
+                uint16_t arp_type) {
+
         DHCP_CLIENT_DONT_DESTROY(client);
         bool need_restart = false;
 
@@ -220,8 +233,7 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
                 return 0;
 
         if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
-                log_dhcp_client(client, "Changing MAC address on running DHCP "
-                                "client, restarting");
+                log_dhcp_client(client, "Changing MAC address on running DHCP client, restarting");
                 need_restart = true;
                 client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
         }
@@ -236,8 +248,11 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
         return 0;
 }
 
-int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
-                                 const uint8_t **data, size_t *data_len) {
+int sd_dhcp_client_get_client_id(
+                sd_dhcp_client *client,
+                uint8_t *type,
+                const uint8_t **data,
+                size_t *data_len) {
 
         assert_return(client, -EINVAL);
         assert_return(type, -EINVAL);
@@ -256,8 +271,12 @@ int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
         return 0;
 }
 
-int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
-                                 const uint8_t *data, size_t data_len) {
+int sd_dhcp_client_set_client_id(
+                sd_dhcp_client *client,
+                uint8_t type,
+                const uint8_t *data,
+                size_t data_len) {
+
         DHCP_CLIENT_DONT_DESTROY(client);
         bool need_restart = false;
 
@@ -266,14 +285,17 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
         assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
 
         switch (type) {
+
         case ARPHRD_ETHER:
                 if (data_len != ETH_ALEN)
                         return -EINVAL;
                 break;
+
         case ARPHRD_INFINIBAND:
                 if (data_len != INFINIBAND_ALEN)
                         return -EINVAL;
                 break;
+
         default:
                 break;
         }
@@ -301,18 +323,37 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
 }
 
 #if 0 /* NM_IGNORED */
-int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
-                                 uint16_t duid_type, uint8_t *duid, size_t duid_len) {
+/**
+ * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
+ * without further modification. Otherwise, if duid_type is supported, DUID
+ * is set based on that type. Otherwise, an error is returned.
+ */
+int sd_dhcp_client_set_iaid_duid(
+                sd_dhcp_client *client,
+                uint32_t iaid,
+                uint16_t duid_type,
+                const void *duid,
+                size_t duid_len) {
+
         DHCP_CLIENT_DONT_DESTROY(client);
         int r;
+        size_t len;
+
         assert_return(client, -EINVAL);
-        zero(client->client_id);
+        assert_return(duid_len == 0 || duid != NULL, -EINVAL);
 
+        if (duid != NULL) {
+                r = dhcp_validate_duid_len(duid_type, duid_len);
+                if (r < 0)
+                        return r;
+        }
+
+        zero(client->client_id);
         client->client_id.type = 255;
 
         /* If IAID is not configured, generate it. */
         if (iaid == 0) {
-                r = dhcp_identifier_set_iaid(client->index, client->mac_addr,
+                r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
                                              client->mac_addr_len,
                                              &client->client_id.ns.iaid);
                 if (r < 0)
@@ -320,22 +361,18 @@ int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
         } else
                 client->client_id.ns.iaid = htobe32(iaid);
 
-        /* If DUID is not configured, generate DUID-EN. */
-        if (duid_len == 0) {
-                r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid,
-                                                &duid_len);
-                if (r < 0)
-                        return r;
-        } else {
-                r = dhcp_validate_duid_len(client->client_id.type, duid_len);
-                if (r < 0)
-                        return r;
+        if (duid != NULL) {
                 client->client_id.ns.duid.type = htobe16(duid_type);
                 memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
-                duid_len += sizeof(client->client_id.ns.duid.type);
-        }
+                len = sizeof(client->client_id.ns.duid.type) + duid_len;
+        } else if (duid_type == DUID_TYPE_EN) {
+                r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
+                if (r < 0)
+                        return r;
+        } else
+                return -EOPNOTSUPP;
 
-        client->client_id_len = sizeof(client->client_id.type) + duid_len +
+        client->client_id_len = sizeof(client->client_id.type) + len +
                                 sizeof(client->client_id.ns.iaid);
 
         if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
@@ -348,8 +385,10 @@ int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
 }
 #endif /* NM_IGNORED */
 
-int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
-                                const char *hostname) {
+int sd_dhcp_client_set_hostname(
+                sd_dhcp_client *client,
+                const char *hostname) {
+
         char *new_hostname = NULL;
 
         assert_return(client, -EINVAL);
@@ -372,8 +411,10 @@ int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
         return 0;
 }
 
-int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client,
-                                               const char *vci) {
+int sd_dhcp_client_set_vendor_class_identifier(
+                sd_dhcp_client *client,
+                const char *vci) {
+
         char *new_vci = NULL;
 
         assert_return(client, -EINVAL);
@@ -400,28 +441,29 @@ int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
 
 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
         assert_return(client, -EINVAL);
-        assert_return(ret, -EINVAL);
 
         if (client->state != DHCP_STATE_BOUND &&
             client->state != DHCP_STATE_RENEWING &&
             client->state != DHCP_STATE_REBINDING)
                 return -EADDRNOTAVAIL;
 
-        *ret = client->lease;
+        if (ret)
+                *ret = client->lease;
 
         return 0;
 }
 
 static void client_notify(sd_dhcp_client *client, int event) {
-        if (client->cb)
-                client->cb(client, event, client->userdata);
+        assert(client);
+
+        if (client->callback)
+                client->callback(client, event, client->userdata);
 }
 
 static int client_initialize(sd_dhcp_client *client) {
         assert_return(client, -EINVAL);
 
-        client->receive_message =
-                sd_event_source_unref(client->receive_message);
+        client->receive_message = sd_event_source_unref(client->receive_message);
 
         client->fd = asynchronous_close(client->fd);
 
@@ -456,8 +498,13 @@ static void client_stop(sd_dhcp_client *client, int error) {
         client_initialize(client);
 }
 
-static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
-                               uint8_t type, size_t *_optlen, size_t *_optoffset) {
+static int client_message_init(
+                sd_dhcp_client *client,
+                DHCPPacket **ret,
+                uint8_t type,
+                size_t *_optlen,
+                size_t *_optoffset) {
+
         _cleanup_free_ DHCPPacket *packet = NULL;
         size_t optlen, optoffset, size;
         be16_t max_size;
@@ -525,7 +572,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
 
                 client->client_id.type = 255;
 
-                r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid);
+                r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid);
                 if (r < 0)
                         return r;
 
@@ -598,8 +645,12 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
         return 0;
 }
 
-static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t *optoffset,
-                                     const char *fqdn) {
+static int client_append_fqdn_option(
+                DHCPMessage *message,
+                size_t optlen,
+                size_t *optoffset,
+                const char *fqdn) {
+
         uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH];
         int r;
 
@@ -616,8 +667,11 @@ static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t
         return r;
 }
 
-static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
-                                size_t len) {
+static int dhcp_client_send_raw(
+                sd_dhcp_client *client,
+                DHCPPacket *packet,
+                size_t len) {
+
         dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
                                       INADDR_BROADCAST, DHCP_PORT_SERVER, len);
 
@@ -704,8 +758,9 @@ static int client_send_request(sd_dhcp_client *client) {
         size_t optoffset, optlen;
         int r;
 
-        r = client_message_init(client, &request, DHCP_REQUEST,
-                                &optlen, &optoffset);
+        assert(client);
+
+        r = client_message_init(client, &request, DHCP_REQUEST, &optlen, &optoffset);
         if (r < 0)
                 return r;
 
@@ -802,18 +857,23 @@ static int client_send_request(sd_dhcp_client *client) {
                 return r;
 
         switch (client->state) {
+
         case DHCP_STATE_REQUESTING:
                 log_dhcp_client(client, "REQUEST (requesting)");
                 break;
+
         case DHCP_STATE_INIT_REBOOT:
                 log_dhcp_client(client, "REQUEST (init-reboot)");
                 break;
+
         case DHCP_STATE_RENEWING:
                 log_dhcp_client(client, "REQUEST (renewing)");
                 break;
+
         case DHCP_STATE_REBINDING:
                 log_dhcp_client(client, "REQUEST (rebinding)");
                 break;
+
         default:
                 log_dhcp_client(client, "REQUEST (invalid)");
                 break;
@@ -824,8 +884,11 @@ static int client_send_request(sd_dhcp_client *client) {
 
 static int client_start(sd_dhcp_client *client);
 
-static int client_timeout_resend(sd_event_source *s, uint64_t usec,
-                                 void *userdata) {
+static int client_timeout_resend(
+                sd_event_source *s,
+                uint64_t usec,
+                void *userdata) {
+
         sd_dhcp_client *client = userdata;
         DHCP_CLIENT_DONT_DESTROY(client);
         usec_t next_timeout = 0;
@@ -842,6 +905,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
                 goto error;
 
         switch (client->state) {
+
         case DHCP_STATE_RENEWING:
 
                 time_left = (client->lease->t2 - client->lease->t1) / 2;
@@ -969,8 +1033,10 @@ error:
         return 0;
 }
 
-static int client_initialize_io_events(sd_dhcp_client *client,
-                                       sd_event_io_handler_t io_callback) {
+static int client_initialize_io_events(
+                sd_dhcp_client *client,
+                sd_event_io_handler_t io_callback) {
+
         int r;
 
         assert(client);
@@ -1037,8 +1103,7 @@ error:
 
 }
 
-static int client_initialize_events(sd_dhcp_client *client,
-                                    sd_event_io_handler_t io_callback) {
+static int client_initialize_events(sd_dhcp_client *client, sd_event_io_handler_t io_callback) {
         client_initialize_io_events(client, io_callback);
         client_initialize_time_events(client);
 
@@ -1050,15 +1115,14 @@ static int client_start_delayed(sd_dhcp_client *client) {
 
         assert_return(client, -EINVAL);
         assert_return(client->event, -EINVAL);
-        assert_return(client->index > 0, -EINVAL);
+        assert_return(client->ifindex > 0, -EINVAL);
         assert_return(client->fd < 0, -EBUSY);
         assert_return(client->xid == 0, -EINVAL);
-        assert_return(client->state == DHCP_STATE_INIT ||
-                      client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
+        assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_INIT_REBOOT), -EBUSY);
 
         client->xid = random_u32();
 
-        r = dhcp_network_bind_raw_socket(client->index, &client->link,
+        r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
                                          client->xid, client->mac_addr,
                                          client->mac_addr_len, client->arp_type);
         if (r < 0) {
@@ -1078,8 +1142,7 @@ static int client_start(sd_dhcp_client *client) {
         return client_start_delayed(client);
 }
 
-static int client_timeout_expire(sd_event_source *s, uint64_t usec,
-                                 void *userdata) {
+static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) {
         sd_dhcp_client *client = userdata;
         DHCP_CLIENT_DONT_DESTROY(client);
 
@@ -1101,13 +1164,15 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
         DHCP_CLIENT_DONT_DESTROY(client);
         int r;
 
+        assert(client);
+
         client->receive_message = sd_event_source_unref(client->receive_message);
         client->fd = asynchronous_close(client->fd);
 
         client->state = DHCP_STATE_REBINDING;
         client->attempt = 1;
 
-        r = dhcp_network_bind_raw_socket(client->index, &client->link,
+        r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
                                          client->xid, client->mac_addr,
                                          client->mac_addr_len, client->arp_type);
         if (r < 0) {
@@ -1119,8 +1184,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
         return client_initialize_events(client, client_receive_message_raw);
 }
 
-static int client_timeout_t1(sd_event_source *s, uint64_t usec,
-                             void *userdata) {
+static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) {
         sd_dhcp_client *client = userdata;
         DHCP_CLIENT_DONT_DESTROY(client);
 
@@ -1130,8 +1194,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec,
         return client_initialize_time_events(client);
 }
 
-static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
-                               size_t len) {
+static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_t len) {
         _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
         int r;
 
@@ -1182,8 +1245,7 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
         return 0;
 }
 
-static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
-                                    size_t len) {
+static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, size_t len) {
         int r;
 
         r = dhcp_option_parse(force, len, NULL, NULL, NULL);
@@ -1195,8 +1257,7 @@ static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
         return 0;
 }
 
-static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
-                             size_t len) {
+static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t len) {
         _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
         _cleanup_free_ char *error_message = NULL;
         int r;
@@ -1424,8 +1485,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
         return 0;
 }
 
-static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
-                                 int len) {
+static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, int len) {
         DHCP_CLIENT_DONT_DESTROY(client);
         char time_string[FORMAT_TIMESPAN_MAX];
         int r = 0, notify_event = 0;
@@ -1571,11 +1631,15 @@ error:
         return r;
 }
 
-static int client_receive_message_udp(sd_event_source *s, int fd,
-                                      uint32_t revents, void *userdata) {
+static int client_receive_message_udp(
+                sd_event_source *s,
+                int fd,
+                uint32_t revents,
+                void *userdata) {
+
         sd_dhcp_client *client = userdata;
         _cleanup_free_ DHCPMessage *message = NULL;
-        const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
+        const struct ether_addr zero_mac = {};
         const struct ether_addr *expected_chaddr = NULL;
         uint8_t expected_hlen = 0;
         ssize_t len, buflen;
@@ -1591,14 +1655,14 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
         if (!message)
                 return -ENOMEM;
 
-        len = read(fd, message, buflen);
+        len = recv(fd, message, buflen, 0);
         if (len < 0) {
                 if (errno == EAGAIN || errno == EINTR)
                         return 0;
 
-                log_dhcp_client(client, "Could not receive message from UDP socket: %m");
-                return -errno;
-        } else if ((size_t)len < sizeof(DHCPMessage)) {
+                return log_dhcp_client_errno(client, errno, "Could not receive message from UDP socket: %m");
+        }
+        if ((size_t) len < sizeof(DHCPMessage)) {
                 log_dhcp_client(client, "Too small to be a DHCP message: ignoring");
                 return 0;
         }
@@ -1649,8 +1713,12 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
         return client_handle_message(client, message, len);
 }
 
-static int client_receive_message_raw(sd_event_source *s, int fd,
-                                      uint32_t revents, void *userdata) {
+static int client_receive_message_raw(
+                sd_event_source *s,
+                int fd,
+                uint32_t revents,
+                void *userdata) {
+
         sd_dhcp_client *client = userdata;
         _cleanup_free_ DHCPPacket *packet = NULL;
         uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
@@ -1725,7 +1793,7 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
 
         r = client_start(client);
         if (r >= 0)
-                log_dhcp_client(client, "STARTED on ifindex %i", client->index);
+                log_dhcp_client(client, "STARTED on ifindex %i", client->ifindex);
 
         return r;
 }
@@ -1769,8 +1837,7 @@ int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
 }
 
 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
-        if (!client)
-                return NULL;
+        assert_return(client, NULL);
 
         return client->event;
 }
@@ -1826,13 +1893,12 @@ int sd_dhcp_client_new(sd_dhcp_client **ret) {
 
         client->n_ref = 1;
         client->state = DHCP_STATE_INIT;
-        client->index = -1;
+        client->ifindex = -1;
         client->fd = -1;
         client->attempt = 1;
         client->mtu = DHCP_DEFAULT_MIN_SIZE;
 
         client->req_opts_size = ELEMENTSOF(default_req_opts);
-
         client->req_opts = memdup(default_req_opts, client->req_opts_size);
         if (!client->req_opts)
                 return -ENOMEM;
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
index 8fa1822f..a05bde63 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
@@ -47,7 +47,7 @@ struct sd_dhcp6_client {
         enum DHCP6State state;
         sd_event *event;
         int event_priority;
-        int index;
+        int ifindex;
         struct in6_addr local_address;
         uint8_t mac_addr[MAX_MAC_ADDR_LEN];
         size_t mac_addr_len;
@@ -66,7 +66,7 @@ struct sd_dhcp6_client {
         uint8_t retransmit_count;
         sd_event_source *timeout_resend;
         sd_event_source *timeout_resend_expire;
-        sd_dhcp6_client_callback_t cb;
+        sd_dhcp6_client_callback_t callback;
         void *userdata;
         struct duid duid;
         size_t duid_len;
@@ -113,27 +113,33 @@ DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
 
 static int client_start(sd_dhcp6_client *client, enum DHCP6State state);
 
-int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_callback_t cb, void *userdata) {
+int sd_dhcp6_client_set_callback(
+                sd_dhcp6_client *client,
+                sd_dhcp6_client_callback_t cb,
+                void *userdata) {
+
         assert_return(client, -EINVAL);
 
-        client->cb = cb;
+        client->callback = cb;
         client->userdata = userdata;
 
         return 0;
 }
 
-int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {
-        assert_return(client, -EINVAL);
-        assert_return(interface_index >= -1, -EINVAL);
+int sd_dhcp6_client_set_ifindex(sd_dhcp6_client *client, int ifindex) {
 
+        assert_return(client, -EINVAL);
+        assert_return(ifindex >= -1, -EINVAL);
         assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
 
-        client->index = interface_index;
-
+        client->ifindex = ifindex;
         return 0;
 }
 
-int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address) {
+int sd_dhcp6_client_set_local_address(
+                sd_dhcp6_client *client,
+                const struct in6_addr *local_address) {
+
         assert_return(client, -EINVAL);
         assert_return(local_address, -EINVAL);
         assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) local_address) > 0, -EINVAL);
@@ -182,20 +188,38 @@ static int client_ensure_duid(sd_dhcp6_client *client) {
         return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
 }
 
-int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type,
-                             uint8_t *duid, size_t duid_len) {
+/**
+ * Sets DUID. If duid is non-null, the DUID is set to duid_type + duid
+ * without further modification. Otherwise, if duid_type is supported, DUID
+ * is set based on that type. Otherwise, an error is returned.
+ */
+int sd_dhcp6_client_set_duid(
+                sd_dhcp6_client *client,
+                uint16_t duid_type,
+                const void *duid,
+                size_t duid_len) {
+
         int r;
         assert_return(client, -EINVAL);
+        assert_return(duid_len == 0 || duid != NULL, -EINVAL);
         assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
 
-        if (duid_len > 0) {
+        if (duid != NULL) {
                 r = dhcp_validate_duid_len(duid_type, duid_len);
                 if (r < 0)
                         return r;
+        }
+
+        if (duid != NULL) {
                 client->duid.type = htobe16(duid_type);
                 memcpy(&client->duid.raw.data, duid, duid_len);
-                client->duid_len = duid_len + sizeof(client->duid.type);
-        }
+                client->duid_len = sizeof(client->duid.type) + duid_len;
+        } else if (duid_type == DUID_TYPE_EN) {
+                r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
+                if (r < 0)
+                        return r;
+        } else
+                return -EOPNOTSUPP;
 
         return 0;
 }
@@ -236,6 +260,7 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
         assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
 
         switch(option) {
+
         case SD_DHCP6_OPTION_DNS_SERVERS:
         case SD_DHCP6_OPTION_DOMAIN_LIST:
         case SD_DHCP6_OPTION_SNTP_SERVERS:
@@ -272,20 +297,25 @@ int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
 }
 
 static void client_notify(sd_dhcp6_client *client, int event) {
-        if (client->cb)
-                client->cb(client, event, client->userdata);
+        assert(client);
+
+        if (client->callback)
+                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_return(client, -EINVAL);
+        assert(client);
 
         client_set_lease(client, NULL);
 
@@ -333,6 +363,8 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
         usec_t elapsed_usec;
         be16_t elapsed_time;
 
+        assert(client);
+
         len = sizeof(DHCP6Message) + optlen;
 
         message = malloc0(len);
@@ -431,13 +463,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
         return 0;
 }
 
-static int client_timeout_t2(sd_event_source *s, uint64_t usec,
-                             void *userdata) {
+static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
         sd_dhcp6_client *client = userdata;
 
-        assert_return(s, -EINVAL);
-        assert_return(client, -EINVAL);
-        assert_return(client->lease, -EINVAL);
+        assert(s);
+        assert(client);
+        assert(client->lease);
 
         client->lease->ia.timeout_t2 =
                 sd_event_source_unref(client->lease->ia.timeout_t2);
@@ -449,13 +480,12 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec,
         return 0;
 }
 
-static int client_timeout_t1(sd_event_source *s, uint64_t usec,
-                             void *userdata) {
+static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) {
         sd_dhcp6_client *client = userdata;
 
-        assert_return(s, -EINVAL);
-        assert_return(client, -EINVAL);
-        assert_return(client->lease, -EINVAL);
+        assert(s);
+        assert(client);
+        assert(client->lease);
 
         client->lease->ia.timeout_t1 =
                 sd_event_source_unref(client->lease->ia.timeout_t1);
@@ -467,8 +497,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec,
         return 0;
 }
 
-static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec,
-                                        void *userdata) {
+static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec, void *userdata) {
         sd_dhcp6_client *client = userdata;
         DHCP6_CLIENT_DONT_DESTROY(client);
         enum DHCP6State state;
@@ -494,8 +523,7 @@ static usec_t client_timeout_compute_random(usec_t val) {
                 (random_u32() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC;
 }
 
-static int client_timeout_resend(sd_event_source *s, uint64_t usec,
-                                 void *userdata) {
+static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userdata) {
         int r = 0;
         sd_dhcp6_client *client = userdata;
         usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0;
@@ -655,16 +683,18 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
         if (client->ia_na.id)
                 return 0;
 
-        r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->ia_na.id);
+        r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, &client->ia_na.id);
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-static int client_parse_message(sd_dhcp6_client *client,
-                                DHCP6Message *message, size_t len,
-                                sd_dhcp6_lease *lease) {
+static int client_parse_message(
+                sd_dhcp6_client *client,
+                DHCP6Message *message,
+                size_t len,
+                sd_dhcp6_lease *lease) {
         int r;
         uint8_t *optval, *option, *id = NULL;
         uint16_t optcode, status;
@@ -672,6 +702,11 @@ static int client_parse_message(sd_dhcp6_client *client,
         bool clientid = false;
         be32_t iaid_lease;
 
+        assert(client);
+        assert(message);
+        assert(len >= sizeof(DHCP6Message));
+        assert(lease);
+
         option = (uint8_t *)message + sizeof(DHCP6Message);
         len -= sizeof(DHCP6Message);
 
@@ -816,9 +851,12 @@ static int client_parse_message(sd_dhcp6_client *client,
 }
 
 static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) {
-        int r;
         _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
         bool rapid_commit;
+        int r;
+
+        assert(client);
+        assert(reply);
 
         if (reply->type != DHCP6_REPLY)
                 return 0;
@@ -847,9 +885,9 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, si
 }
 
 static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) {
-        int r;
         _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
         uint8_t pref_advertise = 0, pref_lease = 0;
+        int r;
 
         if (advertise->type != DHCP6_ADVERTISE)
                 return 0;
@@ -880,7 +918,12 @@ static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *adver
         return r;
 }
 
-static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+static int client_receive_message(
+                sd_event_source *s,
+                int fd, uint32_t
+                revents,
+                void *userdata) {
+
         sd_dhcp6_client *client = userdata;
         DHCP6_CLIENT_DONT_DESTROY(client);
         _cleanup_free_ DHCP6Message *message = NULL;
@@ -899,16 +942,18 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
         if (!message)
                 return -ENOMEM;
 
-        len = read(fd, message, buflen);
+        len = recv(fd, message, buflen, 0);
         if (len < 0) {
                 if (errno == EAGAIN || errno == EINTR)
                         return 0;
 
-                log_dhcp6_client(client, "Could not receive message from UDP socket: %m");
+                return log_dhcp6_client_errno(client, errno, "Could not receive message from UDP socket: %m");
 
-                return -errno;
-        } else if ((size_t)len < sizeof(DHCP6Message))
+        }
+        if ((size_t) len < sizeof(DHCP6Message)) {
+                log_dhcp6_client(client, "Too small to be DHCP6 message: ignoring");
                 return 0;
+        }
 
         switch(message->type) {
         case DHCP6_SOLICIT:
@@ -929,8 +974,7 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
                 break;
 
         default:
-                log_dhcp6_client(client, "unknown message type %d",
-                                 message->type);
+                log_dhcp6_client(client, "Unknown message type %d", message->type);
                 return 0;
         }
 
@@ -989,10 +1033,9 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
                 return 0;
         }
 
-        if (r >= 0) {
+        if (r >= 0)
                 log_dhcp6_client(client, "Recv %s",
                                  dhcp6_message_type_to_string(message->type));
-        }
 
         return 0;
 }
@@ -1004,7 +1047,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
 
         assert_return(client, -EINVAL);
         assert_return(client->event, -EINVAL);
-        assert_return(client->index > 0, -EINVAL);
+        assert_return(client->ifindex > 0, -EINVAL);
         assert_return(client->state != state, -EINVAL);
 
         client->timeout_resend_expire =
@@ -1045,7 +1088,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
                 if (client->lease->ia.lifetime_t1 == 0xffffffff ||
                     client->lease->ia.lifetime_t2 == 0xffffffff) {
 
-                        log_dhcp6_client(client, "infinite T1 0x%08x or T2 0x%08x",
+                        log_dhcp6_client(client, "Infinite T1 0x%08x or T2 0x%08x",
                                          be32toh(client->lease->ia.lifetime_t1),
                                          be32toh(client->lease->ia.lifetime_t2));
 
@@ -1137,12 +1180,12 @@ int sd_dhcp6_client_is_running(sd_dhcp6_client *client) {
 }
 
 int sd_dhcp6_client_start(sd_dhcp6_client *client) {
-        int r = 0;
         enum DHCP6State state = DHCP6_STATE_SOLICITATION;
+        int r = 0;
 
         assert_return(client, -EINVAL);
         assert_return(client->event, -EINVAL);
-        assert_return(client->index > 0, -EINVAL);
+        assert_return(client->ifindex > 0, -EINVAL);
         assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) &client->local_address) > 0, -EINVAL);
 
         if (!IN_SET(client->state, DHCP6_STATE_STOPPED))
@@ -1160,9 +1203,14 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
         if (r < 0)
                 return r;
 
-        r = dhcp6_network_bind_udp_socket(client->index, &client->local_address);
-        if (r < 0)
-                return r;
+        r = dhcp6_network_bind_udp_socket(client->ifindex, &client->local_address);
+        if (r < 0) {
+                _cleanup_free_ char *p = NULL;
+
+                (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &client->local_address, &p);
+                return log_dhcp6_client_errno(client, r,
+                                              "Failed to bind to UDP socket at address %s: %m", strna(p));
+        }
 
         client->fd = r;
 
@@ -1178,7 +1226,7 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
                 goto error;
 
         r = sd_event_source_set_description(client->receive_message,
-                                        "dhcp6-receive-message");
+                                            "dhcp6-receive-message");
         if (r < 0)
                 goto error;
 
@@ -1186,8 +1234,8 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
                 state = DHCP6_STATE_INFORMATION_REQUEST;
 
         log_dhcp6_client(client, "Started in %s mode",
-                        client->information_request? "Information request":
-                        "Managed");
+                         client->information_request? "Information request":
+                         "Managed");
 
         return client_start(client, state);
 
@@ -1224,8 +1272,7 @@ int sd_dhcp6_client_detach_event(sd_dhcp6_client *client) {
 }
 
 sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) {
-        if (!client)
-                return NULL;
+        assert_return(client, NULL);
 
         return client->event;
 }
@@ -1273,15 +1320,11 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
                 return -ENOMEM;
 
         client->n_ref = 1;
-
         client->ia_na.type = SD_DHCP6_OPTION_IA_NA;
-
-        client->index = -1;
-
+        client->ifindex = -1;
         client->fd = -1;
 
         client->req_opts_len = ELEMENTSOF(default_req_opts);
-
         client->req_opts = new0(be16_t, client->req_opts_len);
         if (!client->req_opts)
                 return -ENOMEM;
diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c
index 9b5ce720..59830795 100644
--- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c
+++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c
@@ -30,45 +30,30 @@
 
 #include "alloc-util.h"
 #include "arp-util.h"
+#include "ether-addr-util.h"
 #include "fd-util.h"
 #include "in-addr-util.h"
 #include "list.h"
 #include "random-util.h"
-#include "refcnt.h"
 #include "siphash24.h"
+#include "string-util.h"
 #include "util.h"
 
 /* Constants from the RFC */
-#define PROBE_WAIT 1
-#define PROBE_NUM 3
-#define PROBE_MIN 1
-#define PROBE_MAX 2
-#define ANNOUNCE_WAIT 2
-#define ANNOUNCE_NUM 2
-#define ANNOUNCE_INTERVAL 2
-#define MAX_CONFLICTS 10
-#define RATE_LIMIT_INTERVAL 60
-#define DEFEND_INTERVAL 10
-
-#define IPV4ACD_NETWORK 0xA9FE0000L
-#define IPV4ACD_NETMASK 0xFFFF0000L
-
-#define log_ipv4acd_full(ll, level, error, fmt, ...) log_internal(level, error, __FILE__, __LINE__, __func__, "ACD: " fmt, ##__VA_ARGS__)
-
-#define log_ipv4acd_debug(ll, ...)   log_ipv4acd_full(ll, LOG_DEBUG, 0, ##__VA_ARGS__)
-#define log_ipv4acd_info(ll, ...)    log_ipv4acd_full(ll, LOG_INFO, 0, ##__VA_ARGS__)
-#define log_ipv4acd_notice(ll, ...)  log_ipv4acd_full(ll, LOG_NOTICE, 0, ##__VA_ARGS__)
-#define log_ipv4acd_warning(ll, ...) log_ipv4acd_full(ll, LOG_WARNING, 0, ##__VA_ARGS__)
-#define log_ipv4acd_error(ll, ...)   log_ipv4acd_full(ll, LOG_ERR, 0, ##__VA_ARGS__)
-
-#define log_ipv4acd_debug_errno(ll, error, ...)   log_ipv4acd_full(ll, LOG_DEBUG, error, ##__VA_ARGS__)
-#define log_ipv4acd_info_errno(ll, error, ...)    log_ipv4acd_full(ll, LOG_INFO, error, ##__VA_ARGS__)
-#define log_ipv4acd_notice_errno(ll, error, ...)  log_ipv4acd_full(ll, LOG_NOTICE, error, ##__VA_ARGS__)
-#define log_ipv4acd_warning_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_WARNING, error, ##__VA_ARGS__)
-#define log_ipv4acd_error_errno(ll, error, ...)   log_ipv4acd_full(ll, LOG_ERR, error, ##__VA_ARGS__)
+#define PROBE_WAIT_USEC (1U * USEC_PER_SEC)
+#define PROBE_NUM 3U
+#define PROBE_MIN_USEC (1U * USEC_PER_SEC)
+#define PROBE_MAX_USEC (2U * USEC_PER_SEC)
+#define ANNOUNCE_WAIT_USEC (2U * USEC_PER_SEC)
+#define ANNOUNCE_NUM 2U
+#define ANNOUNCE_INTERVAL_USEC (2U * USEC_PER_SEC)
+#define MAX_CONFLICTS 10U
+#define RATE_LIMIT_INTERVAL_USEC (60U * USEC_PER_SEC)
+#define DEFEND_INTERVAL_USEC (10U * USEC_PER_SEC)
 
 typedef enum IPv4ACDState {
         IPV4ACD_STATE_INIT,
+        IPV4ACD_STATE_STARTED,
         IPV4ACD_STATE_WAITING_PROBE,
         IPV4ACD_STATE_PROBING,
         IPV4ACD_STATE_WAITING_ANNOUNCE,
@@ -79,156 +64,164 @@ typedef enum IPv4ACDState {
 } IPv4ACDState;
 
 struct sd_ipv4acd {
-        RefCount n_ref;
+        unsigned n_ref;
 
         IPv4ACDState state;
-        int index;
+        int ifindex;
         int fd;
-        int iteration;
-        int conflict;
-        sd_event_source *receive_message;
-        sd_event_source *timer;
+
+        unsigned n_iteration;
+        unsigned n_conflict;
+
+        sd_event_source *receive_message_event_source;
+        sd_event_source *timer_event_source;
+
         usec_t defend_window;
         be32_t address;
+
         /* External */
         struct ether_addr mac_addr;
+
         sd_event *event;
         int event_priority;
-        sd_ipv4acd_callback_t cb;
+        sd_ipv4acd_callback_t callback;
         void* userdata;
 };
 
-sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *ll) {
-        if (ll)
-                assert_se(REFCNT_INC(ll->n_ref) >= 2);
+#define log_ipv4acd_errno(acd, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "IPV4ACD: " fmt, ##__VA_ARGS__)
+#define log_ipv4acd(acd, fmt, ...) log_ipv4acd_errno(acd, 0, fmt, ##__VA_ARGS__)
+
+static void ipv4acd_set_state(sd_ipv4acd *acd, IPv4ACDState st, bool reset_counter) {
+        assert(acd);
+        assert(st < _IPV4ACD_STATE_MAX);
+
+        if (st == acd->state && !reset_counter)
+                acd->n_iteration++;
+        else {
+                acd->state = st;
+                acd->n_iteration = 0;
+        }
+}
+
+static void ipv4acd_reset(sd_ipv4acd *acd) {
+        assert(acd);
+
+        acd->timer_event_source = sd_event_source_unref(acd->timer_event_source);
+        acd->receive_message_event_source = sd_event_source_unref(acd->receive_message_event_source);
+
+        acd->fd = safe_close(acd->fd);
+
+        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 ll;
+        return acd;
 }
 
-sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *ll) {
-        if (!ll || REFCNT_DEC(ll->n_ref) > 0)
+sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd) {
+        if (!acd)
                 return NULL;
 
-        ll->receive_message = sd_event_source_unref(ll->receive_message);
-        ll->fd = safe_close(ll->fd);
+        assert_se(acd->n_ref >= 1);
+        acd->n_ref--;
 
-        ll->timer = sd_event_source_unref(ll->timer);
+        if (acd->n_ref > 0)
+                return NULL;
 
-        sd_ipv4acd_detach_event(ll);
+        ipv4acd_reset(acd);
+        sd_ipv4acd_detach_event(acd);
 
-        free(ll);
+        free(acd);
 
         return NULL;
 }
 
 int sd_ipv4acd_new(sd_ipv4acd **ret) {
-        _cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *ll = NULL;
+        _cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *acd = NULL;
 
         assert_return(ret, -EINVAL);
 
-        ll = new0(sd_ipv4acd, 1);
-        if (!ll)
+        acd = new0(sd_ipv4acd, 1);
+        if (!acd)
                 return -ENOMEM;
 
-        ll->n_ref = REFCNT_INIT;
-        ll->state = IPV4ACD_STATE_INIT;
-        ll->index = -1;
-        ll->fd = -1;
+        acd->n_ref = 1;
+        acd->state = IPV4ACD_STATE_INIT;
+        acd->ifindex = -1;
+        acd->fd = -1;
 
-        *ret = ll;
-        ll = NULL;
+        *ret = acd;
+        acd = NULL;
 
         return 0;
 }
 
-static void ipv4acd_set_state(sd_ipv4acd *ll, IPv4ACDState st, bool reset_counter) {
-
-        assert(ll);
-        assert(st < _IPV4ACD_STATE_MAX);
-
-        if (st == ll->state && !reset_counter)
-                ll->iteration++;
-        else {
-                ll->state = st;
-                ll->iteration = 0;
-        }
-}
+static void ipv4acd_client_notify(sd_ipv4acd *acd, int event) {
+        assert(acd);
 
-static void ipv4acd_client_notify(sd_ipv4acd *ll, int event) {
-        assert(ll);
+        if (!acd->callback)
+                return;
 
-        if (ll->cb)
-                ll->cb(ll, event, ll->userdata);
+        acd->callback(acd, event, acd->userdata);
 }
 
-static void ipv4acd_stop(sd_ipv4acd *ll) {
-        assert(ll);
+int sd_ipv4acd_stop(sd_ipv4acd *acd) {
+        assert_return(acd, -EINVAL);
 
-        ll->receive_message = sd_event_source_unref(ll->receive_message);
-        ll->fd = safe_close(ll->fd);
+        ipv4acd_reset(acd);
 
-        ll->timer = sd_event_source_unref(ll->timer);
+        log_ipv4acd(acd, "STOPPED");
 
-        log_ipv4acd_debug(ll, "STOPPED");
-
-        ipv4acd_set_state (ll, IPV4ACD_STATE_INIT, true);
-}
-
-int sd_ipv4acd_stop(sd_ipv4acd *ll) {
-        assert_return(ll, -EINVAL);
-
-        ipv4acd_stop(ll);
-
-        ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_STOP);
+        ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_STOP);
 
         return 0;
 }
 
 static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata);
 
-static int ipv4acd_set_next_wakeup(sd_ipv4acd *ll, int sec, int random_sec) {
+static int ipv4acd_set_next_wakeup(sd_ipv4acd *acd, usec_t usec, usec_t random_usec) {
         _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL;
-        usec_t next_timeout;
-        usec_t time_now;
+        usec_t next_timeout, time_now;
         int r;
 
-        assert(sec >= 0);
-        assert(random_sec >= 0);
-        assert(ll);
+        assert(acd);
 
-        next_timeout = sec * USEC_PER_SEC;
+        next_timeout = usec;
 
-        if (random_sec)
-                next_timeout += random_u32() % (random_sec * USEC_PER_SEC);
+        if (random_usec > 0)
+                next_timeout += (usec_t) random_u64() % random_usec;
 
-        assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &time_now) >= 0);
+        assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &time_now) >= 0);
 
-        r = sd_event_add_time(ll->event, &timer, clock_boottime_or_monotonic(),
-                              time_now + next_timeout, 0, ipv4acd_on_timeout, ll);
+        r = sd_event_add_time(acd->event, &timer, clock_boottime_or_monotonic(), time_now + next_timeout, 0, ipv4acd_on_timeout, acd);
         if (r < 0)
                 return r;
 
-        r = sd_event_source_set_priority(timer, ll->event_priority);
+        r = sd_event_source_set_priority(timer, acd->event_priority);
         if (r < 0)
                 return r;
 
-        r = sd_event_source_set_description(timer, "ipv4acd-timer");
-        if (r < 0)
-                return r;
+        (void) sd_event_source_set_description(timer, "ipv4acd-timer");
 
-        ll->timer = sd_event_source_unref(ll->timer);
-        ll->timer = timer;
+        sd_event_source_unref(acd->timer_event_source);
+        acd->timer_event_source = timer;
         timer = NULL;
 
         return 0;
 }
 
-static bool ipv4acd_arp_conflict(sd_ipv4acd *ll, struct ether_arp *arp) {
-        assert(ll);
+static bool ipv4acd_arp_conflict(sd_ipv4acd *acd, struct ether_arp *arp) {
+        assert(acd);
         assert(arp);
 
         /* see the BPF */
-        if (memcmp(arp->arp_spa, &ll->address, sizeof(ll->address)) == 0)
+        if (memcmp(arp->arp_spa, &acd->address, sizeof(acd->address)) == 0)
                 return true;
 
         /* the TPA matched instead of the SPA, this is not a conflict */
@@ -236,294 +229,300 @@ static bool ipv4acd_arp_conflict(sd_ipv4acd *ll, struct ether_arp *arp) {
 }
 
 static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
-        sd_ipv4acd *ll = userdata;
+        sd_ipv4acd *acd = userdata;
         int r = 0;
 
-        assert(ll);
+        assert(acd);
+
+        switch (acd->state) {
 
-        switch (ll->state) {
-        case IPV4ACD_STATE_INIT:
+        case IPV4ACD_STATE_STARTED:
+                ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_PROBE, true);
 
-                ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_PROBE, true);
+                if (acd->n_conflict >= MAX_CONFLICTS) {
+                        char ts[FORMAT_TIMESPAN_MAX];
+                        log_ipv4acd(acd, "Max conflicts reached, delaying by %s", format_timespan(ts, sizeof(ts), RATE_LIMIT_INTERVAL_USEC, 0));
 
-                if (ll->conflict >= MAX_CONFLICTS) {
-                        log_ipv4acd_notice(ll, "Max conflicts reached, delaying by %us", RATE_LIMIT_INTERVAL);
-                        r = ipv4acd_set_next_wakeup(ll, RATE_LIMIT_INTERVAL, PROBE_WAIT);
+                        r = ipv4acd_set_next_wakeup(acd, RATE_LIMIT_INTERVAL_USEC, PROBE_WAIT_USEC);
                         if (r < 0)
-                                goto out;
+                                goto fail;
 
-                        ll->conflict = 0;
+                        acd->n_conflict = 0;
                 } else {
-                        r = ipv4acd_set_next_wakeup(ll, 0, PROBE_WAIT);
+                        r = ipv4acd_set_next_wakeup(acd, 0, PROBE_WAIT_USEC);
                         if (r < 0)
-                                goto out;
+                                goto fail;
                 }
 
                 break;
+
         case IPV4ACD_STATE_WAITING_PROBE:
         case IPV4ACD_STATE_PROBING:
                 /* Send a probe */
-                r = arp_send_probe(ll->fd, ll->index, ll->address, &ll->mac_addr);
+                r = arp_send_probe(acd->fd, acd->ifindex, acd->address, &acd->mac_addr);
                 if (r < 0) {
-                        log_ipv4acd_error_errno(ll, r, "Failed to send ARP probe: %m");
-                        goto out;
+                        log_ipv4acd_errno(acd, r, "Failed to send ARP probe: %m");
+                        goto fail;
                 } else {
                         _cleanup_free_ char *address = NULL;
-                        union in_addr_union addr = { .in.s_addr = ll->address };
+                        union in_addr_union addr = { .in.s_addr = acd->address };
 
-                        r = in_addr_to_string(AF_INET, &addr, &address);
-                        if (r >= 0)
-                                log_ipv4acd_debug(ll, "Probing %s", address);
+                        (void) in_addr_to_string(AF_INET, &addr, &address);
+                        log_ipv4acd(acd, "Probing %s", strna(address));
                 }
 
-                if (ll->iteration < PROBE_NUM - 2) {
-                        ipv4acd_set_state(ll, IPV4ACD_STATE_PROBING, false);
+                if (acd->n_iteration < PROBE_NUM - 2) {
+                        ipv4acd_set_state(acd, IPV4ACD_STATE_PROBING, false);
 
-                        r = ipv4acd_set_next_wakeup(ll, PROBE_MIN, (PROBE_MAX-PROBE_MIN));
+                        r = ipv4acd_set_next_wakeup(acd, PROBE_MIN_USEC, (PROBE_MAX_USEC-PROBE_MIN_USEC));
                         if (r < 0)
-                                goto out;
+                                goto fail;
                 } else {
-                        ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_ANNOUNCE, true);
+                        ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_ANNOUNCE, true);
 
-                        r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_WAIT, 0);
+                        r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_WAIT_USEC, 0);
                         if (r < 0)
-                                goto out;
+                                goto fail;
                 }
 
                 break;
 
         case IPV4ACD_STATE_ANNOUNCING:
-                if (ll->iteration >= ANNOUNCE_NUM - 1) {
-                        ipv4acd_set_state(ll, IPV4ACD_STATE_RUNNING, false);
-
+                if (acd->n_iteration >= ANNOUNCE_NUM - 1) {
+                        ipv4acd_set_state(acd, IPV4ACD_STATE_RUNNING, false);
                         break;
                 }
+
+                /* fall through */
+
         case IPV4ACD_STATE_WAITING_ANNOUNCE:
                 /* Send announcement packet */
-                r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr);
+                r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr);
                 if (r < 0) {
-                        log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m");
-                        goto out;
+                        log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m");
+                        goto fail;
                 } else
-                        log_ipv4acd_debug(ll, "ANNOUNCE");
+                        log_ipv4acd(acd, "ANNOUNCE");
 
-                ipv4acd_set_state(ll, IPV4ACD_STATE_ANNOUNCING, false);
+                ipv4acd_set_state(acd, IPV4ACD_STATE_ANNOUNCING, false);
 
-                r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_INTERVAL, 0);
+                r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_INTERVAL_USEC, 0);
                 if (r < 0)
-                        goto out;
+                        goto fail;
 
-                if (ll->iteration == 0) {
-                        ll->conflict = 0;
-                        ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_BIND);
+                if (acd->n_iteration == 0) {
+                        acd->n_conflict = 0;
+                        ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_BIND);
                 }
 
                 break;
+
         default:
                 assert_not_reached("Invalid state.");
         }
 
-out:
-        if (r < 0)
-                sd_ipv4acd_stop(ll);
+        return 0;
 
-        return 1;
+fail:
+        sd_ipv4acd_stop(acd);
+        return 0;
 }
 
-static void ipv4acd_on_conflict(sd_ipv4acd *ll) {
+static void ipv4acd_on_conflict(sd_ipv4acd *acd) {
         _cleanup_free_ char *address = NULL;
-        union in_addr_union addr = { .in.s_addr = ll->address };
-        int r;
+        union in_addr_union addr = { .in.s_addr = acd->address };
 
-        assert(ll);
+        assert(acd);
 
-        ll->conflict++;
+        acd->n_conflict++;
 
-        r = in_addr_to_string(AF_INET, &addr, &address);
-        if (r >= 0)
-                log_ipv4acd_debug(ll, "Conflict on %s (%u)", address, ll->conflict);
+        (void) in_addr_to_string(AF_INET, &addr, &address);
+        log_ipv4acd(acd, "Conflict on %s (%u)", strna(address), acd->n_conflict);
 
-        ipv4acd_stop(ll);
-
-        ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_CONFLICT);
+        ipv4acd_reset(acd);
+        ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_CONFLICT);
 }
 
-static int ipv4acd_on_packet(sd_event_source *s, int fd,
-                            uint32_t revents, void *userdata) {
-        sd_ipv4acd *ll = userdata;
+static int ipv4acd_on_packet(
+                sd_event_source *s,
+                int fd,
+                uint32_t revents,
+                void *userdata) {
+
+        sd_ipv4acd *acd = userdata;
         struct ether_arp packet;
+        ssize_t n;
         int r;
 
-        assert(ll);
+        assert(s);
+        assert(acd);
         assert(fd >= 0);
 
-        r = read(fd, &packet, sizeof(struct ether_arp));
-        if (r < (int) sizeof(struct ether_arp))
-                goto out;
+        n = recv(fd, &packet, sizeof(struct ether_arp), 0);
+        if (n < 0) {
+                if (errno == EAGAIN || errno == EINTR)
+                        return 0;
+
+                log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m");
+                goto fail;
+        }
+        if ((size_t) n != sizeof(struct ether_arp)) {
+                log_ipv4acd(acd, "Ignoring too short ARP packet.");
+                return 0;
+        }
+
+        switch (acd->state) {
 
-        switch (ll->state) {
         case IPV4ACD_STATE_ANNOUNCING:
         case IPV4ACD_STATE_RUNNING:
-                if (ipv4acd_arp_conflict(ll, &packet)) {
+
+                if (ipv4acd_arp_conflict(acd, &packet)) {
                         usec_t ts;
 
-                        assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &ts) >= 0);
+                        assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &ts) >= 0);
 
                         /* Defend address */
-                        if (ts > ll->defend_window) {
-                                ll->defend_window = ts + DEFEND_INTERVAL * USEC_PER_SEC;
-                                r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr);
+                        if (ts > acd->defend_window) {
+                                acd->defend_window = ts + DEFEND_INTERVAL_USEC;
+                                r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr);
                                 if (r < 0) {
-                                        log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m");
-                                        goto out;
+                                        log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m");
+                                        goto fail;
                                 } else
-                                        log_ipv4acd_debug(ll, "DEFEND");
+                                        log_ipv4acd(acd, "DEFEND");
 
                         } else
-                                ipv4acd_on_conflict(ll);
+                                ipv4acd_on_conflict(acd);
                 }
-
                 break;
+
         case IPV4ACD_STATE_WAITING_PROBE:
         case IPV4ACD_STATE_PROBING:
         case IPV4ACD_STATE_WAITING_ANNOUNCE:
                 /* BPF ensures this packet indicates a conflict */
-                ipv4acd_on_conflict(ll);
-
+                ipv4acd_on_conflict(acd);
                 break;
+
         default:
                 assert_not_reached("Invalid state.");
         }
 
-out:
-        if (r < 0)
-                sd_ipv4acd_stop(ll);
+        return 0;
 
-        return 1;
+fail:
+        sd_ipv4acd_stop(acd);
+        return 0;
 }
 
-int sd_ipv4acd_set_index(sd_ipv4acd *ll, int interface_index) {
-        assert_return(ll, -EINVAL);
-        assert_return(interface_index > 0, -EINVAL);
-        assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
+int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int ifindex) {
+        assert_return(acd, -EINVAL);
+        assert_return(ifindex > 0, -EINVAL);
+        assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY);
 
-        ll->index = interface_index;
+        acd->ifindex = ifindex;
 
         return 0;
 }
 
-int sd_ipv4acd_set_mac(sd_ipv4acd *ll, const struct ether_addr *addr) {
-        assert_return(ll, -EINVAL);
+int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr) {
+        assert_return(acd, -EINVAL);
         assert_return(addr, -EINVAL);
-        assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
+        assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY);
 
-        memcpy(&ll->mac_addr, addr, ETH_ALEN);
+        acd->mac_addr = *addr;
 
         return 0;
 }
 
-int sd_ipv4acd_detach_event(sd_ipv4acd *ll) {
-        assert_return(ll, -EINVAL);
+int sd_ipv4acd_detach_event(sd_ipv4acd *acd) {
+        assert_return(acd, -EINVAL);
 
-        ll->event = sd_event_unref(ll->event);
+        acd->event = sd_event_unref(acd->event);
 
         return 0;
 }
 
-int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int64_t priority) {
+int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority) {
         int r;
 
-        assert_return(ll, -EINVAL);
-        assert_return(!ll->event, -EBUSY);
+        assert_return(acd, -EINVAL);
+        assert_return(!acd->event, -EBUSY);
 
         if (event)
-                ll->event = sd_event_ref(event);
+                acd->event = sd_event_ref(event);
         else {
-                r = sd_event_default(&ll->event);
+                r = sd_event_default(&acd->event);
                 if (r < 0)
                         return r;
         }
 
-        ll->event_priority = priority;
+        acd->event_priority = priority;
 
         return 0;
 }
 
-int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_callback_t cb, void *userdata) {
-        assert_return(ll, -EINVAL);
+int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata) {
+        assert_return(acd, -EINVAL);
 
-        ll->cb = cb;
-        ll->userdata = userdata;
+        acd->callback = cb;
+        acd->userdata = userdata;
 
         return 0;
 }
 
-int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address) {
-        assert_return(ll, -EINVAL);
+int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address) {
+        assert_return(acd, -EINVAL);
         assert_return(address, -EINVAL);
-        assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
+        assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY);
 
-        ll->address = address->s_addr;
+        acd->address = address->s_addr;
 
         return 0;
 }
 
-int sd_ipv4acd_is_running(sd_ipv4acd *ll) {
-        assert_return(ll, false);
+int sd_ipv4acd_is_running(sd_ipv4acd *acd) {
+        assert_return(acd, false);
 
-        return ll->state != IPV4ACD_STATE_INIT;
+        return acd->state != IPV4ACD_STATE_INIT;
 }
 
-static bool ether_addr_is_nul(const struct ether_addr *addr) {
-        const struct ether_addr nul_addr = {};
-
-        assert(addr);
-
-        return memcmp(addr, &nul_addr, sizeof(struct ether_addr)) == 0;
-}
-
-#define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
-
-int sd_ipv4acd_start(sd_ipv4acd *ll) {
+int sd_ipv4acd_start(sd_ipv4acd *acd) {
         int r;
 
-        assert_return(ll, -EINVAL);
-        assert_return(ll->event, -EINVAL);
-        assert_return(ll->index > 0, -EINVAL);
-        assert_return(ll->address != 0, -EINVAL);
-        assert_return(!ether_addr_is_nul(&ll->mac_addr), -EINVAL);
-        assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);
+        assert_return(acd, -EINVAL);
+        assert_return(acd->event, -EINVAL);
+        assert_return(acd->ifindex > 0, -EINVAL);
+        assert_return(acd->address != 0, -EINVAL);
+        assert_return(!ether_addr_is_null(&acd->mac_addr), -EINVAL);
+        assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY);
 
-        ll->defend_window = 0;
-
-        r = arp_network_bind_raw_socket(ll->index, ll->address, &ll->mac_addr);
+        r = arp_network_bind_raw_socket(acd->ifindex, acd->address, &acd->mac_addr);
         if (r < 0)
-                goto out;
+                return r;
 
-        ll->fd = safe_close(ll->fd);
-        ll->fd = r;
+        safe_close(acd->fd);
+        acd->fd = r;
+        acd->defend_window = 0;
+        acd->n_conflict = 0;
 
-        r = sd_event_add_io(ll->event, &ll->receive_message, ll->fd,
-                            EPOLLIN, ipv4acd_on_packet, ll);
+        r = sd_event_add_io(acd->event, &acd->receive_message_event_source, acd->fd, EPOLLIN, ipv4acd_on_packet, acd);
         if (r < 0)
-                goto out;
+                goto fail;
 
-        r = sd_event_source_set_priority(ll->receive_message, ll->event_priority);
+        r = sd_event_source_set_priority(acd->receive_message_event_source, acd->event_priority);
         if (r < 0)
-                goto out;
+                goto fail;
 
-        r = sd_event_source_set_description(ll->receive_message, "ipv4acd-receive-message");
-        if (r < 0)
-                goto out;
+        (void) sd_event_source_set_description(acd->receive_message_event_source, "ipv4acd-receive-message");
 
-        r = ipv4acd_set_next_wakeup(ll, 0, 0);
+        r = ipv4acd_set_next_wakeup(acd, 0, 0);
         if (r < 0)
-                goto out;
-out:
-        if (r < 0) {
-                ipv4acd_stop(ll);
-                return r;
-        }
+                goto fail;
 
+        ipv4acd_set_state(acd, IPV4ACD_STATE_STARTED, true);
         return 0;
+
+fail:
+        ipv4acd_reset(acd);
+        return r;
 }
diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c
index 391be15a..dc2fa370 100644
--- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c
@@ -30,16 +30,17 @@
 #include "sd-ipv4ll.h"
 
 #include "alloc-util.h"
+#include "ether-addr-util.h"
 #include "in-addr-util.h"
 #include "list.h"
 #include "random-util.h"
-#include "refcnt.h"
 #include "siphash24.h"
 #include "sparse-endian.h"
+#include "string-util.h"
 #include "util.h"
 
-#define IPV4LL_NETWORK 0xA9FE0000L
-#define IPV4LL_NETMASK 0xFFFF0000L
+#define IPV4LL_NETWORK UINT32_C(0xA9FE0000)
+#define IPV4LL_NETMASK UINT32_C(0xFFFF0000)
 
 #define IPV4LL_DONT_DESTROY(ll) \
         _cleanup_(sd_ipv4ll_unrefp) _unused_ sd_ipv4ll *_dont_destroy_##ll = sd_ipv4ll_ref(ll)
@@ -48,16 +49,28 @@ struct sd_ipv4ll {
         unsigned n_ref;
 
         sd_ipv4acd *acd;
+
         be32_t address; /* the address pushed to ACD */
-        struct random_data *random_data;
-        char *random_data_state;
+        struct ether_addr mac;
+
+        struct {
+                le64_t value;
+                le64_t generation;
+        } seed;
+        bool seed_set;
 
         /* External */
         be32_t claimed_address;
-        sd_ipv4ll_callback_t cb;
+
+        sd_ipv4ll_callback_t callback;
         void* userdata;
 };
 
+#define log_ipv4ll_errno(ll, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "IPV4LL: " fmt, ##__VA_ARGS__)
+#define log_ipv4ll(ll, fmt, ...) log_ipv4ll_errno(ll, 0, fmt, ##__VA_ARGS__)
+
+static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata);
+
 sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll) {
         if (!ll)
                 return NULL;
@@ -79,16 +92,11 @@ sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) {
                 return NULL;
 
         sd_ipv4acd_unref(ll->acd);
-
-        free(ll->random_data);
-        free(ll->random_data_state);
         free(ll);
 
         return NULL;
 }
 
-static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata);
-
 int sd_ipv4ll_new(sd_ipv4ll **ret) {
         _cleanup_(sd_ipv4ll_unrefp) sd_ipv4ll *ll = NULL;
         int r;
@@ -116,44 +124,32 @@ int sd_ipv4ll_new(sd_ipv4ll **ret) {
 }
 
 int sd_ipv4ll_stop(sd_ipv4ll *ll) {
-        int r;
-
         assert_return(ll, -EINVAL);
 
-        r = sd_ipv4acd_stop(ll->acd);
-        if (r < 0)
-                return r;
-
-        return 0;
+        return sd_ipv4acd_stop(ll->acd);
 }
 
-int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index) {
+int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int ifindex) {
         assert_return(ll, -EINVAL);
+        assert_return(ifindex > 0, -EINVAL);
+        assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY);
 
-        return sd_ipv4acd_set_index(ll->acd, interface_index);
+        return sd_ipv4acd_set_ifindex(ll->acd, ifindex);
 }
 
-#define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
-
 int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) {
         int r;
 
         assert_return(ll, -EINVAL);
+        assert_return(addr, -EINVAL);
+        assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY);
 
-        if (!ll->random_data) {
-                uint64_t seed;
-
-                /* If no random data is set, generate some from the MAC */
-                seed = siphash24(&addr->ether_addr_octet, ETH_ALEN, HASH_KEY.bytes);
-
-                assert_cc(sizeof(unsigned) <= 8);
-
-                r = sd_ipv4ll_set_address_seed(ll, (unsigned) htole64(seed));
-                if (r < 0)
-                        return r;
-        }
+        r = sd_ipv4acd_set_mac(ll->acd, addr);
+        if (r < 0)
+                return r;
 
-        return sd_ipv4acd_set_mac(ll->acd, addr);
+        ll->mac = *addr;
+        return 0;
 }
 
 int sd_ipv4ll_detach_event(sd_ipv4ll *ll) {
@@ -163,21 +159,15 @@ int sd_ipv4ll_detach_event(sd_ipv4ll *ll) {
 }
 
 int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority) {
-        int r;
-
         assert_return(ll, -EINVAL);
 
-        r = sd_ipv4acd_attach_event(ll->acd, event, priority);
-        if (r < 0)
-                return r;
-
-        return 0;
+        return sd_ipv4acd_attach_event(ll->acd, event, priority);
 }
 
 int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata) {
         assert_return(ll, -EINVAL);
 
-        ll->cb = cb;
+        ll->callback = cb;
         ll->userdata = userdata;
 
         return 0;
@@ -195,32 +185,12 @@ int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address) {
         return 0;
 }
 
-int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, unsigned seed) {
-        _cleanup_free_ struct random_data *random_data = NULL;
-        _cleanup_free_ char *random_data_state = NULL;
-        int r;
-
+int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed) {
         assert_return(ll, -EINVAL);
+        assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY);
 
-        random_data = new0(struct random_data, 1);
-        if (!random_data)
-                return -ENOMEM;
-
-        random_data_state = new0(char, 128);
-        if (!random_data_state)
-                return -ENOMEM;
-
-        r = initstate_r(seed, random_data_state, 128, random_data);
-        if (r < 0)
-                return r;
-
-        free(ll->random_data);
-        ll->random_data = random_data;
-        random_data = NULL;
-
-        free(ll->random_data_state);
-        ll->random_data_state = random_data_state;
-        random_data_state = NULL;
+        ll->seed.value = htole64(seed);
+        ll->seed_set = true;
 
         return 0;
 }
@@ -232,20 +202,12 @@ int sd_ipv4ll_is_running(sd_ipv4ll *ll) {
 }
 
 static bool ipv4ll_address_is_valid(const struct in_addr *address) {
-        uint32_t addr;
-
         assert(address);
 
         if (!in_addr_is_link_local(AF_INET, (const union in_addr_union *) address))
                 return false;
 
-        addr = be32toh(address->s_addr);
-
-        if ((addr & 0x0000FF00) == 0x0000 ||
-            (addr & 0x0000FF00) == 0xFF00)
-                return false;
-
-        return true;
+        return !IN_SET(be32toh(address->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U);
 }
 
 int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) {
@@ -264,48 +226,67 @@ int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) {
         return 0;
 }
 
+#define PICK_HASH_KEY SD_ID128_MAKE(15,ac,82,a6,d6,3f,49,78,98,77,5d,0c,69,02,94,0b)
+
 static int ipv4ll_pick_address(sd_ipv4ll *ll) {
-        struct in_addr in_addr;
+        _cleanup_free_ char *address = NULL;
         be32_t addr;
-        int r;
-        int32_t random;
 
         assert(ll);
-        assert(ll->random_data);
 
         do {
-                r = random_r(ll->random_data, &random);
-                if (r < 0)
-                        return r;
-                addr = htonl((random & 0x0000FFFF) | IPV4LL_NETWORK);
-        } while (addr == ll->address ||
-                (ntohl(addr) & 0x0000FF00) == 0x0000 ||
-                (ntohl(addr) & 0x0000FF00) == 0xFF00);
+                uint64_t h;
 
-        in_addr.s_addr = addr;
+                h = siphash24(&ll->seed, sizeof(ll->seed), PICK_HASH_KEY.bytes);
 
-        r = sd_ipv4ll_set_address(ll, &in_addr);
-        if (r < 0)
-                return r;
+                /* Increase the generation counter by one */
+                ll->seed.generation = htole64(le64toh(ll->seed.generation) + 1);
 
-        return 0;
+                addr = htobe32((h & UINT32_C(0x0000FFFF)) | IPV4LL_NETWORK);
+        } while (addr == ll->address ||
+                 IN_SET(be32toh(addr) & 0x0000FF00U, 0x0000U, 0xFF00U));
+
+        (void) in_addr_to_string(AF_INET, &(union in_addr_union) { .in.s_addr = addr }, &address);
+        log_ipv4ll(ll, "Picked new IP address %s.", strna(address));
+
+        return sd_ipv4ll_set_address(ll, &(struct in_addr) { addr });
 }
 
+#define MAC_HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
+
 int sd_ipv4ll_start(sd_ipv4ll *ll) {
         int r;
+        bool picked_address = false;
 
         assert_return(ll, -EINVAL);
-        assert_return(ll->random_data, -EINVAL);
+        assert_return(!ether_addr_is_null(&ll->mac), -EINVAL);
+        assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY);
+
+        /* If no random seed is set, generate some from the MAC address */
+        if (!ll->seed_set)
+                ll->seed.value = htole64(siphash24(ll->mac.ether_addr_octet, ETH_ALEN, MAC_HASH_KEY.bytes));
+
+        /* Restart the generation counter. */
+        ll->seed.generation = 0;
 
         if (ll->address == 0) {
                 r = ipv4ll_pick_address(ll);
                 if (r < 0)
                         return r;
+
+                picked_address = true;
         }
 
         r = sd_ipv4acd_start(ll->acd);
-        if (r < 0)
+        if (r < 0) {
+
+                /* We couldn't start? If so, let's forget the picked address again, the user might make a change and
+                 * retry, and we want the new data to take effect when picking an address. */
+                if (picked_address)
+                        ll->address = 0;
+
                 return r;
+        }
 
         return 0;
 }
@@ -313,8 +294,8 @@ int sd_ipv4ll_start(sd_ipv4ll *ll) {
 static void ipv4ll_client_notify(sd_ipv4ll *ll, int event) {
         assert(ll);
 
-        if (ll->cb)
-                ll->cb(ll, event, ll->userdata);
+        if (ll->callback)
+                ll->callback(ll, event, ll->userdata);
 }
 
 void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
@@ -326,17 +307,17 @@ void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
         assert(ll);
 
         switch (event) {
+
         case SD_IPV4ACD_EVENT_STOP:
                 ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP);
-
                 ll->claimed_address = 0;
-
                 break;
+
         case SD_IPV4ACD_EVENT_BIND:
                 ll->claimed_address = ll->address;
                 ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_BIND);
-
                 break;
+
         case SD_IPV4ACD_EVENT_CONFLICT:
                 /* if an address was already bound we must call up to the
                    user to handle this, otherwise we just try again */
@@ -355,6 +336,7 @@ void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
                 }
 
                 break;
+
         default:
                 assert_not_reached("Invalid IPv4ACD event.");
         }
diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/systemd/src/libsystemd-network/sd-lldp.c
index 71d15812..f1ae6dac 100644
--- a/src/systemd/src/libsystemd-network/sd-lldp.c
+++ b/src/systemd/src/libsystemd-network/sd-lldp.c
@@ -45,7 +45,6 @@ static void lldp_flush_neighbors(sd_lldp *lldp) {
 
 static void lldp_callback(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n) {
         assert(lldp);
-        assert(n);
 
         log_lldp("Invoking callback for '%c'.", event);
 
@@ -140,6 +139,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. */
+                        old->timestamp = n->timestamp;
                         lldp_start_timer(lldp, old);
                         lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old);
                         return 0;
@@ -173,7 +173,7 @@ static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
 
 finish:
         if (old)
-                lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, n);
+                lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old);
 
         return r;
 }
@@ -204,6 +204,7 @@ static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, v
         _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
         ssize_t space, length;
         sd_lldp *lldp = userdata;
+        struct timespec ts;
 
         assert(fd >= 0);
         assert(lldp);
@@ -217,21 +218,41 @@ static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, v
                 return -ENOMEM;
 
         length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT);
-        if (length < 0)
+        if (length < 0) {
+                if (errno == EAGAIN || errno == EINTR)
+                        return 0;
+
                 return log_lldp_errno(errno, "Failed to read LLDP datagram: %m");
+        }
 
         if ((size_t) length != n->raw_size) {
                 log_lldp("Packet size mismatch.");
                 return -EINVAL;
         }
 
+        /* Try to get the timestamp of this packet if it is known */
+        if (ioctl(fd, SIOCGSTAMPNS, &ts) >= 0)
+                triple_timestamp_from_realtime(&n->timestamp, timespec_load(&ts));
+        else
+                triple_timestamp_get(&n->timestamp);
+
         return lldp_handle_datagram(lldp, n);
 }
 
+static void lldp_reset(sd_lldp *lldp) {
+        assert(lldp);
+
+        lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source);
+        lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
+        lldp->fd = safe_close(lldp->fd);
+}
+
 _public_ int sd_lldp_start(sd_lldp *lldp) {
         int r;
 
         assert_return(lldp, -EINVAL);
+        assert_return(lldp->event, -EINVAL);
+        assert_return(lldp->ifindex > 0, -EINVAL);
 
         if (lldp->fd >= 0)
                 return 0;
@@ -242,24 +263,21 @@ _public_ int sd_lldp_start(sd_lldp *lldp) {
         if (lldp->fd < 0)
                 return lldp->fd;
 
-        if (lldp->event) {
-                r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp);
-                if (r < 0)
-                        goto fail;
+        r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp);
+        if (r < 0)
+                goto fail;
 
-                r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority);
-                if (r < 0)
-                        goto fail;
+        r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority);
+        if (r < 0)
+                goto fail;
 
-                (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io");
-        }
+        (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io");
 
+        log_lldp("Started LLDP client");
         return 1;
 
 fail:
-        lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
-        lldp->fd = safe_close(lldp->fd);
-
+        lldp_reset(lldp);
         return r;
 }
 
@@ -269,10 +287,9 @@ _public_ int sd_lldp_stop(sd_lldp *lldp) {
         if (lldp->fd < 0)
                 return 0;
 
-        lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source);
-        lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
-        lldp->fd = safe_close(lldp->fd);
+        log_lldp("Stopping LLDP client");
 
+        lldp_reset(lldp);
         lldp_flush_neighbors(lldp);
 
         return 1;
@@ -307,6 +324,12 @@ _public_ int sd_lldp_detach_event(sd_lldp *lldp) {
         return 0;
 }
 
+_public_ sd_event* sd_lldp_get_event(sd_lldp *lldp) {
+        assert_return(lldp, NULL);
+
+        return lldp->event;
+}
+
 _public_ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata) {
         assert_return(lldp, -EINVAL);
 
@@ -316,39 +339,60 @@ _public_ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *us
         return 0;
 }
 
+_public_ int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex) {
+        assert_return(lldp, -EINVAL);
+        assert_return(ifindex > 0, -EINVAL);
+        assert_return(lldp->fd < 0, -EBUSY);
+
+        lldp->ifindex = ifindex;
+        return 0;
+}
+
+_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;
+
+        lldp_reset(lldp);
+        sd_lldp_detach_event(lldp);
         lldp_flush_neighbors(lldp);
 
         hashmap_free(lldp->neighbor_by_id);
         prioq_free(lldp->neighbor_by_expiry);
-
-        sd_event_source_unref(lldp->io_event_source);
-        sd_event_source_unref(lldp->timer_event_source);
-        sd_event_unref(lldp->event);
-        safe_close(lldp->fd);
-
         free(lldp);
 
         return NULL;
 }
 
-_public_ int sd_lldp_new(sd_lldp **ret, int ifindex) {
+_public_ int sd_lldp_new(sd_lldp **ret) {
         _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL;
         int r;
 
         assert_return(ret, -EINVAL);
-        assert_return(ifindex > 0, -EINVAL);
 
         lldp = new0(sd_lldp, 1);
         if (!lldp)
                 return -ENOMEM;
 
+        lldp->n_ref = 1;
         lldp->fd = -1;
-        lldp->ifindex = ifindex;
         lldp->neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX;
         lldp->capability_mask = (uint16_t) -1;
 
@@ -488,11 +532,10 @@ _public_ int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *
         /* In order to deal nicely with bridges that send back our own packets, allow one address to be filtered, so
          * that our own can be filtered out here. */
 
-        if (!addr) {
+        if (addr)
+                lldp->filter_address = *addr;
+        else
                 zero(lldp->filter_address);
-                return 0;
-        }
 
-        lldp->filter_address = *addr;
         return 0;
 }
diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c
index 31e8e7fa..0d400661 100644
--- a/src/systemd/src/libsystemd/sd-event/sd-event.c
+++ b/src/systemd/src/libsystemd/sd-event/sd-event.c
@@ -23,9 +23,7 @@
 #include <sys/timerfd.h>
 #include <sys/wait.h>
 
-#if 0 /* NM_IGNORED */
 #include "sd-daemon.h"
-#endif
 #include "sd-event.h"
 #include "sd-id128.h"
 
@@ -34,17 +32,11 @@
 #include "hashmap.h"
 #include "list.h"
 #include "macro.h"
-#if 0 /* NM_IGNORED */
 #include "missing.h"
-#endif
 #include "prioq.h"
-#if 0 /* NM_IGNORED */
 #include "process-util.h"
-#endif
 #include "set.h"
-#if 0 /* NM_IGNORED */
 #include "signal-util.h"
-#endif
 #include "string-table.h"
 #include "string-util.h"
 #include "time-util.h"
@@ -119,8 +111,8 @@ struct sd_event_source {
         int64_t priority;
         unsigned pending_index;
         unsigned prepare_index;
-        unsigned pending_iteration;
-        unsigned prepare_iteration;
+        uint64_t pending_iteration;
+        uint64_t prepare_iteration;
 
         LIST_FIELDS(sd_event_source, sources);
 
@@ -225,9 +217,8 @@ struct sd_event {
 
         pid_t original_pid;
 
-        unsigned iteration;
-        dual_timestamp timestamp;
-        usec_t timestamp_boottime;
+        uint64_t iteration;
+        triple_timestamp timestamp;
         int state;
 
         bool exit_requested:1;
@@ -1082,12 +1073,16 @@ _public_ int sd_event_add_time(
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(e), -ECHILD);
 
+        if (!clock_supported(clock)) /* Checks whether the kernel supports the clock */
+                return -EOPNOTSUPP;
+
+        type = clock_to_event_source_type(clock); /* checks whether sd-event supports this clock */
+        if (type < 0)
+                return -EOPNOTSUPP;
+
         if (!callback)
                 callback = time_exit_callback;
 
-        type = clock_to_event_source_type(clock);
-        assert_return(type >= 0, -EOPNOTSUPP);
-
         d = event_get_clock_data(e, type);
         assert(d);
 
@@ -1156,8 +1151,7 @@ _public_ int sd_event_add_signal(
         int r;
 
         assert_return(e, -EINVAL);
-        assert_return(sig > 0, -EINVAL);
-        assert_return(sig < _NSIG, -EINVAL);
+        assert_return(SIGNAL_VALID(sig), -EINVAL);
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(e), -ECHILD);
 
@@ -2212,7 +2206,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) {
                 if (_unlikely_(n != sizeof(si)))
                         return -EIO;
 
-                assert(si.ssi_signo < _NSIG);
+                assert(SIGNAL_VALID(si.ssi_signo));
 
                 read_one = true;
 
@@ -2539,8 +2533,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
                 goto finish;
         }
 
-        dual_timestamp_get(&e->timestamp);
-        e->timestamp_boottime = now(CLOCK_BOOTTIME);
+        triple_timestamp_get(&e->timestamp);
 
         for (i = 0; i < m; i++) {
 
@@ -2581,7 +2574,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
         if (r < 0)
                 goto finish;
 
-        r = process_timer(e, e->timestamp_boottime, &e->boottime);
+        r = process_timer(e, e->timestamp.boottime, &e->boottime);
         if (r < 0)
                 goto finish;
 
@@ -2593,7 +2586,7 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) {
         if (r < 0)
                 goto finish;
 
-        r = process_timer(e, e->timestamp_boottime, &e->boottime_alarm);
+        r = process_timer(e, e->timestamp.boottime, &e->boottime_alarm);
         if (r < 0)
                 goto finish;
 
@@ -2767,40 +2760,24 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) {
         assert_return(e, -EINVAL);
         assert_return(usec, -EINVAL);
         assert_return(!event_pid_changed(e), -ECHILD);
-        assert_return(IN_SET(clock,
-                             CLOCK_REALTIME,
-                             CLOCK_REALTIME_ALARM,
-                             CLOCK_MONOTONIC,
-                             CLOCK_BOOTTIME,
-                             CLOCK_BOOTTIME_ALARM), -EOPNOTSUPP);
-
-        if (!dual_timestamp_is_set(&e->timestamp)) {
+
+        if (!TRIPLE_TIMESTAMP_HAS_CLOCK(clock))
+                return -EOPNOTSUPP;
+
+        /* Generate a clean error in case CLOCK_BOOTTIME is not available. Note that don't use clock_supported() here,
+         * for a reason: there are systems where CLOCK_BOOTTIME is supported, but CLOCK_BOOTTIME_ALARM is not, but for
+         * the purpose of getting the time this doesn't matter. */
+        if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) && !clock_boottime_supported())
+                return -EOPNOTSUPP;
+
+        if (!triple_timestamp_is_set(&e->timestamp)) {
                 /* Implicitly fall back to now() if we never ran
                  * before and thus have no cached time. */
                 *usec = now(clock);
                 return 1;
         }
 
-        switch (clock) {
-
-        case CLOCK_REALTIME:
-        case CLOCK_REALTIME_ALARM:
-                *usec = e->timestamp.realtime;
-                break;
-
-        case CLOCK_MONOTONIC:
-                *usec = e->timestamp.monotonic;
-                break;
-
-        case CLOCK_BOOTTIME:
-        case CLOCK_BOOTTIME_ALARM:
-                *usec = e->timestamp_boottime;
-                break;
-
-        default:
-                assert_not_reached("Unknown clock?");
-        }
-
+        *usec = triple_timestamp_by_clock(&e->timestamp, clock);
         return 0;
 }
 
@@ -2902,4 +2879,12 @@ _public_ int sd_event_get_watchdog(sd_event *e) {
 
         return e->watchdog;
 }
+
+_public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) {
+        assert_return(e, -EINVAL);
+        assert_return(!event_pid_changed(e), -ECHILD);
+
+        *ret = e->iteration;
+        return 0;
+}
 #endif /* NM_IGNORED */
diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.c b/src/systemd/src/libsystemd/sd-id128/id128-util.c
new file mode 100644
index 00000000..c16052d8
--- /dev/null
+++ b/src/systemd/src/libsystemd/sd-id128/id128-util.c
@@ -0,0 +1,200 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "nm-sd-adapt.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "fd-util.h"
+#include "hexdecoct.h"
+#include "id128-util.h"
+#include "io-util.h"
+#include "stdio-util.h"
+
+#if 0 /* NM_IGNORED */
+char *id128_to_uuid_string(sd_id128_t id, char s[37]) {
+        unsigned n, k = 0;
+
+        assert(s);
+
+        /* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */
+
+        for (n = 0; n < 16; n++) {
+
+                if (IN_SET(n, 4, 6, 8, 10))
+                        s[k++] = '-';
+
+                s[k++] = hexchar(id.bytes[n] >> 4);
+                s[k++] = hexchar(id.bytes[n] & 0xF);
+        }
+
+        assert(k == 36);
+
+        s[k] = 0;
+
+        return s;
+}
+
+bool id128_is_valid(const char *s) {
+        size_t i, l;
+
+        assert(s);
+
+        l = strlen(s);
+        if (l == 32) {
+
+                /* Plain formatted 128bit hex string */
+
+                for (i = 0; i < l; i++) {
+                        char c = s[i];
+
+                        if (!(c >= '0' && c <= '9') &&
+                            !(c >= 'a' && c <= 'z') &&
+                            !(c >= 'A' && c <= 'Z'))
+                                return false;
+                }
+
+        } else if (l == 36) {
+
+                /* Formatted UUID */
+
+                for (i = 0; i < l; i++) {
+                        char c = s[i];
+
+                        if ((i == 8 || i == 13 || i == 18 || i == 23)) {
+                                if (c != '-')
+                                        return false;
+                        } else {
+                                if (!(c >= '0' && c <= '9') &&
+                                    !(c >= 'a' && c <= 'z') &&
+                                    !(c >= 'A' && c <= 'Z'))
+                                        return false;
+                        }
+                }
+
+        } else
+                return false;
+
+        return true;
+}
+#endif /* NM_IGNORED */
+
+int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) {
+        char buffer[36 + 2];
+        ssize_t l;
+
+        assert(fd >= 0);
+        assert(f < _ID128_FORMAT_MAX);
+
+        /* Reads an 128bit ID from a file, which may either be in plain format (32 hex digits), or in UUID format, both
+         * optionally followed by a newline and nothing else. ID files should really be newline terminated, but if they
+         * aren't that's OK too, following the rule of "Be conservative in what you send, be liberal in what you
+         * accept". */
+
+        l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 32/33 or 36/37 chars */
+        if (l < 0)
+                return (int) l;
+        if (l == 0) /* empty? */
+                return -ENOMEDIUM;
+
+        switch (l) {
+
+        case 33: /* plain UUID with trailing newline */
+                if (buffer[32] != '\n')
+                        return -EINVAL;
+
+                /* fall through */
+        case 32: /* plain UUID without trailing newline */
+                if (f == ID128_UUID)
+                        return -EINVAL;
+
+                buffer[32] = 0;
+                break;
+
+        case 37: /* RFC UUID with trailing newline */
+                if (buffer[36] != '\n')
+                        return -EINVAL;
+
+                /* fall through */
+        case 36: /* RFC UUID without trailing newline */
+                if (f == ID128_PLAIN)
+                        return -EINVAL;
+
+                buffer[36] = 0;
+                break;
+
+        default:
+                return -EINVAL;
+        }
+
+        return sd_id128_from_string(buffer, ret);
+}
+
+int id128_read(const char *p, Id128Format f, sd_id128_t *ret) {
+        _cleanup_close_ int fd = -1;
+
+        fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+        if (fd < 0)
+                return -errno;
+
+        return id128_read_fd(fd, f, ret);
+}
+
+#if 0 /* NM_IGNORED */
+int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) {
+        char buffer[36 + 2];
+        size_t sz;
+        int r;
+
+        assert(fd >= 0);
+        assert(f < _ID128_FORMAT_MAX);
+
+        if (f != ID128_UUID) {
+                sd_id128_to_string(id, buffer);
+                buffer[32] = '\n';
+                sz = 33;
+        } else {
+                id128_to_uuid_string(id, buffer);
+                buffer[36] = '\n';
+                sz = 37;
+        }
+
+        r = loop_write(fd, buffer, sz, false);
+        if (r < 0)
+                return r;
+
+        if (do_sync) {
+                if (fsync(fd) < 0)
+                        return -errno;
+        }
+
+        return r;
+}
+
+int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) {
+        _cleanup_close_ int fd = -1;
+
+        fd = open(p, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0444);
+        if (fd < 0)
+                return -errno;
+
+        return id128_write_fd(fd, f, id, do_sync);
+}
+#endif /* NM_IGNORED */
diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.h b/src/systemd/src/libsystemd/sd-id128/id128-util.h
new file mode 100644
index 00000000..3ba59acb
--- /dev/null
+++ b/src/systemd/src/libsystemd/sd-id128/id128-util.h
@@ -0,0 +1,45 @@
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2016 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+
+#include "sd-id128.h"
+#include "macro.h"
+
+char *id128_to_uuid_string(sd_id128_t id, char s[37]);
+
+/* Like SD_ID128_FORMAT_STR, but formats as UUID, not in plain format */
+#define ID128_UUID_FORMAT_STR "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+
+bool id128_is_valid(const char *s) _pure_;
+
+typedef enum Id128Format {
+        ID128_ANY,
+        ID128_PLAIN,  /* formatted as 32 hex chars as-is */
+        ID128_UUID,   /* formatted as 36 character uuid string */
+        _ID128_FORMAT_MAX,
+} Id128Format;
+
+int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret);
+int id128_read(const char *p, Id128Format f, sd_id128_t *ret);
+
+int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync);
+int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync);
diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
index 01b805a1..9408c32b 100644
--- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
@@ -27,6 +27,7 @@
 
 #include "fd-util.h"
 #include "hexdecoct.h"
+#include "id128-util.h"
 #include "io-util.h"
 #include "macro.h"
 #include "random-util.h"
@@ -47,6 +48,7 @@ _public_ char *sd_id128_to_string(sd_id128_t id, char s[SD_ID128_STRING_MAX]) {
 
         return s;
 }
+#endif /* NM_IGNORED */
 
 _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
         unsigned n, i;
@@ -54,7 +56,6 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
         bool is_guid = false;
 
         assert_return(s, -EINVAL);
-        assert_return(ret, -EINVAL);
 
         for (n = 0, i = 0; n < 16;) {
                 int a, b;
@@ -92,125 +93,60 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
         if (s[i] != 0)
                 return -EINVAL;
 
-        *ret = t;
+        if (ret)
+                *ret = t;
         return 0;
 }
 
-static sd_id128_t make_v4_uuid(sd_id128_t id) {
-        /* Stolen from generate_random_uuid() of drivers/char/random.c
-         * in the kernel sources */
-
-        /* Set UUID version to 4 --- truly random generation */
-        id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40;
-
-        /* Set the UUID variant to DCE */
-        id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80;
-
-        return id;
-}
-#endif
-
 _public_ int sd_id128_get_machine(sd_id128_t *ret) {
-        static thread_local sd_id128_t saved_machine_id;
-        static thread_local bool saved_machine_id_valid = false;
-        _cleanup_close_ int fd = -1;
-        char buf[33];
-        unsigned j;
-        sd_id128_t t;
+        static thread_local sd_id128_t saved_machine_id = {};
         int r;
 
         assert_return(ret, -EINVAL);
 
-        if (saved_machine_id_valid) {
-                *ret = saved_machine_id;
-                return 0;
-        }
+        if (sd_id128_is_null(saved_machine_id)) {
+                r = id128_read("/etc/machine-id", ID128_PLAIN, &saved_machine_id);
+                if (r < 0)
+                        return r;
 
-        fd = open("/etc/machine-id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
-        if (fd < 0)
-                return -errno;
-
-        r = loop_read_exact(fd, buf, 33, false);
-        if (r < 0)
-                return r;
-        if (buf[32] !='\n')
-                return -EIO;
-
-        for (j = 0; j < 16; j++) {
-                int a, b;
-
-                a = unhexchar(buf[j*2]);
-                b = unhexchar(buf[j*2+1]);
-
-                if (a < 0 || b < 0)
-                        return -EIO;
-
-                t.bytes[j] = a << 4 | b;
+                if (sd_id128_is_null(saved_machine_id))
+                        return -EINVAL;
         }
 
-        saved_machine_id = t;
-        saved_machine_id_valid = true;
-
-        *ret = t;
+        *ret = saved_machine_id;
         return 0;
 }
 
 _public_ int sd_id128_get_boot(sd_id128_t *ret) {
-        static thread_local sd_id128_t saved_boot_id;
-        static thread_local bool saved_boot_id_valid = false;
-        _cleanup_close_ int fd = -1;
-        char buf[36];
-        unsigned j;
-        sd_id128_t t;
-        char *p;
+        static thread_local sd_id128_t saved_boot_id = {};
         int r;
 
         assert_return(ret, -EINVAL);
 
-        if (saved_boot_id_valid) {
-                *ret = saved_boot_id;
-                return 0;
+        if (sd_id128_is_null(saved_boot_id)) {
+                r = id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID, &saved_boot_id);
+                if (r < 0)
+                        return r;
         }
 
-        fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
-        if (fd < 0)
-                return -errno;
-
-        r = loop_read_exact(fd, buf, 36, false);
-        if (r < 0)
-                return r;
-
-        for (j = 0, p = buf; j < 16; j++) {
-                int a, b;
-
-                if (p >= buf + 35)
-                        return -EIO;
-
-                if (*p == '-') {
-                        p++;
-                        if (p >= buf + 35)
-                                return -EIO;
-                }
-
-                a = unhexchar(p[0]);
-                b = unhexchar(p[1]);
-
-                if (a < 0 || b < 0)
-                        return -EIO;
+        *ret = saved_boot_id;
+        return 0;
+}
 
-                t.bytes[j] = a << 4 | b;
+#if 0 /* NM_IGNORED */
+static sd_id128_t make_v4_uuid(sd_id128_t id) {
+        /* Stolen from generate_random_uuid() of drivers/char/random.c
+         * in the kernel sources */
 
-                p += 2;
-        }
+        /* Set UUID version to 4 --- truly random generation */
+        id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40;
 
-        saved_boot_id = t;
-        saved_boot_id_valid = true;
+        /* Set the UUID variant to DCE */
+        id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80;
 
-        *ret = t;
-        return 0;
+        return id;
 }
 
-#if 0 /* NM_IGNORED */
 _public_ int sd_id128_randomize(sd_id128_t *ret) {
         sd_id128_t t;
         int r;
diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h
index 374ff877..9a90c2ed 100644
--- a/src/systemd/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/src/systemd/sd-dhcp-client.h
@@ -84,28 +84,57 @@ enum {
 
 typedef struct sd_dhcp_client sd_dhcp_client;
 
-typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event,
-                                    void *userdata);
-int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb,
-                                void *userdata);
-
-int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option);
-int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
-                                       const struct in_addr *last_address);
-int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast);
-int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index);
-int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
-                           size_t addr_len, uint16_t arp_type);
-int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
-                                 const uint8_t *data, size_t data_len);
-int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
-                                 uint16_t duid_type, uint8_t *duid, size_t duid_len);
-int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
-                                 const uint8_t **data, size_t *data_len);
-int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu);
-int sd_dhcp_client_set_hostname(sd_dhcp_client *client, const char *hostname);
-int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, const char *vci);
-int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret);
+typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
+int sd_dhcp_client_set_callback(
+                sd_dhcp_client *client,
+                sd_dhcp_client_callback_t cb,
+                void *userdata);
+
+int sd_dhcp_client_set_request_option(
+                sd_dhcp_client *client,
+                uint8_t option);
+int sd_dhcp_client_set_request_address(
+                sd_dhcp_client *client,
+                const struct in_addr *last_address);
+int sd_dhcp_client_set_request_broadcast(
+                sd_dhcp_client *client,
+                int broadcast);
+int sd_dhcp_client_set_ifindex(
+                sd_dhcp_client *client,
+                int interface_index);
+int sd_dhcp_client_set_mac(
+                sd_dhcp_client *client,
+                const uint8_t *addr,
+                size_t addr_len,
+                uint16_t arp_type);
+int sd_dhcp_client_set_client_id(
+                sd_dhcp_client *client,
+                uint8_t type,
+                const uint8_t *data,
+                size_t data_len);
+int sd_dhcp_client_set_iaid_duid(
+                sd_dhcp_client *client,
+                uint32_t iaid,
+                uint16_t duid_type,
+                const void *duid,
+                size_t duid_len);
+int sd_dhcp_client_get_client_id(
+                sd_dhcp_client *client,
+                uint8_t *type,
+                const uint8_t **data,
+                size_t *data_len);
+int sd_dhcp_client_set_mtu(
+                sd_dhcp_client *client,
+                uint32_t mtu);
+int sd_dhcp_client_set_hostname(
+                sd_dhcp_client *client,
+                const char *hostname);
+int sd_dhcp_client_set_vendor_class_identifier(
+                sd_dhcp_client *client,
+                const char *vci);
+int sd_dhcp_client_get_lease(
+                sd_dhcp_client *client,
+                sd_dhcp_lease **ret);
 
 int sd_dhcp_client_stop(sd_dhcp_client *client);
 int sd_dhcp_client_start(sd_dhcp_client *client);
@@ -115,7 +144,10 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);
 
 int sd_dhcp_client_new(sd_dhcp_client **ret);
 
-int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority);
+int sd_dhcp_client_attach_event(
+                sd_dhcp_client *client,
+                sd_event *event,
+                int64_t priority);
 int sd_dhcp_client_detach_event(sd_dhcp_client *client);
 sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client);
 
diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h
index 4604cb63..7819f0d2 100644
--- a/src/systemd/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/src/systemd/sd-dhcp6-client.h
@@ -76,29 +76,52 @@ enum {
 
 typedef struct sd_dhcp6_client sd_dhcp6_client;
 
-typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event,
-                                     void *userdata);
-int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
-                                 sd_dhcp6_client_callback_t cb, void *userdata);
-
-int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index);
-int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address);
-int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
-                            size_t addr_len, uint16_t arp_type);
-int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type,
-                             uint8_t *duid, size_t duid_len);
-int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid);
-int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled);
-int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled);
-int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
-                                       uint16_t option);
-
-int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret);
+typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event, void *userdata);
+int sd_dhcp6_client_set_callback(
+                sd_dhcp6_client *client,
+                sd_dhcp6_client_callback_t cb,
+                void *userdata);
+
+int sd_dhcp6_client_set_ifindex(
+                sd_dhcp6_client *client,
+                int interface_index);
+int sd_dhcp6_client_set_local_address(
+                sd_dhcp6_client *client,
+                const struct in6_addr *local_address);
+int sd_dhcp6_client_set_mac(
+                sd_dhcp6_client *client,
+                const uint8_t *addr,
+                size_t addr_len,
+                uint16_t arp_type);
+int sd_dhcp6_client_set_duid(
+                sd_dhcp6_client *client,
+                uint16_t duid_type,
+                const void *duid,
+                size_t duid_len);
+int sd_dhcp6_client_set_iaid(
+                sd_dhcp6_client *client,
+                uint32_t iaid);
+int sd_dhcp6_client_set_information_request(
+                sd_dhcp6_client *client,
+                int enabled);
+int sd_dhcp6_client_get_information_request(
+                sd_dhcp6_client *client,
+                int *enabled);
+int sd_dhcp6_client_set_request_option(
+                sd_dhcp6_client *client,
+                uint16_t option);
+
+int sd_dhcp6_client_get_lease(
+                sd_dhcp6_client *client,
+                sd_dhcp6_lease **ret);
 
 int sd_dhcp6_client_stop(sd_dhcp6_client *client);
 int sd_dhcp6_client_start(sd_dhcp6_client *client);
 int sd_dhcp6_client_is_running(sd_dhcp6_client *client);
-int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int64_t priority);
+int sd_dhcp6_client_attach_event(
+                sd_dhcp6_client *client,
+                sd_event *event,
+                int64_t priority);
 int sd_dhcp6_client_detach_event(sd_dhcp6_client *client);
 sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client);
 sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client);
diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h
index 531ace1c..cc26b7df 100644
--- a/src/systemd/src/systemd/sd-event.h
+++ b/src/systemd/src/systemd/sd-event.h
@@ -104,6 +104,7 @@ int sd_event_get_tid(sd_event *e, pid_t *tid);
 int sd_event_get_exit_code(sd_event *e, int *code);
 int sd_event_set_watchdog(sd_event *e, int b);
 int sd_event_get_watchdog(sd_event *e);
+int sd_event_get_iteration(sd_event *e, uint64_t *ret);
 
 sd_event_source* sd_event_source_ref(sd_event_source *s);
 sd_event_source* sd_event_source_unref(sd_event_source *s);
diff --git a/src/systemd/src/systemd/sd-ipv4acd.h b/src/systemd/src/systemd/sd-ipv4acd.h
index 9e3e14a3..16d99983 100644
--- a/src/systemd/src/systemd/sd-ipv4acd.h
+++ b/src/systemd/src/systemd/sd-ipv4acd.h
@@ -37,20 +37,20 @@ enum {
 };
 
 typedef struct sd_ipv4acd sd_ipv4acd;
-typedef void (*sd_ipv4acd_callback_t)(sd_ipv4acd *ll, int event, void *userdata);
-
-int sd_ipv4acd_detach_event(sd_ipv4acd *ll);
-int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int64_t priority);
-int sd_ipv4acd_get_address(sd_ipv4acd *ll, struct in_addr *address);
-int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_callback_t cb, void *userdata);
-int sd_ipv4acd_set_mac(sd_ipv4acd *ll, const struct ether_addr *addr);
-int sd_ipv4acd_set_index(sd_ipv4acd *ll, int interface_index);
-int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address);
-int sd_ipv4acd_is_running(sd_ipv4acd *ll);
-int sd_ipv4acd_start(sd_ipv4acd *ll);
-int sd_ipv4acd_stop(sd_ipv4acd *ll);
-sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *ll);
-sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *ll);
+typedef void (*sd_ipv4acd_callback_t)(sd_ipv4acd *acd, int event, void *userdata);
+
+int sd_ipv4acd_detach_event(sd_ipv4acd *acd);
+int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority);
+int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address);
+int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata);
+int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr);
+int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int interface_index);
+int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address);
+int sd_ipv4acd_is_running(sd_ipv4acd *acd);
+int sd_ipv4acd_start(sd_ipv4acd *acd);
+int sd_ipv4acd_stop(sd_ipv4acd *acd);
+sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *acd);
+sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd);
 int sd_ipv4acd_new(sd_ipv4acd **ret);
 
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4acd, sd_ipv4acd_unref);
diff --git a/src/systemd/src/systemd/sd-ipv4ll.h b/src/systemd/src/systemd/sd-ipv4ll.h
index 6fa38a22..1109ec52 100644
--- a/src/systemd/src/systemd/sd-ipv4ll.h
+++ b/src/systemd/src/systemd/sd-ipv4ll.h
@@ -43,15 +43,15 @@ int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority);
 int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address);
 int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata);
 int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr);
-int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index);
+int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int interface_index);
 int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address);
-int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, unsigned seed);
+int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed);
 int sd_ipv4ll_is_running(sd_ipv4ll *ll);
 int sd_ipv4ll_start(sd_ipv4ll *ll);
 int sd_ipv4ll_stop(sd_ipv4ll *ll);
 sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll);
 sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll);
-int sd_ipv4ll_new (sd_ipv4ll **ret);
+int sd_ipv4ll_new(sd_ipv4ll **ret);
 
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4ll, sd_ipv4ll_unref);
 
diff --git a/src/systemd/src/systemd/sd-lldp.h b/src/systemd/src/systemd/sd-lldp.h
index 4f2a3b50..3f35eebe 100644
--- a/src/systemd/src/systemd/sd-lldp.h
+++ b/src/systemd/src/systemd/sd-lldp.h
@@ -23,6 +23,7 @@
 
 #include <inttypes.h>
 #include <net/ethernet.h>
+#include <sys/types.h>
 
 #include "sd-event.h"
 
@@ -30,23 +31,18 @@
 
 _SD_BEGIN_DECLARATIONS;
 
-typedef struct sd_lldp sd_lldp;
-typedef struct sd_lldp_neighbor sd_lldp_neighbor;
-
-#define SD_LLDP_MULTICAST_ADDR     { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
-
 /* IEEE 802.3AB Clause 9: TLV Types */
 enum {
-        SD_LLDP_TYPE_END                  =   0,
-        SD_LLDP_TYPE_CHASSIS_ID           =   1,
-        SD_LLDP_TYPE_PORT_ID              =   2,
-        SD_LLDP_TYPE_TTL                  =   3,
-        SD_LLDP_TYPE_PORT_DESCRIPTION     =   4,
-        SD_LLDP_TYPE_SYSTEM_NAME          =   5,
-        SD_LLDP_TYPE_SYSTEM_DESCRIPTION   =   6,
-        SD_LLDP_TYPE_SYSTEM_CAPABILITIES  =   7,
-        SD_LLDP_TYPE_MGMT_ADDRESS         =   8,
-        SD_LLDP_TYPE_PRIVATE              =   127,
+        SD_LLDP_TYPE_END                 = 0,
+        SD_LLDP_TYPE_CHASSIS_ID          = 1,
+        SD_LLDP_TYPE_PORT_ID             = 2,
+        SD_LLDP_TYPE_TTL                 = 3,
+        SD_LLDP_TYPE_PORT_DESCRIPTION    = 4,
+        SD_LLDP_TYPE_SYSTEM_NAME         = 5,
+        SD_LLDP_TYPE_SYSTEM_DESCRIPTION  = 6,
+        SD_LLDP_TYPE_SYSTEM_CAPABILITIES = 7,
+        SD_LLDP_TYPE_MGMT_ADDRESS        = 8,
+        SD_LLDP_TYPE_PRIVATE             = 127,
 };
 
 /* IEEE 802.3AB Clause 9.5.2: Chassis subtypes */
@@ -63,28 +59,28 @@ enum {
 
 /* IEEE 802.3AB Clause 9.5.3: Port subtype */
 enum {
-        SD_LLDP_PORT_SUBTYPE_RESERVED           = 0,
-        SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS    = 1,
-        SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT     = 2,
-        SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS        = 3,
-        SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS    = 4,
-        SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME     = 5,
-        SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID   = 6,
-        SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED   = 7,
+        SD_LLDP_PORT_SUBTYPE_RESERVED         = 0,
+        SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS  = 1,
+        SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT   = 2,
+        SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS      = 3,
+        SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS  = 4,
+        SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME   = 5,
+        SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6,
+        SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7,
 };
 
 enum {
-        SD_LLDP_SYSTEM_CAPABILITIES_OTHER        = 1 << 0,
-        SD_LLDP_SYSTEM_CAPABILITIES_REPEATER     = 1 << 1,
-        SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE       = 1 << 2,
-        SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP      = 1 << 3,
-        SD_LLDP_SYSTEM_CAPABILITIES_ROUTER       = 1 << 4,
-        SD_LLDP_SYSTEM_CAPABILITIES_PHONE        = 1 << 5,
-        SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS       = 1 << 6,
-        SD_LLDP_SYSTEM_CAPABILITIES_STATION      = 1 << 7,
-        SD_LLDP_SYSTEM_CAPABILITIES_CVLAN        = 1 << 8,
-        SD_LLDP_SYSTEM_CAPABILITIES_SVLAN        = 1 << 9,
-        SD_LLDP_SYSTEM_CAPABILITIES_TPMR         = 1 << 10,
+        SD_LLDP_SYSTEM_CAPABILITIES_OTHER    = 1 << 0,
+        SD_LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1,
+        SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE   = 1 << 2,
+        SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP  = 1 << 3,
+        SD_LLDP_SYSTEM_CAPABILITIES_ROUTER   = 1 << 4,
+        SD_LLDP_SYSTEM_CAPABILITIES_PHONE    = 1 << 5,
+        SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS   = 1 << 6,
+        SD_LLDP_SYSTEM_CAPABILITIES_STATION  = 1 << 7,
+        SD_LLDP_SYSTEM_CAPABILITIES_CVLAN    = 1 << 8,
+        SD_LLDP_SYSTEM_CAPABILITIES_SVLAN    = 1 << 9,
+        SD_LLDP_SYSTEM_CAPABILITIES_TPMR     = 1 << 10,
 };
 
 #define SD_LLDP_SYSTEM_CAPABILITIES_ALL ((uint16_t) -1)
@@ -100,20 +96,22 @@ enum {
           SD_LLDP_SYSTEM_CAPABILITIES_SVLAN|                            \
           SD_LLDP_SYSTEM_CAPABILITIES_TPMR))
 
-
 #define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
 #define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }
 
 enum {
-        SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID            = 1,
-        SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID   = 2,
-        SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME               = 3,
-        SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY       = 4,
-        SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST        = 5,
-        SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID          = 6,
-        SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION        = 7,
+        SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID          = 1,
+        SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2,
+        SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME             = 3,
+        SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY     = 4,
+        SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST      = 5,
+        SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID        = 6,
+        SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION      = 7,
 };
 
+typedef struct sd_lldp sd_lldp;
+typedef struct sd_lldp_neighbor sd_lldp_neighbor;
+
 typedef enum sd_lldp_event {
         SD_LLDP_EVENT_ADDED     = 'a',
         SD_LLDP_EVENT_REMOVED   = 'r',
@@ -123,7 +121,8 @@ typedef enum sd_lldp_event {
 
 typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata);
 
-int sd_lldp_new(sd_lldp **ret, int ifindex);
+int sd_lldp_new(sd_lldp **ret);
+sd_lldp* sd_lldp_ref(sd_lldp *lldp);
 sd_lldp* sd_lldp_unref(sd_lldp *lldp);
 
 int sd_lldp_start(sd_lldp *lldp);
@@ -131,8 +130,10 @@ int sd_lldp_stop(sd_lldp *lldp);
 
 int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority);
 int sd_lldp_detach_event(sd_lldp *lldp);
+sd_event *sd_lldp_get_event(sd_lldp *lldp);
 
 int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata);
+int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex);
 
 /* Controls how much and what to store in the neighbors database */
 int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t n);
@@ -148,6 +149,7 @@ sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n);
 /* Access to LLDP frame metadata */
 int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address);
 int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address);
+int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret);
 int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size);
 
 /* High-level, direct, parsed out field access. These fields exist at most once, hence may be queried directly. */
@@ -155,7 +157,7 @@ int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const vo
 int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret);
 int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size);
 int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret);
-int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret);
+int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec);
 int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret);
 int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret);
 int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret);
diff --git a/src/systemd/src/systemd/sd-ndisc.h b/src/systemd/src/systemd/sd-ndisc.h
index 29bcbe8e..9f7d4ef7 100644
--- a/src/systemd/src/systemd/sd-ndisc.h
+++ b/src/systemd/src/systemd/sd-ndisc.h
@@ -22,6 +22,8 @@
 
 #include <inttypes.h>
 #include <net/ethernet.h>
+#include <netinet/in.h>
+#include <sys/types.h>
 
 #include "sd-event.h"
 
@@ -29,55 +31,99 @@
 
 _SD_BEGIN_DECLARATIONS;
 
+/* Neightbor Discovery Options, RFC 4861, Section 4.6 and
+ * https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-5 */
 enum {
-        SD_NDISC_EVENT_STOP     = 0,
-        SD_NDISC_EVENT_TIMEOUT  = 1,
+        SD_NDISC_OPTION_SOURCE_LL_ADDRESS  = 1,
+        SD_NDISC_OPTION_TARGET_LL_ADDRESS  = 2,
+        SD_NDISC_OPTION_PREFIX_INFORMATION = 3,
+        SD_NDISC_OPTION_MTU                = 5,
+        SD_NDISC_OPTION_ROUTE_INFORMATION  = 24,
+        SD_NDISC_OPTION_RDNSS              = 25,
+        SD_NDISC_OPTION_FLAGS_EXTENSION    = 26,
+        SD_NDISC_OPTION_DNSSL              = 31,
+        SD_NDISC_OPTION_CAPTIVE_PORTAL     = 37,
+};
+
+/* Route preference, RFC 4191, Section 2.1 */
+enum {
+        SD_NDISC_PREFERENCE_LOW    = 3U,
+        SD_NDISC_PREFERENCE_MEDIUM = 0U,
+        SD_NDISC_PREFERENCE_HIGH   = 1U,
 };
 
 typedef struct sd_ndisc sd_ndisc;
+typedef struct sd_ndisc_router sd_ndisc_router;
 
-typedef void(*sd_ndisc_router_callback_t)(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata);
-typedef void(*sd_ndisc_prefix_onlink_callback_t)(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen,
-                                                 unsigned lifetime, void *userdata);
-typedef void(*sd_ndisc_prefix_autonomous_callback_t)(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen,
-                                                     unsigned lifetime_prefered, unsigned lifetime_valid, void *userdata);
-typedef void(*sd_ndisc_callback_t)(sd_ndisc *nd, int event, void *userdata);
-
-int sd_ndisc_set_callback(sd_ndisc *nd,
-                          sd_ndisc_router_callback_t rcb,
-                          sd_ndisc_prefix_onlink_callback_t plcb,
-                          sd_ndisc_prefix_autonomous_callback_t pacb,
-                          sd_ndisc_callback_t cb,
-                          void *userdata);
-int sd_ndisc_set_index(sd_ndisc *nd, int interface_index);
-int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr);
+typedef enum sd_ndisc_event {
+        SD_NDISC_EVENT_TIMEOUT = 't',
+        SD_NDISC_EVENT_ROUTER  = 'r',
+} sd_ndisc_event;
 
-int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int64_t priority);
-int sd_ndisc_detach_event(sd_ndisc *nd);
-sd_event *sd_ndisc_get_event(sd_ndisc *nd);
+typedef void (*sd_ndisc_callback_t)(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata);
 
+int sd_ndisc_new(sd_ndisc **ret);
 sd_ndisc *sd_ndisc_ref(sd_ndisc *nd);
 sd_ndisc *sd_ndisc_unref(sd_ndisc *nd);
-int sd_ndisc_new(sd_ndisc **ret);
-
-int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *mtu);
 
+int sd_ndisc_start(sd_ndisc *nd);
 int sd_ndisc_stop(sd_ndisc *nd);
-int sd_ndisc_router_discovery_start(sd_ndisc *nd);
 
-#define SD_NDISC_ADDRESS_FORMAT_STR "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int64_t priority);
+int sd_ndisc_detach_event(sd_ndisc *nd);
+sd_event *sd_ndisc_get_event(sd_ndisc *nd);
+
+int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_callback_t cb, void *userdata);
+int sd_ndisc_set_ifindex(sd_ndisc *nd, int interface_index);
+int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr);
 
-#define SD_NDISC_ADDRESS_FORMAT_VAL(address) \
-        be16toh((address).s6_addr16[0]),        \
-        be16toh((address).s6_addr16[1]),        \
-        be16toh((address).s6_addr16[2]),        \
-        be16toh((address).s6_addr16[3]),        \
-        be16toh((address).s6_addr16[4]),        \
-        be16toh((address).s6_addr16[5]),        \
-        be16toh((address).s6_addr16[6]),        \
-        be16toh((address).s6_addr16[7])
+int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *ret);
+int sd_ndisc_get_hop_limit(sd_ndisc *nd, uint8_t *ret);
+
+int sd_ndisc_router_from_raw(sd_ndisc_router **ret, const void *raw, size_t raw_size);
+sd_ndisc_router *sd_ndisc_router_ref(sd_ndisc_router *rt);
+sd_ndisc_router *sd_ndisc_router_unref(sd_ndisc_router *rt);
+
+int sd_ndisc_router_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr);
+int sd_ndisc_router_get_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret);
+int sd_ndisc_router_get_raw(sd_ndisc_router *rt, const void **ret, size_t *size);
+
+int sd_ndisc_router_get_hop_limit(sd_ndisc_router *rt, uint8_t *ret);
+int sd_ndisc_router_get_flags(sd_ndisc_router *rt, uint64_t *ret_flags);
+int sd_ndisc_router_get_preference(sd_ndisc_router *rt, unsigned *ret);
+int sd_ndisc_router_get_lifetime(sd_ndisc_router *rt, uint16_t *ret_lifetime);
+int sd_ndisc_router_get_mtu(sd_ndisc_router *rt, uint32_t *ret);
+
+/* Generic option access */
+int sd_ndisc_router_option_rewind(sd_ndisc_router *rt);
+int sd_ndisc_router_option_next(sd_ndisc_router *rt);
+int sd_ndisc_router_option_get_type(sd_ndisc_router *rt, uint8_t *ret);
+int sd_ndisc_router_option_is_type(sd_ndisc_router *rt, uint8_t type);
+int sd_ndisc_router_option_get_raw(sd_ndisc_router *rt, const void **ret, size_t *size);
+
+/* Specific option access: SD_NDISC_OPTION_PREFIX_INFORMATION */
+int sd_ndisc_router_prefix_get_valid_lifetime(sd_ndisc_router *rt, uint32_t *ret);
+int sd_ndisc_router_prefix_get_preferred_lifetime(sd_ndisc_router *rt, uint32_t *ret);
+int sd_ndisc_router_prefix_get_flags(sd_ndisc_router *rt, uint8_t *ret);
+int sd_ndisc_router_prefix_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr);
+int sd_ndisc_router_prefix_get_prefixlen(sd_ndisc_router *rt, unsigned *prefixlen);
+
+/* Specific option access: SD_NDISC_OPTION_ROUTE_INFORMATION */
+int sd_ndisc_router_route_get_lifetime(sd_ndisc_router *rt, uint32_t *ret);
+int sd_ndisc_router_route_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr);
+int sd_ndisc_router_route_get_prefixlen(sd_ndisc_router *rt, unsigned *prefixlen);
+int sd_ndisc_router_route_get_preference(sd_ndisc_router *rt, unsigned *ret);
+
+/* Specific option access: SD_NDISC_OPTION_RDNSS */
+int sd_ndisc_router_rdnss_get_addresses(sd_ndisc_router *rt, const struct in6_addr **ret);
+int sd_ndisc_router_rdnss_get_lifetime(sd_ndisc_router *rt, uint32_t *ret);
+
+/* Specific option access: SD_NDISC_OPTION_DNSSL */
+int sd_ndisc_router_dnssl_get_domains(sd_ndisc_router *rt, char ***ret);
+int sd_ndisc_router_dnssl_get_lifetime(sd_ndisc_router *rt, uint32_t *ret);
 
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc, sd_ndisc_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc_router, sd_ndisc_router_unref);
 
 _SD_END_DECLARATIONS;