summary refs log tree commit diff
path: root/src/systemd
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2019-07-31 10:51:42 +0200
committerMichael Biebl <biebl@debian.org>2019-07-31 10:51:42 +0200
commit2e5fa45ddfbb5cffa1e78221f1cea706e2f298af (patch)
tree86f69d36c56de3074280456eddc854a780b8e04b /src/systemd
parent85563b7fc7ec2cd21e38debb9b28db342e2e8e7c (diff)
New upstream version 1.19.90 upstream/1.19.90
Diffstat (limited to 'src/systemd')
-rw-r--r--src/systemd/meson.build3
-rw-r--r--src/systemd/nm-sd-utils-dhcp.c54
-rw-r--r--src/systemd/nm-sd-utils-dhcp.h34
-rw-r--r--src/systemd/nm-sd.c5
-rw-r--r--src/systemd/nm-sd.h1
-rw-r--r--src/systemd/sd-adapt-core/nm-sd-adapt-core.c1
-rw-r--r--src/systemd/sd-adapt-core/nm-sd-adapt-core.h2
-rw-r--r--src/systemd/src/libsystemd-network/arp-util.c3
-rw-r--r--src/systemd/src/libsystemd-network/arp-util.h2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.c2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-internal.h2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-network.c1
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-option.c3
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-packet.c1
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-internal.h2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-network.c1
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-option.c1
-rw-r--r--src/systemd/src/libsystemd-network/lldp-internal.h2
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.c253
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.h15
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c131
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-lease.c5
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-client.c2
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-lease.c17
-rw-r--r--src/systemd/src/libsystemd-network/sd-ipv4acd.c4
-rw-r--r--src/systemd/src/libsystemd-network/sd-ipv4ll.c3
-rw-r--r--src/systemd/src/libsystemd/sd-event/event-util.c1
-rw-r--r--src/systemd/src/libsystemd/sd-event/sd-event.c22
-rw-r--r--src/systemd/src/libsystemd/sd-id128/id128-util.c1
-rw-r--r--src/systemd/src/libsystemd/sd-id128/sd-id128.c1
-rw-r--r--src/systemd/src/shared/dns-domain.c1387
-rw-r--r--src/systemd/src/shared/dns-domain.h113
-rw-r--r--src/systemd/src/systemd/sd-dhcp-client.h7
-rw-r--r--src/systemd/src/systemd/sd-event.h2
-rw-r--r--src/systemd/src/systemd/sd-id128.h1
35 files changed, 470 insertions, 1615 deletions
diff --git a/src/systemd/meson.build b/src/systemd/meson.build
index 257a9462..af1d0c8b 100644
--- a/src/systemd/meson.build
+++ b/src/systemd/meson.build
@@ -23,9 +23,9 @@ libnm_systemd_core = static_library(
     'src/libsystemd/sd-event/sd-event.c',
     'src/libsystemd/sd-id128/id128-util.c',
     'src/libsystemd/sd-id128/sd-id128.c',
-    'src/shared/dns-domain.c',
     'nm-sd.c',
     'nm-sd-utils-core.c',
+    'nm-sd-utils-dhcp.c',
   ),
   include_directories: [
     src_inc,
@@ -33,7 +33,6 @@ libnm_systemd_core = static_library(
       'sd-adapt-core',
       'src/libsystemd-network',
       'src/libsystemd/sd-event',
-      'src/shared',
       'src/systemd',
     )
   ],
diff --git a/src/systemd/nm-sd-utils-dhcp.c b/src/systemd/nm-sd-utils-dhcp.c
new file mode 100644
index 00000000..49a924b6
--- /dev/null
+++ b/src/systemd/nm-sd-utils-dhcp.c
@@ -0,0 +1,54 @@
+/*
+ * This library 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 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-sd-utils-dhcp.h"
+
+#include "sd-adapt-core/nm-sd-adapt-core.h"
+#include "src/libsystemd-network/dhcp-lease-internal.h"
+
+int
+nm_sd_dhcp_lease_get_private_options (sd_dhcp_lease *lease, nm_sd_dhcp_option **out_options)
+{
+	struct sd_dhcp_raw_option *raw_option;
+	int cnt = 0;
+
+	g_return_val_if_fail (lease, -EINVAL);
+	g_return_val_if_fail (out_options, -EINVAL);
+	g_return_val_if_fail (*out_options == NULL, -EINVAL);
+
+	if (lease->private_options == NULL)
+		return -ENODATA;
+
+	LIST_FOREACH (options, raw_option, lease->private_options)
+		cnt++;
+
+	*out_options = g_new (nm_sd_dhcp_option, cnt);
+	cnt = 0;
+
+	LIST_FOREACH (options, raw_option, lease->private_options) {
+		(*out_options)[cnt].code = raw_option->tag;
+		(*out_options)[cnt].data = raw_option->data;
+		(*out_options)[cnt].data_len = raw_option->length;
+		cnt++;
+	}
+
+	return cnt;
+}
diff --git a/src/systemd/nm-sd-utils-dhcp.h b/src/systemd/nm-sd-utils-dhcp.h
new file mode 100644
index 00000000..496bf374
--- /dev/null
+++ b/src/systemd/nm-sd-utils-dhcp.h
@@ -0,0 +1,34 @@
+/*
+ * This library 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 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2019 Red Hat, Inc.
+ */
+
+#ifndef __NETWORKMANAGER_DHCP_SYSTEMD_UTILS_H__
+#define __NETWORKMANAGER_DHCP_SYSTEMD_UTILS_H__
+
+#include "nm-sd.h"
+
+typedef struct {
+	uint8_t code;
+	uint8_t data_len;
+	void *data;
+} nm_sd_dhcp_option;
+
+int
+nm_sd_dhcp_lease_get_private_options (sd_dhcp_lease *lease, nm_sd_dhcp_option **out_options);
+
+#endif /* __NETWORKMANAGER_DHCP_SYSTEMD_UTILS_H__ */
diff --git a/src/systemd/nm-sd.c b/src/systemd/nm-sd.c
index 4009c617..bcab328f 100644
--- a/src/systemd/nm-sd.c
+++ b/src/systemd/nm-sd.c
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
@@ -133,10 +132,6 @@ nm_sd_event_attach_default (void)
 
 /*****************************************************************************/
 
-const bool mempool_use_allowed = true;
-
-/*****************************************************************************/
-
 /* ensure that defines in nm-sd.h correspond to the internal defines. */
 
 #include "nm-sd-adapt-core.h"
diff --git a/src/systemd/nm-sd.h b/src/systemd/nm-sd.h
index f988dfd0..07fc2ad4 100644
--- a/src/systemd/nm-sd.h
+++ b/src/systemd/nm-sd.h
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
diff --git a/src/systemd/sd-adapt-core/nm-sd-adapt-core.c b/src/systemd/sd-adapt-core/nm-sd-adapt-core.c
index d7ed687e..c461752e 100644
--- a/src/systemd/sd-adapt-core/nm-sd-adapt-core.c
+++ b/src/systemd/sd-adapt-core/nm-sd-adapt-core.c
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
diff --git a/src/systemd/sd-adapt-core/nm-sd-adapt-core.h b/src/systemd/sd-adapt-core/nm-sd-adapt-core.h
index 8c07c53a..bd71dd18 100644
--- a/src/systemd/sd-adapt-core/nm-sd-adapt-core.h
+++ b/src/systemd/sd-adapt-core/nm-sd-adapt-core.h
@@ -50,8 +50,6 @@
 #include <sys/syscall.h>
 #include <sys/ioctl.h>
 
-#include <net/if_arp.h>
-
 /* Missing in Linux 3.2.0, in Ubuntu 12.04 */
 #ifndef BPF_XOR
 #define BPF_XOR 0xa0
diff --git a/src/systemd/src/libsystemd-network/arp-util.c b/src/systemd/src/libsystemd-network/arp-util.c
index 154ba6b7..e48e4bfe 100644
--- a/src/systemd/src/libsystemd-network/arp-util.c
+++ b/src/systemd/src/libsystemd-network/arp-util.c
@@ -5,8 +5,9 @@
 
 #include "nm-sd-adapt-core.h"
 
-#include <linux/filter.h>
 #include <arpa/inet.h>
+#include <linux/filter.h>
+#include <netinet/if_ether.h>
 
 #include "arp-util.h"
 #include "fd-util.h"
diff --git a/src/systemd/src/libsystemd-network/arp-util.h b/src/systemd/src/libsystemd-network/arp-util.h
index 10c68486..9a4427e8 100644
--- a/src/systemd/src/libsystemd-network/arp-util.h
+++ b/src/systemd/src/libsystemd-network/arp-util.h
@@ -5,7 +5,7 @@
   Copyright © 2014 Axis Communications AB. All rights reserved.
 ***/
 
-#include <netinet/if_ether.h>
+#include <net/ethernet.h>
 
 #include "socket-util.h"
 #include "sparse-endian.h"
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c
index e3af362d..b28e0ba0 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.c
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c
@@ -197,7 +197,7 @@ int dhcp_identifier_set_iaid(
                                 /* device is under renaming */
                                 return -EBUSY;
 
-                        name = net_get_name(device);
+                        name = net_get_name_persistent(device);
                 }
         }
 
diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h
index a0f9c229..e0269b54 100644
--- a/src/systemd/src/libsystemd-network/dhcp-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-internal.h
@@ -51,5 +51,5 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, ui
 #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_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_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_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 45d2ed89..858fe57c 100644
--- a/src/systemd/src/libsystemd-network/dhcp-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp-network.c
@@ -5,6 +5,7 @@
 
 #include "nm-sd-adapt-core.h"
 
+#include <errno.h>
 #include <net/ethernet.h>
 #include <net/if.h>
 #include <net/if_arp.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp-option.c b/src/systemd/src/libsystemd-network/dhcp-option.c
index eaf044bf..50238b0a 100644
--- a/src/systemd/src/libsystemd-network/dhcp-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp-option.c
@@ -5,6 +5,7 @@
 
 #include "nm-sd-adapt-core.h"
 
+#include <errno.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
@@ -199,7 +200,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
                                 if (memchr(option, 0, len - 1))
                                         return -EINVAL;
 
-                                string = strndup((const char *) option, len);
+                                string = memdup_suffix0((const char *) option, len);
                                 if (!string)
                                         return -ENOMEM;
 
diff --git a/src/systemd/src/libsystemd-network/dhcp-packet.c b/src/systemd/src/libsystemd-network/dhcp-packet.c
index 91e8a54e..9e565e28 100644
--- a/src/systemd/src/libsystemd-network/dhcp-packet.c
+++ b/src/systemd/src/libsystemd-network/dhcp-packet.c
@@ -5,6 +5,7 @@
 
 #include "nm-sd-adapt-core.h"
 
+#include <errno.h>
 #include <net/ethernet.h>
 #include <net/if_arp.h>
 #include <string.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h
index 157fc0aa..f28ba68d 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h
@@ -79,7 +79,7 @@ struct DHCP6IA {
 
 typedef struct DHCP6IA DHCP6IA;
 
-#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_errno(p, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_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,
diff --git a/src/systemd/src/libsystemd-network/dhcp6-network.c b/src/systemd/src/libsystemd-network/dhcp6-network.c
index d786756e..73c195a7 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-network.c
@@ -5,6 +5,7 @@
 
 #include "nm-sd-adapt-core.h"
 
+#include <errno.h>
 #include <netinet/in.h>
 #include <netinet/ip6.h>
 #include <stdio.h>
diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c
index 6172c368..562a34b5 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-option.c
@@ -5,6 +5,7 @@
 
 #include "nm-sd-adapt-core.h"
 
+#include <errno.h>
 #include <netinet/in.h>
 #include <string.h>
 
diff --git a/src/systemd/src/libsystemd-network/lldp-internal.h b/src/systemd/src/libsystemd-network/lldp-internal.h
index 88b54933..9598438d 100644
--- a/src/systemd/src/libsystemd-network/lldp-internal.h
+++ b/src/systemd/src/libsystemd-network/lldp-internal.h
@@ -32,7 +32,7 @@ struct sd_lldp {
         struct ether_addr filter_address;
 };
 
-#define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__)
+#define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__)
 #define log_lldp(fmt, ...) log_lldp_errno(0, fmt, ##__VA_ARGS__)
 
 const char* lldp_event_to_string(sd_lldp_event e) _const_;
diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c
index de219a6d..209ce884 100644
--- a/src/systemd/src/libsystemd-network/network-internal.c
+++ b/src/systemd/src/libsystemd-network/network-internal.c
@@ -14,6 +14,7 @@
 #include "conf-parser.h"
 #include "device-util.h"
 #include "dhcp-lease-internal.h"
+#include "env-util.h"
 #include "ether-addr-util.h"
 #include "hexdecoct.h"
 #include "log.h"
@@ -27,7 +28,7 @@
 #include "util.h"
 
 #if 0 /* NM_IGNORED */
-const char *net_get_name(sd_device *device) {
+const char *net_get_name_persistent(sd_device *device) {
         const char *name, *field;
 
         assert(device);
@@ -42,7 +43,7 @@ const char *net_get_name(sd_device *device) {
 
 #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
 
-int net_get_unique_predictable_data(sd_device *device, uint64_t *result) {
+int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result) {
         size_t l, sz = 0;
         const char *name;
         int r;
@@ -50,10 +51,10 @@ int net_get_unique_predictable_data(sd_device *device, uint64_t *result) {
 
         assert(device);
 
-        /* net_get_name() will return one of the device names based on stable information about the
-         * device. If this is not available, we fall back to using the device name. */
-        name = net_get_name(device);
-        if (!name)
+        /* net_get_name_persistent() will return one of the device names based on stable information about
+         * the device. If this is not available, we fall back to using the actual device name. */
+        name = net_get_name_persistent(device);
+        if (!name && use_sysname)
                 (void) sd_device_get_sysname(device, &name);
         if (!name)
                 return log_device_debug_errno(device, SYNTHETIC_ERRNO(ENODATA),
@@ -76,26 +77,66 @@ int net_get_unique_predictable_data(sd_device *device, uint64_t *result) {
         return 0;
 }
 
-static bool net_condition_test_strv(char * const *raw_patterns,
-                                    const char *string) {
-        if (strv_isempty(raw_patterns))
+static bool net_condition_test_strv(char * const *patterns, const char *string) {
+        char * const *p;
+        bool match = false, has_positive_rule = false;
+
+        if (strv_isempty(patterns))
                 return true;
 
-        /* If the patterns begin with "!", edit it out and negate the test. */
-        if (raw_patterns[0][0] == '!') {
-                char **patterns;
-                size_t i, length;
+        STRV_FOREACH(p, patterns) {
+                const char *q = *p;
+                bool invert;
+
+                invert = *q == '!';
+                q += invert;
+
+                if (!invert)
+                        has_positive_rule = true;
+
+                if (string && fnmatch(q, string, 0) == 0) {
+                        if (invert)
+                                return false;
+                        else
+                                match = true;
+                }
+        }
+
+        return has_positive_rule ? match : true;
+}
+
+static int net_condition_test_property(char * const *match_property, sd_device *device) {
+        char * const *p;
+
+        if (strv_isempty(match_property))
+                return true;
+
+        STRV_FOREACH(p, match_property) {
+                _cleanup_free_ char *key = NULL;
+                const char *val, *dev_val;
+                bool invert, v;
+
+                invert = **p == '!';
+
+                val = strchr(*p + invert, '=');
+                if (!val)
+                        return -EINVAL;
 
-                length = strv_length(raw_patterns) + 1; /* Include the NULL. */
-                patterns = newa(char*, length);
-                patterns[0] = raw_patterns[0] + 1; /* Skip the "!". */
-                for (i = 1; i < length; i++)
-                        patterns[i] = raw_patterns[i];
+                key = strndup(*p + invert, val - *p - invert);
+                if (!key)
+                        return -ENOMEM;
+
+                val++;
 
-                return !string || !strv_fnmatch(patterns, string, 0);
+                v = device &&
+                        sd_device_get_property_value(device, key, &dev_val) >= 0 &&
+                        fnmatch(val, dev_val, 0) == 0;
+
+                if (invert ? v : !v)
+                        return false;
         }
 
-        return string && strv_fnmatch(raw_patterns, string, 0);
+        return true;
 }
 
 bool net_match_config(Set *match_mac,
@@ -103,12 +144,25 @@ bool net_match_config(Set *match_mac,
                       char * const *match_drivers,
                       char * const *match_types,
                       char * const *match_names,
+                      char * const *match_property,
+                      sd_device *device,
                       const struct ether_addr *dev_mac,
-                      const char *dev_path,
-                      const char *dev_driver,
-                      const char *dev_type,
                       const char *dev_name) {
 
+        const char *dev_path = NULL, *dev_driver = NULL, *dev_type = NULL, *mac_str;
+
+        if (device) {
+                (void) sd_device_get_property_value(device, "ID_PATH", &dev_path);
+                (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &dev_driver);
+                (void) sd_device_get_devtype(device, &dev_type);
+
+                if (!dev_name)
+                        (void) sd_device_get_sysname(device, &dev_name);
+                if (!dev_mac &&
+                    sd_device_get_sysattr_value(device, "address", &mac_str) >= 0)
+                        dev_mac = ether_aton(mac_str);
+        }
+
         if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac)))
                 return false;
 
@@ -124,6 +178,9 @@ bool net_match_config(Set *match_mac,
         if (!net_condition_test_strv(match_names, dev_name))
                 return false;
 
+        if (!net_condition_test_property(match_property, device))
+                return false;
+
         return true;
 }
 
@@ -167,7 +224,7 @@ int config_parse_net_condition(const char *unit,
         return 0;
 }
 
-int config_parse_ifnames(
+int config_parse_match_strv(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -179,7 +236,9 @@ int config_parse_ifnames(
                 void *data,
                 void *userdata) {
 
+        const char *p = rvalue;
         char ***sv = data;
+        bool invert;
         int r;
 
         assert(filename);
@@ -187,30 +246,154 @@ int config_parse_ifnames(
         assert(rvalue);
         assert(data);
 
+        if (isempty(rvalue)) {
+                *sv = strv_free(*sv);
+                return 0;
+        }
+
+        invert = *p == '!';
+        p += invert;
+
         for (;;) {
-                _cleanup_free_ char *word = NULL;
+                _cleanup_free_ char *word = NULL, *k = NULL;
 
-                r = extract_first_word(&rvalue, &word, NULL, 0);
+                r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
+                if (r == 0)
+                        return 0;
+                if (r == -ENOMEM)
+                        return log_oom();
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse interface name list: %s", rvalue);
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
                         return 0;
                 }
+
+                if (invert) {
+                        k = strjoin("!", word);
+                        if (!k)
+                                return log_oom();
+                } else
+                        k = TAKE_PTR(word);
+
+                r = strv_consume(sv, TAKE_PTR(k));
+                if (r < 0)
+                        return log_oom();
+        }
+}
+
+int config_parse_match_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) {
+
+        const char *p = rvalue;
+        char ***sv = data;
+        bool invert;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        invert = *p == '!';
+        p += invert;
+
+        for (;;) {
+                _cleanup_free_ char *word = NULL, *k = NULL;
+
+                r = extract_first_word(&p, &word, NULL, 0);
                 if (r == 0)
-                        break;
+                        return 0;
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Failed to parse interface name list: %s", rvalue);
+                        return 0;
+                }
 
                 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;
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Interface name is not valid or too long, ignoring assignment: %s", word);
+                        continue;
                 }
 
-                r = strv_push(sv, word);
+                if (invert) {
+                        k = strjoin("!", word);
+                        if (!k)
+                                return log_oom();
+                } else
+                        k = TAKE_PTR(word);
+
+                r = strv_consume(sv, TAKE_PTR(k));
                 if (r < 0)
                         return log_oom();
-
-                word = NULL;
         }
+}
 
-        return 0;
+int config_parse_match_property(
+                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) {
+
+        const char *p = rvalue;
+        char ***sv = data;
+        bool invert;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        invert = *p == '!';
+        p += invert;
+
+        for (;;) {
+                _cleanup_free_ char *word = NULL, *k = NULL;
+
+                r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
+                if (r == 0)
+                        return 0;
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Invalid syntax, ignoring: %s", rvalue);
+                        return 0;
+                }
+
+                if (!env_assignment_is_valid(word)) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Invalid property or value, ignoring assignment: %s", word);
+                        continue;
+                }
+
+                if (invert) {
+                        k = strjoin("!", word);
+                        if (!k)
+                                return log_oom();
+                } else
+                        k = TAKE_PTR(word);
+
+                r = strv_consume(sv, TAKE_PTR(k));
+                if (r < 0)
+                        return log_oom();
+        }
 }
 
 int config_parse_ifalias(const char *unit,
@@ -616,7 +799,7 @@ int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t siz
         assert(data);
 
         hex_buf = hexmem(data, size);
-        if (hex_buf == NULL)
+        if (!hex_buf)
                 return -ENOMEM;
 
         fprintf(f, "%s=%s\n", key, hex_buf);
diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h
index d895103b..487421fb 100644
--- a/src/systemd/src/libsystemd-network/network-internal.h
+++ b/src/systemd/src/libsystemd-network/network-internal.h
@@ -14,27 +14,28 @@
 #define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
 #define LINK_BRIDGE_PORT_PRIORITY_MAX 63
 
+#if 0 /* NM_IGNORED */
 bool net_match_config(Set *match_mac,
                       char * const *match_path,
                       char * const *match_driver,
                       char * const *match_type,
                       char * const *match_name,
+                      char * const *match_property,
+                      sd_device *device,
                       const struct ether_addr *dev_mac,
-                      const char *dev_path,
-                      const char *dev_driver,
-                      const char *dev_type,
                       const char *dev_name);
 
-#if 0 /* NM_IGNORED */
 CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
 CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
 CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
-CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_strv);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_ifnames);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_property);
 CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
 CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
 
-int net_get_unique_predictable_data(sd_device *device, uint64_t *result);
-const char *net_get_name(sd_device *device);
+int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result);
+const char *net_get_name_persistent(sd_device *device);
 #endif /* NM_IGNORED */
 
 size_t serialize_in_addrs(FILE *f,
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index cadcc8a8..2f531bc7 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -5,6 +5,7 @@
 
 #include "nm-sd-adapt-core.h"
 
+#include <errno.h>
 #include <net/ethernet.h>
 #include <net/if_arp.h>
 #include <stdio.h>
@@ -89,7 +90,8 @@ struct sd_dhcp_client {
         uint32_t mtu;
         uint32_t xid;
         usec_t start_time;
-        unsigned attempt;
+        uint64_t attempt;
+        uint64_t max_attempts;
         usec_t request_sent;
         sd_event_source *timeout_t1;
         sd_event_source *timeout_t2;
@@ -524,10 +526,18 @@ int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
         return 0;
 }
 
+int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempts) {
+        assert_return(client, -EINVAL);
+
+        client->max_attempts = max_attempts;
+
+        return 0;
+}
+
 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
         assert_return(client, -EINVAL);
 
-        if (!IN_SET(client->state, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING))
+        if (!IN_SET(client->state, DHCP_STATE_SELECTING, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING))
                 return -EADDRNOTAVAIL;
 
         if (ret)
@@ -536,11 +546,13 @@ int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
         return 0;
 }
 
-static void client_notify(sd_dhcp_client *client, int event) {
+static int client_notify(sd_dhcp_client *client, int event) {
         assert(client);
 
         if (client->callback)
-                client->callback(client, event, client->userdata);
+                return client->callback(client, event, client->userdata);
+
+        return 0;
 }
 
 static int client_initialize(sd_dhcp_client *client) {
@@ -555,7 +567,7 @@ static int client_initialize(sd_dhcp_client *client) {
         (void) event_source_disable(client->timeout_t2);
         (void) event_source_disable(client->timeout_expire);
 
-        client->attempt = 1;
+        client->attempt = 0;
 
         client->state = DHCP_STATE_INIT;
         client->xid = 0;
@@ -569,7 +581,7 @@ static void client_stop(sd_dhcp_client *client, int error) {
         assert(client);
 
         if (error < 0)
-                log_dhcp_client(client, "STOPPED: %s", strerror(-error));
+                log_dhcp_client_errno(client, error, "STOPPED: %m");
         else if (error == SD_DHCP_CLIENT_EVENT_STOP)
                 log_dhcp_client(client, "STOPPED");
         else
@@ -599,7 +611,7 @@ static int client_message_init(
         assert(ret);
         assert(_optlen);
         assert(_optoffset);
-        assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST));
+        assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST, DHCP_RELEASE));
 
         optlen = DHCP_MIN_OPTIONS_SIZE;
         size = sizeof(DHCPPacket) + optlen;
@@ -690,7 +702,7 @@ static int client_message_init(
            MAY contain the Parameter Request List option. */
         /* NOTE: in case that there would be an option to do not send
          * any PRL at all, the size should be checked before sending */
-        if (client->req_opts_size > 0) {
+        if (client->req_opts_size > 0 && type != DHCP_RELEASE) {
                 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
                                        SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
                                        client->req_opts_size, client->req_opts);
@@ -722,7 +734,7 @@ static int client_message_init(
          */
         /* RFC7844 section 3:
            SHOULD NOT contain any other option. */
-        if (!client->anonymize) {
+        if (!client->anonymize && type != DHCP_RELEASE) {
                 max_size = htobe16(size);
                 r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
                                        SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
@@ -854,6 +866,41 @@ static int client_send_discover(sd_dhcp_client *client) {
         return 0;
 }
 
+static int client_send_release(sd_dhcp_client *client) {
+        _cleanup_free_ DHCPPacket *release = NULL;
+        size_t optoffset, optlen;
+        int r;
+
+        assert(client);
+        assert(!IN_SET(client->state, DHCP_STATE_STOPPED));
+
+        r = client_message_init(client, &release, DHCP_RELEASE,
+                                &optlen, &optoffset);
+        if (r < 0)
+                return r;
+
+        /* Fill up release IP and MAC */
+        release->dhcp.ciaddr = client->lease->address;
+        memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len);
+
+        r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0,
+                               SD_DHCP_OPTION_END, 0, NULL);
+        if (r < 0)
+                return r;
+
+        r = dhcp_network_send_udp_socket(client->fd,
+                                         client->lease->server_address,
+                                         DHCP_PORT_SERVER,
+                                         &release->dhcp,
+                                         sizeof(DHCPMessage) + optoffset);
+        if (r < 0)
+                return r;
+
+        log_dhcp_client(client, "RELEASE");
+
+        return 0;
+}
+
 static int client_send_request(sd_dhcp_client *client) {
         _cleanup_free_ DHCPPacket *request = NULL;
         size_t optoffset, optlen;
@@ -1054,10 +1101,12 @@ static int client_timeout_resend(
         case DHCP_STATE_REQUESTING:
         case DHCP_STATE_BOUND:
 
-                if (client->attempt < 64)
-                        client->attempt *= 2;
+                if (client->attempt < client->max_attempts)
+                        client->attempt++;
+                else
+                        goto error;
 
-                next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
+                next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC;
 
                 break;
 
@@ -1081,17 +1130,15 @@ static int client_timeout_resend(
                 r = client_send_discover(client);
                 if (r >= 0) {
                         client->state = DHCP_STATE_SELECTING;
-                        client->attempt = 1;
-                } else {
-                        if (client->attempt >= 64)
-                                goto error;
-                }
+                        client->attempt = 0;
+                } else if (client->attempt >= client->max_attempts)
+                        goto error;
 
                 break;
 
         case DHCP_STATE_SELECTING:
                 r = client_send_discover(client);
-                if (r < 0 && client->attempt >= 64)
+                if (r < 0 && client->attempt >= client->max_attempts)
                         goto error;
 
                 break;
@@ -1101,7 +1148,7 @@ static int client_timeout_resend(
         case DHCP_STATE_RENEWING:
         case DHCP_STATE_REBINDING:
                 r = client_send_request(client);
-                if (r < 0 && client->attempt >= 64)
+                if (r < 0 && client->attempt >= client->max_attempts)
                          goto error;
 
                 if (client->state == DHCP_STATE_INIT_REBOOT)
@@ -1253,7 +1300,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
         client->fd = asynchronous_close(client->fd);
 
         client->state = DHCP_STATE_REBINDING;
-        client->attempt = 1;
+        client->attempt = 0;
 
         r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
                                          client->xid, client->mac_addr,
@@ -1273,7 +1320,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata)
         DHCP_CLIENT_DONT_DESTROY(client);
 
         client->state = DHCP_STATE_RENEWING;
-        client->attempt = 1;
+        client->attempt = 0;
 
         return client_initialize_time_events(client);
 }
@@ -1323,6 +1370,9 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_
         sd_dhcp_lease_unref(client->lease);
         client->lease = TAKE_PTR(lease);
 
+        if (client_notify(client, SD_DHCP_CLIENT_EVENT_SELECTING) < 0)
+                return -ENOMSG;
+
         log_dhcp_client(client, "OFFER");
 
         return 0;
@@ -1340,6 +1390,23 @@ static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
         return 0;
 }
 
+static bool lease_equal(const sd_dhcp_lease *a, const sd_dhcp_lease *b) {
+        if (a->address != b->address)
+                return false;
+
+        if (a->subnet_mask != b->subnet_mask)
+                return false;
+
+        if (a->router_size != b->router_size)
+                return false;
+
+        for (size_t i = 0; i < a->router_size; i++)
+                if (a->router[i].s_addr != b->router[i].s_addr)
+                        return false;
+
+        return true;
+}
+
 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;
@@ -1392,12 +1459,10 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t le
 
         r = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
         if (client->lease) {
-                if (client->lease->address != lease->address ||
-                    client->lease->subnet_mask != lease->subnet_mask ||
-                    client->lease->router != lease->router) {
-                        r = SD_DHCP_CLIENT_EVENT_IP_CHANGE;
-                } else
+                if (lease_equal(client->lease, lease))
                         r = SD_DHCP_CLIENT_EVENT_RENEW;
+                else
+                        r = SD_DHCP_CLIENT_EVENT_IP_CHANGE;
 
                 client->lease = sd_dhcp_lease_unref(client->lease);
         }
@@ -1557,7 +1622,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
                 if (r >= 0) {
 
                         client->state = DHCP_STATE_REQUESTING;
-                        client->attempt = 1;
+                        client->attempt = 0;
 
                         r = event_reset_time(client->event, &client->timeout_resend,
                                              clock_boottime_or_monotonic(),
@@ -1592,7 +1657,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
                                 notify_event = r;
 
                         client->state = DHCP_STATE_BOUND;
-                        client->attempt = 1;
+                        client->attempt = 0;
 
                         client->last_addr = client->lease->address;
 
@@ -1848,6 +1913,14 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
         return r;
 }
 
+int sd_dhcp_client_send_release(sd_dhcp_client *client) {
+        assert_return(client, -EINVAL);
+
+        client_send_release(client);
+
+        return 0;
+}
+
 int sd_dhcp_client_stop(sd_dhcp_client *client) {
         DHCP_CLIENT_DONT_DESTROY(client);
 
@@ -1931,10 +2004,10 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
                 .state = DHCP_STATE_INIT,
                 .ifindex = -1,
                 .fd = -1,
-                .attempt = 1,
                 .mtu = DHCP_DEFAULT_MIN_SIZE,
                 .port = DHCP_PORT_CLIENT,
                 .anonymize = !!anonymize,
+                .max_attempts = (uint64_t) -1,
         };
         /* NOTE: this could be moved to a function. */
         if (anonymize) {
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
index 6c7aecc8..7559d066 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
@@ -6,8 +6,8 @@
 #include "nm-sd-adapt-core.h"
 
 #include <arpa/inet.h>
+#include <errno.h>
 #include <stdio.h>
-#include <stdio_ext.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
@@ -335,7 +335,7 @@ static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
                 if (memchr(option, 0, len - 1))
                         return -EINVAL;
 
-                string = strndup((const char *) option, len);
+                string = memdup_suffix0((const char *) option, len);
                 if (!string)
                         return -ENOMEM;
 
@@ -833,7 +833,6 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
         if (r < 0)
                 goto fail;
 
-        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
         (void) fchmod(fileno(f), 0644);
 
         fprintf(f,
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
index b72cd82d..f67a45bd 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
@@ -5,8 +5,10 @@
 
 #include "nm-sd-adapt-core.h"
 
+#include <errno.h>
 #include <string.h>
 #include <sys/ioctl.h>
+#include <linux/if_arp.h>
 #include <linux/if_infiniband.h>
 
 #include "sd-dhcp6-client.h"
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
index 7263c96f..35caec7a 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
@@ -5,6 +5,7 @@
 
 #include "nm-sd-adapt-core.h"
 
+#include <errno.h>
 
 #include "alloc-util.h"
 #include "dhcp6-lease-internal.h"
@@ -206,12 +207,8 @@ int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
         r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->dns,
                                         lease->dns_count,
                                         &lease->dns_allocated);
-        if (r < 0) {
-                log_dhcp6_client(client, "Invalid DNS server option: %s",
-                                 strerror(-r));
-
-                return r;
-        }
+        if (r < 0)
+                return log_dhcp6_client_errno(client, r, "Invalid DNS server option: %m");
 
         lease->dns_count = r;
 
@@ -337,12 +334,8 @@ int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen)
         r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp,
                                         lease->ntp_count,
                                         &lease->ntp_allocated);
-        if (r < 0) {
-                log_dhcp6_client(client, "Invalid SNTP server option: %s",
-                                 strerror(-r));
-
-                return r;
-        }
+        if (r < 0)
+                return log_dhcp6_client_errno(client, r, "Invalid SNTP server option: %m");
 
         lease->ntp_count = r;
 
diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c
index 53ce8929..e7561480 100644
--- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c
+++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c
@@ -6,6 +6,8 @@
 #include "nm-sd-adapt-core.h"
 
 #include <arpa/inet.h>
+#include <errno.h>
+#include <netinet/if_ether.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -73,7 +75,7 @@ struct sd_ipv4acd {
         void* userdata;
 };
 
-#define log_ipv4acd_errno(acd, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "IPV4ACD: " fmt, ##__VA_ARGS__)
+#define log_ipv4acd_errno(acd, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_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) {
diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c
index 4f186762..daac8839 100644
--- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c
@@ -6,6 +6,7 @@
 #include "nm-sd-adapt-core.h"
 
 #include <arpa/inet.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -51,7 +52,7 @@ struct sd_ipv4ll {
         void* userdata;
 };
 
-#define log_ipv4ll_errno(ll, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "IPV4LL: " fmt, ##__VA_ARGS__)
+#define log_ipv4ll_errno(ll, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_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);
diff --git a/src/systemd/src/libsystemd/sd-event/event-util.c b/src/systemd/src/libsystemd/sd-event/event-util.c
index 2afacfe6..e8384cfd 100644
--- a/src/systemd/src/libsystemd/sd-event/event-util.c
+++ b/src/systemd/src/libsystemd/sd-event/event-util.c
@@ -2,6 +2,7 @@
 
 #include "nm-sd-adapt-core.h"
 
+#include <errno.h>
 
 #include "event-source.h"
 #include "event-util.h"
diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c
index dad0801b..c3781706 100644
--- a/src/systemd/src/libsystemd/sd-event/sd-event.c
+++ b/src/systemd/src/libsystemd/sd-event/sd-event.c
@@ -25,6 +25,7 @@
 #include "signal-util.h"
 #include "string-table.h"
 #include "string-util.h"
+#include "strxcpyx.h"
 #include "time-util.h"
 
 #define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC)
@@ -341,6 +342,12 @@ fail:
 
 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
 
+_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
+        if (s)
+                (void) sd_event_source_set_enabled(s, SD_EVENT_OFF);
+        return sd_event_source_unref(s);
+}
+
 static bool event_pid_changed(sd_event *e) {
         assert(e);
 
@@ -3026,7 +3033,7 @@ static void event_close_inode_data_fds(sd_event *e) {
 
         /* Close the fds pointing to the inodes to watch now. We need to close them as they might otherwise pin
          * filesystems. But we can't close them right-away as we need them as long as the user still wants to make
-         * adjustments to the even source, such as changing the priority (which requires us to remove and readd a watch
+         * adjustments to the even source, such as changing the priority (which requires us to remove and re-add a watch
          * for the inode). Hence, let's close them when entering the first iteration after they were added, as a
          * compromise. */
 
@@ -3246,15 +3253,16 @@ _public_ int sd_event_dispatch(sd_event *e) {
 }
 
 static void event_log_delays(sd_event *e) {
-        char b[ELEMENTSOF(e->delays) * DECIMAL_STR_MAX(unsigned) + 1];
-        unsigned i;
-        int o;
+        char b[ELEMENTSOF(e->delays) * DECIMAL_STR_MAX(unsigned) + 1], *p;
+        size_t l, i;
 
-        for (i = o = 0; i < ELEMENTSOF(e->delays); i++) {
-                o += snprintf(&b[o], sizeof(b) - o, "%u ", e->delays[i]);
+        p = b;
+        l = sizeof(b);
+        for (i = 0; i < ELEMENTSOF(e->delays); i++) {
+                l = strpcpyf(&p, l, "%u ", e->delays[i]);
                 e->delays[i] = 0;
         }
-        log_debug("Event loop iterations: %.*s", o, b);
+        log_debug("Event loop iterations: %s", b);
 }
 
 _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.c b/src/systemd/src/libsystemd/sd-id128/id128-util.c
index 6245e9df..f8f0883c 100644
--- a/src/systemd/src/libsystemd/sd-id128/id128-util.c
+++ b/src/systemd/src/libsystemd/sd-id128/id128-util.c
@@ -2,6 +2,7 @@
 
 #include "nm-sd-adapt-core.h"
 
+#include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
 
diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
index d0cae981..eeb29e97 100644
--- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c
@@ -2,6 +2,7 @@
 
 #include "nm-sd-adapt-core.h"
 
+#include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
 
diff --git a/src/systemd/src/shared/dns-domain.c b/src/systemd/src/shared/dns-domain.c
deleted file mode 100644
index ebea861f..00000000
--- a/src/systemd/src/shared/dns-domain.c
+++ /dev/null
@@ -1,1387 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-
-#include "nm-sd-adapt-core.h"
-
-#if 0 /* NM_IGNORED */
-#if HAVE_LIBIDN2
-#  include <idn2.h>
-#elif HAVE_LIBIDN
-#  include <idna.h>
-#  include <stringprep.h>
-#endif
-#endif
-
-#include <endian.h>
-#include <netinet/in.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/socket.h>
-
-#include "alloc-util.h"
-#include "dns-domain.h"
-#include "hashmap.h"
-#include "hexdecoct.h"
-#include "hostname-util.h"
-#include "in-addr-util.h"
-#include "macro.h"
-#include "parse-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "utf8.h"
-
-int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags flags) {
-        const char *n;
-        char *d, last_char = 0;
-        int r = 0;
-
-        assert(name);
-        assert(*name);
-
-        n = *name;
-        d = dest;
-
-        for (;;) {
-                if (*n == 0 || *n == '.') {
-                        if (FLAGS_SET(flags, DNS_LABEL_LDH) && last_char == '-')
-                                /* Trailing dash */
-                                return -EINVAL;
-
-                        if (*n == '.')
-                                n++;
-                        break;
-                }
-
-                if (r >= DNS_LABEL_MAX)
-                        return -EINVAL;
-
-                if (sz <= 0)
-                        return -ENOBUFS;
-
-                if (*n == '\\') {
-                        /* Escaped character */
-                        if (FLAGS_SET(flags, DNS_LABEL_NO_ESCAPES))
-                                return -EINVAL;
-
-                        n++;
-
-                        if (*n == 0)
-                                /* Ending NUL */
-                                return -EINVAL;
-
-                        else if (IN_SET(*n, '\\', '.')) {
-                                /* Escaped backslash or dot */
-
-                                if (FLAGS_SET(flags, DNS_LABEL_LDH))
-                                        return -EINVAL;
-
-                                last_char = *n;
-                                if (d)
-                                        *(d++) = *n;
-                                sz--;
-                                r++;
-                                n++;
-
-                        } else if (n[0] >= '0' && n[0] <= '9') {
-                                unsigned k;
-
-                                /* Escaped literal ASCII character */
-
-                                if (!(n[1] >= '0' && n[1] <= '9') ||
-                                    !(n[2] >= '0' && n[2] <= '9'))
-                                        return -EINVAL;
-
-                                k = ((unsigned) (n[0] - '0') * 100) +
-                                        ((unsigned) (n[1] - '0') * 10) +
-                                        ((unsigned) (n[2] - '0'));
-
-                                /* Don't allow anything that doesn't
-                                 * fit in 8bit. Note that we do allow
-                                 * control characters, as some servers
-                                 * (e.g. cloudflare) are happy to
-                                 * generate labels with them
-                                 * inside. */
-                                if (k > 255)
-                                        return -EINVAL;
-
-                                if (FLAGS_SET(flags, DNS_LABEL_LDH) &&
-                                    !valid_ldh_char((char) k))
-                                        return -EINVAL;
-
-                                last_char = (char) k;
-                                if (d)
-                                        *(d++) = (char) k;
-                                sz--;
-                                r++;
-
-                                n += 3;
-                        } else
-                                return -EINVAL;
-
-                } else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) {
-
-                        /* Normal character */
-
-                        if (FLAGS_SET(flags, DNS_LABEL_LDH)) {
-                                if (!valid_ldh_char(*n))
-                                        return -EINVAL;
-                                if (r == 0 && *n == '-')
-                                        /* Leading dash */
-                                        return -EINVAL;
-                        }
-
-                        last_char = *n;
-                        if (d)
-                                *(d++) = *n;
-                        sz--;
-                        r++;
-                        n++;
-                } else
-                        return -EINVAL;
-        }
-
-        /* Empty label that is not at the end? */
-        if (r == 0 && *n)
-                return -EINVAL;
-
-        /* More than one trailing dot? */
-        if (*n == '.')
-                return -EINVAL;
-
-        if (sz >= 1 && d)
-                *d = 0;
-
-        *name = n;
-        return r;
-}
-
-#if 0 /* NM_IGNORED */
-/* @label_terminal: terminal character of a label, updated to point to the terminal character of
- *                  the previous label (always skipping one dot) or to NULL if there are no more
- *                  labels. */
-int dns_label_unescape_suffix(const char *name, const char **label_terminal, char *dest, size_t sz) {
-        const char *terminal;
-        int r;
-
-        assert(name);
-        assert(label_terminal);
-        assert(dest);
-
-        /* no more labels */
-        if (!*label_terminal) {
-                if (sz >= 1)
-                        *dest = 0;
-
-                return 0;
-        }
-
-        terminal = *label_terminal;
-        assert(IN_SET(*terminal, 0, '.'));
-
-        /* Skip current terminal character (and accept domain names ending it ".") */
-        if (*terminal == 0)
-                terminal--;
-        if (terminal >= name && *terminal == '.')
-                terminal--;
-
-        /* Point name to the last label, and terminal to the preceding terminal symbol (or make it a NULL pointer) */
-        for (;;) {
-                if (terminal < name) {
-                        /* Reached the first label, so indicate that there are no more */
-                        terminal = NULL;
-                        break;
-                }
-
-                /* Find the start of the last label */
-                if (*terminal == '.') {
-                        const char *y;
-                        unsigned slashes = 0;
-
-                        for (y = terminal - 1; y >= name && *y == '\\'; y--)
-                                slashes++;
-
-                        if (slashes % 2 == 0) {
-                                /* The '.' was not escaped */
-                                name = terminal + 1;
-                                break;
-                        } else {
-                                terminal = y;
-                                continue;
-                        }
-                }
-
-                terminal--;
-        }
-
-        r = dns_label_unescape(&name, dest, sz, 0);
-        if (r < 0)
-                return r;
-
-        *label_terminal = terminal;
-
-        return r;
-}
-#endif /* NM_IGNORED */
-
-int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) {
-        char *q;
-
-        /* DNS labels must be between 1 and 63 characters long. A
-         * zero-length label does not exist. See RFC 2182, Section
-         * 11. */
-
-        if (l <= 0 || l > DNS_LABEL_MAX)
-                return -EINVAL;
-        if (sz < 1)
-                return -ENOBUFS;
-
-        assert(p);
-        assert(dest);
-
-        q = dest;
-        while (l > 0) {
-
-                if (IN_SET(*p, '.', '\\')) {
-
-                        /* Dot or backslash */
-
-                        if (sz < 3)
-                                return -ENOBUFS;
-
-                        *(q++) = '\\';
-                        *(q++) = *p;
-
-                        sz -= 2;
-
-                } else if (IN_SET(*p, '_', '-') ||
-                           (*p >= '0' && *p <= '9') ||
-                           (*p >= 'a' && *p <= 'z') ||
-                           (*p >= 'A' && *p <= 'Z')) {
-
-                        /* Proper character */
-
-                        if (sz < 2)
-                                return -ENOBUFS;
-
-                        *(q++) = *p;
-                        sz -= 1;
-
-                } else {
-
-                        /* Everything else */
-
-                        if (sz < 5)
-                                return -ENOBUFS;
-
-                        *(q++) = '\\';
-                        *(q++) = '0' + (char) ((uint8_t) *p / 100);
-                        *(q++) = '0' + (char) (((uint8_t) *p / 10) % 10);
-                        *(q++) = '0' + (char) ((uint8_t) *p % 10);
-
-                        sz -= 4;
-                }
-
-                p++;
-                l--;
-        }
-
-        *q = 0;
-        return (int) (q - dest);
-}
-
-#if 0 /* NM_IGNORED */
-int dns_label_escape_new(const char *p, size_t l, char **ret) {
-        _cleanup_free_ char *s = NULL;
-        int r;
-
-        assert(p);
-        assert(ret);
-
-        if (l <= 0 || l > DNS_LABEL_MAX)
-                return -EINVAL;
-
-        s = new(char, DNS_LABEL_ESCAPED_MAX);
-        if (!s)
-                return -ENOMEM;
-
-        r = dns_label_escape(p, l, s, DNS_LABEL_ESCAPED_MAX);
-        if (r < 0)
-                return r;
-
-        *ret = TAKE_PTR(s);
-
-        return r;
-}
-
-#if HAVE_LIBIDN
-int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
-        _cleanup_free_ uint32_t *input = NULL;
-        size_t input_size, l;
-        const char *p;
-        bool contains_8bit = false;
-        char buffer[DNS_LABEL_MAX+1];
-
-        assert(encoded);
-        assert(decoded);
-
-        /* Converts an U-label into an A-label */
-
-        if (encoded_size <= 0)
-                return -EINVAL;
-
-        for (p = encoded; p < encoded + encoded_size; p++)
-                if ((uint8_t) *p > 127)
-                        contains_8bit = true;
-
-        if (!contains_8bit) {
-                if (encoded_size > DNS_LABEL_MAX)
-                        return -EINVAL;
-
-                return 0;
-        }
-
-        input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
-        if (!input)
-                return -ENOMEM;
-
-        if (idna_to_ascii_4i(input, input_size, buffer, 0) != 0)
-                return -EINVAL;
-
-        l = strlen(buffer);
-
-        /* Verify that the result is not longer than one DNS label. */
-        if (l <= 0 || l > DNS_LABEL_MAX)
-                return -EINVAL;
-        if (l > decoded_max)
-                return -ENOBUFS;
-
-        memcpy(decoded, buffer, l);
-
-        /* If there's room, append a trailing NUL byte, but only then */
-        if (decoded_max > l)
-                decoded[l] = 0;
-
-        return (int) l;
-}
-
-int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
-        size_t input_size, output_size;
-        _cleanup_free_ uint32_t *input = NULL;
-        _cleanup_free_ char *result = NULL;
-        uint32_t *output = NULL;
-        size_t w;
-
-        /* To be invoked after unescaping. Converts an A-label into an U-label. */
-
-        assert(encoded);
-        assert(decoded);
-
-        if (encoded_size <= 0 || encoded_size > DNS_LABEL_MAX)
-                return -EINVAL;
-
-        if (!memory_startswith(encoded, encoded_size, IDNA_ACE_PREFIX))
-                return 0;
-
-        input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
-        if (!input)
-                return -ENOMEM;
-
-        output_size = input_size;
-        output = newa(uint32_t, output_size);
-
-        idna_to_unicode_44i(input, input_size, output, &output_size, 0);
-
-        result = stringprep_ucs4_to_utf8(output, output_size, NULL, &w);
-        if (!result)
-                return -ENOMEM;
-        if (w <= 0)
-                return -EINVAL;
-        if (w > decoded_max)
-                return -ENOBUFS;
-
-        memcpy(decoded, result, w);
-
-        /* Append trailing NUL byte if there's space, but only then. */
-        if (decoded_max > w)
-                decoded[w] = 0;
-
-        return w;
-}
-#endif
-#endif /* NM_IGNORED */
-
-int dns_name_concat(const char *a, const char *b, DNSLabelFlags flags, char **_ret) {
-        _cleanup_free_ char *ret = NULL;
-        size_t n = 0, allocated = 0;
-        const char *p;
-        bool first = true;
-        int r;
-
-        if (a)
-                p = a;
-        else if (b)
-                p = TAKE_PTR(b);
-        else
-                goto finish;
-
-        for (;;) {
-                char label[DNS_LABEL_MAX];
-
-                r = dns_label_unescape(&p, label, sizeof label, flags);
-                if (r < 0)
-                        return r;
-                if (r == 0) {
-                        if (*p != 0)
-                                return -EINVAL;
-
-                        if (b) {
-                                /* Now continue with the second string, if there is one */
-                                p = TAKE_PTR(b);
-                                continue;
-                        }
-
-                        break;
-                }
-
-                if (_ret) {
-                        if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
-                                return -ENOMEM;
-
-                        r = dns_label_escape(label, r, ret + n + !first, DNS_LABEL_ESCAPED_MAX);
-                        if (r < 0)
-                                return r;
-
-                        if (!first)
-                                ret[n] = '.';
-                } else {
-                        char escaped[DNS_LABEL_ESCAPED_MAX];
-
-                        r = dns_label_escape(label, r, escaped, sizeof(escaped));
-                        if (r < 0)
-                                return r;
-                }
-
-                if (!first)
-                        n++;
-                else
-                        first = false;
-
-                n += r;
-        }
-
-finish:
-        if (n > DNS_HOSTNAME_MAX)
-                return -EINVAL;
-
-        if (_ret) {
-                if (n == 0) {
-                        /* Nothing appended? If so, generate at least a single dot, to indicate the DNS root domain */
-                        if (!GREEDY_REALLOC(ret, allocated, 2))
-                                return -ENOMEM;
-
-                        ret[n++] = '.';
-                } else {
-                        if (!GREEDY_REALLOC(ret, allocated, n + 1))
-                                return -ENOMEM;
-                }
-
-                ret[n] = 0;
-                *_ret = TAKE_PTR(ret);
-        }
-
-        return 0;
-}
-
-#if 0 /* NM_IGNORED */
-void dns_name_hash_func(const char *p, struct siphash *state) {
-        int r;
-
-        assert(p);
-
-        for (;;) {
-                char label[DNS_LABEL_MAX+1];
-
-                r = dns_label_unescape(&p, label, sizeof label, 0);
-                if (r < 0)
-                        break;
-                if (r == 0)
-                        break;
-
-                ascii_strlower_n(label, r);
-                siphash24_compress(label, r, state);
-                siphash24_compress_byte(0, state); /* make sure foobar and foo.bar result in different hashes */
-        }
-
-        /* enforce that all names are terminated by the empty label */
-        string_hash_func("", state);
-}
-
-int dns_name_compare_func(const char *a, const char *b) {
-        const char *x, *y;
-        int r, q;
-
-        assert(a);
-        assert(b);
-
-        x = a + strlen(a);
-        y = b + strlen(b);
-
-        for (;;) {
-                char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
-
-                if (x == NULL && y == NULL)
-                        return 0;
-
-                r = dns_label_unescape_suffix(a, &x, la, sizeof(la));
-                q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb));
-                if (r < 0 || q < 0)
-                        return CMP(r, q);
-
-                r = ascii_strcasecmp_nn(la, r, lb, q);
-                if (r != 0)
-                        return r;
-        }
-}
-
-DEFINE_HASH_OPS(dns_name_hash_ops, char, dns_name_hash_func, dns_name_compare_func);
-
-int dns_name_equal(const char *x, const char *y) {
-        int r, q;
-
-        assert(x);
-        assert(y);
-
-        for (;;) {
-                char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
-
-                r = dns_label_unescape(&x, la, sizeof la, 0);
-                if (r < 0)
-                        return r;
-
-                q = dns_label_unescape(&y, lb, sizeof lb, 0);
-                if (q < 0)
-                        return q;
-
-                if (r != q)
-                        return false;
-                if (r == 0)
-                        return true;
-
-                if (ascii_strcasecmp_n(la, lb, r) != 0)
-                        return false;
-        }
-}
-
-int dns_name_endswith(const char *name, const char *suffix) {
-        const char *n, *s, *saved_n = NULL;
-        int r, q;
-
-        assert(name);
-        assert(suffix);
-
-        n = name;
-        s = suffix;
-
-        for (;;) {
-                char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX];
-
-                r = dns_label_unescape(&n, ln, sizeof ln, 0);
-                if (r < 0)
-                        return r;
-
-                if (!saved_n)
-                        saved_n = n;
-
-                q = dns_label_unescape(&s, ls, sizeof ls, 0);
-                if (q < 0)
-                        return q;
-
-                if (r == 0 && q == 0)
-                        return true;
-                if (r == 0 && saved_n == n)
-                        return false;
-
-                if (r != q || ascii_strcasecmp_n(ln, ls, r) != 0) {
-
-                        /* Not the same, let's jump back, and try with the next label again */
-                        s = suffix;
-                        n = TAKE_PTR(saved_n);
-                }
-        }
-}
-
-int dns_name_startswith(const char *name, const char *prefix) {
-        const char *n, *p;
-        int r, q;
-
-        assert(name);
-        assert(prefix);
-
-        n = name;
-        p = prefix;
-
-        for (;;) {
-                char ln[DNS_LABEL_MAX], lp[DNS_LABEL_MAX];
-
-                r = dns_label_unescape(&p, lp, sizeof lp, 0);
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        return true;
-
-                q = dns_label_unescape(&n, ln, sizeof ln, 0);
-                if (q < 0)
-                        return q;
-
-                if (r != q)
-                        return false;
-                if (ascii_strcasecmp_n(ln, lp, r) != 0)
-                        return false;
-        }
-}
-
-int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret) {
-        const char *n, *s, *saved_before = NULL, *saved_after = NULL, *prefix;
-        int r, q;
-
-        assert(name);
-        assert(old_suffix);
-        assert(new_suffix);
-        assert(ret);
-
-        n = name;
-        s = old_suffix;
-
-        for (;;) {
-                char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX];
-
-                if (!saved_before)
-                        saved_before = n;
-
-                r = dns_label_unescape(&n, ln, sizeof ln, 0);
-                if (r < 0)
-                        return r;
-
-                if (!saved_after)
-                        saved_after = n;
-
-                q = dns_label_unescape(&s, ls, sizeof ls, 0);
-                if (q < 0)
-                        return q;
-
-                if (r == 0 && q == 0)
-                        break;
-                if (r == 0 && saved_after == n) {
-                        *ret = NULL; /* doesn't match */
-                        return 0;
-                }
-
-                if (r != q || ascii_strcasecmp_n(ln, ls, r) != 0) {
-
-                        /* Not the same, let's jump back, and try with the next label again */
-                        s = old_suffix;
-                        n = TAKE_PTR(saved_after);
-                        saved_before = NULL;
-                }
-        }
-
-        /* Found it! Now generate the new name */
-        prefix = strndupa(name, saved_before - name);
-
-        r = dns_name_concat(prefix, new_suffix, 0, ret);
-        if (r < 0)
-                return r;
-
-        return 1;
-}
-
-int dns_name_between(const char *a, const char *b, const char *c) {
-        /* Determine if b is strictly greater than a and strictly smaller than c.
-           We consider the order of names to be circular, so that if a is
-           strictly greater than c, we consider b to be between them if it is
-           either greater than a or smaller than c. This is how the canonical
-           DNS name order used in NSEC records work. */
-
-        if (dns_name_compare_func(a, c) < 0)
-                /*
-                   a and c are properly ordered:
-                   a<---b--->c
-                */
-                return dns_name_compare_func(a, b) < 0 &&
-                       dns_name_compare_func(b, c) < 0;
-        else
-                /*
-                   a and c are equal or 'reversed':
-                   <--b--c         a----->
-                   or:
-                   <-----c         a--b-->
-                */
-                return dns_name_compare_func(b, c) < 0 ||
-                       dns_name_compare_func(a, b) < 0;
-}
-
-int dns_name_reverse(int family, const union in_addr_union *a, char **ret) {
-        const uint8_t *p;
-        int r;
-
-        assert(a);
-        assert(ret);
-
-        p = (const uint8_t*) a;
-
-        if (family == AF_INET)
-                r = asprintf(ret, "%u.%u.%u.%u.in-addr.arpa", p[3], p[2], p[1], p[0]);
-        else if (family == AF_INET6)
-                r = asprintf(ret, "%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.ip6.arpa",
-                             hexchar(p[15] & 0xF), hexchar(p[15] >> 4), hexchar(p[14] & 0xF), hexchar(p[14] >> 4),
-                             hexchar(p[13] & 0xF), hexchar(p[13] >> 4), hexchar(p[12] & 0xF), hexchar(p[12] >> 4),
-                             hexchar(p[11] & 0xF), hexchar(p[11] >> 4), hexchar(p[10] & 0xF), hexchar(p[10] >> 4),
-                             hexchar(p[ 9] & 0xF), hexchar(p[ 9] >> 4), hexchar(p[ 8] & 0xF), hexchar(p[ 8] >> 4),
-                             hexchar(p[ 7] & 0xF), hexchar(p[ 7] >> 4), hexchar(p[ 6] & 0xF), hexchar(p[ 6] >> 4),
-                             hexchar(p[ 5] & 0xF), hexchar(p[ 5] >> 4), hexchar(p[ 4] & 0xF), hexchar(p[ 4] >> 4),
-                             hexchar(p[ 3] & 0xF), hexchar(p[ 3] >> 4), hexchar(p[ 2] & 0xF), hexchar(p[ 2] >> 4),
-                             hexchar(p[ 1] & 0xF), hexchar(p[ 1] >> 4), hexchar(p[ 0] & 0xF), hexchar(p[ 0] >> 4));
-        else
-                return -EAFNOSUPPORT;
-        if (r < 0)
-                return -ENOMEM;
-
-        return 0;
-}
-
-int dns_name_address(const char *p, int *family, union in_addr_union *address) {
-        int r;
-
-        assert(p);
-        assert(family);
-        assert(address);
-
-        r = dns_name_endswith(p, "in-addr.arpa");
-        if (r < 0)
-                return r;
-        if (r > 0) {
-                uint8_t a[4];
-                unsigned i;
-
-                for (i = 0; i < ELEMENTSOF(a); i++) {
-                        char label[DNS_LABEL_MAX+1];
-
-                        r = dns_label_unescape(&p, label, sizeof label, 0);
-                        if (r < 0)
-                                return r;
-                        if (r == 0)
-                                return -EINVAL;
-                        if (r > 3)
-                                return -EINVAL;
-
-                        r = safe_atou8(label, &a[i]);
-                        if (r < 0)
-                                return r;
-                }
-
-                r = dns_name_equal(p, "in-addr.arpa");
-                if (r <= 0)
-                        return r;
-
-                *family = AF_INET;
-                address->in.s_addr = htobe32(((uint32_t) a[3] << 24) |
-                                             ((uint32_t) a[2] << 16) |
-                                             ((uint32_t) a[1] << 8) |
-                                              (uint32_t) a[0]);
-
-                return 1;
-        }
-
-        r = dns_name_endswith(p, "ip6.arpa");
-        if (r < 0)
-                return r;
-        if (r > 0) {
-                struct in6_addr a;
-                unsigned i;
-
-                for (i = 0; i < ELEMENTSOF(a.s6_addr); i++) {
-                        char label[DNS_LABEL_MAX+1];
-                        int x, y;
-
-                        r = dns_label_unescape(&p, label, sizeof label, 0);
-                        if (r <= 0)
-                                return r;
-                        if (r != 1)
-                                return -EINVAL;
-                        x = unhexchar(label[0]);
-                        if (x < 0)
-                                return -EINVAL;
-
-                        r = dns_label_unescape(&p, label, sizeof label, 0);
-                        if (r <= 0)
-                                return r;
-                        if (r != 1)
-                                return -EINVAL;
-                        y = unhexchar(label[0]);
-                        if (y < 0)
-                                return -EINVAL;
-
-                        a.s6_addr[ELEMENTSOF(a.s6_addr) - i - 1] = (uint8_t) y << 4 | (uint8_t) x;
-                }
-
-                r = dns_name_equal(p, "ip6.arpa");
-                if (r <= 0)
-                        return r;
-
-                *family = AF_INET6;
-                address->in6 = a;
-                return 1;
-        }
-
-        return 0;
-}
-#endif /* NM_IGNORED */
-
-bool dns_name_is_root(const char *name) {
-
-        assert(name);
-
-        /* There are exactly two ways to encode the root domain name:
-         * as empty string, or with a single dot. */
-
-        return STR_IN_SET(name, "", ".");
-}
-
-bool dns_name_is_single_label(const char *name) {
-        int r;
-
-        assert(name);
-
-        r = dns_name_parent(&name);
-        if (r <= 0)
-                return false;
-
-        return dns_name_is_root(name);
-}
-
-/* Encode a domain name according to RFC 1035 Section 3.1, without compression */
-int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, bool canonical) {
-        uint8_t *label_length, *out;
-        int r;
-
-        assert(domain);
-        assert(buffer);
-
-        out = buffer;
-
-        do {
-                /* Reserve a byte for label length */
-                if (len <= 0)
-                        return -ENOBUFS;
-                len--;
-                label_length = out;
-                out++;
-
-                /* Convert and copy a single label. Note that
-                 * dns_label_unescape() returns 0 when it hits the end
-                 * of the domain name, which we rely on here to encode
-                 * the trailing NUL byte. */
-                r = dns_label_unescape(&domain, (char *) out, len, 0);
-                if (r < 0)
-                        return r;
-
-                /* Optionally, output the name in DNSSEC canonical
-                 * format, as described in RFC 4034, section 6.2. Or
-                 * in other words: in lower-case. */
-                if (canonical)
-                        ascii_strlower_n((char*) out, (size_t) r);
-
-                /* Fill label length, move forward */
-                *label_length = r;
-                out += r;
-                len -= r;
-
-        } while (r != 0);
-
-        /* Verify the maximum size of the encoded name. The trailing
-         * dot + NUL byte account are included this time, hence
-         * compare against DNS_HOSTNAME_MAX + 2 (which is 255) this
-         * time. */
-        if (out - buffer > DNS_HOSTNAME_MAX + 2)
-                return -EINVAL;
-
-        return out - buffer;
-}
-
-#if 0 /* NM_IGNORED */
-static bool srv_type_label_is_valid(const char *label, size_t n) {
-        size_t k;
-
-        assert(label);
-
-        if (n < 2) /* Label needs to be at least 2 chars long */
-                return false;
-
-        if (label[0] != '_') /* First label char needs to be underscore */
-                return false;
-
-        /* Second char must be a letter */
-        if (!(label[1] >= 'A' && label[1] <= 'Z') &&
-            !(label[1] >= 'a' && label[1] <= 'z'))
-                return false;
-
-        /* Third and further chars must be alphanumeric or a hyphen */
-        for (k = 2; k < n; k++) {
-                if (!(label[k] >= 'A' && label[k] <= 'Z') &&
-                    !(label[k] >= 'a' && label[k] <= 'z') &&
-                    !(label[k] >= '0' && label[k] <= '9') &&
-                    label[k] != '-')
-                        return false;
-        }
-
-        return true;
-}
-
-bool dns_srv_type_is_valid(const char *name) {
-        unsigned c = 0;
-        int r;
-
-        if (!name)
-                return false;
-
-        for (;;) {
-                char label[DNS_LABEL_MAX];
-
-                /* This more or less implements RFC 6335, Section 5.1 */
-
-                r = dns_label_unescape(&name, label, sizeof label, 0);
-                if (r < 0)
-                        return false;
-                if (r == 0)
-                        break;
-
-                if (c >= 2)
-                        return false;
-
-                if (!srv_type_label_is_valid(label, r))
-                        return false;
-
-                c++;
-        }
-
-        return c == 2; /* exactly two labels */
-}
-
-bool dnssd_srv_type_is_valid(const char *name) {
-        return dns_srv_type_is_valid(name) &&
-                ((dns_name_endswith(name, "_tcp") > 0) ||
-                 (dns_name_endswith(name, "_udp") > 0)); /* Specific to DNS-SD. RFC 6763, Section 7 */
-}
-
-bool dns_service_name_is_valid(const char *name) {
-        size_t l;
-
-        /* This more or less implements RFC 6763, Section 4.1.1 */
-
-        if (!name)
-                return false;
-
-        if (!utf8_is_valid(name))
-                return false;
-
-        if (string_has_cc(name, NULL))
-                return false;
-
-        l = strlen(name);
-        if (l <= 0)
-                return false;
-        if (l > 63)
-                return false;
-
-        return true;
-}
-
-int dns_service_join(const char *name, const char *type, const char *domain, char **ret) {
-        char escaped[DNS_LABEL_ESCAPED_MAX];
-        _cleanup_free_ char *n = NULL;
-        int r;
-
-        assert(type);
-        assert(domain);
-        assert(ret);
-
-        if (!dns_srv_type_is_valid(type))
-                return -EINVAL;
-
-        if (!name)
-                return dns_name_concat(type, domain, 0, ret);
-
-        if (!dns_service_name_is_valid(name))
-                return -EINVAL;
-
-        r = dns_label_escape(name, strlen(name), escaped, sizeof(escaped));
-        if (r < 0)
-                return r;
-
-        r = dns_name_concat(type, domain, 0, &n);
-        if (r < 0)
-                return r;
-
-        return dns_name_concat(escaped, n, 0, ret);
-}
-
-static bool dns_service_name_label_is_valid(const char *label, size_t n) {
-        char *s;
-
-        assert(label);
-
-        if (memchr(label, 0, n))
-                return false;
-
-        s = strndupa(label, n);
-        return dns_service_name_is_valid(s);
-}
-
-int dns_service_split(const char *joined, char **_name, char **_type, char **_domain) {
-        _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
-        const char *p = joined, *q = NULL, *d = NULL;
-        char a[DNS_LABEL_MAX], b[DNS_LABEL_MAX], c[DNS_LABEL_MAX];
-        int an, bn, cn, r;
-        unsigned x = 0;
-
-        assert(joined);
-
-        /* Get first label from the full name */
-        an = dns_label_unescape(&p, a, sizeof(a), 0);
-        if (an < 0)
-                return an;
-
-        if (an > 0) {
-                x++;
-
-                /* If there was a first label, try to get the second one */
-                bn = dns_label_unescape(&p, b, sizeof(b), 0);
-                if (bn < 0)
-                        return bn;
-
-                if (bn > 0) {
-                        x++;
-
-                        /* If there was a second label, try to get the third one */
-                        q = p;
-                        cn = dns_label_unescape(&p, c, sizeof(c), 0);
-                        if (cn < 0)
-                                return cn;
-
-                        if (cn > 0)
-                                x++;
-                } else
-                        cn = 0;
-        } else
-                an = 0;
-
-        if (x >= 2 && srv_type_label_is_valid(b, bn)) {
-
-                if (x >= 3 && srv_type_label_is_valid(c, cn)) {
-
-                        if (dns_service_name_label_is_valid(a, an)) {
-                                /* OK, got <name> . <type> . <type2> . <domain> */
-
-                                name = strndup(a, an);
-                                if (!name)
-                                        return -ENOMEM;
-
-                                type = strjoin(b, ".", c);
-                                if (!type)
-                                        return -ENOMEM;
-
-                                d = p;
-                                goto finish;
-                        }
-
-                } else if (srv_type_label_is_valid(a, an)) {
-
-                        /* OK, got <type> . <type2> . <domain> */
-
-                        name = NULL;
-
-                        type = strjoin(a, ".", b);
-                        if (!type)
-                                return -ENOMEM;
-
-                        d = q;
-                        goto finish;
-                }
-        }
-
-        name = NULL;
-        type = NULL;
-        d = joined;
-
-finish:
-        r = dns_name_normalize(d, 0, &domain);
-        if (r < 0)
-                return r;
-
-        if (_domain)
-                *_domain = TAKE_PTR(domain);
-
-        if (_type)
-                *_type = TAKE_PTR(type);
-
-        if (_name)
-                *_name = TAKE_PTR(name);
-
-        return 0;
-}
-
-static int dns_name_build_suffix_table(const char *name, const char *table[]) {
-        const char *p;
-        unsigned n = 0;
-        int r;
-
-        assert(name);
-        assert(table);
-
-        p = name;
-        for (;;) {
-                if (n > DNS_N_LABELS_MAX)
-                        return -EINVAL;
-
-                table[n] = p;
-                r = dns_name_parent(&p);
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        break;
-
-                n++;
-        }
-
-        return (int) n;
-}
-
-int dns_name_suffix(const char *name, unsigned n_labels, const char **ret) {
-        const char* labels[DNS_N_LABELS_MAX+1];
-        int n;
-
-        assert(name);
-        assert(ret);
-
-        n = dns_name_build_suffix_table(name, labels);
-        if (n < 0)
-                return n;
-
-        if ((unsigned) n < n_labels)
-                return -EINVAL;
-
-        *ret = labels[n - n_labels];
-        return (int) (n - n_labels);
-}
-
-int dns_name_skip(const char *a, unsigned n_labels, const char **ret) {
-        int r;
-
-        assert(a);
-        assert(ret);
-
-        for (; n_labels > 0; n_labels--) {
-                r = dns_name_parent(&a);
-                if (r < 0)
-                        return r;
-                if (r == 0) {
-                        *ret = "";
-                        return 0;
-                }
-        }
-
-        *ret = a;
-        return 1;
-}
-
-int dns_name_count_labels(const char *name) {
-        unsigned n = 0;
-        const char *p;
-        int r;
-
-        assert(name);
-
-        p = name;
-        for (;;) {
-                r = dns_name_parent(&p);
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        break;
-
-                if (n >= DNS_N_LABELS_MAX)
-                        return -EINVAL;
-
-                n++;
-        }
-
-        return (int) n;
-}
-
-int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b) {
-        int r;
-
-        assert(a);
-        assert(b);
-
-        r = dns_name_skip(a, n_labels, &a);
-        if (r <= 0)
-                return r;
-
-        return dns_name_equal(a, b);
-}
-
-int dns_name_common_suffix(const char *a, const char *b, const char **ret) {
-        const char *a_labels[DNS_N_LABELS_MAX+1], *b_labels[DNS_N_LABELS_MAX+1];
-        int n = 0, m = 0, k = 0, r, q;
-
-        assert(a);
-        assert(b);
-        assert(ret);
-
-        /* Determines the common suffix of domain names a and b */
-
-        n = dns_name_build_suffix_table(a, a_labels);
-        if (n < 0)
-                return n;
-
-        m = dns_name_build_suffix_table(b, b_labels);
-        if (m < 0)
-                return m;
-
-        for (;;) {
-                char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
-                const char *x, *y;
-
-                if (k >= n || k >= m) {
-                        *ret = a_labels[n - k];
-                        return 0;
-                }
-
-                x = a_labels[n - 1 - k];
-                r = dns_label_unescape(&x, la, sizeof la, 0);
-                if (r < 0)
-                        return r;
-
-                y = b_labels[m - 1 - k];
-                q = dns_label_unescape(&y, lb, sizeof lb, 0);
-                if (q < 0)
-                        return q;
-
-                if (r != q || ascii_strcasecmp_n(la, lb, r) != 0) {
-                        *ret = a_labels[n - k];
-                        return 0;
-                }
-
-                k++;
-        }
-}
-
-int dns_name_apply_idna(const char *name, char **ret) {
-        /* Return negative on error, 0 if not implemented, positive on success. */
-
-#if HAVE_LIBIDN2
-        int r;
-        _cleanup_free_ char *t = NULL;
-
-        assert(name);
-        assert(ret);
-
-        r = idn2_lookup_u8((uint8_t*) name, (uint8_t**) &t,
-                           IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL);
-        log_debug("idn2_lookup_u8: %s → %s", name, t);
-        if (r == IDN2_OK) {
-                if (!startswith(name, "xn--")) {
-                        _cleanup_free_ char *s = NULL;
-
-                        r = idn2_to_unicode_8z8z(t, &s, 0);
-                        if (r != IDN2_OK) {
-                                log_debug("idn2_to_unicode_8z8z(\"%s\") failed: %d/%s",
-                                          t, r, idn2_strerror(r));
-                                return 0;
-                        }
-
-                        if (!streq_ptr(name, s)) {
-                                log_debug("idn2 roundtrip failed: \"%s\" → \"%s\" → \"%s\", ignoring.",
-                                          name, t, s);
-                                return 0;
-                        }
-                }
-
-                *ret = TAKE_PTR(t);
-
-                return 1; /* *ret has been written */
-        }
-
-        log_debug("idn2_lookup_u8(\"%s\") failed: %d/%s", name, r, idn2_strerror(r));
-        if (r == IDN2_2HYPHEN)
-                /* The name has two hyphens — forbidden by IDNA2008 in some cases */
-                return 0;
-        if (IN_SET(r, IDN2_TOO_BIG_DOMAIN, IDN2_TOO_BIG_LABEL))
-                return -ENOSPC;
-        return -EINVAL;
-#elif HAVE_LIBIDN
-        _cleanup_free_ char *buf = NULL;
-        size_t n = 0, allocated = 0;
-        bool first = true;
-        int r, q;
-
-        assert(name);
-        assert(ret);
-
-        for (;;) {
-                char label[DNS_LABEL_MAX];
-
-                r = dns_label_unescape(&name, label, sizeof label, 0);
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        break;
-
-                q = dns_label_apply_idna(label, r, label, sizeof label);
-                if (q < 0)
-                        return q;
-                if (q > 0)
-                        r = q;
-
-                if (!GREEDY_REALLOC(buf, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
-                        return -ENOMEM;
-
-                r = dns_label_escape(label, r, buf + n + !first, DNS_LABEL_ESCAPED_MAX);
-                if (r < 0)
-                        return r;
-
-                if (first)
-                        first = false;
-                else
-                        buf[n++] = '.';
-
-                n += r;
-        }
-
-        if (n > DNS_HOSTNAME_MAX)
-                return -EINVAL;
-
-        if (!GREEDY_REALLOC(buf, allocated, n + 1))
-                return -ENOMEM;
-
-        buf[n] = 0;
-        *ret = TAKE_PTR(buf);
-
-        return 1;
-#else
-        return 0;
-#endif
-}
-
-int dns_name_is_valid_or_address(const char *name) {
-        /* Returns > 0 if the specified name is either a valid IP address formatted as string or a valid DNS name */
-
-        if (isempty(name))
-                return 0;
-
-        if (in_addr_from_string_auto(name, NULL, NULL) >= 0)
-                return 1;
-
-        return dns_name_is_valid(name);
-}
-#endif /* NM_IGNORED */
diff --git a/src/systemd/src/shared/dns-domain.h b/src/systemd/src/shared/dns-domain.h
deleted file mode 100644
index 17db7c52..00000000
--- a/src/systemd/src/shared/dns-domain.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-#pragma once
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include "hashmap.h"
-#include "in-addr-util.h"
-
-/* Length of a single label, with all escaping removed, excluding any trailing dot or NUL byte */
-#define DNS_LABEL_MAX 63
-
-/* Worst case length of a single label, with all escaping applied and room for a trailing NUL byte. */
-#define DNS_LABEL_ESCAPED_MAX (DNS_LABEL_MAX*4+1)
-
-/* Maximum length of a full hostname, consisting of a series of unescaped labels, and no trailing dot or NUL byte */
-#define DNS_HOSTNAME_MAX 253
-
-/* Maximum length of a full hostname, on the wire, including the final NUL byte */
-#define DNS_WIRE_FORMAT_HOSTNAME_MAX 255
-
-/* Maximum number of labels per valid hostname */
-#define DNS_N_LABELS_MAX 127
-
-typedef enum DNSLabelFlags {
-        DNS_LABEL_LDH        = 1 << 0, /* Follow the "LDH" rule — only letters, digits, and internal hyphens. */
-        DNS_LABEL_NO_ESCAPES = 1 << 1, /* Do not treat backslashes specially */
-} DNSLabelFlags;
-
-int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags flags);
-int dns_label_unescape_suffix(const char *name, const char **label_end, char *dest, size_t sz);
-int dns_label_escape(const char *p, size_t l, char *dest, size_t sz);
-int dns_label_escape_new(const char *p, size_t l, char **ret);
-
-static inline int dns_name_parent(const char **name) {
-        return dns_label_unescape(name, NULL, DNS_LABEL_MAX, 0);
-}
-
-#if 0 /* NM_IGNORED */
-#if HAVE_LIBIDN
-int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
-int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
-#endif
-#endif /* NM_IGNORED */
-
-int dns_name_concat(const char *a, const char *b, DNSLabelFlags flags, char **ret);
-
-static inline int dns_name_normalize(const char *s, DNSLabelFlags flags, char **ret) {
-        /* dns_name_concat() normalizes as a side-effect */
-        return dns_name_concat(s, NULL, flags, ret);
-}
-
-static inline int dns_name_is_valid(const char *s) {
-        int r;
-
-        /* dns_name_normalize() verifies as a side effect */
-        r = dns_name_normalize(s, 0, NULL);
-        if (r == -EINVAL)
-                return 0;
-        if (r < 0)
-                return r;
-        return 1;
-}
-
-static inline int dns_name_is_valid_ldh(const char *s) {
-        int r;
-
-        r = dns_name_concat(s, NULL, DNS_LABEL_LDH|DNS_LABEL_NO_ESCAPES, NULL);
-        if (r == -EINVAL)
-                return 0;
-        if (r < 0)
-                return r;
-        return 1;
-}
-
-void dns_name_hash_func(const char *s, struct siphash *state);
-int dns_name_compare_func(const char *a, const char *b);
-extern const struct hash_ops dns_name_hash_ops;
-
-int dns_name_between(const char *a, const char *b, const char *c);
-int dns_name_equal(const char *x, const char *y);
-int dns_name_endswith(const char *name, const char *suffix);
-int dns_name_startswith(const char *name, const char *prefix);
-
-int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret);
-
-int dns_name_reverse(int family, const union in_addr_union *a, char **ret);
-int dns_name_address(const char *p, int *family, union in_addr_union *a);
-
-bool dns_name_is_root(const char *name);
-bool dns_name_is_single_label(const char *name);
-
-int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, bool canonical);
-
-bool dns_srv_type_is_valid(const char *name);
-bool dnssd_srv_type_is_valid(const char *name);
-bool dns_service_name_is_valid(const char *name);
-
-int dns_service_join(const char *name, const char *type, const char *domain, char **ret);
-int dns_service_split(const char *joined, char **name, char **type, char **domain);
-
-int dns_name_suffix(const char *name, unsigned n_labels, const char **ret);
-int dns_name_count_labels(const char *name);
-
-int dns_name_skip(const char *a, unsigned n_labels, const char **ret);
-int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b);
-
-int dns_name_common_suffix(const char *a, const char *b, const char **ret);
-
-int dns_name_apply_idna(const char *name, char **ret);
-
-int dns_name_is_valid_or_address(const char *name);
diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h
index bd0d429d..ab62368e 100644
--- a/src/systemd/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/src/systemd/sd-dhcp-client.h
@@ -38,6 +38,7 @@ enum {
         SD_DHCP_CLIENT_EVENT_IP_CHANGE          = 2,
         SD_DHCP_CLIENT_EVENT_EXPIRED            = 3,
         SD_DHCP_CLIENT_EVENT_RENEW              = 4,
+        SD_DHCP_CLIENT_EVENT_SELECTING          = 5,
 };
 
 enum {
@@ -98,7 +99,7 @@ enum {
 
 typedef struct sd_dhcp_client sd_dhcp_client;
 
-typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
+typedef int (*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,
@@ -154,6 +155,9 @@ int sd_dhcp_client_get_client_id(
 int sd_dhcp_client_set_mtu(
                 sd_dhcp_client *client,
                 uint32_t mtu);
+int sd_dhcp_client_set_max_attempts(
+                sd_dhcp_client *client,
+                uint64_t attempt);
 int sd_dhcp_client_set_client_port(
                 sd_dhcp_client *client,
                 uint16_t port);
@@ -172,6 +176,7 @@ int sd_dhcp_client_get_lease(
 
 int sd_dhcp_client_stop(sd_dhcp_client *client);
 int sd_dhcp_client_start(sd_dhcp_client *client);
+int sd_dhcp_client_send_release(sd_dhcp_client *client);
 
 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client);
 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);
diff --git a/src/systemd/src/systemd/sd-event.h b/src/systemd/src/systemd/sd-event.h
index 7bb86093..b14c9269 100644
--- a/src/systemd/src/systemd/sd-event.h
+++ b/src/systemd/src/systemd/sd-event.h
@@ -113,6 +113,7 @@ 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);
+sd_event_source* sd_event_source_disable_unref(sd_event_source *s);
 
 sd_event *sd_event_source_get_event(sd_event_source *s);
 void* sd_event_source_get_userdata(sd_event_source *s);
@@ -149,6 +150,7 @@ int sd_event_source_set_floating(sd_event_source *s, int b);
 /* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_disable_unref);
 
 _SD_END_DECLARATIONS;
 
diff --git a/src/systemd/src/systemd/sd-id128.h b/src/systemd/src/systemd/sd-id128.h
index c5fbe0a4..9b00b76e 100644
--- a/src/systemd/src/systemd/sd-id128.h
+++ b/src/systemd/src/systemd/sd-id128.h
@@ -54,7 +54,6 @@ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret);
 #define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \
         ((const sd_id128_t) SD_ID128_ARRAY(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15))
 
-
 /* Note that SD_ID128_FORMAT_VAL will evaluate the passed argument 16
  * times. It is hence not a good idea to call this macro with an
  * expensive function as parameter or an expression with side