summary refs log tree commit diff
path: root/src/libnm-systemd-core
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnm-systemd-core')
-rw-r--r--src/libnm-systemd-core/meson.build8
-rw-r--r--src/libnm-systemd-core/nm-sd-utils-dhcp.c40
-rw-r--r--src/libnm-systemd-core/nm-sd-utils-dhcp.h19
-rw-r--r--src/libnm-systemd-core/nm-sd.c1
-rw-r--r--src/libnm-systemd-core/nm-sd.h12
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/arp-util.c142
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/arp-util.h36
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c58
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h7
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h84
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-lease-internal.h90
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-network.c257
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-option.c443
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-packet.c196
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp-protocol.h108
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h3
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c30
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.c6
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/network-internal.c243
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/network-internal.h31
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c2285
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-lease.c1508
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c127
-rw-r--r--src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c40
-rw-r--r--src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c14
-rw-r--r--src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h5
-rw-r--r--src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c164
-rw-r--r--src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c28
-rw-r--r--src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.h2
-rw-r--r--src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c26
-rw-r--r--src/libnm-systemd-core/src/systemd/_sd-common.h4
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-dhcp-client.h345
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-dhcp-lease.h91
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-dhcp-option.h38
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h17
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h2
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-dhcp6-option.h2
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-event.h2
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-id128.h6
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-lldp-rx.h6
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-lldp.h14
-rw-r--r--src/libnm-systemd-core/src/systemd/sd-ndisc.h11
42 files changed, 321 insertions, 6230 deletions
diff --git a/src/libnm-systemd-core/meson.build b/src/libnm-systemd-core/meson.build
index 8bbc02a7..70293a61 100644
--- a/src/libnm-systemd-core/meson.build
+++ b/src/libnm-systemd-core/meson.build
@@ -3,20 +3,13 @@
 libnm_systemd_core = static_library(
   'nm-systemd-core',
   sources: files(
-    'src/libsystemd-network/arp-util.c',
     'src/libsystemd-network/dhcp-identifier.c',
-    'src/libsystemd-network/dhcp-network.c',
-    'src/libsystemd-network/dhcp-option.c',
-    'src/libsystemd-network/dhcp-packet.c',
     'src/libsystemd-network/dhcp6-network.c',
     'src/libsystemd-network/dhcp6-option.c',
     'src/libsystemd-network/dhcp6-protocol.c',
     'src/libsystemd-network/lldp-neighbor.c',
     'src/libsystemd-network/lldp-network.c',
     'src/libsystemd-network/network-common.c',
-    'src/libsystemd-network/network-internal.c',
-    'src/libsystemd-network/sd-dhcp-client.c',
-    'src/libsystemd-network/sd-dhcp-lease.c',
     'src/libsystemd-network/sd-dhcp6-client.c',
     'src/libsystemd-network/sd-dhcp6-lease.c',
     'src/libsystemd-network/sd-lldp-rx.c',
@@ -25,7 +18,6 @@ libnm_systemd_core = static_library(
     'src/libsystemd/sd-id128/id128-util.c',
     'src/libsystemd/sd-id128/sd-id128.c',
     'nm-sd.c',
-    'nm-sd-utils-dhcp.c',
     'sd-adapt-core/nm-sd-adapt-core.c',
   ),
   include_directories: [
diff --git a/src/libnm-systemd-core/nm-sd-utils-dhcp.c b/src/libnm-systemd-core/nm-sd-utils-dhcp.c
deleted file mode 100644
index 13c75055..00000000
--- a/src/libnm-systemd-core/nm-sd-utils-dhcp.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2019 Red Hat, Inc.
- */
-
-#include "libnm-systemd-core/nm-default-systemd-core.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)
-{
-    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/libnm-systemd-core/nm-sd-utils-dhcp.h b/src/libnm-systemd-core/nm-sd-utils-dhcp.h
deleted file mode 100644
index 6487a90d..00000000
--- a/src/libnm-systemd-core/nm-sd-utils-dhcp.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 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/libnm-systemd-core/nm-sd.c b/src/libnm-systemd-core/nm-sd.c
index 9978a159..b512e3fc 100644
--- a/src/libnm-systemd-core/nm-sd.c
+++ b/src/libnm-systemd-core/nm-sd.c
@@ -108,6 +108,5 @@ nm_sd_event_attach_default(void)
 /* ensure that defines in nm-sd.h correspond to the internal defines. */
 
 #include "nm-sd-adapt-core.h"
-#include "dhcp-lease-internal.h"
 
 /*****************************************************************************/
diff --git a/src/libnm-systemd-core/nm-sd.h b/src/libnm-systemd-core/nm-sd.h
index 421f5372..79bc5031 100644
--- a/src/libnm-systemd-core/nm-sd.h
+++ b/src/libnm-systemd-core/nm-sd.h
@@ -6,7 +6,6 @@
 #ifndef __NM_SD_H__
 #define __NM_SD_H__
 
-#include "src/systemd/sd-dhcp-client.h"
 #include "src/systemd/sd-dhcp6-client.h"
 #include "src/systemd/sd-lldp-rx.h"
 
@@ -14,15 +13,4 @@
 
 guint nm_sd_event_attach_default(void);
 
-/*****************************************************************************
- * expose internal systemd API
- *
- * FIXME: don't use any internal systemd API.
- *****************************************************************************/
-
-struct sd_dhcp_lease;
-
-int dhcp_lease_save(struct sd_dhcp_lease *lease, const char *lease_file);
-int dhcp_lease_load(struct sd_dhcp_lease **ret, const char *lease_file);
-
 #endif /* __NM_SD_H__ */
diff --git a/src/libnm-systemd-core/src/libsystemd-network/arp-util.c b/src/libnm-systemd-core/src/libsystemd-network/arp-util.c
deleted file mode 100644
index c8a73111..00000000
--- a/src/libnm-systemd-core/src/libsystemd-network/arp-util.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/***
-  Copyright © 2014 Axis Communications AB. All rights reserved.
-***/
-
-#include "nm-sd-adapt-core.h"
-
-#include <arpa/inet.h>
-#include <linux/filter.h>
-#include <netinet/if_ether.h>
-
-#include "arp-util.h"
-#include "ether-addr-util.h"
-#include "fd-util.h"
-#include "in-addr-util.h"
-#include "unaligned.h"
-#include "util.h"
-
-int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr *mac) {
-        struct sock_filter filter[] = {
-                BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0),                                         /* A <- packet length */
-                BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ether_arp), 1, 0),           /* packet >= arp packet ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                                  /* ignore */
-                BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_hrd)), /* A <- header */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPHRD_ETHER, 1, 0),                       /* header == ethernet ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                                  /* ignore */
-                BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_pro)), /* A <- protocol */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 1, 0),                       /* protocol == IP ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                                  /* ignore */
-                BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_hln)), /* A <- hardware address length */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, sizeof(struct ether_addr), 1, 0),          /* length == sizeof(ether_addr)? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                                  /* ignore */
-                BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_pln)), /* A <- protocol address length */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, sizeof(struct in_addr), 1, 0),             /* length == sizeof(in_addr) ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                                  /* ignore */
-                BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_op)),  /* A <- operation */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REQUEST, 2, 0),                      /* protocol == request ? */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 1, 0),                        /* protocol == reply ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                                  /* ignore */
-                /* Sender Hardware Address must be different from our own */
-                BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be32(&mac->ether_addr_octet[0])),   /* X <- 4 bytes of client's MAC */
-                BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_sha)),       /* A <- 4 bytes of SHA */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 0, 4),                                  /* A == X ? */
-                BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be16(&mac->ether_addr_octet[4])),   /* X <- remainder of client's MAC */
-                BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, arp_sha) + 4),   /* A <- remainder of SHA */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 0, 1),                                  /* A == X ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                                  /* ignore */
-                /* Sender Protocol Address or Target Protocol Address must be equal to the one we care about */
-                BPF_STMT(BPF_LDX + BPF_IMM, htobe32(a->s_addr)),                               /* X <- clients IP */
-                BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_spa)),       /* A <- SPA */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 0, 1),                                  /* A == X ? */
-                BPF_STMT(BPF_RET + BPF_K, UINT32_MAX),                                         /* accept */
-                BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_tpa)),       /* A <- TPA */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 0, 1),                                  /* A == 0 ? */
-                BPF_STMT(BPF_RET + BPF_K, UINT32_MAX),                                         /* accept */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                                  /* ignore */
-        };
-        struct sock_fprog fprog = {
-                .len    = ELEMENTSOF(filter),
-                .filter = (struct sock_filter*) filter,
-        };
-
-        assert(fd >= 0);
-
-        if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) < 0)
-                return -errno;
-
-        return 0;
-}
-
-int arp_network_bind_raw_socket(int ifindex, const struct in_addr *a, const struct ether_addr *mac) {
-        union sockaddr_union link = {
-                .ll.sll_family   = AF_PACKET,
-                .ll.sll_protocol = htobe16(ETH_P_ARP),
-                .ll.sll_ifindex  = ifindex,
-                .ll.sll_halen    = ETH_ALEN,
-                .ll.sll_addr     = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
-        };
-        _cleanup_close_ int s = -1;
-        int r;
-
-        assert(ifindex > 0);
-        assert(mac);
-
-        s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
-        if (s < 0)
-                return -errno;
-
-        r = arp_update_filter(s, a, mac);
-        if (r < 0)
-                return r;
-
-        if (bind(s, &link.sa, sizeof(link.ll)) < 0)
-                return -errno;
-
-        return TAKE_FD(s);
-}
-
-int arp_send_packet(
-                int fd,
-                int ifindex,
-                const struct in_addr *pa,
-                const struct ether_addr *ha,
-                bool announce) {
-
-        union sockaddr_union link = {
-                .ll.sll_family   = AF_PACKET,
-                .ll.sll_protocol = htobe16(ETH_P_ARP),
-                .ll.sll_ifindex  = ifindex,
-                .ll.sll_halen    = ETH_ALEN,
-                .ll.sll_addr     = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
-        };
-        struct ether_arp arp = {
-                .ea_hdr.ar_hrd = htobe16(ARPHRD_ETHER),  /* HTYPE */
-                .ea_hdr.ar_pro = htobe16(ETHERTYPE_IP),  /* PTYPE */
-                .ea_hdr.ar_hln = ETH_ALEN,               /* HLEN */
-                .ea_hdr.ar_pln = sizeof(struct in_addr), /* PLEN */
-                .ea_hdr.ar_op  = htobe16(ARPOP_REQUEST), /* REQUEST */
-        };
-        ssize_t n;
-
-        assert(fd >= 0);
-        assert(ifindex > 0);
-        assert(pa);
-        assert(in4_addr_is_set(pa));
-        assert(ha);
-        assert(!ether_addr_is_null(ha));
-
-        memcpy(&arp.arp_sha, ha, ETH_ALEN);
-        memcpy(&arp.arp_tpa, pa, sizeof(struct in_addr));
-
-        if (announce)
-                memcpy(&arp.arp_spa, pa, sizeof(struct in_addr));
-
-        n = sendto(fd, &arp, sizeof(struct ether_arp), 0, &link.sa, sizeof(link.ll));
-        if (n < 0)
-                return -errno;
-        if (n != sizeof(struct ether_arp))
-                return -EIO;
-
-        return 0;
-}
diff --git a/src/libnm-systemd-core/src/libsystemd-network/arp-util.h b/src/libnm-systemd-core/src/libsystemd-network/arp-util.h
deleted file mode 100644
index b66a81bf..00000000
--- a/src/libnm-systemd-core/src/libsystemd-network/arp-util.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-/***
-  Copyright © 2014 Axis Communications AB. All rights reserved.
-***/
-
-#include <net/ethernet.h>
-#include <netinet/in.h>
-
-#include "socket-util.h"
-#include "sparse-endian.h"
-
-int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr *mac);
-int arp_network_bind_raw_socket(int ifindex, const struct in_addr *a, const struct ether_addr *mac);
-
-int arp_send_packet(
-                int fd,
-                int ifindex,
-                const struct in_addr *pa,
-                const struct ether_addr *ha,
-                bool announce);
-static inline int arp_send_probe(
-                int fd,
-                int ifindex,
-                const struct in_addr *pa,
-                const struct ether_addr *ha) {
-        return arp_send_packet(fd, ifindex, pa, ha, false);
-}
-static inline int arp_send_announcement(
-                int fd,
-                int ifindex,
-                const struct in_addr *pa,
-                const struct ether_addr *ha) {
-        return arp_send_packet(fd, ifindex, pa, ha, true);
-}
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c
index f2d94214..2636d796 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c
+++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c
@@ -13,7 +13,6 @@
 #include "netif-util.h"
 #include "siphash24.h"
 #include "sparse-endian.h"
-#include "stat-util.h"
 #include "string-table.h"
 #include "udev-util.h"
 
@@ -67,20 +66,26 @@ int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict) {
 }
 
 #if 0 /* NM_IGNORED */
-static int dhcp_identifier_set_duid_llt(const uint8_t *addr, size_t addr_len, uint16_t arp_type, usec_t t, struct duid *ret_duid, size_t *ret_len) {
+static int dhcp_identifier_set_duid_llt(
+                const struct hw_addr_data *hw_addr,
+                uint16_t arp_type,
+                usec_t t,
+                struct duid *ret_duid,
+                size_t *ret_len) {
+
         uint16_t time_from_2000y;
 
-        assert(addr);
+        assert(hw_addr);
         assert(ret_duid);
         assert(ret_len);
 
-        if (addr_len == 0)
+        if (hw_addr->length == 0)
                 return -EOPNOTSUPP;
 
         if (arp_type == ARPHRD_ETHER)
-                assert_return(addr_len == ETH_ALEN, -EINVAL);
+                assert_return(hw_addr->length == ETH_ALEN, -EINVAL);
         else if (arp_type == ARPHRD_INFINIBAND)
-                assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
+                assert_return(hw_addr->length == INFINIBAND_ALEN, -EINVAL);
         else
                 return -EOPNOTSUPP;
 
@@ -92,33 +97,38 @@ static int dhcp_identifier_set_duid_llt(const uint8_t *addr, size_t addr_len, ui
         unaligned_write_be16(&ret_duid->type, DUID_TYPE_LLT);
         unaligned_write_be16(&ret_duid->llt.htype, arp_type);
         unaligned_write_be32(&ret_duid->llt.time, time_from_2000y);
-        memcpy(ret_duid->llt.haddr, addr, addr_len);
+        memcpy(ret_duid->llt.haddr, hw_addr->bytes, hw_addr->length);
 
-        *ret_len = offsetof(struct duid, llt.haddr) + addr_len;
+        *ret_len = offsetof(struct duid, llt.haddr) + hw_addr->length;
 
         return 0;
 }
 
-static int dhcp_identifier_set_duid_ll(const uint8_t *addr, size_t addr_len, uint16_t arp_type, struct duid *ret_duid, size_t *ret_len) {
-        assert(addr);
+static int dhcp_identifier_set_duid_ll(
+                const struct hw_addr_data *hw_addr,
+                uint16_t arp_type,
+                struct duid *ret_duid,
+                size_t *ret_len) {
+
+        assert(hw_addr);
         assert(ret_duid);
         assert(ret_len);
 
-        if (addr_len == 0)
+        if (hw_addr->length == 0)
                 return -EOPNOTSUPP;
 
         if (arp_type == ARPHRD_ETHER)
-                assert_return(addr_len == ETH_ALEN, -EINVAL);
+                assert_return(hw_addr->length == ETH_ALEN, -EINVAL);
         else if (arp_type == ARPHRD_INFINIBAND)
-                assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
+                assert_return(hw_addr->length == INFINIBAND_ALEN, -EINVAL);
         else
                 return -EOPNOTSUPP;
 
         unaligned_write_be16(&ret_duid->type, DUID_TYPE_LL);
         unaligned_write_be16(&ret_duid->ll.htype, arp_type);
-        memcpy(ret_duid->ll.haddr, addr, addr_len);
+        memcpy(ret_duid->ll.haddr, hw_addr->bytes, hw_addr->length);
 
-        *ret_len = offsetof(struct duid, ll.haddr) + addr_len;
+        *ret_len = offsetof(struct duid, ll.haddr) + hw_addr->length;
 
         return 0;
 }
@@ -180,8 +190,7 @@ static int dhcp_identifier_set_duid_uuid(struct duid *ret_duid, size_t *ret_len)
 
 int dhcp_identifier_set_duid(
                 DUIDType duid_type,
-                const uint8_t *addr,
-                size_t addr_len,
+                const struct hw_addr_data *hw_addr,
                 uint16_t arp_type,
                 usec_t llt_time,
                 bool test_mode,
@@ -190,11 +199,11 @@ int dhcp_identifier_set_duid(
 
         switch (duid_type) {
         case DUID_TYPE_LLT:
-                return dhcp_identifier_set_duid_llt(addr, addr_len, arp_type, llt_time, ret_duid, ret_len);
+                return dhcp_identifier_set_duid_llt(hw_addr, arp_type, llt_time, ret_duid, ret_len);
         case DUID_TYPE_EN:
                 return dhcp_identifier_set_duid_en(test_mode, ret_duid, ret_len);
         case DUID_TYPE_LL:
-                return dhcp_identifier_set_duid_ll(addr, addr_len, arp_type, ret_duid, ret_len);
+                return dhcp_identifier_set_duid_ll(hw_addr, arp_type, ret_duid, ret_len);
         case DUID_TYPE_UUID:
                 return dhcp_identifier_set_duid_uuid(ret_duid, ret_len);
         default:
@@ -205,8 +214,7 @@ int dhcp_identifier_set_duid(
 
 int dhcp_identifier_set_iaid(
                 int ifindex,
-                const uint8_t *mac,
-                size_t mac_len,
+                const struct hw_addr_data *hw_addr,
                 bool legacy_unstable_byteorder,
                 bool use_mac,
                 void *ret) {
@@ -220,7 +228,11 @@ int dhcp_identifier_set_iaid(
         uint64_t id;
         int r;
 
-        if (path_is_read_only_fs("/sys") <= 0 && !use_mac) {
+        assert(ifindex > 0);
+        assert(hw_addr);
+        assert(ret);
+
+        if (udev_available() && !use_mac) {
                 /* udev should be around */
 
                 r = sd_device_new_from_ifindex(&device, ifindex);
@@ -248,7 +260,7 @@ int dhcp_identifier_set_iaid(
                 id = siphash24(name, strlen(name), HASH_KEY.bytes);
         else
                 /* fall back to MAC address if no predictable name available */
-                id = siphash24(mac, mac_len, HASH_KEY.bytes);
+                id = siphash24(hw_addr->bytes, hw_addr->length, HASH_KEY.bytes);
 
         id32 = (id & 0xffffffff) ^ (id >> 32);
 
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h
index 697ba3bf..8acb8c32 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h
+++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.h
@@ -3,6 +3,7 @@
 
 #include "sd-id128.h"
 
+#include "ether-addr-util.h"
 #include "macro.h"
 #include "sparse-endian.h"
 #include "time-util.h"
@@ -58,8 +59,7 @@ int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict);
 int dhcp_identifier_set_duid_en(bool test_mode, struct duid *ret_duid, size_t *ret_len);
 int dhcp_identifier_set_duid(
                 DUIDType duid_type,
-                const uint8_t *addr,
-                size_t addr_len,
+                const struct hw_addr_data *hw_addr,
                 uint16_t arp_type,
                 usec_t llt_time,
                 bool test_mode,
@@ -67,8 +67,7 @@ int dhcp_identifier_set_duid(
                 size_t *ret_len);
 int dhcp_identifier_set_iaid(
                 int ifindex,
-                const uint8_t *mac,
-                size_t mac_len,
+                const struct hw_addr_data *hw_addr,
                 bool legacy_unstable_byteorder,
                 bool use_mac,
                 void *ret);
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h
deleted file mode 100644
index 466d8e4b..00000000
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-/***
-  Copyright © 2013 Intel Corporation. All rights reserved.
-***/
-
-#include <linux/if_packet.h>
-#include <net/ethernet.h>
-#include <stdint.h>
-
-#include "sd-dhcp-client.h"
-
-#include "dhcp-protocol.h"
-#include "network-common.h"
-#include "socket-util.h"
-
-typedef struct sd_dhcp_option {
-        unsigned n_ref;
-
-        uint8_t option;
-        void *data;
-        size_t length;
-} sd_dhcp_option;
-
-typedef struct DHCPServerData {
-        struct in_addr *addr;
-        size_t size;
-} DHCPServerData;
-
-extern const struct hash_ops dhcp_option_hash_ops;
-
-typedef struct sd_dhcp_client sd_dhcp_client;
-
-int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid,
-                                 const uint8_t *mac_addr, size_t mac_addr_len,
-                                 const uint8_t *bcast_addr, size_t bcast_addr_len,
-                                 uint16_t arp_type, uint16_t port);
-int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type);
-int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
-                                 const void *packet, size_t len);
-int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
-                                 const void *packet, size_t len);
-
-int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_t overload,
-                       uint8_t code, size_t optlen, const void *optval);
-int dhcp_option_find_option(uint8_t *options, size_t length, uint8_t wanted_code, size_t *ret_offset);
-int dhcp_option_remove_option(uint8_t *options, size_t buflen, uint8_t option_code);
-
-typedef int (*dhcp_option_callback_t)(uint8_t code, uint8_t len,
-                                const void *option, void *userdata);
-
-int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t cb, void *userdata, char **error_message);
-
-int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
-                      uint8_t type, uint16_t arp_type, uint8_t hlen, const uint8_t *chaddr,
-                      size_t optlen, size_t *optoffset);
-
-uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len);
-
-void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr,
-                                   uint16_t source, be32_t destination_addr,
-                                   uint16_t destination, uint16_t len, int ip_service_type);
-
-int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port);
-
-void dhcp_client_set_test_mode(sd_dhcp_client *client, bool test_mode);
-
-/* If we are invoking callbacks of a dhcp-client, ensure unreffing the
- * client from the callback doesn't destroy the object we are working
- * on */
-#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_interface_prefix_full_errno(                        \
-                "DHCPv4 client: ",                              \
-                sd_dhcp_client, client,                         \
-                error, fmt, ##__VA_ARGS__)
-#define log_dhcp_client(client, fmt, ...)                       \
-        log_interface_prefix_full_errno_zerook(                 \
-                "DHCPv4 client: ",                              \
-                sd_dhcp_client, client,                         \
-                0, fmt, ##__VA_ARGS__)
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-lease-internal.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp-lease-internal.h
deleted file mode 100644
index c67e9511..00000000
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-lease-internal.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-/***
-  Copyright © 2013 Intel Corporation. All rights reserved.
-***/
-
-#include "sd-dhcp-client.h"
-
-#include "dhcp-internal.h"
-#include "dhcp-protocol.h"
-#include "list.h"
-#include "util.h"
-
-struct sd_dhcp_route {
-        struct in_addr dst_addr;
-        struct in_addr gw_addr;
-        unsigned char dst_prefixlen;
-};
-
-struct sd_dhcp_raw_option {
-        LIST_FIELDS(struct sd_dhcp_raw_option, options);
-
-        uint8_t tag;
-        uint8_t length;
-        void *data;
-};
-
-struct sd_dhcp_lease {
-        unsigned n_ref;
-
-        /* each 0 if unset */
-        uint32_t t1;
-        uint32_t t2;
-        uint32_t lifetime;
-
-        /* each 0 if unset */
-        be32_t address;
-        be32_t server_address;
-        be32_t next_server;
-
-        bool have_subnet_mask;
-        be32_t subnet_mask;
-
-        bool have_broadcast;
-        be32_t broadcast;
-
-        struct in_addr *router;
-        size_t router_size;
-
-        DHCPServerData servers[_SD_DHCP_LEASE_SERVER_TYPE_MAX];
-
-        struct sd_dhcp_route *static_routes;
-        size_t n_static_routes;
-        struct sd_dhcp_route *classless_routes;
-        size_t n_classless_routes;
-
-        uint16_t mtu; /* 0 if unset */
-
-        char *domainname;
-        char **search_domains;
-        char *hostname;
-        char *root_path;
-
-        void *client_id;
-        size_t client_id_len;
-
-        void *vendor_specific;
-        size_t vendor_specific_len;
-
-        char *timezone;
-
-        uint8_t sixrd_ipv4masklen;
-        uint8_t sixrd_prefixlen;
-        struct in6_addr sixrd_prefix;
-        struct in_addr *sixrd_br_addresses;
-        size_t sixrd_n_br_addresses;
-
-        LIST_HEAD(struct sd_dhcp_raw_option, private_options);
-};
-
-int dhcp_lease_new(sd_dhcp_lease **ret);
-
-int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata);
-int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***domains);
-int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len);
-
-int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease);
-
-int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len);
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-network.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp-network.c
deleted file mode 100644
index 1c5f3427..00000000
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-network.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/***
-  Copyright © 2013 Intel Corporation. All rights reserved.
-***/
-
-#include "nm-sd-adapt-core.h"
-
-#include <errno.h>
-#include <net/ethernet.h>
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <stdio.h>
-#include <string.h>
-#include <linux/filter.h>
-#include <linux/if_infiniband.h>
-#include <linux/if_packet.h>
-
-#include "dhcp-internal.h"
-#include "fd-util.h"
-#include "socket-util.h"
-#include "unaligned.h"
-
-static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
-                            uint32_t xid,
-                            const uint8_t *bcast_addr,
-                            size_t bcast_addr_len,
-                            const struct ether_addr *eth_mac,
-                            uint16_t arp_type, uint8_t dhcp_hlen,
-                            uint16_t port) {
-        struct sock_filter filter[] = {
-                BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0),                                 /* A <- packet length */
-                BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 0),         /* packet >= DHCPPacket ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
-                BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, ip.protocol)), /* A <- IP protocol */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 1, 0),                /* IP protocol == UDP ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
-                BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, ip.frag_off)), /* A <- Flags */
-                BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x20),                             /* A <- A & 0x20 (More Fragments bit) */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),                          /* A == 0 ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
-                BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, ip.frag_off)), /* A <- Flags + Fragment offset */
-                BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x1fff),                           /* A <- A & 0x1fff (Fragment offset) */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),                          /* A == 0 ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
-                BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, udp.dest)),    /* A <- UDP destination port */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, port, 1, 0),                       /* UDP destination port == DHCP client port ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
-                BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.op)),     /* A <- DHCP op */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, BOOTREPLY, 1, 0),                  /* op == BOOTREPLY ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
-                BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.htype)),  /* A <- DHCP header type */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arp_type, 1, 0),                   /* header type == arp_type ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
-                BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.xid)),    /* A <- client identifier */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0),                        /* client identifier == xid ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
-                BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.hlen)),   /* A <- MAC address length */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, dhcp_hlen, 1, 0),                  /* address length == dhcp_hlen ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
-
-                /* We only support MAC address length to be either 0 or 6 (ETH_ALEN). Optionally
-                 * compare chaddr for ETH_ALEN bytes. */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_ALEN, 0, 8),                                   /* A (the MAC address length) == ETH_ALEN ? */
-                BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be32(&eth_mac->ether_addr_octet[0])),       /* X <- 4 bytes of client's MAC */
-                BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr)),                 /* A <- 4 bytes of MAC from dhcp.chaddr */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0),                                          /* A == X ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                                          /* ignore */
-                BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be16(&eth_mac->ether_addr_octet[4])),       /* X <- remainder of client's MAC */
-                BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr) + 4),             /* A <- remainder of MAC from dhcp.chaddr */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0),                                          /* A == X ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                                          /* ignore */
-
-                BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.magic)),  /* A <- DHCP magic cookie */
-                BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_MAGIC_COOKIE, 1, 0),          /* cookie == DHCP magic cookie ? */
-                BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
-                BPF_STMT(BPF_RET + BPF_K, UINT32_MAX),                                 /* accept */
-        };
-        struct sock_fprog fprog = {
-                .len = ELEMENTSOF(filter),
-                .filter = filter
-        };
-        _cleanup_close_ int s = -1;
-        int r;
-
-        assert(ifindex > 0);
-        assert(link);
-
-        s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
-        if (s < 0)
-                return -errno;
-
-        r = setsockopt_int(s, SOL_PACKET, PACKET_AUXDATA, true);
-        if (r < 0)
-                return r;
-
-        r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog));
-        if (r < 0)
-                return -errno;
-
-        link->ll = (struct sockaddr_ll) {
-                .sll_family = AF_PACKET,
-                .sll_protocol = htobe16(ETH_P_IP),
-                .sll_ifindex = ifindex,
-                .sll_hatype = htobe16(arp_type),
-                .sll_halen = bcast_addr_len,
-        };
-        memcpy(link->ll.sll_addr, bcast_addr, bcast_addr_len); /* We may overflow link->ll. link->ll_buffer ensures we have enough space. */
-
-        r = bind(s, &link->sa, SOCKADDR_LL_LEN(link->ll));
-        if (r < 0)
-                return -errno;
-
-        return TAKE_FD(s);
-}
-
-int dhcp_network_bind_raw_socket(
-                int ifindex,
-                union sockaddr_union *link,
-                uint32_t xid,
-                const uint8_t *mac_addr,
-                size_t mac_addr_len,
-                const uint8_t *bcast_addr,
-                size_t bcast_addr_len,
-                uint16_t arp_type,
-                uint16_t port) {
-
-        static const uint8_t eth_bcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-        /* Default broadcast address for IPoIB */
-        static const uint8_t ib_bcast[] = {
-                0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x40, 0x1b,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0xff, 0xff, 0xff, 0xff
-        };
-        struct ether_addr eth_mac = { { 0, 0, 0, 0, 0, 0 } };
-        const uint8_t *default_bcast_addr;
-        size_t expected_bcast_addr_len;
-        uint8_t dhcp_hlen = 0;
-
-        if (arp_type == ARPHRD_ETHER) {
-                assert_return(mac_addr_len == ETH_ALEN, -EINVAL);
-                memcpy(&eth_mac, mac_addr, ETH_ALEN);
-                dhcp_hlen = ETH_ALEN;
-
-                default_bcast_addr = eth_bcast;
-                expected_bcast_addr_len = ETH_ALEN;
-        } else if (arp_type == ARPHRD_INFINIBAND) {
-                default_bcast_addr = ib_bcast;
-                expected_bcast_addr_len = INFINIBAND_ALEN;
-        } else
-                return -EINVAL;
-
-        if (bcast_addr && bcast_addr_len > 0)
-                assert_return(bcast_addr_len == expected_bcast_addr_len, -EINVAL);
-        else {
-                bcast_addr = default_bcast_addr;
-                bcast_addr_len = expected_bcast_addr_len;
-        }
-
-        return _bind_raw_socket(ifindex, link, xid, bcast_addr, bcast_addr_len,
-                                &eth_mac, arp_type, dhcp_hlen, port);
-}
-
-int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) {
-        union sockaddr_union src = {
-                .in.sin_family = AF_INET,
-                .in.sin_port = htobe16(port),
-                .in.sin_addr.s_addr = address,
-        };
-        _cleanup_close_ int s = -1;
-        int r;
-
-        s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
-        if (s < 0)
-                return -errno;
-
-        if (ip_service_type >= 0)
-                r = setsockopt_int(s, IPPROTO_IP, IP_TOS, ip_service_type);
-        else
-                r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6);
-        if (r < 0)
-                return r;
-
-        r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
-        if (r < 0)
-                return r;
-
-        if (ifindex > 0) {
-                r = socket_bind_to_ifindex(s, ifindex);
-                if (r < 0)
-                        return r;
-        }
-
-        if (port == DHCP_PORT_SERVER) {
-                r = setsockopt_int(s, SOL_SOCKET, SO_BROADCAST, true);
-                if (r < 0)
-                        return r;
-                if (address == INADDR_ANY) {
-                        /* IP_PKTINFO filter should not be applied when packets are
-                           allowed to enter/leave through the interface other than
-                           DHCP server sits on(BindToInterface option). */
-                        r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
-                        if (r < 0)
-                                return r;
-                }
-        } else {
-                r = setsockopt_int(s, IPPROTO_IP, IP_FREEBIND, true);
-                if (r < 0)
-                        return r;
-        }
-
-        if (bind(s, &src.sa, sizeof(src.in)) < 0)
-                return -errno;
-
-        return TAKE_FD(s);
-}
-
-int dhcp_network_send_raw_socket(
-                int s,
-                const union sockaddr_union *link,
-                const void *packet,
-                size_t len) {
-
-        /* Do not add assert(s >= 0) here, as this is called in fuzz-dhcp-server, and in that case this
-         * function should fail with negative errno. */
-
-        assert(link);
-        assert(packet);
-        assert(len > 0);
-
-        if (sendto(s, packet, len, 0, &link->sa, SOCKADDR_LL_LEN(link->ll)) < 0)
-                return -errno;
-
-        return 0;
-}
-
-int dhcp_network_send_udp_socket(
-                int s,
-                be32_t address,
-                uint16_t port,
-                const void *packet,
-                size_t len) {
-
-        union sockaddr_union dest = {
-                .in.sin_family = AF_INET,
-                .in.sin_port = htobe16(port),
-                .in.sin_addr.s_addr = address,
-        };
-
-        assert(s >= 0);
-        assert(packet);
-        assert(len > 0);
-
-        if (sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in)) < 0)
-                return -errno;
-
-        return 0;
-}
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-option.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp-option.c
deleted file mode 100644
index 712f6097..00000000
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-option.c
+++ /dev/null
@@ -1,443 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/***
-  Copyright © 2013 Intel Corporation. All rights reserved.
-***/
-
-#include "nm-sd-adapt-core.h"
-
-#include <errno.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include "alloc-util.h"
-#include "dhcp-internal.h"
-#include "dhcp-server-internal.h"
-#include "memory-util.h"
-#include "strv.h"
-#include "utf8.h"
-
-/* Append type-length value structure to the options buffer */
-static int dhcp_option_append_tlv(uint8_t options[], size_t size, size_t *offset, uint8_t code, size_t optlen, const void *optval) {
-        assert(options);
-        assert(size > 0);
-        assert(offset);
-        assert(optlen <= UINT8_MAX);
-        assert(*offset < size);
-
-        if (*offset + 2 + optlen > size)
-                return -ENOBUFS;
-
-        options[*offset] = code;
-        options[*offset + 1] = optlen;
-
-        memcpy_safe(&options[*offset + 2], optval, optlen);
-        *offset += 2 + optlen;
-        return 0;
-}
-
-static int option_append(uint8_t options[], size_t size, size_t *offset,
-                         uint8_t code, size_t optlen, const void *optval) {
-        assert(options);
-        assert(size > 0);
-        assert(offset);
-
-        int r;
-
-        if (code != SD_DHCP_OPTION_END)
-                /* always make sure there is space for an END option */
-                size--;
-
-        switch (code) {
-
-        case SD_DHCP_OPTION_PAD:
-        case SD_DHCP_OPTION_END:
-                if (*offset + 1 > size)
-                        return -ENOBUFS;
-
-                options[*offset] = code;
-                *offset += 1;
-                break;
-
-        case SD_DHCP_OPTION_USER_CLASS: {
-                size_t total = 0;
-
-                if (strv_isempty((char **) optval))
-                        return -EINVAL;
-
-                STRV_FOREACH(s, (char **) optval) {
-                        size_t len = strlen(*s);
-
-                        if (len > 255 || len == 0)
-                                return -EINVAL;
-
-                        total += 1 + len;
-                }
-
-                if (*offset + 2 + total > size)
-                        return -ENOBUFS;
-
-                options[*offset] = code;
-                options[*offset + 1] = total;
-                *offset += 2;
-
-                STRV_FOREACH(s, (char **) optval) {
-                        size_t len = strlen(*s);
-
-                        options[*offset] = len;
-                        memcpy(&options[*offset + 1], *s, len);
-                        *offset += 1 + len;
-                }
-
-                break;
-        }
-        case SD_DHCP_OPTION_SIP_SERVER:
-                if (*offset + 3 + optlen > size)
-                        return -ENOBUFS;
-
-                options[*offset] = code;
-                options[*offset + 1] = optlen + 1;
-                options[*offset + 2] = 1;
-
-                memcpy_safe(&options[*offset + 3], optval, optlen);
-                *offset += 3 + optlen;
-
-                break;
-        case SD_DHCP_OPTION_VENDOR_SPECIFIC: {
-                OrderedSet *s = (OrderedSet *) optval;
-                struct sd_dhcp_option *p;
-                size_t l = 0;
-
-                ORDERED_SET_FOREACH(p, s)
-                        l += p->length + 2;
-
-                if (*offset + l + 2 > size)
-                        return -ENOBUFS;
-
-                options[*offset] = code;
-                options[*offset + 1] = l;
-                *offset += 2;
-
-                ORDERED_SET_FOREACH(p, s) {
-                        r = dhcp_option_append_tlv(options, size, offset, p->option, p->length, p->data);
-                        if (r < 0)
-                                return r;
-                }
-                break;
-        }
-        case SD_DHCP_OPTION_RELAY_AGENT_INFORMATION: {
-#if 0 /* NM_IGNORED */
-                sd_dhcp_server *server = (sd_dhcp_server *) optval;
-                size_t current_offset = *offset + 2;
-
-                if (server->agent_circuit_id) {
-                        r = dhcp_option_append_tlv(options, size, &current_offset, SD_DHCP_RELAY_AGENT_CIRCUIT_ID,
-                                                   strlen(server->agent_circuit_id), server->agent_circuit_id);
-                        if (r < 0)
-                                return r;
-                }
-                if (server->agent_remote_id) {
-                        r = dhcp_option_append_tlv(options, size, &current_offset, SD_DHCP_RELAY_AGENT_REMOTE_ID,
-                                                   strlen(server->agent_remote_id), server->agent_remote_id);
-                        if (r < 0)
-                                return r;
-                }
-
-                options[*offset] = code;
-                options[*offset + 1] = current_offset - *offset - 2;
-                assert(current_offset - *offset - 2 <= UINT8_MAX);
-                *offset = current_offset;
-                break;
-#endif /* NM_IGNORED */
-                g_return_val_if_reached(-EINVAL);
-        }
-        default:
-                return dhcp_option_append_tlv(options, size, offset, code, optlen, optval);
-        }
-        return 0;
-}
-
-static int option_length(uint8_t *options, size_t length, size_t offset) {
-        assert(options);
-        assert(offset < length);
-
-        if (IN_SET(options[offset], SD_DHCP_OPTION_PAD, SD_DHCP_OPTION_END))
-                return 1;
-        if (length < offset + 2)
-                return -ENOBUFS;
-
-        /* validating that buffer is long enough */
-        if (length < offset + 2 + options[offset + 1])
-                return -ENOBUFS;
-
-        return options[offset + 1] + 2;
-}
-
-int dhcp_option_find_option(uint8_t *options, size_t length, uint8_t code, size_t *ret_offset) {
-        int r;
-
-        assert(options);
-        assert(ret_offset);
-
-        for (size_t offset = 0; offset < length; offset += r) {
-                r = option_length(options, length, offset);
-                if (r < 0)
-                        return r;
-
-                if (code == options[offset]) {
-                        *ret_offset = offset;
-                        return r;
-                }
-        }
-        return -ENOENT;
-}
-
-int dhcp_option_remove_option(uint8_t *options, size_t length, uint8_t option_code) {
-        int r;
-        size_t offset;
-
-        assert(options);
-
-        r = dhcp_option_find_option(options, length, option_code, &offset);
-        if (r < 0)
-                return r;
-
-        memmove(options + offset, options + offset + r, length - offset - r);
-        return length - r;
-}
-
-int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
-                       uint8_t overload,
-                       uint8_t code, size_t optlen, const void *optval) {
-        const bool use_file = overload & DHCP_OVERLOAD_FILE;
-        const bool use_sname = overload & DHCP_OVERLOAD_SNAME;
-        int r;
-
-        assert(message);
-        assert(offset);
-
-        /* If *offset is in range [0, size), we are writing to ->options,
-         * if *offset is in range [size, size + sizeof(message->file)) and use_file, we are writing to ->file,
-         * if *offset is in range [size + use_file*sizeof(message->file), size + use_file*sizeof(message->file) + sizeof(message->sname))
-         * and use_sname, we are writing to ->sname.
-         */
-
-        if (*offset < size) {
-                /* still space in the options array */
-                r = option_append(message->options, size, offset, code, optlen, optval);
-                if (r >= 0)
-                        return 0;
-                else if (r == -ENOBUFS && (use_file || use_sname)) {
-                        /* did not fit, but we have more buffers to try
-                           close the options array and move the offset to its end */
-                        r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
-                        if (r < 0)
-                                return r;
-
-                        *offset = size;
-                } else
-                        return r;
-        }
-
-        if (use_file) {
-                size_t file_offset = *offset - size;
-
-                if (file_offset < sizeof(message->file)) {
-                        /* still space in the 'file' array */
-                        r = option_append(message->file, sizeof(message->file), &file_offset, code, optlen, optval);
-                        if (r >= 0) {
-                                *offset = size + file_offset;
-                                return 0;
-                        } else if (r == -ENOBUFS && use_sname) {
-                                /* did not fit, but we have more buffers to try
-                                   close the file array and move the offset to its end */
-                                r = option_append(message->file, sizeof(message->file), &file_offset, SD_DHCP_OPTION_END, 0, NULL);
-                                if (r < 0)
-                                        return r;
-
-                                *offset = size + sizeof(message->file);
-                        } else
-                                return r;
-                }
-        }
-
-        if (use_sname) {
-                size_t sname_offset = *offset - size - use_file*sizeof(message->file);
-
-                if (sname_offset < sizeof(message->sname)) {
-                        /* still space in the 'sname' array */
-                        r = option_append(message->sname, sizeof(message->sname), &sname_offset, code, optlen, optval);
-                        if (r >= 0) {
-                                *offset = size + use_file*sizeof(message->file) + sname_offset;
-                                return 0;
-                        } else
-                                /* no space, or other error, give up */
-                                return r;
-                }
-        }
-
-        return -ENOBUFS;
-}
-
-static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overload,
-                         uint8_t *message_type, char **error_message, dhcp_option_callback_t cb,
-                         void *userdata) {
-        uint8_t code, len;
-        const uint8_t *option;
-        size_t offset = 0;
-
-        while (offset < buflen) {
-                code = options[offset ++];
-
-                switch (code) {
-                case SD_DHCP_OPTION_PAD:
-                        continue;
-
-                case SD_DHCP_OPTION_END:
-                        return 0;
-                }
-
-                if (buflen < offset + 1)
-                        return -ENOBUFS;
-
-                len = options[offset ++];
-
-                if (buflen < offset + len)
-                        return -EINVAL;
-
-                option = &options[offset];
-
-                switch (code) {
-                case SD_DHCP_OPTION_MESSAGE_TYPE:
-                        if (len != 1)
-                                return -EINVAL;
-
-                        if (message_type)
-                                *message_type = *option;
-
-                        break;
-
-                case SD_DHCP_OPTION_ERROR_MESSAGE:
-                        if (len == 0)
-                                return -EINVAL;
-
-                        if (error_message) {
-                                _cleanup_free_ char *string = NULL;
-
-                                /* Accept a trailing NUL byte */
-                                if (memchr(option, 0, len - 1))
-                                        return -EINVAL;
-
-                                string = memdup_suffix0((const char *) option, len);
-                                if (!string)
-                                        return -ENOMEM;
-
-                                if (!ascii_is_valid(string))
-                                        return -EINVAL;
-
-                                free_and_replace(*error_message, string);
-                        }
-
-                        break;
-                case SD_DHCP_OPTION_OVERLOAD:
-                        if (len != 1)
-                                return -EINVAL;
-
-                        if (overload)
-                                *overload = *option;
-
-                        break;
-
-                default:
-                        if (cb)
-                                cb(code, len, option, userdata);
-
-                        break;
-                }
-
-                offset += len;
-        }
-
-        if (offset < buflen)
-                return -EINVAL;
-
-        return 0;
-}
-
-int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t cb, void *userdata, char **_error_message) {
-        _cleanup_free_ char *error_message = NULL;
-        uint8_t overload = 0;
-        uint8_t message_type = 0;
-        int r;
-
-        if (!message)
-                return -EINVAL;
-
-        if (len < sizeof(DHCPMessage))
-                return -EINVAL;
-
-        len -= sizeof(DHCPMessage);
-
-        r = parse_options(message->options, len, &overload, &message_type, &error_message, cb, userdata);
-        if (r < 0)
-                return r;
-
-        if (overload & DHCP_OVERLOAD_FILE) {
-                r = parse_options(message->file, sizeof(message->file), NULL, &message_type, &error_message, cb, userdata);
-                if (r < 0)
-                        return r;
-        }
-
-        if (overload & DHCP_OVERLOAD_SNAME) {
-                r = parse_options(message->sname, sizeof(message->sname), NULL, &message_type, &error_message, cb, userdata);
-                if (r < 0)
-                        return r;
-        }
-
-        if (message_type == 0)
-                return -ENOMSG;
-
-        if (_error_message && IN_SET(message_type, DHCP_NAK, DHCP_DECLINE))
-                *_error_message = TAKE_PTR(error_message);
-
-        return message_type;
-}
-
-static sd_dhcp_option* dhcp_option_free(sd_dhcp_option *i) {
-        if (!i)
-                return NULL;
-
-        free(i->data);
-        return mfree(i);
-}
-
-int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret) {
-        assert_return(ret, -EINVAL);
-        assert_return(length == 0 || data, -EINVAL);
-
-        _cleanup_free_ void *q = memdup(data, length);
-        if (!q)
-                return -ENOMEM;
-
-        sd_dhcp_option *p = new(sd_dhcp_option, 1);
-        if (!p)
-                return -ENOMEM;
-
-        *p = (sd_dhcp_option) {
-                .n_ref = 1,
-                .option = option,
-                .length = length,
-                .data = TAKE_PTR(q),
-        };
-
-        *ret = TAKE_PTR(p);
-        return 0;
-}
-
-DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option, sd_dhcp_option, dhcp_option_free);
-DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
-                dhcp_option_hash_ops,
-                void,
-                trivial_hash_func,
-                trivial_compare_func,
-                sd_dhcp_option,
-                sd_dhcp_option_unref);
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-packet.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp-packet.c
deleted file mode 100644
index 25a69a61..00000000
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-packet.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/***
-  Copyright © 2013 Intel Corporation. All rights reserved.
-***/
-
-#include "nm-sd-adapt-core.h"
-
-#include <errno.h>
-#include <net/ethernet.h>
-#include <net/if_arp.h>
-#include <string.h>
-
-#include "dhcp-internal.h"
-#include "dhcp-protocol.h"
-#include "memory-util.h"
-
-#define DHCP_CLIENT_MIN_OPTIONS_SIZE            312
-
-int dhcp_message_init(
-                DHCPMessage *message,
-                uint8_t op,
-                uint32_t xid,
-                uint8_t type,
-                uint16_t arp_type,
-                uint8_t hlen,
-                const uint8_t *chaddr,
-                size_t optlen,
-                size_t *optoffset) {
-
-        size_t offset = 0;
-        int r;
-
-        assert(IN_SET(op, BOOTREQUEST, BOOTREPLY));
-        assert(chaddr || hlen == 0);
-
-        message->op = op;
-        message->htype = arp_type;
-
-        /* RFC2131 section 4.1.1:
-           The client MUST include its hardware address in the ’chaddr’ field, if
-           necessary for delivery of DHCP reply messages.
-
-           RFC 4390 section 2.1:
-           A DHCP client, when working over an IPoIB interface, MUST follow the
-           following rules:
-           "htype" (hardware address type) MUST be 32 [ARPPARAM].
-           "hlen" (hardware address length) MUST be 0.
-           "chaddr" (client hardware address) field MUST be zeroed.
-         */
-        message->hlen = (arp_type == ARPHRD_INFINIBAND) ? 0 : hlen;
-        memcpy_safe(message->chaddr, chaddr, message->hlen);
-
-        message->xid = htobe32(xid);
-        message->magic = htobe32(DHCP_MAGIC_COOKIE);
-
-        r = dhcp_option_append(message, optlen, &offset, 0,
-                               SD_DHCP_OPTION_MESSAGE_TYPE, 1, &type);
-        if (r < 0)
-                return r;
-
-        *optoffset = offset;
-
-        return 0;
-}
-
-uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len) {
-        uint64_t *buf_64 = (uint64_t*)buf;
-        uint64_t *end_64 = buf_64 + (len / sizeof(uint64_t));
-        uint64_t sum = 0;
-
-        /* See RFC1071 */
-
-        while (buf_64 < end_64) {
-                sum += *buf_64;
-                if (sum < *buf_64)
-                        /* wrap around in one's complement */
-                        sum++;
-
-                buf_64++;
-        }
-
-        if (len % sizeof(uint64_t)) {
-                /* If the buffer is not aligned to 64-bit, we need
-                   to zero-pad the last few bytes and add them in */
-                uint64_t buf_tail = 0;
-
-                memcpy(&buf_tail, buf_64, len % sizeof(uint64_t));
-
-                sum += buf_tail;
-                if (sum < buf_tail)
-                        /* wrap around */
-                        sum++;
-        }
-
-        while (sum >> 16)
-                sum = (sum & 0xffff) + (sum >> 16);
-
-        return ~sum;
-}
-
-void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr,
-                                   uint16_t source_port, be32_t destination_addr,
-                                   uint16_t destination_port, uint16_t len, int ip_service_type) {
-        packet->ip.version = IPVERSION;
-        packet->ip.ihl = DHCP_IP_SIZE / 4;
-        packet->ip.tot_len = htobe16(len);
-
-        if (ip_service_type >= 0)
-                packet->ip.tos = ip_service_type;
-        else
-                packet->ip.tos = IPTOS_CLASS_CS6;
-
-        packet->ip.protocol = IPPROTO_UDP;
-        packet->ip.saddr = source_addr;
-        packet->ip.daddr = destination_addr;
-
-        packet->udp.source = htobe16(source_port);
-        packet->udp.dest = htobe16(destination_port);
-
-        packet->udp.len = htobe16(len - DHCP_IP_SIZE);
-
-        packet->ip.check = packet->udp.len;
-        packet->udp.check = dhcp_packet_checksum((uint8_t*)&packet->ip.ttl, len - 8);
-
-        packet->ip.ttl = IPDEFTTL;
-        packet->ip.check = 0;
-        packet->ip.check = dhcp_packet_checksum((uint8_t*)&packet->ip, DHCP_IP_SIZE);
-}
-
-int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port) {
-        size_t hdrlen;
-
-        assert(packet);
-
-        /* IP */
-
-        if (packet->ip.version != IPVERSION)
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "ignoring packet: not IPv4");
-
-        if (packet->ip.ihl < 5)
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "ignoring packet: IPv4 IHL (%u words) invalid",
-                                       packet->ip.ihl);
-
-        hdrlen = packet->ip.ihl * 4;
-        if (hdrlen < 20)
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "ignoring packet: IPv4 IHL (%zu bytes) "
-                                       "smaller than minimum (20 bytes)",
-                                       hdrlen);
-
-        if (len < hdrlen)
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "ignoring packet: packet (%zu bytes) "
-                                       "smaller than expected (%zu) by IP header",
-                                       len, hdrlen);
-
-        /* UDP */
-
-        if (packet->ip.protocol != IPPROTO_UDP)
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "ignoring packet: not UDP");
-
-        if (len < hdrlen + be16toh(packet->udp.len))
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "ignoring packet: packet (%zu bytes) "
-                                       "smaller than expected (%zu) by UDP header",
-                                       len, hdrlen + be16toh(packet->udp.len));
-
-        if (be16toh(packet->udp.dest) != port)
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "ignoring packet: to port %u, which "
-                                       "is not the DHCP client port (%u)",
-                                       be16toh(packet->udp.dest), port);
-
-        /* checksums - computing these is relatively expensive, so only do it
-           if all the other checks have passed
-         */
-
-        if (dhcp_packet_checksum((uint8_t*)&packet->ip, hdrlen))
-                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "ignoring packet: invalid IP checksum");
-
-        if (checksum && packet->udp.check) {
-                packet->ip.check = packet->udp.len;
-                packet->ip.ttl = 0;
-
-                if (dhcp_packet_checksum((uint8_t*)&packet->ip.ttl,
-                                  be16toh(packet->udp.len) + 12))
-                        return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
-                                               "ignoring packet: invalid UDP checksum");
-        }
-
-        return 0;
-}
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-protocol.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp-protocol.h
deleted file mode 100644
index dd54bcf6..00000000
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-protocol.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-/***
-  Copyright © 2013 Intel Corporation. All rights reserved.
-***/
-
-#include <netinet/ip.h>
-#include <netinet/udp.h>
-#include <stdint.h>
-
-#include "macro.h"
-#include "sparse-endian.h"
-
-struct DHCPMessage {
-        uint8_t op;
-        uint8_t htype;
-        uint8_t hlen;
-        uint8_t hops;
-        be32_t xid;
-        be16_t secs;
-        be16_t flags;
-        be32_t ciaddr;
-        be32_t yiaddr;
-        be32_t siaddr;
-        be32_t giaddr;
-        uint8_t chaddr[16];
-        uint8_t sname[64];
-        uint8_t file[128];
-        be32_t magic;
-        uint8_t options[0];
-} _packed_;
-
-typedef struct DHCPMessage DHCPMessage;
-
-struct DHCPPacket {
-        struct iphdr ip;
-        struct udphdr udp;
-        DHCPMessage dhcp;
-} _packed_;
-
-typedef struct DHCPPacket DHCPPacket;
-
-#define DHCP_IP_SIZE            (int32_t)(sizeof(struct iphdr))
-#define DHCP_IP_UDP_SIZE        (int32_t)(sizeof(struct udphdr) + DHCP_IP_SIZE)
-#define DHCP_MESSAGE_SIZE       (int32_t)(sizeof(DHCPMessage))
-#define DHCP_DEFAULT_MIN_SIZE   576 /* the minimum internet hosts must be able to receive */
-#define DHCP_MIN_OPTIONS_SIZE   (DHCP_DEFAULT_MIN_SIZE - DHCP_IP_UDP_SIZE - DHCP_MESSAGE_SIZE)
-#define DHCP_MAGIC_COOKIE       (uint32_t)(0x63825363)
-
-enum {
-        DHCP_PORT_SERVER                        = 67,
-        DHCP_PORT_CLIENT                        = 68,
-};
-
-enum DHCPState {
-        DHCP_STATE_INIT                         = 0,
-        DHCP_STATE_SELECTING                    = 1,
-        DHCP_STATE_INIT_REBOOT                  = 2,
-        DHCP_STATE_REBOOTING                    = 3,
-        DHCP_STATE_REQUESTING                   = 4,
-        DHCP_STATE_BOUND                        = 5,
-        DHCP_STATE_RENEWING                     = 6,
-        DHCP_STATE_REBINDING                    = 7,
-        DHCP_STATE_STOPPED                      = 8,
-};
-
-typedef enum DHCPState DHCPState;
-
-enum {
-        BOOTREQUEST                             = 1,
-        BOOTREPLY                               = 2,
-};
-
-enum {
-        DHCP_DISCOVER                           = 1,  /* [RFC2132] */
-        DHCP_OFFER                              = 2,  /* [RFC2132] */
-        DHCP_REQUEST                            = 3,  /* [RFC2132] */
-        DHCP_DECLINE                            = 4,  /* [RFC2132] */
-        DHCP_ACK                                = 5,  /* [RFC2132] */
-        DHCP_NAK                                = 6,  /* [RFC2132] */
-        DHCP_RELEASE                            = 7,  /* [RFC2132] */
-        DHCP_INFORM                             = 8,  /* [RFC2132] */
-        DHCP_FORCERENEW                         = 9,  /* [RFC3203] */
-        DHCPLEASEQUERY                          = 10, /* [RFC4388] */
-        DHCPLEASEUNASSIGNED                     = 11, /* [RFC4388] */
-        DHCPLEASEUNKNOWN                        = 12, /* [RFC4388] */
-        DHCPLEASEACTIVE                         = 13, /* [RFC4388] */
-        DHCPBULKLEASEQUERY                      = 14, /* [RFC6926] */
-        DHCPLEASEQUERYDONE                      = 15, /* [RFC6926] */
-        DHCPACTIVELEASEQUERY                    = 16, /* [RFC7724] */
-        DHCPLEASEQUERYSTATUS                    = 17, /* [RFC7724] */
-        DHCPTLS                                 = 18, /* [RFC7724] */
-};
-
-enum {
-        DHCP_OVERLOAD_FILE                      = 1,
-        DHCP_OVERLOAD_SNAME                     = 2,
-};
-
-#define DHCP_MAX_FQDN_LENGTH 255
-
-enum {
-        DHCP_FQDN_FLAG_S = (1 << 0),
-        DHCP_FQDN_FLAG_O = (1 << 1),
-        DHCP_FQDN_FLAG_E = (1 << 2),
-        DHCP_FQDN_FLAG_N = (1 << 3),
-};
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h
index 0d7813f6..65f6cb05 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h
@@ -64,13 +64,14 @@ struct sd_dhcp6_client {
         struct duid duid;
         size_t duid_len;
         be16_t *req_opts;
-        size_t req_opts_len;
+        size_t n_req_opts;
         char *fqdn;
         char *mudurl;
         char **user_class;
         char **vendor_class;
         OrderedHashmap *extra_options;
         OrderedSet *vendor_options;
+        bool rapid_commit;
 
         struct sd_dhcp6_lease *lease;
 
diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c
index 03d56371..05f2a383 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c
+++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c
@@ -53,18 +53,20 @@ bool dhcp6_option_can_request(uint16_t option) {
                 return false;
         case SD_DHCP6_OPTION_SIP_SERVER_DOMAIN_NAME:
         case SD_DHCP6_OPTION_SIP_SERVER_ADDRESS:
-        case SD_DHCP6_OPTION_DNS_SERVERS:
-        case SD_DHCP6_OPTION_DOMAIN_LIST:
+        case SD_DHCP6_OPTION_DNS_SERVER:
+        case SD_DHCP6_OPTION_DOMAIN:
                 return true;
         case SD_DHCP6_OPTION_IA_PD:
         case SD_DHCP6_OPTION_IA_PD_PREFIX:
                 return false;
-        case SD_DHCP6_OPTION_NIS_SERVERS:
-        case SD_DHCP6_OPTION_NISP_SERVERS:
+        case SD_DHCP6_OPTION_NIS_SERVER:
+        case SD_DHCP6_OPTION_NISP_SERVER:
         case SD_DHCP6_OPTION_NIS_DOMAIN_NAME:
         case SD_DHCP6_OPTION_NISP_DOMAIN_NAME:
-        case SD_DHCP6_OPTION_SNTP_SERVERS:
+        case SD_DHCP6_OPTION_SNTP_SERVER:
+                return true;
         case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
+                return false; /* This is automatically set when sending INFORMATION_REQUEST message. */
         case SD_DHCP6_OPTION_BCMCS_SERVER_D:
         case SD_DHCP6_OPTION_BCMCS_SERVER_A:
         case SD_DHCP6_OPTION_GEOCONF_CIVIC:
@@ -126,9 +128,9 @@ bool dhcp6_option_can_request(uint16_t option) {
         case SD_DHCP6_OPTION_CLIENT_LINKLAYER_ADDR:
         case SD_DHCP6_OPTION_LINK_ADDRESS:
         case SD_DHCP6_OPTION_RADIUS:
+        case SD_DHCP6_OPTION_SOL_MAX_RT: /* Automatically set when sending SOLICIT message. */
+        case SD_DHCP6_OPTION_INF_MAX_RT: /* Automatically set when sending INFORMATION_REQUEST message. */
                 return false;
-        case SD_DHCP6_OPTION_SOL_MAX_RT:
-        case SD_DHCP6_OPTION_INF_MAX_RT:
         case SD_DHCP6_OPTION_ADDRSEL:
         case SD_DHCP6_OPTION_ADDRSEL_TABLE:
         case SD_DHCP6_OPTION_V6_PCP_SERVER:
@@ -508,7 +510,7 @@ int dhcp6_option_parse(
         if (buflen < offsetof(DHCP6Option, data))
                 return -EBADMSG;
 
-        if (*offset >= buflen - offsetof(DHCP6Option, data))
+        if (*offset > buflen - offsetof(DHCP6Option, data))
                 return -EBADMSG;
 
         len = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, len));
@@ -518,14 +520,14 @@ int dhcp6_option_parse(
 
         *ret_option_code = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, code));
         *ret_option_data_len = len;
-        *ret_option_data = buf + *offset + offsetof(DHCP6Option, data);
+        *ret_option_data = len == 0 ? NULL : buf + *offset + offsetof(DHCP6Option, data);
         *offset += offsetof(DHCP6Option, data) + len;
 
         return 0;
 }
 
 int dhcp6_option_parse_status(const uint8_t *data, size_t data_len, char **ret_status_message) {
-        assert(data);
+        assert(data || data_len == 0);
 
         if (data_len < sizeof(uint16_t))
                 return -EBADMSG;
@@ -803,7 +805,7 @@ int dhcp6_option_parse_addresses(
                 struct in6_addr **addrs,
                 size_t *count) {
 
-        assert(optval);
+        assert(optval || optlen == 0);
         assert(addrs);
         assert(count);
 
@@ -826,8 +828,8 @@ static int parse_domain(const uint8_t **data, size_t *len, char **ret) {
         int r;
 
         assert(data);
-        assert(*data);
         assert(len);
+        assert(*data || *len == 0);
         assert(ret);
 
         optval = *data;
@@ -891,7 +893,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, size_t optlen, char **r
         _cleanup_free_ char *domain = NULL;
         int r;
 
-        assert(optval);
+        assert(optval || optlen == 0);
         assert(ret);
 
         r = parse_domain(&optval, &optlen, &domain);
@@ -910,7 +912,7 @@ int dhcp6_option_parse_domainname_list(const uint8_t *optval, size_t optlen, cha
         _cleanup_strv_free_ char **names = NULL;
         int r;
 
-        assert(optval);
+        assert(optval || optlen == 0);
         assert(ret);
 
         if (optlen <= 1)
diff --git a/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.c b/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.c
index f56929ad..d4aec944 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.c
+++ b/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.c
@@ -118,6 +118,9 @@ sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n) {
 sd_lldp_neighbor *lldp_neighbor_new(size_t raw_size) {
         sd_lldp_neighbor *n;
 
+        if (raw_size > SIZE_MAX - ALIGN(sizeof(sd_lldp_neighbor)))
+                return NULL;
+
         n = malloc0(ALIGN(sizeof(sd_lldp_neighbor)) + raw_size);
         if (!n)
                 return NULL;
@@ -651,7 +654,8 @@ int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t ra
         if (!n)
                 return -ENOMEM;
 
-        memcpy(LLDP_NEIGHBOR_RAW(n), raw, raw_size);
+        memcpy_safe(LLDP_NEIGHBOR_RAW(n), raw, raw_size);
+
         r = lldp_neighbor_parse(n);
         if (r < 0)
                 return r;
diff --git a/src/libnm-systemd-core/src/libsystemd-network/network-internal.c b/src/libnm-systemd-core/src/libsystemd-network/network-internal.c
deleted file mode 100644
index 60ce47ea..00000000
--- a/src/libnm-systemd-core/src/libsystemd-network/network-internal.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include "nm-sd-adapt-core.h"
-
-#include <arpa/inet.h>
-#include <linux/if.h>
-#include <netinet/ether.h>
-
-#include "sd-ndisc.h"
-
-#include "alloc-util.h"
-#include "dhcp-lease-internal.h"
-#include "extract-word.h"
-#include "hexdecoct.h"
-#include "log.h"
-#include "network-internal.h"
-#include "parse-util.h"
-
-size_t serialize_in_addrs(FILE *f,
-                          const struct in_addr *addresses,
-                          size_t size,
-                          bool *with_leading_space,
-                          bool (*predicate)(const struct in_addr *addr)) {
-        assert(f);
-        assert(addresses);
-
-        size_t count = 0;
-        bool _space = false;
-        if (!with_leading_space)
-                with_leading_space = &_space;
-
-        for (size_t i = 0; i < size; i++) {
-                char sbuf[INET_ADDRSTRLEN];
-
-                if (predicate && !predicate(&addresses[i]))
-                        continue;
-
-                if (*with_leading_space)
-                        fputc(' ', f);
-                fputs(inet_ntop(AF_INET, &addresses[i], sbuf, sizeof(sbuf)), f);
-                count++;
-                *with_leading_space = true;
-        }
-
-        return count;
-}
-
-int deserialize_in_addrs(struct in_addr **ret, const char *string) {
-        _cleanup_free_ struct in_addr *addresses = NULL;
-        int size = 0;
-
-        assert(ret);
-        assert(string);
-
-        for (;;) {
-                _cleanup_free_ char *word = NULL;
-                struct in_addr *new_addresses;
-                int r;
-
-                r = extract_first_word(&string, &word, NULL, 0);
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        break;
-
-                new_addresses = reallocarray(addresses, size + 1, sizeof(struct in_addr));
-                if (!new_addresses)
-                        return -ENOMEM;
-                else
-                        addresses = new_addresses;
-
-                r = inet_pton(AF_INET, word, &(addresses[size]));
-                if (r <= 0)
-                        continue;
-
-                size++;
-        }
-
-        *ret = size > 0 ? TAKE_PTR(addresses) : NULL;
-
-        return size;
-}
-
-void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, size_t size, bool *with_leading_space) {
-        assert(f);
-        assert(addresses);
-        assert(size);
-
-        bool _space = false;
-        if (!with_leading_space)
-                with_leading_space = &_space;
-
-        for (size_t i = 0; i < size; i++) {
-                char buffer[INET6_ADDRSTRLEN];
-
-                if (*with_leading_space)
-                        fputc(' ', f);
-                fputs(inet_ntop(AF_INET6, addresses+i, buffer, sizeof(buffer)), f);
-                *with_leading_space = true;
-        }
-}
-
-int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
-        _cleanup_free_ struct in6_addr *addresses = NULL;
-        int size = 0;
-
-        assert(ret);
-        assert(string);
-
-        for (;;) {
-                _cleanup_free_ char *word = NULL;
-                struct in6_addr *new_addresses;
-                int r;
-
-                r = extract_first_word(&string, &word, NULL, 0);
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        break;
-
-                new_addresses = reallocarray(addresses, size + 1, sizeof(struct in6_addr));
-                if (!new_addresses)
-                        return -ENOMEM;
-                else
-                        addresses = new_addresses;
-
-                r = inet_pton(AF_INET6, word, &(addresses[size]));
-                if (r <= 0)
-                        continue;
-
-                size++;
-        }
-
-        *ret = TAKE_PTR(addresses);
-
-        return size;
-}
-
-void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) {
-        assert(f);
-        assert(key);
-        assert(routes);
-        assert(size);
-
-        fprintf(f, "%s=", key);
-
-        for (size_t i = 0; i < size; i++) {
-                char sbuf[INET_ADDRSTRLEN];
-                struct in_addr dest, gw;
-                uint8_t length;
-
-                assert_se(sd_dhcp_route_get_destination(routes[i], &dest) >= 0);
-                assert_se(sd_dhcp_route_get_gateway(routes[i], &gw) >= 0);
-                assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &length) >= 0);
-
-                fprintf(f, "%s/%" PRIu8, inet_ntop(AF_INET, &dest, sbuf, sizeof sbuf), length);
-                fprintf(f, ",%s%s", inet_ntop(AF_INET, &gw, sbuf, sizeof sbuf), i < size - 1 ? " ": "");
-        }
-
-        fputs("\n", f);
-}
-
-int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, const char *string) {
-        _cleanup_free_ struct sd_dhcp_route *routes = NULL;
-        size_t size = 0;
-
-        assert(ret);
-        assert(ret_size);
-        assert(string);
-
-         /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
-        for (;;) {
-                _cleanup_free_ char *word = NULL;
-                char *tok, *tok_end;
-                unsigned n;
-                int r;
-
-                r = extract_first_word(&string, &word, NULL, 0);
-                if (r < 0)
-                        return r;
-                if (r == 0)
-                        break;
-
-                if (!GREEDY_REALLOC(routes, size + 1))
-                        return -ENOMEM;
-
-                tok = word;
-
-                /* get the subnet */
-                tok_end = strchr(tok, '/');
-                if (!tok_end)
-                        continue;
-                *tok_end = '\0';
-
-                r = inet_aton(tok, &routes[size].dst_addr);
-                if (r == 0)
-                        continue;
-
-                tok = tok_end + 1;
-
-                /* get the prefixlen */
-                tok_end = strchr(tok, ',');
-                if (!tok_end)
-                        continue;
-
-                *tok_end = '\0';
-
-                r = safe_atou(tok, &n);
-                if (r < 0 || n > 32)
-                        continue;
-
-                routes[size].dst_prefixlen = (uint8_t) n;
-                tok = tok_end + 1;
-
-                /* get the gateway */
-                r = inet_aton(tok, &routes[size].gw_addr);
-                if (r == 0)
-                        continue;
-
-                size++;
-        }
-
-        *ret_size = size;
-        *ret = TAKE_PTR(routes);
-
-        return 0;
-}
-
-int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) {
-        _cleanup_free_ char *hex_buf = NULL;
-
-        assert(f);
-        assert(key);
-        assert(data);
-
-        hex_buf = hexmem(data, size);
-        if (!hex_buf)
-                return -ENOMEM;
-
-        fprintf(f, "%s=%s\n", key, hex_buf);
-
-        return 0;
-}
diff --git a/src/libnm-systemd-core/src/libsystemd-network/network-internal.h b/src/libnm-systemd-core/src/libsystemd-network/network-internal.h
deleted file mode 100644
index 5aa225e9..00000000
--- a/src/libnm-systemd-core/src/libsystemd-network/network-internal.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-#include <stdbool.h>
-#include <stdio.h>
-
-#include "sd-dhcp-lease.h"
-
-size_t serialize_in_addrs(FILE *f,
-                          const struct in_addr *addresses,
-                          size_t size,
-                          bool *with_leading_space,
-                          bool (*predicate)(const struct in_addr *addr));
-int deserialize_in_addrs(struct in_addr **addresses, const char *string);
-void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
-                         size_t size,
-                         bool *with_leading_space);
-int deserialize_in6_addrs(struct in6_addr **addresses, const char *string);
-
-/* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */
-struct sd_dhcp_route;
-struct sd_dhcp_lease;
-
-void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route **routes, size_t size);
-int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, const char *string);
-
-/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */
-int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
-
-int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
-int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c
deleted file mode 100644
index d56978ad..00000000
--- a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c
+++ /dev/null
@@ -1,2285 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/***
-  Copyright © 2013 Intel Corporation. All rights reserved.
-***/
-
-#include "nm-sd-adapt-core.h"
-
-#include <errno.h>
-#include <net/ethernet.h>
-#include <net/if_arp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <linux/if_infiniband.h>
-
-#include "sd-dhcp-client.h"
-
-#include "alloc-util.h"
-#include "dhcp-identifier.h"
-#include "dhcp-internal.h"
-#include "dhcp-lease-internal.h"
-#include "dhcp-protocol.h"
-#include "dns-domain.h"
-#include "event-util.h"
-#include "fd-util.h"
-#include "hostname-util.h"
-#include "io-util.h"
-#include "memory-util.h"
-#include "network-common.h"
-#include "random-util.h"
-#include "set.h"
-#include "sort-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "time-util.h"
-#include "utf8.h"
-#include "web-util.h"
-
-#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN)  /* Arbitrary limit */
-#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
-
-#define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
-#define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
-
-#define TRANSIENT_FAILURE_ATTEMPTS 3 /* Arbitrary limit: how many attempts are considered enough to report
-                                      * transient failure. */
-
-typedef struct sd_dhcp_client_id {
-        uint8_t type;
-        union {
-                struct {
-                        /* 0: Generic (non-LL) (RFC 2132) */
-                        uint8_t data[MAX_CLIENT_ID_LEN];
-                } _packed_ gen;
-                struct {
-                        /* 1: Ethernet Link-Layer (RFC 2132) */
-                        uint8_t haddr[ETH_ALEN];
-                } _packed_ eth;
-                struct {
-                        /* 2 - 254: ARP/Link-Layer (RFC 2132) */
-                        uint8_t haddr[0];
-                } _packed_ ll;
-                struct {
-                        /* 255: Node-specific (RFC 4361) */
-                        be32_t iaid;
-                        struct duid duid;
-                } _packed_ ns;
-                struct {
-                        uint8_t data[MAX_CLIENT_ID_LEN];
-                } _packed_ raw;
-        };
-} _packed_ sd_dhcp_client_id;
-
-struct sd_dhcp_client {
-        unsigned n_ref;
-
-        DHCPState state;
-        sd_event *event;
-        int event_priority;
-        sd_event_source *timeout_resend;
-        int ifindex;
-        char *ifname;
-        int fd;
-        uint16_t port;
-        union sockaddr_union link;
-        sd_event_source *receive_message;
-        bool request_broadcast;
-        Set *req_opts;
-        bool anonymize;
-        be32_t last_addr;
-        uint8_t mac_addr[MAX_MAC_ADDR_LEN];
-        size_t mac_addr_len;
-        uint8_t bcast_addr[MAX_MAC_ADDR_LEN];
-        size_t bcast_addr_len;
-        uint16_t arp_type;
-        sd_dhcp_client_id client_id;
-        size_t client_id_len;
-        char *hostname;
-        char *vendor_class_identifier;
-        char *mudurl;
-        char **user_class;
-        uint32_t mtu;
-        uint32_t fallback_lease_lifetime;
-        uint32_t xid;
-        usec_t start_time;
-        usec_t t1_time;
-        usec_t t2_time;
-        usec_t expire_time;
-        uint64_t attempt;
-        uint64_t max_attempts;
-        OrderedHashmap *extra_options;
-        OrderedHashmap *vendor_options;
-        usec_t request_sent;
-        sd_event_source *timeout_t1;
-        sd_event_source *timeout_t2;
-        sd_event_source *timeout_expire;
-        sd_dhcp_client_callback_t callback;
-        void *userdata;
-        sd_dhcp_lease *lease;
-        usec_t start_delay;
-        int ip_service_type;
-
-        /* Ignore ifindex when generating iaid. See dhcp_identifier_set_iaid(). */
-        bool test_mode;
-};
-
-static const uint8_t default_req_opts[] = {
-        SD_DHCP_OPTION_SUBNET_MASK,
-        SD_DHCP_OPTION_ROUTER,
-        SD_DHCP_OPTION_HOST_NAME,
-        SD_DHCP_OPTION_DOMAIN_NAME,
-        SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
-};
-
-/* RFC7844 section 3:
-   MAY contain the Parameter Request List option.
-   RFC7844 section 3.6:
-   The client intending to protect its privacy SHOULD only request a
-   minimal number of options in the PRL and SHOULD also randomly shuffle
-   the ordering of option codes in the PRL.  If this random ordering
-   cannot be implemented, the client MAY order the option codes in the
-   PRL by option code number (lowest to highest).
-*/
-/* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */
-static const uint8_t default_req_opts_anonymize[] = {
-        SD_DHCP_OPTION_SUBNET_MASK,                     /* 1 */
-        SD_DHCP_OPTION_ROUTER,                          /* 3 */
-        SD_DHCP_OPTION_DOMAIN_NAME_SERVER,              /* 6 */
-        SD_DHCP_OPTION_DOMAIN_NAME,                     /* 15 */
-        SD_DHCP_OPTION_ROUTER_DISCOVERY,                /* 31 */
-        SD_DHCP_OPTION_STATIC_ROUTE,                    /* 33 */
-        SD_DHCP_OPTION_VENDOR_SPECIFIC,                 /* 43 */
-        SD_DHCP_OPTION_NETBIOS_NAME_SERVER,             /* 44 */
-        SD_DHCP_OPTION_NETBIOS_NODE_TYPE,               /* 46 */
-        SD_DHCP_OPTION_NETBIOS_SCOPE,                   /* 47 */
-        SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE,          /* 121 */
-        SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE,  /* 249 */
-        SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY,     /* 252 */
-};
-
-static int client_receive_message_raw(
-                sd_event_source *s,
-                int fd,
-                uint32_t revents,
-                void *userdata);
-static int client_receive_message_udp(
-                sd_event_source *s,
-                int fd,
-                uint32_t revents,
-                void *userdata);
-static void client_stop(sd_dhcp_client *client, int error);
-
-int sd_dhcp_client_id_to_string(const void *data, size_t len, char **ret) {
-        const sd_dhcp_client_id *client_id = data;
-        _cleanup_free_ char *t = NULL;
-        int r = 0;
-
-        assert_return(data, -EINVAL);
-        assert_return(len >= 1, -EINVAL);
-        assert_return(ret, -EINVAL);
-
-        len -= 1;
-        if (len > MAX_CLIENT_ID_LEN)
-                return -EINVAL;
-
-        switch (client_id->type) {
-        case 0:
-                if (utf8_is_printable((char *) client_id->gen.data, len))
-                        r = asprintf(&t, "%.*s", (int) len, client_id->gen.data);
-                else
-                        r = asprintf(&t, "DATA");
-                break;
-        case 1:
-                if (len != sizeof_field(sd_dhcp_client_id, eth))
-                        return -EINVAL;
-
-                r = asprintf(&t, "%02x:%02x:%02x:%02x:%02x:%02x",
-                             client_id->eth.haddr[0],
-                             client_id->eth.haddr[1],
-                             client_id->eth.haddr[2],
-                             client_id->eth.haddr[3],
-                             client_id->eth.haddr[4],
-                             client_id->eth.haddr[5]);
-                break;
-        case 2 ... 254:
-                r = asprintf(&t, "ARP/LL");
-                break;
-        case 255:
-                if (len < 6)
-                        return -EINVAL;
-
-                uint32_t iaid = be32toh(client_id->ns.iaid);
-                uint16_t duid_type = be16toh(client_id->ns.duid.type);
-                if (dhcp_validate_duid_len(duid_type, len - 6, true) < 0)
-                        return -EINVAL;
-
-                r = asprintf(&t, "IAID:0x%x/DUID", iaid);
-                break;
-        }
-
-        if (r < 0)
-                return -ENOMEM;
-        *ret = TAKE_PTR(t);
-        return 0;
-}
-
-int sd_dhcp_client_set_callback(
-                sd_dhcp_client *client,
-                sd_dhcp_client_callback_t cb,
-                void *userdata) {
-
-        assert_return(client, -EINVAL);
-
-        client->callback = cb;
-        client->userdata = userdata;
-
-        return 0;
-}
-
-int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) {
-        assert_return(client, -EINVAL);
-
-        client->request_broadcast = broadcast;
-
-        return 0;
-}
-
-int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
-        assert_return(client, -EINVAL);
-        assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY);
-
-        switch (option) {
-
-        case SD_DHCP_OPTION_PAD:
-        case SD_DHCP_OPTION_OVERLOAD:
-        case SD_DHCP_OPTION_MESSAGE_TYPE:
-        case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST:
-        case SD_DHCP_OPTION_END:
-                return -EINVAL;
-
-        default:
-                break;
-        }
-
-        return set_ensure_put(&client->req_opts, NULL, UINT8_TO_PTR(option));
-}
-
-int sd_dhcp_client_set_request_address(
-                sd_dhcp_client *client,
-                const struct in_addr *last_addr) {
-
-        assert_return(client, -EINVAL);
-        assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY);
-
-        if (last_addr)
-                client->last_addr = last_addr->s_addr;
-        else
-                client->last_addr = INADDR_ANY;
-
-        return 0;
-}
-
-int sd_dhcp_client_set_ifindex(sd_dhcp_client *client, int ifindex) {
-        assert_return(client, -EINVAL);
-        assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY);
-        assert_return(ifindex > 0, -EINVAL);
-
-        client->ifindex = ifindex;
-        return 0;
-}
-
-int sd_dhcp_client_set_ifname(sd_dhcp_client *client, const char *ifname) {
-        assert_return(client, -EINVAL);
-        assert_return(ifname, -EINVAL);
-
-        if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
-                return -EINVAL;
-
-        return free_and_strdup(&client->ifname, ifname);
-}
-
-int sd_dhcp_client_get_ifname(sd_dhcp_client *client, const char **ret) {
-        int r;
-
-        assert_return(client, -EINVAL);
-
-        r = get_ifname(client->ifindex, &client->ifname);
-        if (r < 0)
-                return r;
-
-        if (ret)
-                *ret = client->ifname;
-
-        return 0;
-}
-
-int sd_dhcp_client_set_mac(
-                sd_dhcp_client *client,
-                const uint8_t *addr,
-                const uint8_t *bcast_addr,
-                size_t addr_len,
-                uint16_t arp_type) {
-
-        DHCP_CLIENT_DONT_DESTROY(client);
-        bool need_restart = false;
-        int r;
-
-        assert_return(client, -EINVAL);
-        assert_return(addr, -EINVAL);
-        assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
-        assert_return(arp_type > 0, -EINVAL);
-
-        if (arp_type == ARPHRD_ETHER)
-                assert_return(addr_len == ETH_ALEN, -EINVAL);
-        else if (arp_type == ARPHRD_INFINIBAND)
-                assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
-        else
-                return -EINVAL;
-
-        if (client->mac_addr_len == addr_len &&
-            memcmp(&client->mac_addr, addr, addr_len) == 0 &&
-            (client->bcast_addr_len > 0) == !!bcast_addr &&
-            (!bcast_addr || memcmp(&client->bcast_addr, bcast_addr, addr_len) == 0))
-                return 0;
-
-        if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
-                log_dhcp_client(client, "Changing MAC address on running DHCP client, restarting");
-                need_restart = true;
-                client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
-        }
-
-        memcpy(&client->mac_addr, addr, addr_len);
-        client->mac_addr_len = addr_len;
-        client->arp_type = arp_type;
-        client->bcast_addr_len = 0;
-
-        if (bcast_addr) {
-                memcpy(&client->bcast_addr, bcast_addr, addr_len);
-                client->bcast_addr_len = addr_len;
-        }
-
-        if (need_restart && client->state != DHCP_STATE_STOPPED) {
-                r = sd_dhcp_client_start(client);
-                if (r < 0)
-                        return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m");
-        }
-
-        return 0;
-}
-
-int sd_dhcp_client_get_client_id(
-                sd_dhcp_client *client,
-                uint8_t *type,
-                const uint8_t **data,
-                size_t *data_len) {
-
-        assert_return(client, -EINVAL);
-        assert_return(type, -EINVAL);
-        assert_return(data, -EINVAL);
-        assert_return(data_len, -EINVAL);
-
-        if (client->client_id_len) {
-                *type = client->client_id.type;
-                *data = client->client_id.raw.data;
-                *data_len = client->client_id_len - sizeof(client->client_id.type);
-        } else {
-                *type = 0;
-                *data = NULL;
-                *data_len = 0;
-        }
-
-        return 0;
-}
-
-int sd_dhcp_client_set_client_id(
-                sd_dhcp_client *client,
-                uint8_t type,
-                const uint8_t *data,
-                size_t data_len) {
-
-        DHCP_CLIENT_DONT_DESTROY(client);
-        bool need_restart = false;
-        int r;
-
-        assert_return(client, -EINVAL);
-        assert_return(data, -EINVAL);
-        assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
-        G_STATIC_ASSERT_EXPR (_NM_MAX_CLIENT_ID_LEN == MAX_CLIENT_ID_LEN);
-
-        if (client->client_id_len == data_len + sizeof(client->client_id.type) &&
-            client->client_id.type == type &&
-            memcmp(&client->client_id.raw.data, data, data_len) == 0)
-                return 0;
-
-        /* For hardware types, log debug message about unexpected data length.
-         *
-         * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
-         * the last 8 bytes of the address are stable and suitable to put into
-         * the client-id. The caller is advised to account for that. */
-        if ((type == ARPHRD_ETHER && data_len != ETH_ALEN) ||
-            (type == ARPHRD_INFINIBAND && data_len != 8))
-                log_dhcp_client(client, "Changing client ID to hardware type %u with "
-                                "unexpected address length %zu",
-                                type, data_len);
-
-        if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
-                log_dhcp_client(client, "Changing client ID on running DHCP "
-                                "client, restarting");
-                need_restart = true;
-                client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
-        }
-
-        client->client_id.type = type;
-        memcpy(&client->client_id.raw.data, data, data_len);
-        client->client_id_len = data_len + sizeof (client->client_id.type);
-
-        if (need_restart && client->state != DHCP_STATE_STOPPED) {
-                r = sd_dhcp_client_start(client);
-                if (r < 0)
-                        return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m");
-        }
-
-        return 0;
-}
-
-#if 0 /* NM_IGNORED */
-/**
- * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid
- * without further modification. Otherwise, if duid_type is supported, DUID
- * is set based on that type. Otherwise, an error is returned.
- */
-static int dhcp_client_set_iaid_duid_internal(
-                sd_dhcp_client *client,
-                bool iaid_append,
-                bool iaid_set,
-                uint32_t iaid,
-                DUIDType duid_type,
-                const void *duid,
-                size_t duid_len,
-                usec_t llt_time) {
-
-        DHCP_CLIENT_DONT_DESTROY(client);
-        int r;
-        size_t len;
-
-        assert_return(client, -EINVAL);
-        assert_return(duid_len == 0 || duid, -EINVAL);
-
-        if (duid) {
-                r = dhcp_validate_duid_len(duid_type, duid_len, true);
-                if (r < 0)
-                        return log_dhcp_client_errno(client, r, "Failed to validate length of DUID: %m");
-        }
-
-        zero(client->client_id);
-        client->client_id.type = 255;
-
-        if (iaid_append) {
-                if (iaid_set)
-                        client->client_id.ns.iaid = htobe32(iaid);
-                else {
-                        r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
-                                                     client->mac_addr_len,
-                                                     /* legacy_unstable_byteorder = */ true,
-                                                     /* use_mac = */ client->test_mode,
-                                                     &client->client_id.ns.iaid);
-                        if (r < 0)
-                                return log_dhcp_client_errno(client, r, "Failed to set IAID: %m");
-                }
-        }
-
-        if (duid) {
-                client->client_id.ns.duid.type = htobe16(duid_type);
-                memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
-                len = sizeof(client->client_id.ns.duid.type) + duid_len;
-
-        } else {
-                r = dhcp_identifier_set_duid(duid_type, client->mac_addr, client->mac_addr_len,
-                                             client->arp_type, llt_time, client->test_mode,
-                                             &client->client_id.ns.duid, &len);
-                if (r == -EOPNOTSUPP)
-                        return log_dhcp_client_errno(client, r,
-                                                     "Failed to set %s. MAC address is not set or "
-                                                     "interface type is not supported.",
-                                                     duid_type_to_string(duid_type));
-                if (r < 0)
-                        return log_dhcp_client_errno(client, r, "Failed to set %s: %m",
-                                                     duid_type_to_string(duid_type));
-        }
-
-        client->client_id_len = sizeof(client->client_id.type) + len +
-                                (iaid_append ? sizeof(client->client_id.ns.iaid) : 0);
-
-        if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
-                log_dhcp_client(client, "Configured %sDUID, restarting.", iaid_append ? "IAID+" : "");
-                client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
-                r = sd_dhcp_client_start(client);
-                if (r < 0)
-                        return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m");
-        }
-
-        return 0;
-}
-
-int sd_dhcp_client_set_iaid_duid(
-                sd_dhcp_client *client,
-                bool iaid_set,
-                uint32_t iaid,
-                uint16_t duid_type,
-                const void *duid,
-                size_t duid_len) {
-        return dhcp_client_set_iaid_duid_internal(client, true, iaid_set, iaid, duid_type, duid, duid_len, 0);
-}
-
-int sd_dhcp_client_set_iaid_duid_llt(
-                sd_dhcp_client *client,
-                bool iaid_set,
-                uint32_t iaid,
-                usec_t llt_time) {
-        return dhcp_client_set_iaid_duid_internal(client, true, iaid_set, iaid, DUID_TYPE_LLT, NULL, 0, llt_time);
-}
-
-int sd_dhcp_client_set_duid(
-                sd_dhcp_client *client,
-                uint16_t duid_type,
-                const void *duid,
-                size_t duid_len) {
-        return dhcp_client_set_iaid_duid_internal(client, false, false, 0, duid_type, duid, duid_len, 0);
-}
-
-int sd_dhcp_client_set_duid_llt(
-                sd_dhcp_client *client,
-                usec_t llt_time) {
-        return dhcp_client_set_iaid_duid_internal(client, false, false, 0, DUID_TYPE_LLT, NULL, 0, llt_time);
-}
-#endif /* NM_IGNORED */
-
-void dhcp_client_set_test_mode(sd_dhcp_client *client, bool test_mode) {
-        assert(client);
-
-        client->test_mode = test_mode;
-}
-
-int sd_dhcp_client_set_hostname(
-                sd_dhcp_client *client,
-                const char *hostname) {
-
-        assert_return(client, -EINVAL);
-
-        /* Make sure hostnames qualify as DNS and as Linux hostnames */
-        if (hostname &&
-            !(hostname_is_valid(hostname, 0) && dns_name_is_valid(hostname) > 0))
-                return -EINVAL;
-
-        return free_and_strdup(&client->hostname, hostname);
-}
-
-int sd_dhcp_client_set_vendor_class_identifier(
-                sd_dhcp_client *client,
-                const char *vci) {
-
-        assert_return(client, -EINVAL);
-
-        return free_and_strdup(&client->vendor_class_identifier, vci);
-}
-
-int sd_dhcp_client_set_mud_url(
-                sd_dhcp_client *client,
-                const char *mudurl) {
-
-        assert_return(client, -EINVAL);
-        assert_return(mudurl, -EINVAL);
-        assert_return(strlen(mudurl) <= 255, -EINVAL);
-        assert_return(http_url_is_valid(mudurl), -EINVAL);
-
-        return free_and_strdup(&client->mudurl, mudurl);
-}
-
-int sd_dhcp_client_set_user_class(
-                sd_dhcp_client *client,
-                char * const *user_class) {
-
-        char **s = NULL;
-
-        assert_return(client, -EINVAL);
-        assert_return(!strv_isempty(user_class), -EINVAL);
-
-        STRV_FOREACH(p, user_class) {
-                size_t n = strlen(*p);
-
-                if (n > 255 || n == 0)
-                        return -EINVAL;
-        }
-
-        s = strv_copy(user_class);
-        if (!s)
-                return -ENOMEM;
-
-        return strv_free_and_replace(client->user_class, s);
-}
-
-int sd_dhcp_client_set_client_port(
-                sd_dhcp_client *client,
-                uint16_t port) {
-
-        assert_return(client, -EINVAL);
-
-        client->port = port;
-
-        return 0;
-}
-
-int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
-        assert_return(client, -EINVAL);
-        assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE);
-
-        client->mtu = 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_add_option(sd_dhcp_client *client, sd_dhcp_option *v) {
-        int r;
-
-        assert_return(client, -EINVAL);
-        assert_return(v, -EINVAL);
-
-        r = ordered_hashmap_ensure_put(&client->extra_options, &dhcp_option_hash_ops, UINT_TO_PTR(v->option), v);
-        if (r < 0)
-                return r;
-
-        sd_dhcp_option_ref(v);
-        return 0;
-}
-
-int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v) {
-        int r;
-
-        assert_return(client, -EINVAL);
-        assert_return(v, -EINVAL);
-
-        r = ordered_hashmap_ensure_allocated(&client->vendor_options, &dhcp_option_hash_ops);
-        if (r < 0)
-                return -ENOMEM;
-
-        r = ordered_hashmap_put(client->vendor_options, v, v);
-        if (r < 0)
-                return r;
-
-        sd_dhcp_option_ref(v);
-
-        return 1;
-}
-
-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_SELECTING, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING))
-                return -EADDRNOTAVAIL;
-
-        if (ret)
-                *ret = client->lease;
-
-        return 0;
-}
-
-int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) {
-        assert_return(client, -EINVAL);
-
-        client->ip_service_type = type;
-
-        return 0;
-}
-
-int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client *client, uint32_t fallback_lease_lifetime) {
-        assert_return(client, -EINVAL);
-        assert_return(fallback_lease_lifetime > 0, -EINVAL);
-
-        client->fallback_lease_lifetime = fallback_lease_lifetime;
-
-        return 0;
-}
-
-static int client_notify(sd_dhcp_client *client, int event) {
-        assert(client);
-
-        if (client->callback)
-                return client->callback(client, event, client->userdata);
-
-        return 0;
-}
-
-static int client_initialize(sd_dhcp_client *client) {
-        assert_return(client, -EINVAL);
-
-        client->receive_message = sd_event_source_disable_unref(client->receive_message);
-
-        client->fd = safe_close(client->fd);
-
-        (void) event_source_disable(client->timeout_resend);
-        (void) event_source_disable(client->timeout_t1);
-        (void) event_source_disable(client->timeout_t2);
-        (void) event_source_disable(client->timeout_expire);
-
-        client->attempt = 0;
-
-        client->state = DHCP_STATE_INIT;
-        client->xid = 0;
-
-        client->lease = sd_dhcp_lease_unref(client->lease);
-
-        return 0;
-}
-
-static void client_stop(sd_dhcp_client *client, int error) {
-        assert(client);
-
-        if (error < 0)
-                log_dhcp_client_errno(client, error, "STOPPED: %m");
-        else if (error == SD_DHCP_CLIENT_EVENT_STOP)
-                log_dhcp_client(client, "STOPPED");
-        else
-                log_dhcp_client(client, "STOPPED: Unknown event");
-
-        client_notify(client, error);
-
-        client_initialize(client);
-}
-
-/* RFC2131 section 4.1:
- * retransmission delays should include -1 to +1 sec of random 'fuzz'. */
-#define RFC2131_RANDOM_FUZZ \
-        ((int64_t)(random_u64() % (2 * USEC_PER_SEC)) - (int64_t)USEC_PER_SEC)
-
-/* RFC2131 section 4.1:
- * for retransmission delays, timeout should start at 4s then double
- * each attempt with max of 64s, with -1 to +1 sec of random 'fuzz' added.
- * This assumes the first call will be using attempt 1. */
-static usec_t client_compute_request_timeout(usec_t now, uint64_t attempt) {
-        usec_t timeout = (UINT64_C(1) << MIN(attempt + 1, UINT64_C(6))) * USEC_PER_SEC;
-
-        return usec_sub_signed(usec_add(now, timeout), RFC2131_RANDOM_FUZZ);
-}
-
-/* RFC2131 section 4.4.5:
- * T1 defaults to (0.5 * duration_of_lease).
- * T2 defaults to (0.875 * duration_of_lease). */
-#define T1_DEFAULT(lifetime) ((lifetime) / 2)
-#define T2_DEFAULT(lifetime) (((lifetime) * 7) / 8)
-
-/* RFC2131 section 4.4.5:
- * the client SHOULD wait one-half of the remaining time until T2 (in RENEWING state)
- * and one-half of the remaining lease time (in REBINDING state), down to a minimum
- * of 60 seconds.
- * Note that while the default T1/T2 initial times do have random 'fuzz' applied,
- * the RFC sec 4.4.5 does not mention adding any fuzz to retries. */
-static usec_t client_compute_reacquisition_timeout(usec_t now, usec_t expire) {
-        return now + MAX(usec_sub_unsigned(expire, now) / 2, 60 * USEC_PER_SEC);
-}
-
-static int cmp_uint8(const uint8_t *a, const uint8_t *b) {
-        return CMP(*a, *b);
-}
-
-static int client_message_init(
-                sd_dhcp_client *client,
-                DHCPPacket **ret,
-                uint8_t type,
-                size_t *_optlen,
-                size_t *_optoffset) {
-
-        _cleanup_free_ DHCPPacket *packet = NULL;
-        size_t optlen, optoffset, size;
-        be16_t max_size;
-        usec_t time_now;
-        uint16_t secs;
-        int r;
-
-        assert(client);
-        assert(client->start_time);
-        assert(ret);
-        assert(_optlen);
-        assert(_optoffset);
-        assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST, DHCP_RELEASE, DHCP_DECLINE));
-
-        optlen = DHCP_MIN_OPTIONS_SIZE;
-        size = sizeof(DHCPPacket) + optlen;
-
-        packet = malloc0(size);
-        if (!packet)
-                return -ENOMEM;
-
-        r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
-                              client->arp_type, client->mac_addr_len, client->mac_addr,
-                              optlen, &optoffset);
-        if (r < 0)
-                return r;
-
-        /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
-           refuse to issue an DHCP lease if 'secs' is set to zero */
-        r = sd_event_now(client->event, CLOCK_BOOTTIME, &time_now);
-        if (r < 0)
-                return r;
-        assert(time_now >= client->start_time);
-
-        /* seconds between sending first and last DISCOVER
-         * must always be strictly positive to deal with broken servers */
-        secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
-        packet->dhcp.secs = htobe16(secs);
-
-        /* RFC2131 section 4.1
-           A client that cannot receive unicast IP datagrams until its protocol
-           software has been configured with an IP address SHOULD set the
-           BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or
-           DHCPREQUEST messages that client sends.  The BROADCAST bit will
-           provide a hint to the DHCP server and BOOTP relay agent to broadcast
-           any messages to the client on the client's subnet.
-
-           Note: some interfaces needs this to be enabled, but some networks
-           needs this to be disabled as broadcasts are filteretd, so this
-           needs to be configurable */
-        if (client->request_broadcast || client->arp_type != ARPHRD_ETHER)
-                packet->dhcp.flags = htobe16(0x8000);
-
-        /* If no client identifier exists, construct an RFC 4361-compliant one */
-        if (client->client_id_len == 0) {
-                size_t duid_len;
-
-                client->client_id.type = 255;
-
-                r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len,
-                                             /* legacy_unstable_byteorder = */ true,
-                                             /* use_mac = */ client->test_mode,
-                                             &client->client_id.ns.iaid);
-                if (r < 0)
-                        return r;
-
-                r = dhcp_identifier_set_duid_en(client->test_mode, &client->client_id.ns.duid, &duid_len);
-                if (r < 0)
-                        return r;
-
-                client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + duid_len;
-        }
-
-        /* Some DHCP servers will refuse to issue an DHCP lease if the Client
-           Identifier option is not set */
-        if (client->client_id_len) {
-                r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
-                                       SD_DHCP_OPTION_CLIENT_IDENTIFIER,
-                                       client->client_id_len,
-                                       &client->client_id);
-                if (r < 0)
-                        return r;
-        }
-
-        /* RFC2131 section 3.5:
-           in its initial DHCPDISCOVER or DHCPREQUEST message, a
-           client may provide the server with a list of specific
-           parameters the client is interested in. If the client
-           includes a list of parameters in a DHCPDISCOVER message,
-           it MUST include that list in any subsequent DHCPREQUEST
-           messages.
-         */
-
-        /* RFC7844 section 3:
-           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 (!set_isempty(client->req_opts) && type != DHCP_RELEASE) {
-                _cleanup_free_ uint8_t *opts = NULL;
-                size_t n_opts, i = 0;
-                void *val;
-
-                n_opts = set_size(client->req_opts);
-                opts = new(uint8_t, n_opts);
-                if (!opts)
-                        return -ENOMEM;
-
-                SET_FOREACH(val, client->req_opts)
-                        opts[i++] = PTR_TO_UINT8(val);
-                assert(i == n_opts);
-
-                /* For anonymizing the request, let's sort the options. */
-                typesafe_qsort(opts, n_opts, cmp_uint8);
-
-                r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
-                                       SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
-                                       n_opts, opts);
-                if (r < 0)
-                        return r;
-        }
-
-        /* RFC2131 section 3.5:
-           The client SHOULD include the ’maximum DHCP message size’ option to
-           let the server know how large the server may make its DHCP messages.
-
-           Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
-           than the defined default size unless the Maximum Message Size option
-           is explicitly set
-
-           RFC3442 "Requirements to Avoid Sizing Constraints":
-           Because a full routing table can be quite large, the standard 576
-           octet maximum size for a DHCP message may be too short to contain
-           some legitimate Classless Static Route options.  Because of this,
-           clients implementing the Classless Static Route option SHOULD send a
-           Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
-           stack is capable of receiving larger IP datagrams.  In this case, the
-           client SHOULD set the value of this option to at least the MTU of the
-           interface that the client is configuring.  The client MAY set the
-           value of this option higher, up to the size of the largest UDP packet
-           it is prepared to accept.  (Note that the value specified in the
-           Maximum DHCP Message Size option is the total maximum packet size,
-           including IP and UDP headers.)
-         */
-        /* RFC7844 section 3:
-           SHOULD NOT contain any other option. */
-        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,
-                                       2, &max_size);
-                if (r < 0)
-                        return r;
-        }
-
-        *_optlen = optlen;
-        *_optoffset = optoffset;
-        *ret = TAKE_PTR(packet);
-
-        return 0;
-}
-
-static int client_append_fqdn_option(
-                DHCPMessage *message,
-                size_t optlen,
-                size_t *optoffset,
-                const char *fqdn) {
-
-        uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH];
-        int r;
-
-        buffer[0] = DHCP_FQDN_FLAG_S | /* Request server to perform A RR DNS updates */
-                    DHCP_FQDN_FLAG_E;  /* Canonical wire format */
-        buffer[1] = 0;                 /* RCODE1 (deprecated) */
-        buffer[2] = 0;                 /* RCODE2 (deprecated) */
-
-        r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3, false);
-        if (r > 0)
-                r = dhcp_option_append(message, optlen, optoffset, 0,
-                                       SD_DHCP_OPTION_FQDN, 3 + r, buffer);
-
-        return r;
-}
-
-static int dhcp_client_send_raw(
-                sd_dhcp_client *client,
-                DHCPPacket *packet,
-                size_t len) {
-
-        dhcp_packet_append_ip_headers(packet, INADDR_ANY, client->port,
-                                      INADDR_BROADCAST, DHCP_PORT_SERVER, len, client->ip_service_type);
-
-        return dhcp_network_send_raw_socket(client->fd, &client->link,
-                                            packet, len);
-}
-
-static int client_append_common_discover_request_options(sd_dhcp_client *client, DHCPPacket *packet, size_t *optoffset, size_t optlen) {
-        sd_dhcp_option *j;
-        int r;
-
-        assert(client);
-
-        if (client->hostname) {
-                /* According to RFC 4702 "clients that send the Client FQDN option in
-                   their messages MUST NOT also send the Host Name option". Just send
-                   one of the two depending on the hostname type.
-                */
-                if (dns_name_is_single_label(client->hostname)) {
-                        /* it is unclear from RFC 2131 if client should send hostname in
-                           DHCPDISCOVER but dhclient does and so we do as well
-                        */
-                        r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
-                                               SD_DHCP_OPTION_HOST_NAME,
-                                               strlen(client->hostname), client->hostname);
-                } else
-                        r = client_append_fqdn_option(&packet->dhcp, optlen, optoffset,
-                                                      client->hostname);
-                if (r < 0)
-                        return r;
-        }
-
-        if (client->vendor_class_identifier) {
-                r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
-                                       SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
-                                       strlen(client->vendor_class_identifier),
-                                       client->vendor_class_identifier);
-                if (r < 0)
-                        return r;
-        }
-
-        if (client->mudurl) {
-                r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
-                                       SD_DHCP_OPTION_MUD_URL,
-                                       strlen(client->mudurl),
-                                       client->mudurl);
-                if (r < 0)
-                        return r;
-        }
-
-        if (client->user_class) {
-                r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
-                                       SD_DHCP_OPTION_USER_CLASS,
-                                       strv_length(client->user_class),
-                                       client->user_class);
-                if (r < 0)
-                        return r;
-        }
-
-        ORDERED_HASHMAP_FOREACH(j, client->extra_options) {
-                r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0,
-                                       j->option, j->length, j->data);
-                if (r < 0)
-                        return r;
-        }
-
-        if (!ordered_hashmap_isempty(client->vendor_options)) {
-                r = dhcp_option_append(
-                                &packet->dhcp, optlen, optoffset, 0,
-                                SD_DHCP_OPTION_VENDOR_SPECIFIC,
-                                ordered_hashmap_size(client->vendor_options), client->vendor_options);
-                if (r < 0)
-                        return r;
-        }
-
-
-        return 0;
-}
-
-static int client_send_discover(sd_dhcp_client *client) {
-        _cleanup_free_ DHCPPacket *discover = NULL;
-        size_t optoffset, optlen;
-        int r;
-
-        assert(client);
-        assert(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_SELECTING));
-
-        r = client_message_init(client, &discover, DHCP_DISCOVER,
-                                &optlen, &optoffset);
-        if (r < 0)
-                return r;
-
-        /* the client may suggest values for the network address
-           and lease time in the DHCPDISCOVER message. The client may include
-           the ’requested IP address’ option to suggest that a particular IP
-           address be assigned, and may include the ’IP address lease time’
-           option to suggest the lease time it would like.
-         */
-        /* RFC7844 section 3:
-           SHOULD NOT contain any other option. */
-        if (!client->anonymize && client->last_addr != INADDR_ANY) {
-                r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
-                                       SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
-                                       4, &client->last_addr);
-                if (r < 0)
-                        return r;
-        }
-
-        r = client_append_common_discover_request_options(client, discover, &optoffset, optlen);
-        if (r < 0)
-                return r;
-
-        r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
-                               SD_DHCP_OPTION_END, 0, NULL);
-        if (r < 0)
-                return r;
-
-        /* We currently ignore:
-           The client SHOULD wait a random time between one and ten seconds to
-           desynchronize the use of DHCP at startup.
-         */
-        r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset);
-        if (r < 0)
-                return r;
-
-        log_dhcp_client(client, "DISCOVER");
-
-        return 0;
-}
-
-static int client_send_request(sd_dhcp_client *client) {
-        _cleanup_free_ DHCPPacket *request = NULL;
-        size_t optoffset, optlen;
-        int r;
-
-        assert(client);
-
-        r = client_message_init(client, &request, DHCP_REQUEST, &optlen, &optoffset);
-        if (r < 0)
-                return r;
-
-        switch (client->state) {
-        /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC,
-           SELECTING should be REQUESTING)
-         */
-
-        case DHCP_STATE_REQUESTING:
-                /* Client inserts the address of the selected server in ’server
-                   identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be
-                   filled in with the yiaddr value from the chosen DHCPOFFER.
-                 */
-
-                r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                                       SD_DHCP_OPTION_SERVER_IDENTIFIER,
-                                       4, &client->lease->server_address);
-                if (r < 0)
-                        return r;
-
-                r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                                       SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
-                                       4, &client->lease->address);
-                if (r < 0)
-                        return r;
-
-                break;
-
-        case DHCP_STATE_INIT_REBOOT:
-                /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
-                   option MUST be filled in with client’s notion of its previously
-                   assigned address. ’ciaddr’ MUST be zero.
-                 */
-                r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                                       SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
-                                       4, &client->last_addr);
-                if (r < 0)
-                        return r;
-                break;
-
-        case DHCP_STATE_RENEWING:
-                /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
-                   option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
-                   client’s IP address.
-                */
-
-        case DHCP_STATE_REBINDING:
-                /* ’server identifier’ MUST NOT be filled in, ’requested IP address’
-                   option MUST NOT be filled in, ’ciaddr’ MUST be filled in with
-                   client’s IP address.
-
-                   This message MUST be broadcast to the 0xffffffff IP broadcast address.
-                 */
-                request->dhcp.ciaddr = client->lease->address;
-
-                break;
-
-        case DHCP_STATE_INIT:
-        case DHCP_STATE_SELECTING:
-        case DHCP_STATE_REBOOTING:
-        case DHCP_STATE_BOUND:
-        case DHCP_STATE_STOPPED:
-                return -EINVAL;
-        }
-
-        r = client_append_common_discover_request_options(client, request, &optoffset, optlen);
-        if (r < 0)
-                return r;
-
-        r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
-                               SD_DHCP_OPTION_END, 0, NULL);
-        if (r < 0)
-                return r;
-
-        if (client->state == DHCP_STATE_RENEWING)
-                r = dhcp_network_send_udp_socket(client->fd,
-                                                 client->lease->server_address,
-                                                 DHCP_PORT_SERVER,
-                                                 &request->dhcp,
-                                                 sizeof(DHCPMessage) + optoffset);
-        else
-                r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset);
-        if (r < 0)
-                return r;
-
-        switch (client->state) {
-
-        case DHCP_STATE_REQUESTING:
-                log_dhcp_client(client, "REQUEST (requesting)");
-                break;
-
-        case DHCP_STATE_INIT_REBOOT:
-                log_dhcp_client(client, "REQUEST (init-reboot)");
-                break;
-
-        case DHCP_STATE_RENEWING:
-                log_dhcp_client(client, "REQUEST (renewing)");
-                break;
-
-        case DHCP_STATE_REBINDING:
-                log_dhcp_client(client, "REQUEST (rebinding)");
-                break;
-
-        default:
-                log_dhcp_client(client, "REQUEST (invalid)");
-                break;
-        }
-
-        return 0;
-}
-
-static int client_start(sd_dhcp_client *client);
-
-static int client_timeout_resend(
-                sd_event_source *s,
-                uint64_t usec,
-                void *userdata) {
-
-        sd_dhcp_client *client = userdata;
-        DHCP_CLIENT_DONT_DESTROY(client);
-        usec_t next_timeout;
-        uint64_t time_now;
-        int r;
-
-        assert(s);
-        assert(client);
-        assert(client->event);
-
-        r = sd_event_now(client->event, CLOCK_BOOTTIME, &time_now);
-        if (r < 0)
-                goto error;
-
-        switch (client->state) {
-
-        case DHCP_STATE_RENEWING:
-                next_timeout = client_compute_reacquisition_timeout(time_now, client->t2_time);
-                break;
-
-        case DHCP_STATE_REBINDING:
-                next_timeout = client_compute_reacquisition_timeout(time_now, client->expire_time);
-                break;
-
-        case DHCP_STATE_REBOOTING:
-                /* start over as we did not receive a timely ack or nak */
-                r = client_initialize(client);
-                if (r < 0)
-                        goto error;
-
-                r = client_start(client);
-                if (r < 0)
-                        goto error;
-
-                log_dhcp_client(client, "REBOOTED");
-                return 0;
-
-        case DHCP_STATE_INIT:
-        case DHCP_STATE_INIT_REBOOT:
-        case DHCP_STATE_SELECTING:
-        case DHCP_STATE_REQUESTING:
-        case DHCP_STATE_BOUND:
-                if (client->attempt >= client->max_attempts)
-                        goto error;
-
-                client->attempt++;
-                next_timeout = client_compute_request_timeout(time_now, client->attempt);
-                break;
-
-        case DHCP_STATE_STOPPED:
-                r = -EINVAL;
-                goto error;
-
-        default:
-                assert_not_reached();
-        }
-
-        r = event_reset_time(client->event, &client->timeout_resend,
-                             CLOCK_BOOTTIME,
-                             next_timeout, 10 * USEC_PER_MSEC,
-                             client_timeout_resend, client,
-                             client->event_priority, "dhcp4-resend-timer", true);
-        if (r < 0)
-                goto error;
-
-        switch (client->state) {
-        case DHCP_STATE_INIT:
-                r = client_send_discover(client);
-                if (r >= 0) {
-                        client->state = DHCP_STATE_SELECTING;
-                        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 >= client->max_attempts)
-                        goto error;
-
-                break;
-
-        case DHCP_STATE_INIT_REBOOT:
-        case DHCP_STATE_REQUESTING:
-        case DHCP_STATE_RENEWING:
-        case DHCP_STATE_REBINDING:
-                r = client_send_request(client);
-                if (r < 0 && client->attempt >= client->max_attempts)
-                         goto error;
-
-                if (client->state == DHCP_STATE_INIT_REBOOT)
-                        client->state = DHCP_STATE_REBOOTING;
-
-                client->request_sent = time_now;
-                break;
-
-        case DHCP_STATE_REBOOTING:
-        case DHCP_STATE_BOUND:
-                break;
-
-        case DHCP_STATE_STOPPED:
-                r = -EINVAL;
-                goto error;
-        }
-
-        if (client->attempt >= TRANSIENT_FAILURE_ATTEMPTS)
-                client_notify(client, SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE);
-
-        return 0;
-
-error:
-        client_stop(client, r);
-
-        /* Errors were dealt with when stopping the client, don't spill
-           errors into the event loop handler */
-        return 0;
-}
-
-static int client_initialize_io_events(
-                sd_dhcp_client *client,
-                sd_event_io_handler_t io_callback) {
-
-        int r;
-
-        assert(client);
-        assert(client->event);
-
-        r = sd_event_add_io(client->event, &client->receive_message,
-                            client->fd, EPOLLIN, io_callback,
-                            client);
-        if (r < 0)
-                goto error;
-
-        r = sd_event_source_set_priority(client->receive_message,
-                                         client->event_priority);
-        if (r < 0)
-                goto error;
-
-        r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message");
-        if (r < 0)
-                goto error;
-
-error:
-        if (r < 0)
-                client_stop(client, r);
-
-        return 0;
-}
-
-static int client_initialize_time_events(sd_dhcp_client *client) {
-        uint64_t usec = 0;
-        int r;
-
-        assert(client);
-        assert(client->event);
-
-        if (client->start_delay > 0) {
-                assert_se(sd_event_now(client->event, CLOCK_BOOTTIME, &usec) >= 0);
-                usec += client->start_delay;
-        }
-
-        r = event_reset_time(client->event, &client->timeout_resend,
-                             CLOCK_BOOTTIME,
-                             usec, 0,
-                             client_timeout_resend, client,
-                             client->event_priority, "dhcp4-resend-timer", true);
-        if (r < 0)
-                client_stop(client, r);
-
-        return 0;
-
-}
-
-static int client_initialize_events(sd_dhcp_client *client, sd_event_io_handler_t io_callback) {
-        client_initialize_io_events(client, io_callback);
-        client_initialize_time_events(client);
-
-        return 0;
-}
-
-static int client_start_delayed(sd_dhcp_client *client) {
-        int r;
-
-        assert_return(client, -EINVAL);
-        assert_return(client->event, -EINVAL);
-        assert_return(client->ifindex > 0, -EINVAL);
-        assert_return(client->fd < 0, -EBUSY);
-        assert_return(client->xid == 0, -EINVAL);
-        assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_INIT_REBOOT), -EBUSY);
-
-        client->xid = random_u32();
-
-        r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid,
-                                         client->mac_addr, client->mac_addr_len,
-                                         client->bcast_addr, client->bcast_addr_len,
-                                         client->arp_type, client->port);
-        if (r < 0) {
-                client_stop(client, r);
-                return r;
-        }
-        client->fd = r;
-
-        if (IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_INIT_REBOOT))
-                client->start_time = now(CLOCK_BOOTTIME);
-
-        return client_initialize_events(client, client_receive_message_raw);
-}
-
-static int client_start(sd_dhcp_client *client) {
-        client->start_delay = 0;
-        return client_start_delayed(client);
-}
-
-static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) {
-        sd_dhcp_client *client = userdata;
-        DHCP_CLIENT_DONT_DESTROY(client);
-
-        log_dhcp_client(client, "EXPIRED");
-
-        client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED);
-
-        /* lease was lost, start over if not freed or stopped in callback */
-        if (client->state != DHCP_STATE_STOPPED) {
-                client_initialize(client);
-                client_start(client);
-        }
-
-        return 0;
-}
-
-static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
-        sd_dhcp_client *client = userdata;
-        DHCP_CLIENT_DONT_DESTROY(client);
-        int r;
-
-        assert(client);
-
-        client->receive_message = sd_event_source_disable_unref(client->receive_message);
-        client->fd = safe_close(client->fd);
-
-        client->state = DHCP_STATE_REBINDING;
-        client->attempt = 0;
-
-        r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid,
-                                         client->mac_addr, client->mac_addr_len,
-                                         client->bcast_addr, client->bcast_addr_len,
-                                         client->arp_type, client->port);
-        if (r < 0) {
-                client_stop(client, r);
-                return 0;
-        }
-        client->fd = r;
-
-        return client_initialize_events(client, client_receive_message_raw);
-}
-
-static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) {
-        sd_dhcp_client *client = userdata;
-        DHCP_CLIENT_DONT_DESTROY(client);
-
-        if (client->lease)
-                client->state = DHCP_STATE_RENEWING;
-        else if (client->state != DHCP_STATE_INIT)
-                client->state = DHCP_STATE_INIT_REBOOT;
-        client->attempt = 0;
-
-        return client_initialize_time_events(client);
-}
-
-static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_t len) {
-        _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
-        int r;
-
-        r = dhcp_lease_new(&lease);
-        if (r < 0)
-                return r;
-
-        if (client->client_id_len) {
-                r = dhcp_lease_set_client_id(lease,
-                                             (uint8_t *) &client->client_id,
-                                             client->client_id_len);
-                if (r < 0)
-                        return r;
-        }
-
-        r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease, NULL);
-        if (r != DHCP_OFFER) {
-                log_dhcp_client(client, "received message was not an OFFER, ignoring");
-                return -ENOMSG;
-        }
-
-        lease->next_server = offer->siaddr;
-        lease->address = offer->yiaddr;
-
-        if (lease->lifetime == 0 && client->fallback_lease_lifetime > 0)
-                lease->lifetime = client->fallback_lease_lifetime;
-
-        if (lease->address == 0 ||
-            lease->server_address == 0 ||
-            lease->lifetime == 0) {
-                log_dhcp_client(client, "received lease lacks address, server address or lease lifetime, ignoring");
-                return -ENOMSG;
-        }
-
-        if (!lease->have_subnet_mask) {
-                r = dhcp_lease_set_default_subnet_mask(lease);
-                if (r < 0) {
-                        log_dhcp_client(client,
-                                        "received lease lacks subnet mask, "
-                                        "and a fallback one cannot be generated, ignoring");
-                        return -ENOMSG;
-                }
-        }
-
-        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;
-}
-
-static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, size_t len) {
-        int r;
-
-        r = dhcp_option_parse(force, len, NULL, NULL, NULL);
-        if (r != DHCP_FORCERENEW)
-                return -ENOMSG;
-
-#if 0
-        log_dhcp_client(client, "FORCERENEW");
-
-        return 0;
-#else
-        /* FIXME: Ignore FORCERENEW requests until we implement RFC3118 (Authentication for DHCP
-         * Messages) and/or RFC6704 (Forcerenew Nonce Authentication), as unauthenticated FORCERENEW
-         * requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). */
-        log_dhcp_client(client, "Received FORCERENEW, ignoring.");
-        return -ENOMSG;
-#endif
-}
-
-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;
-        int r;
-
-        r = dhcp_lease_new(&lease);
-        if (r < 0)
-                return r;
-
-        if (client->client_id_len) {
-                r = dhcp_lease_set_client_id(lease,
-                                             (uint8_t *) &client->client_id,
-                                             client->client_id_len);
-                if (r < 0)
-                        return r;
-        }
-
-        r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease, &error_message);
-        if (r == DHCP_NAK) {
-                log_dhcp_client(client, "NAK: %s", strna(error_message));
-                return -EADDRNOTAVAIL;
-        }
-
-        if (r != DHCP_ACK) {
-                log_dhcp_client(client, "received message was not an ACK, ignoring");
-                return -ENOMSG;
-        }
-
-        lease->next_server = ack->siaddr;
-
-        lease->address = ack->yiaddr;
-
-        if (lease->address == INADDR_ANY ||
-            lease->server_address == INADDR_ANY ||
-            lease->lifetime == 0) {
-                log_dhcp_client(client, "received lease lacks address, server "
-                                "address or lease lifetime, ignoring");
-                return -ENOMSG;
-        }
-
-        if (lease->subnet_mask == INADDR_ANY) {
-                r = dhcp_lease_set_default_subnet_mask(lease);
-                if (r < 0) {
-                        log_dhcp_client(client,
-                                        "received lease lacks subnet mask, "
-                                        "and a fallback one cannot be generated, ignoring");
-                        return -ENOMSG;
-                }
-        }
-
-        r = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
-        if (client->lease) {
-                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);
-        }
-
-        client->lease = TAKE_PTR(lease);
-
-        log_dhcp_client(client, "ACK");
-
-        return r;
-}
-
-static int client_set_lease_timeouts(sd_dhcp_client *client) {
-        usec_t time_now;
-        int r;
-
-        assert(client);
-        assert(client->event);
-        assert(client->lease);
-        assert(client->lease->lifetime);
-
-        /* don't set timers for infinite leases */
-        if (client->lease->lifetime == 0xffffffff) {
-                (void) event_source_disable(client->timeout_t1);
-                (void) event_source_disable(client->timeout_t2);
-                (void) event_source_disable(client->timeout_expire);
-
-                return 0;
-        }
-
-        r = sd_event_now(client->event, CLOCK_BOOTTIME, &time_now);
-        if (r < 0)
-                return r;
-        assert(client->request_sent <= time_now);
-
-        /* verify that 0 < t2 < lifetime */
-        if (client->lease->t2 == 0 || client->lease->t2 >= client->lease->lifetime)
-                client->lease->t2 = T2_DEFAULT(client->lease->lifetime);
-        /* verify that 0 < t1 < lifetime */
-        if (client->lease->t1 == 0 || client->lease->t1 >= client->lease->t2)
-                client->lease->t1 = T1_DEFAULT(client->lease->lifetime);
-        /* now, if t1 >= t2, t1 *must* be T1_DEFAULT, since the previous check
-         * could not evalate to false if t1 >= t2; so setting t2 to T2_DEFAULT
-         * guarantees t1 < t2. */
-        if (client->lease->t1 >= client->lease->t2)
-                client->lease->t2 = T2_DEFAULT(client->lease->lifetime);
-
-        client->expire_time = client->request_sent + client->lease->lifetime * USEC_PER_SEC;
-        client->t1_time = client->request_sent + client->lease->t1 * USEC_PER_SEC;
-        client->t2_time = client->request_sent + client->lease->t2 * USEC_PER_SEC;
-
-        /* RFC2131 section 4.4.5:
-         * Times T1 and T2 SHOULD be chosen with some random "fuzz".
-         * Since the RFC doesn't specify here the exact 'fuzz' to use,
-         * we use the range from section 4.1: -1 to +1 sec. */
-        client->t1_time = usec_sub_signed(client->t1_time, RFC2131_RANDOM_FUZZ);
-        client->t2_time = usec_sub_signed(client->t2_time, RFC2131_RANDOM_FUZZ);
-
-        /* after fuzzing, ensure t2 is still >= t1 */
-        client->t2_time = MAX(client->t1_time, client->t2_time);
-
-        /* arm lifetime timeout */
-        r = event_reset_time(client->event, &client->timeout_expire,
-                             CLOCK_BOOTTIME,
-                             client->expire_time, 10 * USEC_PER_MSEC,
-                             client_timeout_expire, client,
-                             client->event_priority, "dhcp4-lifetime", true);
-        if (r < 0)
-                return r;
-
-        /* don't arm earlier timeouts if this has already expired */
-        if (client->expire_time <= time_now)
-                return 0;
-
-        log_dhcp_client(client, "lease expires in %s",
-                        FORMAT_TIMESPAN(client->expire_time - time_now, USEC_PER_SEC));
-
-        /* arm T2 timeout */
-        r = event_reset_time(client->event, &client->timeout_t2,
-                             CLOCK_BOOTTIME,
-                             client->t2_time, 10 * USEC_PER_MSEC,
-                             client_timeout_t2, client,
-                             client->event_priority, "dhcp4-t2-timeout", true);
-        if (r < 0)
-                return r;
-
-        /* don't arm earlier timeout if this has already expired */
-        if (client->t2_time <= time_now)
-                return 0;
-
-        log_dhcp_client(client, "T2 expires in %s",
-                        FORMAT_TIMESPAN(client->t2_time - time_now, USEC_PER_SEC));
-
-        /* arm T1 timeout */
-        r = event_reset_time(client->event, &client->timeout_t1,
-                             CLOCK_BOOTTIME,
-                             client->t1_time, 10 * USEC_PER_MSEC,
-                             client_timeout_t1, client,
-                             client->event_priority, "dhcp4-t1-timer", true);
-        if (r < 0)
-                return r;
-
-        if (client->t1_time > time_now)
-                log_dhcp_client(client, "T1 expires in %s",
-                                FORMAT_TIMESPAN(client->t1_time - time_now, USEC_PER_SEC));
-
-        return 0;
-}
-
-static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, int len) {
-        DHCP_CLIENT_DONT_DESTROY(client);
-        int r, notify_event;
-
-        assert(client);
-        assert(client->event);
-        assert(message);
-
-        switch (client->state) {
-        case DHCP_STATE_SELECTING:
-
-                r = client_handle_offer(client, message, len);
-                if (r == -ENOMSG)
-                        return 0; /* invalid message, let's ignore it */
-                if (r < 0)
-                        goto error;
-
-                client->state = DHCP_STATE_REQUESTING;
-                client->attempt = 0;
-
-                r = event_reset_time(client->event, &client->timeout_resend,
-                                     CLOCK_BOOTTIME,
-                                     0, 0,
-                                     client_timeout_resend, client,
-                                     client->event_priority, "dhcp4-resend-timer", true);
-                break;
-
-        case DHCP_STATE_REBOOTING:
-        case DHCP_STATE_REQUESTING:
-        case DHCP_STATE_RENEWING:
-        case DHCP_STATE_REBINDING:
-
-                r = client_handle_ack(client, message, len);
-                if (r == -ENOMSG)
-                        return 0; /* invalid message, let's ignore it */
-                if (r == -EADDRNOTAVAIL) {
-                        /* got a NAK, let's restart the client */
-                        client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED);
-
-                        r = client_initialize(client);
-                        if (r < 0)
-                                goto error;
-
-                        r = client_start_delayed(client);
-                        if (r < 0)
-                                goto error;
-
-                        log_dhcp_client(client, "REBOOT in %s", FORMAT_TIMESPAN(client->start_delay, USEC_PER_SEC));
-
-                        client->start_delay = CLAMP(client->start_delay * 2,
-                                                    RESTART_AFTER_NAK_MIN_USEC, RESTART_AFTER_NAK_MAX_USEC);
-                        return 0;
-                }
-                if (r < 0)
-                        goto error;
-
-                if (IN_SET(client->state, DHCP_STATE_REQUESTING, DHCP_STATE_REBOOTING))
-                        notify_event = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
-                else
-                        notify_event = r;
-
-                client->start_delay = 0;
-                (void) event_source_disable(client->timeout_resend);
-                client->receive_message = sd_event_source_disable_unref(client->receive_message);
-                client->fd = safe_close(client->fd);
-
-                client->state = DHCP_STATE_BOUND;
-                client->attempt = 0;
-
-                client->last_addr = client->lease->address;
-
-                r = client_set_lease_timeouts(client);
-                if (r < 0) {
-                        log_dhcp_client(client, "could not set lease timeouts");
-                        goto error;
-                }
-
-                r = dhcp_network_bind_udp_socket(client->ifindex, client->lease->address, client->port, client->ip_service_type);
-                if (r < 0) {
-                        log_dhcp_client(client, "could not bind UDP socket");
-                        goto error;
-                }
-
-                client->fd = r;
-
-                client_initialize_io_events(client, client_receive_message_udp);
-
-                if (IN_SET(client->state, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING) &&
-                    notify_event == SD_DHCP_CLIENT_EVENT_IP_ACQUIRE)
-                        /* FIXME: hmm, maybe this is a bug... */
-                        log_dhcp_client(client, "client_handle_ack() returned SD_DHCP_CLIENT_EVENT_IP_ACQUIRE while DHCP client is %s the address, skipping callback.",
-                                        client->state == DHCP_STATE_RENEWING ? "renewing" : "rebinding");
-                else
-                        client_notify(client, notify_event);
-                break;
-
-        case DHCP_STATE_BOUND:
-                r = client_handle_forcerenew(client, message, len);
-                if (r == -ENOMSG)
-                        return 0; /* invalid message, let's ignore it */
-                if (r < 0)
-                        goto error;
-
-                r = client_timeout_t1(NULL, 0, client);
-                break;
-
-        case DHCP_STATE_INIT:
-        case DHCP_STATE_INIT_REBOOT:
-                r = 0;
-                break;
-
-        case DHCP_STATE_STOPPED:
-                r = -EINVAL;
-                goto error;
-        default:
-                assert_not_reached();
-        }
-
-error:
-        if (r < 0)
-                client_stop(client, r);
-
-        return r;
-}
-
-static int client_receive_message_udp(
-                sd_event_source *s,
-                int fd,
-                uint32_t revents,
-                void *userdata) {
-
-        sd_dhcp_client *client = userdata;
-        _cleanup_free_ DHCPMessage *message = NULL;
-        const uint8_t *expected_chaddr = NULL;
-        uint8_t expected_hlen = 0;
-        ssize_t len, buflen;
-
-        assert(s);
-        assert(client);
-
-        buflen = next_datagram_size_fd(fd);
-        if (buflen < 0) {
-                if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen))
-                        return 0;
-
-                log_dhcp_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m");
-                return 0;
-        }
-
-        message = malloc0(buflen);
-        if (!message)
-                return -ENOMEM;
-
-        len = recv(fd, message, buflen, 0);
-        if (len < 0) {
-                if (ERRNO_IS_TRANSIENT(errno) || ERRNO_IS_DISCONNECT(errno))
-                        return 0;
-
-                log_dhcp_client_errno(client, errno, "Could not receive message from UDP socket, ignoring: %m");
-                return 0;
-        }
-        if ((size_t) len < sizeof(DHCPMessage)) {
-                log_dhcp_client(client, "Too small to be a DHCP message: ignoring");
-                return 0;
-        }
-
-        if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
-                log_dhcp_client(client, "Not a DHCP message: ignoring");
-                return 0;
-        }
-
-        if (message->op != BOOTREPLY) {
-                log_dhcp_client(client, "Not a BOOTREPLY message: ignoring");
-                return 0;
-        }
-
-        if (message->htype != client->arp_type) {
-                log_dhcp_client(client, "Packet type does not match client type");
-                return 0;
-        }
-
-        if (client->arp_type == ARPHRD_ETHER) {
-                expected_hlen = ETH_ALEN;
-                expected_chaddr = &client->mac_addr[0];
-        }
-
-        if (message->hlen != expected_hlen) {
-                log_dhcp_client(client, "Unexpected packet hlen %d", message->hlen);
-                return 0;
-        }
-
-        if (expected_hlen > 0 && memcmp(&message->chaddr[0], expected_chaddr, expected_hlen)) {
-                log_dhcp_client(client, "Received chaddr does not match expected: ignoring");
-                return 0;
-        }
-
-        if (client->state != DHCP_STATE_BOUND &&
-            be32toh(message->xid) != client->xid) {
-                /* in BOUND state, we may receive FORCERENEW with xid set by server,
-                   so ignore the xid in this case */
-                log_dhcp_client(client, "Received xid (%u) does not match expected (%u): ignoring",
-                                be32toh(message->xid), client->xid);
-                return 0;
-        }
-
-        log_dhcp_client(client, "Received message from UDP socket, processing.");
-        (void) client_handle_message(client, message, len);
-        return 0;
-}
-
-static int client_receive_message_raw(
-                sd_event_source *s,
-                int fd,
-                uint32_t revents,
-                void *userdata) {
-
-        sd_dhcp_client *client = userdata;
-        _cleanup_free_ DHCPPacket *packet = NULL;
-        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct tpacket_auxdata))) control;
-        struct iovec iov = {};
-        struct msghdr msg = {
-                .msg_iov = &iov,
-                .msg_iovlen = 1,
-                .msg_control = &control,
-                .msg_controllen = sizeof(control),
-        };
-        struct cmsghdr *cmsg;
-        bool checksum = true;
-        ssize_t buflen, len;
-        int r;
-
-        assert(s);
-        assert(client);
-
-        buflen = next_datagram_size_fd(fd);
-        if (buflen < 0) {
-                if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen))
-                        return 0;
-
-                log_dhcp_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m");
-                return 0;
-        }
-
-        packet = malloc0(buflen);
-        if (!packet)
-                return -ENOMEM;
-
-        iov = IOVEC_MAKE(packet, buflen);
-
-        len = recvmsg_safe(fd, &msg, 0);
-        if (len < 0) {
-                if (ERRNO_IS_TRANSIENT(len) || ERRNO_IS_DISCONNECT(len))
-                        return 0;
-
-                log_dhcp_client_errno(client, len, "Could not receive message from raw socket, ignoring: %m");
-                return 0;
-        }
-        if ((size_t) len < sizeof(DHCPPacket))
-                return 0;
-
-        cmsg = cmsg_find(&msg, SOL_PACKET, PACKET_AUXDATA, CMSG_LEN(sizeof(struct tpacket_auxdata)));
-        if (cmsg) {
-                struct tpacket_auxdata *aux = (struct tpacket_auxdata*) CMSG_DATA(cmsg);
-                checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY);
-        }
-
-        r = dhcp_packet_verify_headers(packet, len, checksum, client->port);
-        if (r < 0)
-                return 0;
-
-        len -= DHCP_IP_UDP_SIZE;
-
-        log_dhcp_client(client, "Received message from RAW socket, processing.");
-        (void) client_handle_message(client, &packet->dhcp, len);
-        return 0;
-}
-
-int sd_dhcp_client_send_renew(sd_dhcp_client *client) {
-        assert_return(client, -EINVAL);
-        assert_return(client->fd >= 0, -EINVAL);
-
-        if (!client->lease)
-                return 0;
-
-        client->start_delay = 0;
-        client->attempt = 1;
-        client->state = DHCP_STATE_RENEWING;
-
-        return client_initialize_time_events(client);
-}
-
-int sd_dhcp_client_is_running(sd_dhcp_client *client) {
-        if (!client)
-                return 0;
-
-        return !IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED);
-}
-
-int sd_dhcp_client_start(sd_dhcp_client *client) {
-        int r;
-
-        assert_return(client, -EINVAL);
-
-        r = client_initialize(client);
-        if (r < 0)
-                return r;
-
-        /* RFC7844 section 3.3:
-           SHOULD perform a complete four-way handshake, starting with a
-           DHCPDISCOVER, to obtain a new address lease.  If the client can
-           ascertain that this is exactly the same network to which it was
-           previously connected, and if the link-layer address did not change,
-           the client MAY issue a DHCPREQUEST to try to reclaim the current
-           address. */
-        if (client->last_addr && !client->anonymize)
-                client->state = DHCP_STATE_INIT_REBOOT;
-
-        r = client_start(client);
-        if (r >= 0)
-                log_dhcp_client(client, "STARTED on ifindex %i", client->ifindex);
-
-        return r;
-}
-
-int sd_dhcp_client_send_release(sd_dhcp_client *client) {
-        assert_return(client, -EINVAL);
-        assert_return(client->state != DHCP_STATE_STOPPED, -ESTALE);
-        assert_return(client->lease, -EUNATCH);
-
-        _cleanup_free_ DHCPPacket *release = NULL;
-        size_t optoffset, optlen;
-        int r;
-
-        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;
-}
-
-int sd_dhcp_client_send_decline(sd_dhcp_client *client) {
-        assert_return(client, -EINVAL);
-        assert_return(client->state != DHCP_STATE_STOPPED, -ESTALE);
-        assert_return(client->lease, -EUNATCH);
-
-        _cleanup_free_ DHCPPacket *release = NULL;
-        size_t optoffset, optlen;
-        int r;
-
-        r = client_message_init(client, &release, DHCP_DECLINE, &optlen, &optoffset);
-        if (r < 0)
-                return r;
-
-        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, "DECLINE");
-
-        client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
-
-        if (client->state != DHCP_STATE_STOPPED) {
-                r = sd_dhcp_client_start(client);
-                if (r < 0)
-                        return r;
-        }
-
-        return 0;
-}
-
-int sd_dhcp_client_stop(sd_dhcp_client *client) {
-        if (!client)
-                return 0;
-
-        DHCP_CLIENT_DONT_DESTROY(client);
-
-        client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
-        client->state = DHCP_STATE_STOPPED;
-
-        return 0;
-}
-
-int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority) {
-        int r;
-
-        assert_return(client, -EINVAL);
-        assert_return(!client->event, -EBUSY);
-
-        if (event)
-                client->event = sd_event_ref(event);
-        else {
-                r = sd_event_default(&client->event);
-                if (r < 0)
-                        return 0;
-        }
-
-        client->event_priority = priority;
-
-        return 0;
-}
-
-int sd_dhcp_client_detach_event(sd_dhcp_client *client) {
-        assert_return(client, -EINVAL);
-
-        client->event = sd_event_unref(client->event);
-
-        return 0;
-}
-
-sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
-        assert_return(client, NULL);
-
-        return client->event;
-}
-
-static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) {
-        if (!client)
-                return NULL;
-
-        log_dhcp_client(client, "FREE");
-
-        client_initialize(client);
-
-        client->timeout_resend = sd_event_source_unref(client->timeout_resend);
-        client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
-        client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
-        client->timeout_expire = sd_event_source_unref(client->timeout_expire);
-
-        sd_dhcp_client_detach_event(client);
-
-        set_free(client->req_opts);
-        free(client->hostname);
-        free(client->vendor_class_identifier);
-        free(client->mudurl);
-        client->user_class = strv_free(client->user_class);
-        ordered_hashmap_free(client->extra_options);
-        ordered_hashmap_free(client->vendor_options);
-        free(client->ifname);
-        return mfree(client);
-}
-
-DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free);
-
-int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
-        const uint8_t *opts;
-        size_t n_opts;
-        int r;
-
-        assert_return(ret, -EINVAL);
-
-        _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = new(sd_dhcp_client, 1);
-        if (!client)
-                return -ENOMEM;
-
-        *client = (sd_dhcp_client) {
-                .n_ref = 1,
-                .state = DHCP_STATE_INIT,
-                .ifindex = -1,
-                .fd = -1,
-                .mtu = DHCP_DEFAULT_MIN_SIZE,
-                .port = DHCP_PORT_CLIENT,
-                .anonymize = !!anonymize,
-                .max_attempts = UINT64_MAX,
-                .ip_service_type = -1,
-        };
-        /* NOTE: this could be moved to a function. */
-        if (anonymize) {
-                n_opts = ELEMENTSOF(default_req_opts_anonymize);
-                opts = default_req_opts_anonymize;
-        } else {
-                n_opts = ELEMENTSOF(default_req_opts);
-                opts = default_req_opts;
-        }
-
-        for (size_t i = 0; i < n_opts; i++) {
-                r = sd_dhcp_client_set_request_option(client, opts[i]);
-                if (r < 0)
-                        return r;
-        }
-
-        *ret = TAKE_PTR(client);
-
-        return 0;
-}
diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-lease.c b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-lease.c
deleted file mode 100644
index 5f83fa66..00000000
--- a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-lease.c
+++ /dev/null
@@ -1,1508 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/***
-  Copyright © 2013 Intel Corporation. All rights reserved.
-***/
-
-#include "nm-sd-adapt-core.h"
-
-#include <arpa/inet.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "sd-dhcp-lease.h"
-
-#include "alloc-util.h"
-#include "dhcp-lease-internal.h"
-#include "dhcp-protocol.h"
-#include "dns-domain.h"
-#include "env-file.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "fs-util.h"
-#include "hexdecoct.h"
-#include "hostname-util.h"
-#include "in-addr-util.h"
-#include "network-internal.h"
-#include "parse-util.h"
-#include "stdio-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "tmpfile-util.h"
-#include "unaligned.h"
-
-int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
-        assert_return(lease, -EINVAL);
-        assert_return(addr, -EINVAL);
-
-        if (lease->address == 0)
-                return -ENODATA;
-
-        addr->s_addr = lease->address;
-        return 0;
-}
-
-int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr) {
-        assert_return(lease, -EINVAL);
-        assert_return(addr, -EINVAL);
-
-        if (!lease->have_broadcast)
-                return -ENODATA;
-
-        addr->s_addr = lease->broadcast;
-        return 0;
-}
-
-int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) {
-        assert_return(lease, -EINVAL);
-        assert_return(lifetime, -EINVAL);
-
-        if (lease->lifetime <= 0)
-                return -ENODATA;
-
-        *lifetime = lease->lifetime;
-        return 0;
-}
-
-int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1) {
-        assert_return(lease, -EINVAL);
-        assert_return(t1, -EINVAL);
-
-        if (lease->t1 <= 0)
-                return -ENODATA;
-
-        *t1 = lease->t1;
-        return 0;
-}
-
-int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2) {
-        assert_return(lease, -EINVAL);
-        assert_return(t2, -EINVAL);
-
-        if (lease->t2 <= 0)
-                return -ENODATA;
-
-        *t2 = lease->t2;
-        return 0;
-}
-
-int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) {
-        assert_return(lease, -EINVAL);
-        assert_return(mtu, -EINVAL);
-
-        if (lease->mtu <= 0)
-                return -ENODATA;
-
-        *mtu = lease->mtu;
-        return 0;
-}
-
-int sd_dhcp_lease_get_servers(
-                sd_dhcp_lease *lease,
-                sd_dhcp_lease_server_type_t what,
-                const struct in_addr **addr) {
-
-        assert_return(lease, -EINVAL);
-        assert_return(what >= 0, -EINVAL);
-        assert_return(what < _SD_DHCP_LEASE_SERVER_TYPE_MAX, -EINVAL);
-
-        if (lease->servers[what].size <= 0)
-                return -ENODATA;
-
-        if (addr)
-                *addr = lease->servers[what].addr;
-
-        return (int) lease->servers[what].size;
-}
-
-int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) {
-        return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_DNS, addr);
-}
-int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) {
-        return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_NTP, addr);
-}
-int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) {
-        return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SIP, addr);
-}
-int sd_dhcp_lease_get_pop3(sd_dhcp_lease *lease, const struct in_addr **addr) {
-        return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_POP3, addr);
-}
-int sd_dhcp_lease_get_smtp(sd_dhcp_lease *lease, const struct in_addr **addr) {
-        return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SMTP, addr);
-}
-int sd_dhcp_lease_get_lpr(sd_dhcp_lease *lease, const struct in_addr **addr) {
-        return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_LPR, addr);
-}
-
-int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
-        assert_return(lease, -EINVAL);
-        assert_return(domainname, -EINVAL);
-
-        if (!lease->domainname)
-                return -ENODATA;
-
-        *domainname = lease->domainname;
-        return 0;
-}
-
-int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) {
-        assert_return(lease, -EINVAL);
-        assert_return(hostname, -EINVAL);
-
-        if (!lease->hostname)
-                return -ENODATA;
-
-        *hostname = lease->hostname;
-        return 0;
-}
-
-int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) {
-        assert_return(lease, -EINVAL);
-        assert_return(root_path, -EINVAL);
-
-        if (!lease->root_path)
-                return -ENODATA;
-
-        *root_path = lease->root_path;
-        return 0;
-}
-
-int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr) {
-        assert_return(lease, -EINVAL);
-        assert_return(addr, -EINVAL);
-
-        if (lease->router_size <= 0)
-                return -ENODATA;
-
-        *addr = lease->router;
-        return (int) lease->router_size;
-}
-
-int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
-        assert_return(lease, -EINVAL);
-        assert_return(addr, -EINVAL);
-
-        if (!lease->have_subnet_mask)
-                return -ENODATA;
-
-        addr->s_addr = lease->subnet_mask;
-        return 0;
-}
-
-int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr) {
-        assert_return(lease, -EINVAL);
-        assert_return(addr, -EINVAL);
-
-        if (lease->server_address == 0)
-                return -ENODATA;
-
-        addr->s_addr = lease->server_address;
-        return 0;
-}
-
-int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {
-        assert_return(lease, -EINVAL);
-        assert_return(addr, -EINVAL);
-
-        if (lease->next_server == 0)
-                return -ENODATA;
-
-        addr->s_addr = lease->next_server;
-        return 0;
-}
-
-/*
- * The returned routes array must be freed by the caller.
- * Route objects have the same lifetime of the lease and must not be freed.
- */
-static int dhcp_lease_get_routes(sd_dhcp_route *routes, size_t n_routes, sd_dhcp_route ***ret) {
-        assert(routes || n_routes == 0);
-
-        if (n_routes <= 0)
-                return -ENODATA;
-
-        if (ret) {
-                sd_dhcp_route **buf;
-
-                buf = new(sd_dhcp_route*, n_routes);
-                if (!buf)
-                        return -ENOMEM;
-
-                for (size_t i = 0; i < n_routes; i++)
-                        buf[i] = &routes[i];
-
-                *ret = buf;
-        }
-
-        return (int) n_routes;
-}
-
-int sd_dhcp_lease_get_static_routes(sd_dhcp_lease *lease, sd_dhcp_route ***ret) {
-        assert_return(lease, -EINVAL);
-
-        return dhcp_lease_get_routes(lease->static_routes, lease->n_static_routes, ret);
-}
-
-int sd_dhcp_lease_get_classless_routes(sd_dhcp_lease *lease, sd_dhcp_route ***ret) {
-        assert_return(lease, -EINVAL);
-
-        return dhcp_lease_get_routes(lease->classless_routes, lease->n_classless_routes, ret);
-}
-
-int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) {
-        size_t r;
-
-        assert_return(lease, -EINVAL);
-        assert_return(domains, -EINVAL);
-
-        r = strv_length(lease->search_domains);
-        if (r > 0) {
-                *domains = lease->search_domains;
-                return (int) r;
-        }
-
-        return -ENODATA;
-}
-
-int sd_dhcp_lease_get_6rd(
-                sd_dhcp_lease *lease,
-                uint8_t *ret_ipv4masklen,
-                uint8_t *ret_prefixlen,
-                struct in6_addr *ret_prefix,
-                const struct in_addr **ret_br_addresses,
-                size_t *ret_n_br_addresses) {
-
-        assert_return(lease, -EINVAL);
-
-        if (lease->sixrd_n_br_addresses <= 0)
-                return -ENODATA;
-
-        if (ret_ipv4masklen)
-                *ret_ipv4masklen = lease->sixrd_ipv4masklen;
-        if (ret_prefixlen)
-                *ret_prefixlen = lease->sixrd_prefixlen;
-        if (ret_prefix)
-                *ret_prefix = lease->sixrd_prefix;
-        if (ret_br_addresses)
-                *ret_br_addresses = lease->sixrd_br_addresses;
-        if (ret_n_br_addresses)
-                *ret_n_br_addresses = lease->sixrd_n_br_addresses;
-
-        return 0;
-}
-
-int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) {
-        assert_return(lease, -EINVAL);
-        assert_return(data, -EINVAL);
-        assert_return(data_len, -EINVAL);
-
-        if (lease->vendor_specific_len <= 0)
-                return -ENODATA;
-
-        *data = lease->vendor_specific;
-        *data_len = lease->vendor_specific_len;
-        return 0;
-}
-
-static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) {
-        assert(lease);
-
-        while (lease->private_options) {
-                struct sd_dhcp_raw_option *option = lease->private_options;
-
-                LIST_REMOVE(options, lease->private_options, option);
-
-                free(option->data);
-                free(option);
-        }
-
-        free(lease->root_path);
-        free(lease->router);
-        free(lease->timezone);
-        free(lease->hostname);
-        free(lease->domainname);
-
-        for (sd_dhcp_lease_server_type_t i = 0; i < _SD_DHCP_LEASE_SERVER_TYPE_MAX; i++)
-                free(lease->servers[i].addr);
-
-        free(lease->static_routes);
-        free(lease->classless_routes);
-        free(lease->client_id);
-        free(lease->vendor_specific);
-        strv_free(lease->search_domains);
-        free(lease->sixrd_br_addresses);
-        return mfree(lease);
-}
-
-DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_lease, sd_dhcp_lease, dhcp_lease_free);
-
-static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {
-        assert(option);
-        assert(ret);
-
-        if (len != 4)
-                return -EINVAL;
-
-        *ret = unaligned_read_be32((be32_t*) option);
-        if (*ret < min)
-                *ret = min;
-
-        return 0;
-}
-
-static int lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) {
-        assert(option);
-        assert(ret);
-
-        if (len != 2)
-                return -EINVAL;
-
-        *ret = unaligned_read_be16((be16_t*) option);
-        if (*ret < min)
-                *ret = min;
-
-        return 0;
-}
-
-static int lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) {
-        assert(option);
-        assert(ret);
-
-        if (len != 4)
-                return -EINVAL;
-
-        memcpy(ret, option, 4);
-        return 0;
-}
-
-static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
-        assert(option);
-        assert(ret);
-
-        if (len <= 0)
-                *ret = mfree(*ret);
-        else {
-                char *string;
-
-                /*
-                 * One trailing NUL byte is OK, we don't mind. See:
-                 * https://github.com/systemd/systemd/issues/1337
-                 */
-                if (memchr(option, 0, len - 1))
-                        return -EINVAL;
-
-                string = memdup_suffix0((const char *) option, len);
-                if (!string)
-                        return -ENOMEM;
-
-                free_and_replace(*ret, string);
-        }
-
-        return 0;
-}
-
-static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) {
-        _cleanup_free_ char *name = NULL, *normalized = NULL;
-        int r;
-
-        assert(option);
-        assert(ret);
-
-        r = lease_parse_string(option, len, &name);
-        if (r < 0)
-                return r;
-        if (!name) {
-                *ret = mfree(*ret);
-                return 0;
-        }
-
-        r = dns_name_normalize(name, 0, &normalized);
-        if (r < 0)
-                return r;
-
-        if (is_localhost(normalized))
-                return -EINVAL;
-
-        if (dns_name_is_root(normalized))
-                return -EINVAL;
-
-        free_and_replace(*ret, normalized);
-
-        return 0;
-}
-
-static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
-        assert(option || len == 0);
-        assert(ret);
-        assert(n_ret);
-
-        if (len <= 0) {
-                *ret = mfree(*ret);
-                *n_ret = 0;
-        } else {
-                size_t n_addresses;
-                struct in_addr *addresses;
-
-                if (len % 4 != 0)
-                        return -EINVAL;
-
-                n_addresses = len / 4;
-
-                addresses = newdup(struct in_addr, option, n_addresses);
-                if (!addresses)
-                        return -ENOMEM;
-
-                free(*ret);
-                *ret = addresses;
-                *n_ret = n_addresses;
-        }
-
-        return 0;
-}
-
-static int lease_parse_sip_server(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
-        assert(option || len == 0);
-        assert(ret);
-        assert(n_ret);
-
-        if (len <= 0)
-                return -EINVAL;
-
-        /* The SIP record is like the other, regular server records, but prefixed with a single "encoding"
-         * byte that is either 0 or 1. We only support it to be 1 for now. Let's drop it and parse it like
-         * the other fields */
-
-        if (option[0] != 1) { /* We only support IP address encoding for now */
-                *ret = mfree(*ret);
-                *n_ret = 0;
-                return 0;
-        }
-
-        return lease_parse_in_addrs(option + 1, len - 1, ret, n_ret);
-}
-
-static int lease_parse_static_routes(sd_dhcp_lease *lease, const uint8_t *option, size_t len) {
-        int r;
-
-        assert(lease);
-        assert(option || len <= 0);
-
-        if (len % 8 != 0)
-                return -EINVAL;
-
-        while (len >= 8) {
-                struct in_addr dst, gw;
-                uint8_t prefixlen;
-
-                assert_se(lease_parse_be32(option, 4, &dst.s_addr) >= 0);
-                option += 4;
-
-                assert_se(lease_parse_be32(option, 4, &gw.s_addr) >= 0);
-                option += 4;
-
-                len -= 8;
-
-                r = in4_addr_default_prefixlen(&dst, &prefixlen);
-                if (r < 0) {
-                        log_debug("sd-dhcp-lease: cannot determine class of received static route, ignoring.");
-                        continue;
-                }
-
-                (void) in4_addr_mask(&dst, prefixlen);
-
-                if (!GREEDY_REALLOC(lease->static_routes, lease->n_static_routes + 1))
-                        return -ENOMEM;
-
-                lease->static_routes[lease->n_static_routes++] = (struct sd_dhcp_route) {
-                        .dst_addr = dst,
-                        .gw_addr = gw,
-                        .dst_prefixlen = prefixlen,
-                };
-        }
-
-        return 0;
-}
-
-/* parses RFC3442 Classless Static Route Option */
-static int lease_parse_classless_routes(sd_dhcp_lease *lease, const uint8_t *option, size_t len) {
-        assert(lease);
-        assert(option || len <= 0);
-
-        /* option format: (subnet-mask-width significant-subnet-octets gateway-ip) */
-
-        while (len > 0) {
-                uint8_t prefixlen, dst_octets;
-                struct in_addr dst = {}, gw;
-
-                prefixlen = *option;
-                option++;
-                len--;
-
-                dst_octets = DIV_ROUND_UP(prefixlen, 8);
-
-                /* can't have more than 4 octets in IPv4 */
-                if (dst_octets > 4 || len < dst_octets)
-                        return -EINVAL;
-
-                memcpy(&dst, option, dst_octets);
-                option += dst_octets;
-                len -= dst_octets;
-
-                if (len < 4)
-                        return -EINVAL;
-
-                assert_se(lease_parse_be32(option, 4, &gw.s_addr) >= 0);
-                option += 4;
-                len -= 4;
-
-                if (!GREEDY_REALLOC(lease->classless_routes, lease->n_classless_routes + 1))
-                        return -ENOMEM;
-
-                lease->classless_routes[lease->n_classless_routes++] = (struct sd_dhcp_route) {
-                        .dst_addr = dst,
-                        .gw_addr = gw,
-                        .dst_prefixlen = prefixlen,
-                };
-        }
-
-        return 0;
-}
-
-static int lease_parse_6rd(sd_dhcp_lease *lease, const uint8_t *option, size_t len) {
-        uint8_t ipv4masklen, prefixlen;
-        struct in6_addr prefix;
-        _cleanup_free_ struct in_addr *br_addresses = NULL;
-        size_t n_br_addresses;
-
-        assert(lease);
-        assert(option);
-
-        /* See RFC 5969 Section 7.1.1 */
-
-        if (lease->sixrd_n_br_addresses > 0)
-                /* Multiple 6rd option?? */
-                return -EINVAL;
-
-        /* option-length: The length of the DHCP option in octets (22 octets with one BR IPv4 address). */
-        if (len < 2 + sizeof(struct in6_addr) + sizeof(struct in_addr) ||
-            (len - 2 - sizeof(struct in6_addr)) % sizeof(struct in_addr) != 0)
-                return -EINVAL;
-
-        /* IPv4MaskLen: The number of high-order bits that are identical across all CE IPv4 addresses
-         *              within a given 6rd domain. This may be any value between 0 and 32. Any value
-         *              greater than 32 is invalid. */
-        ipv4masklen = option[0];
-        if (ipv4masklen > 32)
-                return -EINVAL;
-
-        /* 6rdPrefixLen: The IPv6 prefix length of the SP's 6rd IPv6 prefix in number of bits. For the
-         *               purpose of bounds checking by DHCP option processing, the sum of
-         *               (32 - IPv4MaskLen) + 6rdPrefixLen MUST be less than or equal to 128. */
-        prefixlen = option[1];
-        if (32 - ipv4masklen + prefixlen > 128)
-                return -EINVAL;
-
-        /* 6rdPrefix: The service provider's 6rd IPv6 prefix represented as a 16-octet IPv6 address.
-         *            The bits in the prefix after the 6rdPrefixlen number of bits are reserved and
-         *            MUST be initialized to zero by the sender and ignored by the receiver. */
-        memcpy(&prefix, option + 2, sizeof(struct in6_addr));
-        (void) in6_addr_mask(&prefix, prefixlen);
-
-        /* 6rdBRIPv4Address: One or more IPv4 addresses of the 6rd Border Relay(s) for a given 6rd domain. */
-        n_br_addresses = (len - 2 - sizeof(struct in6_addr)) / sizeof(struct in_addr);
-        br_addresses = newdup(struct in_addr, option + 2 + sizeof(struct in6_addr), n_br_addresses);
-        if (!br_addresses)
-                return -ENOMEM;
-
-        lease->sixrd_ipv4masklen = ipv4masklen;
-        lease->sixrd_prefixlen = prefixlen;
-        lease->sixrd_prefix = prefix;
-        lease->sixrd_br_addresses = TAKE_PTR(br_addresses);
-        lease->sixrd_n_br_addresses = n_br_addresses;
-
-        return 0;
-}
-
-int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata) {
-        sd_dhcp_lease *lease = userdata;
-        int r;
-
-        assert(lease);
-
-        switch (code) {
-
-        case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
-                r = lease_parse_u32(option, len, &lease->lifetime, 1);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse lease time, ignoring: %m");
-
-                break;
-
-        case SD_DHCP_OPTION_SERVER_IDENTIFIER:
-                r = lease_parse_be32(option, len, &lease->server_address);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse server identifier, ignoring: %m");
-
-                break;
-
-        case SD_DHCP_OPTION_SUBNET_MASK:
-                r = lease_parse_be32(option, len, &lease->subnet_mask);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse subnet mask, ignoring: %m");
-                else
-                        lease->have_subnet_mask = true;
-                break;
-
-        case SD_DHCP_OPTION_BROADCAST:
-                r = lease_parse_be32(option, len, &lease->broadcast);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse broadcast address, ignoring: %m");
-                else
-                        lease->have_broadcast = true;
-                break;
-
-        case SD_DHCP_OPTION_ROUTER:
-                r = lease_parse_in_addrs(option, len, &lease->router, &lease->router_size);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse router addresses, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_DOMAIN_NAME_SERVER:
-                r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_DNS].addr, &lease->servers[SD_DHCP_LEASE_DNS].size);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse DNS server, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_NTP_SERVER:
-                r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_NTP].addr, &lease->servers[SD_DHCP_LEASE_NTP].size);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse NTP server, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_SIP_SERVER:
-                r = lease_parse_sip_server(option, len, &lease->servers[SD_DHCP_LEASE_SIP].addr, &lease->servers[SD_DHCP_LEASE_SIP].size);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse SIP server, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_POP3_SERVER:
-                r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_POP3].addr, &lease->servers[SD_DHCP_LEASE_POP3].size);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse POP3 server, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_SMTP_SERVER:
-                r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_SMTP].addr, &lease->servers[SD_DHCP_LEASE_SMTP].size);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse SMTP server, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_LPR_SERVER:
-                r = lease_parse_in_addrs(option, len, &lease->servers[SD_DHCP_LEASE_LPR].addr, &lease->servers[SD_DHCP_LEASE_LPR].size);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse LPR server, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_STATIC_ROUTE:
-                r = lease_parse_static_routes(lease, option, len);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse static routes, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_MTU_INTERFACE:
-                r = lease_parse_u16(option, len, &lease->mtu, 68);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse MTU, ignoring: %m");
-                if (lease->mtu < DHCP_DEFAULT_MIN_SIZE) {
-                        log_debug("MTU value of %" PRIu16 " too small. Using default MTU value of %d instead.", lease->mtu, DHCP_DEFAULT_MIN_SIZE);
-                        lease->mtu = DHCP_DEFAULT_MIN_SIZE;
-                }
-
-                break;
-
-        case SD_DHCP_OPTION_DOMAIN_NAME:
-                r = lease_parse_domain(option, len, &lease->domainname);
-                if (r < 0) {
-                        log_debug_errno(r, "Failed to parse domain name, ignoring: %m");
-                        return 0;
-                }
-
-                break;
-
-        case SD_DHCP_OPTION_DOMAIN_SEARCH:
-                r = dhcp_lease_parse_search_domains(option, len, &lease->search_domains);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse Domain Search List, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_HOST_NAME:
-                r = lease_parse_domain(option, len, &lease->hostname);
-                if (r < 0) {
-                        log_debug_errno(r, "Failed to parse hostname, ignoring: %m");
-                        return 0;
-                }
-
-                break;
-
-        case SD_DHCP_OPTION_ROOT_PATH:
-                r = lease_parse_string(option, len, &lease->root_path);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse root path, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_RENEWAL_TIME:
-                r = lease_parse_u32(option, len, &lease->t1, 1);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse T1 time, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_REBINDING_TIME:
-                r = lease_parse_u32(option, len, &lease->t2, 1);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse T2 time, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
-                r = lease_parse_classless_routes(lease, option, len);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse classless routes, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_TZDB_TIMEZONE: {
-                _cleanup_free_ char *tz = NULL;
-
-                r = lease_parse_string(option, len, &tz);
-                if (r < 0) {
-                        log_debug_errno(r, "Failed to parse timezone option, ignoring: %m");
-                        return 0;
-                }
-
-                if (!timezone_is_valid(tz, LOG_DEBUG)) {
-                        log_debug("Timezone is not valid, ignoring.");
-                        return 0;
-                }
-
-                free_and_replace(lease->timezone, tz);
-
-                break;
-        }
-
-        case SD_DHCP_OPTION_VENDOR_SPECIFIC:
-
-                if (len <= 0)
-                        lease->vendor_specific = mfree(lease->vendor_specific);
-                else {
-                        void *p;
-
-                        p = memdup(option, len);
-                        if (!p)
-                                return -ENOMEM;
-
-                        free(lease->vendor_specific);
-                        lease->vendor_specific = p;
-                }
-
-                lease->vendor_specific_len = len;
-                break;
-
-        case SD_DHCP_OPTION_6RD:
-                r = lease_parse_6rd(lease, option, len);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse 6rd option, ignoring: %m");
-                break;
-
-        case SD_DHCP_OPTION_PRIVATE_BASE ... SD_DHCP_OPTION_PRIVATE_LAST:
-                r = dhcp_lease_insert_private_option(lease, code, option, len);
-                if (r < 0)
-                        return r;
-
-                break;
-
-        default:
-                log_debug("Ignoring option DHCP option %"PRIu8" while parsing.", code);
-                break;
-        }
-
-        return 0;
-}
-
-/* Parses compressed domain names. */
-int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***domains) {
-        _cleanup_strv_free_ char **names = NULL;
-        size_t pos = 0, cnt = 0;
-        int r;
-
-        assert(domains);
-        assert_return(option && len > 0, -ENODATA);
-
-        while (pos < len) {
-                _cleanup_free_ char *name = NULL;
-                size_t n = 0;
-                size_t jump_barrier = pos, next_chunk = 0;
-                bool first = true;
-
-                for (;;) {
-                        uint8_t c;
-                        c = option[pos++];
-
-                        if (c == 0) {
-                                /* End of name */
-                                break;
-                        } else if (c <= 63) {
-                                const char *label;
-
-                                /* Literal label */
-                                label = (const char*) (option + pos);
-                                pos += c;
-                                if (pos >= len)
-                                        return -EBADMSG;
-
-                                if (!GREEDY_REALLOC(name, n + !first + DNS_LABEL_ESCAPED_MAX))
-                                        return -ENOMEM;
-
-                                if (first)
-                                        first = false;
-                                else
-                                        name[n++] = '.';
-
-                                r = dns_label_escape(label, c, name + n, DNS_LABEL_ESCAPED_MAX);
-                                if (r < 0)
-                                        return r;
-
-                                n += r;
-                        } else if (FLAGS_SET(c, 0xc0)) {
-                                /* Pointer */
-
-                                uint8_t d;
-                                uint16_t ptr;
-
-                                if (pos >= len)
-                                        return -EBADMSG;
-
-                                d = option[pos++];
-                                ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
-
-                                /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
-                                if (ptr >= jump_barrier)
-                                        return -EBADMSG;
-                                jump_barrier = ptr;
-
-                                /* Save current location so we don't end up re-parsing what's parsed so far. */
-                                if (next_chunk == 0)
-                                        next_chunk = pos;
-
-                                pos = ptr;
-                        } else
-                                return -EBADMSG;
-                }
-
-                if (!GREEDY_REALLOC(name, n + 1))
-                        return -ENOMEM;
-                name[n] = 0;
-
-                r = strv_extend(&names, name);
-                if (r < 0)
-                        return r;
-
-                cnt++;
-
-                if (next_chunk != 0)
-                      pos = next_chunk;
-        }
-
-        strv_free_and_replace(*domains, names);
-
-        return cnt;
-}
-
-int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len) {
-        struct sd_dhcp_raw_option *option, *before = NULL;
-
-        assert(lease);
-
-        LIST_FOREACH(options, cur, lease->private_options) {
-                if (tag < cur->tag) {
-                        before = cur;
-                        break;
-                }
-                if (tag == cur->tag) {
-                        log_debug("Ignoring duplicate option, tagged %i.", tag);
-                        return 0;
-                }
-        }
-
-        option = new(struct sd_dhcp_raw_option, 1);
-        if (!option)
-                return -ENOMEM;
-
-        option->tag = tag;
-        option->length = len;
-        option->data = memdup(data, len);
-        if (!option->data) {
-                free(option);
-                return -ENOMEM;
-        }
-
-        LIST_INSERT_BEFORE(options, lease->private_options, before, option);
-        return 0;
-}
-
-int dhcp_lease_new(sd_dhcp_lease **ret) {
-        sd_dhcp_lease *lease;
-
-        lease = new0(sd_dhcp_lease, 1);
-        if (!lease)
-                return -ENOMEM;
-
-        lease->n_ref = 1;
-
-        *ret = lease;
-        return 0;
-}
-
-int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
-        _cleanup_(unlink_and_freep) char *temp_path = NULL;
-        _cleanup_fclose_ FILE *f = NULL;
-        struct in_addr address;
-        const struct in_addr *addresses;
-        const void *client_id, *data;
-        size_t client_id_len, data_len;
-        char sbuf[INET_ADDRSTRLEN];
-        const char *string;
-        uint16_t mtu;
-        _cleanup_free_ sd_dhcp_route **routes = NULL;
-        char **search_domains;
-        uint32_t t1, t2, lifetime;
-        int r;
-
-        assert(lease);
-        assert(lease_file);
-
-        r = fopen_temporary(lease_file, &f, &temp_path);
-        if (r < 0)
-                return r;
-
-        (void) fchmod(fileno(f), 0644);
-
-        fprintf(f,
-                "# This is private data. Do not parse.\n");
-
-        r = sd_dhcp_lease_get_address(lease, &address);
-        if (r >= 0)
-                fprintf(f, "ADDRESS=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
-
-        r = sd_dhcp_lease_get_netmask(lease, &address);
-        if (r >= 0)
-                fprintf(f, "NETMASK=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
-
-        r = sd_dhcp_lease_get_router(lease, &addresses);
-        if (r > 0) {
-                fputs("ROUTER=", f);
-                serialize_in_addrs(f, addresses, r, false, NULL);
-                fputc('\n', f);
-        }
-
-        r = sd_dhcp_lease_get_server_identifier(lease, &address);
-        if (r >= 0)
-                fprintf(f, "SERVER_ADDRESS=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
-
-        r = sd_dhcp_lease_get_next_server(lease, &address);
-        if (r >= 0)
-                fprintf(f, "NEXT_SERVER=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
-
-        r = sd_dhcp_lease_get_broadcast(lease, &address);
-        if (r >= 0)
-                fprintf(f, "BROADCAST=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf)));
-
-        r = sd_dhcp_lease_get_mtu(lease, &mtu);
-        if (r >= 0)
-                fprintf(f, "MTU=%" PRIu16 "\n", mtu);
-
-        r = sd_dhcp_lease_get_t1(lease, &t1);
-        if (r >= 0)
-                fprintf(f, "T1=%" PRIu32 "\n", t1);
-
-        r = sd_dhcp_lease_get_t2(lease, &t2);
-        if (r >= 0)
-                fprintf(f, "T2=%" PRIu32 "\n", t2);
-
-        r = sd_dhcp_lease_get_lifetime(lease, &lifetime);
-        if (r >= 0)
-                fprintf(f, "LIFETIME=%" PRIu32 "\n", lifetime);
-
-        r = sd_dhcp_lease_get_dns(lease, &addresses);
-        if (r > 0) {
-                fputs("DNS=", f);
-                serialize_in_addrs(f, addresses, r, false, NULL);
-                fputc('\n', f);
-        }
-
-        r = sd_dhcp_lease_get_ntp(lease, &addresses);
-        if (r > 0) {
-                fputs("NTP=", f);
-                serialize_in_addrs(f, addresses, r, false, NULL);
-                fputc('\n', f);
-        }
-
-        r = sd_dhcp_lease_get_sip(lease, &addresses);
-        if (r > 0) {
-                fputs("SIP=", f);
-                serialize_in_addrs(f, addresses, r, false, NULL);
-                fputc('\n', f);
-        }
-
-        r = sd_dhcp_lease_get_domainname(lease, &string);
-        if (r >= 0)
-                fprintf(f, "DOMAINNAME=%s\n", string);
-
-        r = sd_dhcp_lease_get_search_domains(lease, &search_domains);
-        if (r > 0) {
-                fputs("DOMAIN_SEARCH_LIST=", f);
-                fputstrv(f, search_domains, NULL, NULL);
-                fputc('\n', f);
-        }
-
-        r = sd_dhcp_lease_get_hostname(lease, &string);
-        if (r >= 0)
-                fprintf(f, "HOSTNAME=%s\n", string);
-
-        r = sd_dhcp_lease_get_root_path(lease, &string);
-        if (r >= 0)
-                fprintf(f, "ROOT_PATH=%s\n", string);
-
-        r = sd_dhcp_lease_get_static_routes(lease, &routes);
-        if (r > 0)
-                serialize_dhcp_routes(f, "STATIC_ROUTES", routes, r);
-
-        routes = mfree(routes);
-        r = sd_dhcp_lease_get_classless_routes(lease, &routes);
-        if (r > 0)
-                serialize_dhcp_routes(f, "CLASSLESS_ROUTES", routes, r);
-
-        r = sd_dhcp_lease_get_timezone(lease, &string);
-        if (r >= 0)
-                fprintf(f, "TIMEZONE=%s\n", string);
-
-        r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len);
-        if (r >= 0) {
-                _cleanup_free_ char *client_id_hex = NULL;
-
-                client_id_hex = hexmem(client_id, client_id_len);
-                if (!client_id_hex)
-                        return -ENOMEM;
-                fprintf(f, "CLIENTID=%s\n", client_id_hex);
-        }
-
-        r = sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len);
-        if (r >= 0) {
-                _cleanup_free_ char *option_hex = NULL;
-
-                option_hex = hexmem(data, data_len);
-                if (!option_hex)
-                        return -ENOMEM;
-                fprintf(f, "VENDOR_SPECIFIC=%s\n", option_hex);
-        }
-
-        LIST_FOREACH(options, option, lease->private_options) {
-                char key[STRLEN("OPTION_000")+1];
-
-                xsprintf(key, "OPTION_%" PRIu8, option->tag);
-                r = serialize_dhcp_option(f, key, option->data, option->length);
-                if (r < 0)
-                        return r;
-        }
-
-        r = fflush_and_check(f);
-        if (r < 0)
-                return r;
-
-        r = conservative_rename(temp_path, lease_file);
-        if (r < 0)
-                return r;
-
-        temp_path = mfree(temp_path);
-
-        return 0;
-}
-
-static char **private_options_free(char **options) {
-        if (!options)
-                return NULL;
-
-        for (unsigned i = 0; i < SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE + 1; i++)
-                free(options[i]);
-
-        return mfree(options);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(char**, private_options_free);
-
-int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
-        _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
-        _cleanup_free_ char
-                *address = NULL,
-                *router = NULL,
-                *netmask = NULL,
-                *server_address = NULL,
-                *next_server = NULL,
-                *broadcast = NULL,
-                *dns = NULL,
-                *ntp = NULL,
-                *sip = NULL,
-                *pop3 = NULL,
-                *smtp = NULL,
-                *lpr = NULL,
-                *mtu = NULL,
-                *static_routes = NULL,
-                *classless_routes = NULL,
-                *domains = NULL,
-                *client_id_hex = NULL,
-                *vendor_specific_hex = NULL,
-                *lifetime = NULL,
-                *t1 = NULL,
-                *t2 = NULL;
-        _cleanup_(private_options_freep) char **options = NULL;
-
-        int r, i;
-
-        assert(lease_file);
-        assert(ret);
-
-        r = dhcp_lease_new(&lease);
-        if (r < 0)
-                return r;
-
-        options = new0(char*, SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE + 1);
-        if (!options)
-                return -ENOMEM;
-
-        r = parse_env_file(NULL, lease_file,
-                           "ADDRESS", &address,
-                           "ROUTER", &router,
-                           "NETMASK", &netmask,
-                           "SERVER_ADDRESS", &server_address,
-                           "NEXT_SERVER", &next_server,
-                           "BROADCAST", &broadcast,
-                           "DNS", &dns,
-                           "NTP", &ntp,
-                           "SIP", &sip,
-                           "POP3", &pop3,
-                           "SMTP", &smtp,
-                           "LPR", &lpr,
-                           "MTU", &mtu,
-                           "DOMAINNAME", &lease->domainname,
-                           "HOSTNAME", &lease->hostname,
-                           "DOMAIN_SEARCH_LIST", &domains,
-                           "ROOT_PATH", &lease->root_path,
-                           "STATIC_ROUTES", &static_routes,
-                           "CLASSLESS_ROUTES", &classless_routes,
-                           "CLIENTID", &client_id_hex,
-                           "TIMEZONE", &lease->timezone,
-                           "VENDOR_SPECIFIC", &vendor_specific_hex,
-                           "LIFETIME", &lifetime,
-                           "T1", &t1,
-                           "T2", &t2,
-                           "OPTION_224", &options[0],
-                           "OPTION_225", &options[1],
-                           "OPTION_226", &options[2],
-                           "OPTION_227", &options[3],
-                           "OPTION_228", &options[4],
-                           "OPTION_229", &options[5],
-                           "OPTION_230", &options[6],
-                           "OPTION_231", &options[7],
-                           "OPTION_232", &options[8],
-                           "OPTION_233", &options[9],
-                           "OPTION_234", &options[10],
-                           "OPTION_235", &options[11],
-                           "OPTION_236", &options[12],
-                           "OPTION_237", &options[13],
-                           "OPTION_238", &options[14],
-                           "OPTION_239", &options[15],
-                           "OPTION_240", &options[16],
-                           "OPTION_241", &options[17],
-                           "OPTION_242", &options[18],
-                           "OPTION_243", &options[19],
-                           "OPTION_244", &options[20],
-                           "OPTION_245", &options[21],
-                           "OPTION_246", &options[22],
-                           "OPTION_247", &options[23],
-                           "OPTION_248", &options[24],
-                           "OPTION_249", &options[25],
-                           "OPTION_250", &options[26],
-                           "OPTION_251", &options[27],
-                           "OPTION_252", &options[28],
-                           "OPTION_253", &options[29],
-                           "OPTION_254", &options[30]);
-        if (r < 0)
-                return r;
-
-        if (address) {
-                r = inet_pton(AF_INET, address, &lease->address);
-                if (r <= 0)
-                        log_debug("Failed to parse address %s, ignoring.", address);
-        }
-
-        if (router) {
-                r = deserialize_in_addrs(&lease->router, router);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to deserialize router addresses %s, ignoring: %m", router);
-                else
-                        lease->router_size = r;
-        }
-
-        if (netmask) {
-                r = inet_pton(AF_INET, netmask, &lease->subnet_mask);
-                if (r <= 0)
-                        log_debug("Failed to parse netmask %s, ignoring.", netmask);
-                else
-                        lease->have_subnet_mask = true;
-        }
-
-        if (server_address) {
-                r = inet_pton(AF_INET, server_address, &lease->server_address);
-                if (r <= 0)
-                        log_debug("Failed to parse server address %s, ignoring.", server_address);
-        }
-
-        if (next_server) {
-                r = inet_pton(AF_INET, next_server, &lease->next_server);
-                if (r <= 0)
-                        log_debug("Failed to parse next server %s, ignoring.", next_server);
-        }
-
-        if (broadcast) {
-                r = inet_pton(AF_INET, broadcast, &lease->broadcast);
-                if (r <= 0)
-                        log_debug("Failed to parse broadcast address %s, ignoring.", broadcast);
-                else
-                        lease->have_broadcast = true;
-        }
-
-        if (dns) {
-                r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_DNS].addr, dns);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to deserialize DNS servers %s, ignoring: %m", dns);
-                else
-                        lease->servers[SD_DHCP_LEASE_DNS].size = r;
-        }
-
-        if (ntp) {
-                r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_NTP].addr, ntp);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to deserialize NTP servers %s, ignoring: %m", ntp);
-                else
-                        lease->servers[SD_DHCP_LEASE_NTP].size = r;
-        }
-
-        if (sip) {
-                r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_SIP].addr, sip);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to deserialize SIP servers %s, ignoring: %m", sip);
-                else
-                        lease->servers[SD_DHCP_LEASE_SIP].size = r;
-        }
-
-        if (pop3) {
-                r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_POP3].addr, pop3);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to deserialize POP3 server %s, ignoring: %m", pop3);
-                else
-                        lease->servers[SD_DHCP_LEASE_POP3].size = r;
-        }
-
-        if (smtp) {
-                r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_SMTP].addr, smtp);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to deserialize SMTP server %s, ignoring: %m", smtp);
-                else
-                        lease->servers[SD_DHCP_LEASE_SMTP].size = r;
-        }
-
-        if (lpr) {
-                r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_LPR].addr, lpr);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to deserialize LPR server %s, ignoring: %m", lpr);
-                else
-                        lease->servers[SD_DHCP_LEASE_LPR].size = r;
-        }
-
-        if (mtu) {
-                r = safe_atou16(mtu, &lease->mtu);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse MTU %s, ignoring: %m", mtu);
-        }
-
-        if (domains) {
-                _cleanup_strv_free_ char **a = NULL;
-                a = strv_split(domains, " ");
-                if (!a)
-                        return -ENOMEM;
-
-                if (!strv_isempty(a))
-                        lease->search_domains = TAKE_PTR(a);
-        }
-
-        if (static_routes) {
-                r = deserialize_dhcp_routes(
-                                &lease->static_routes,
-                                &lease->n_static_routes,
-                                static_routes);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse DHCP static routes %s, ignoring: %m", static_routes);
-        }
-
-        if (classless_routes) {
-                r = deserialize_dhcp_routes(
-                                &lease->classless_routes,
-                                &lease->n_classless_routes,
-                                classless_routes);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse DHCP classless routes %s, ignoring: %m", classless_routes);
-        }
-
-        if (lifetime) {
-                r = safe_atou32(lifetime, &lease->lifetime);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse lifetime %s, ignoring: %m", lifetime);
-        }
-
-        if (t1) {
-                r = safe_atou32(t1, &lease->t1);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse T1 %s, ignoring: %m", t1);
-        }
-
-        if (t2) {
-                r = safe_atou32(t2, &lease->t2);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse T2 %s, ignoring: %m", t2);
-        }
-
-        if (client_id_hex) {
-                r = unhexmem(client_id_hex, SIZE_MAX, &lease->client_id, &lease->client_id_len);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse client ID %s, ignoring: %m", client_id_hex);
-        }
-
-        if (vendor_specific_hex) {
-                r = unhexmem(vendor_specific_hex, SIZE_MAX, &lease->vendor_specific, &lease->vendor_specific_len);
-                if (r < 0)
-                        log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex);
-        }
-
-        for (i = 0; i <= SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE; i++) {
-                _cleanup_free_ void *data = NULL;
-                size_t len;
-
-                if (!options[i])
-                        continue;
-
-                r = unhexmem(options[i], SIZE_MAX, &data, &len);
-                if (r < 0) {
-                        log_debug_errno(r, "Failed to parse private DHCP option %s, ignoring: %m", options[i]);
-                        continue;
-                }
-
-                r = dhcp_lease_insert_private_option(lease, SD_DHCP_OPTION_PRIVATE_BASE + i, data, len);
-                if (r < 0)
-                        return r;
-        }
-
-        *ret = TAKE_PTR(lease);
-
-        return 0;
-}
-
-int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) {
-        struct in_addr address, mask;
-        int r;
-
-        assert(lease);
-
-        if (lease->address == 0)
-                return -ENODATA;
-
-        address.s_addr = lease->address;
-
-        /* fall back to the default subnet masks based on address class */
-        r = in4_addr_default_subnet_mask(&address, &mask);
-        if (r < 0)
-                return r;
-
-        lease->subnet_mask = mask.s_addr;
-        lease->have_subnet_mask = true;
-
-        return 0;
-}
-
-int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len) {
-        assert_return(lease, -EINVAL);
-        assert_return(client_id, -EINVAL);
-        assert_return(client_id_len, -EINVAL);
-
-        if (!lease->client_id)
-                return -ENODATA;
-
-        *client_id = lease->client_id;
-        *client_id_len = lease->client_id_len;
-
-        return 0;
-}
-
-int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len) {
-        assert_return(lease, -EINVAL);
-        assert_return(client_id || client_id_len <= 0, -EINVAL);
-
-        if (client_id_len <= 0)
-                lease->client_id = mfree(lease->client_id);
-        else {
-                void *p;
-
-                p = memdup(client_id, client_id_len);
-                if (!p)
-                        return -ENOMEM;
-
-                free(lease->client_id);
-                lease->client_id = p;
-                lease->client_id_len = client_id_len;
-        }
-
-        return 0;
-}
-
-int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) {
-        assert_return(lease, -EINVAL);
-        assert_return(tz, -EINVAL);
-
-        if (!lease->timezone)
-                return -ENODATA;
-
-        *tz = lease->timezone;
-        return 0;
-}
-
-int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination) {
-        assert_return(route, -EINVAL);
-        assert_return(destination, -EINVAL);
-
-        *destination = route->dst_addr;
-        return 0;
-}
-
-int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length) {
-        assert_return(route, -EINVAL);
-        assert_return(length, -EINVAL);
-
-        *length = route->dst_prefixlen;
-        return 0;
-}
-
-int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) {
-        assert_return(route, -EINVAL);
-        assert_return(gateway, -EINVAL);
-
-        *gateway = route->gw_addr;
-        return 0;
-}
diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c
index 4394ef49..fbe15f00 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c
@@ -29,16 +29,10 @@
 #include "io-util.h"
 #include "random-util.h"
 #include "socket-util.h"
+#include "sort-util.h"
 #include "strv.h"
 #include "web-util.h"
 
-static const uint16_t default_req_opts[] = {
-        SD_DHCP6_OPTION_DNS_SERVERS,
-        SD_DHCP6_OPTION_DOMAIN_LIST,
-        SD_DHCP6_OPTION_NTP_SERVER,
-        SD_DHCP6_OPTION_SNTP_SERVERS,
-};
-
 #define DHCP6_CLIENT_DONT_DESTROY(client) \
         _cleanup_(sd_dhcp6_client_unrefp) _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client)
 
@@ -128,9 +122,8 @@ int sd_dhcp6_client_set_mac(
                 return 0;
         }
 
-        memcpy(client->hw_addr.bytes, addr, addr_len);
-        client->hw_addr.length = addr_len;
         client->arp_type = arp_type;
+        hw_addr_set(&client->hw_addr, addr, addr_len);
 
         return 0;
 }
@@ -229,8 +222,8 @@ static int dhcp6_client_set_duid_internal(
 
         } else {
 #if 0 /* NM_IGNORED */
-                r = dhcp_identifier_set_duid(duid_type, client->hw_addr.bytes, client->hw_addr.length,
-                                             client->arp_type, llt_time, client->test_mode, &client->duid, &client->duid_len);
+                r = dhcp_identifier_set_duid(duid_type, &client->hw_addr, client->arp_type, llt_time,
+                                             client->test_mode, &client->duid, &client->duid_len);
                 if (r == -EOPNOTSUPP)
                         return log_dhcp6_client_errno(client, r,
                                                       "Failed to set %s. MAC address is not set or "
@@ -316,7 +309,7 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
         if (client->iaid_set)
                 return 0;
 
-        r = dhcp_identifier_set_iaid(client->ifindex, client->hw_addr.bytes, client->hw_addr.length,
+        r = dhcp_identifier_set_iaid(client->ifindex, &client->hw_addr,
                                      /* legacy_unstable_byteorder = */ true,
                                      /* use_mac = */ client->test_mode,
                                      &iaid);
@@ -381,8 +374,12 @@ int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enable
         return 0;
 }
 
+static int be16_compare_func(const be16_t *a, const be16_t *b) {
+        return CMP(be16toh(*a), be16toh(*b));
+}
+
 int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) {
-        size_t t;
+        be16_t opt;
 
         assert_return(client, -EINVAL);
         assert_return(!sd_dhcp6_client_is_running(client), -EBUSY);
@@ -390,15 +387,17 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
         if (!dhcp6_option_can_request(option))
                 return -EINVAL;
 
-        for (t = 0; t < client->req_opts_len; t++)
-                if (client->req_opts[t] == htobe16(option))
-                        return -EEXIST;
+        opt = htobe16(option);
+        if (typesafe_bsearch(&opt, client->req_opts, client->n_req_opts, be16_compare_func))
+                return -EEXIST;
 
-        if (!GREEDY_REALLOC(client->req_opts, client->req_opts_len + 1))
+        if (!GREEDY_REALLOC(client->req_opts, client->n_req_opts + 1))
                 return -ENOMEM;
 
-        client->req_opts[client->req_opts_len++] = htobe16(option);
+        client->req_opts[client->n_req_opts++] = opt;
 
+        /* Sort immediately to make the above binary search will work for the next time. */
+        typesafe_qsort(client->req_opts, client->n_req_opts, be16_compare_func);
         return 0;
 }
 
@@ -501,6 +500,14 @@ int dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transactio
         return 0;
 }
 
+int sd_dhcp6_client_set_rapid_commit(sd_dhcp6_client *client, int enable) {
+        assert_return(client, -EINVAL);
+        assert_return(!sd_dhcp6_client_is_running(client), -EBUSY);
+
+        client->rapid_commit = enable;
+        return 0;
+}
+
 int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
         assert_return(client, -EINVAL);
 
@@ -645,6 +652,51 @@ static DHCP6MessageType client_message_type_from_state(sd_dhcp6_client *client)
         }
 }
 
+static int client_append_oro(sd_dhcp6_client *client, uint8_t **opt, size_t *optlen) {
+        _cleanup_free_ be16_t *buf = NULL;
+        be16_t *req_opts;
+        size_t n;
+
+        assert(client);
+        assert(opt);
+        assert(optlen);
+
+        switch (client->state) {
+        case DHCP6_STATE_INFORMATION_REQUEST:
+                n = client->n_req_opts;
+                buf = new(be16_t, n + 2);
+                if (!buf)
+                        return -ENOMEM;
+
+                memcpy_safe(buf, client->req_opts, n * sizeof(be16_t));
+                buf[n++] = htobe16(SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME); /* RFC 8415 section 21.23 */
+                buf[n++] = htobe16(SD_DHCP6_OPTION_INF_MAX_RT); /* RFC 8415 section 21.25 */
+
+                typesafe_qsort(buf, n, be16_compare_func);
+                req_opts = buf;
+                break;
+
+        case DHCP6_STATE_SOLICITATION:
+                n = client->n_req_opts;
+                buf = new(be16_t, n + 1);
+                if (!buf)
+                        return -ENOMEM;
+
+                memcpy_safe(buf, client->req_opts, n * sizeof(be16_t));
+                buf[n++] = htobe16(SD_DHCP6_OPTION_SOL_MAX_RT); /* RFC 8415 section 21.24 */
+
+                typesafe_qsort(buf, n, be16_compare_func);
+                req_opts = buf;
+                break;
+
+        default:
+                n = client->n_req_opts;
+                req_opts = client->req_opts;
+        }
+
+        return dhcp6_option_append(opt, optlen, SD_DHCP6_OPTION_ORO, n * sizeof(be16_t), req_opts);
+}
+
 int dhcp6_client_send_message(sd_dhcp6_client *client) {
         _cleanup_free_ DHCP6Message *message = NULL;
         struct in6_addr all_servers =
@@ -679,9 +731,11 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
                 break;
 
         case DHCP6_STATE_SOLICITATION:
-                r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
-                if (r < 0)
-                        return r;
+                if (client->rapid_commit) {
+                        r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
+                        if (r < 0)
+                                return r;
+                }
 
                 r = client_append_common_options_in_managed_mode(client, &opt, &optlen,
                                                                  &client->ia_na, &client->ia_pd);
@@ -722,9 +776,7 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
                         return r;
         }
 
-        r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ORO,
-                                client->req_opts_len * sizeof(be16_t),
-                                client->req_opts);
+        r = client_append_oro(client, &opt, &optlen);
         if (r < 0)
                 return r;
 
@@ -1127,6 +1179,10 @@ static int client_process_advertise_or_rapid_commit_reply(
         if (message->type == DHCP6_MESSAGE_REPLY) {
                 bool rapid_commit;
 
+                if (!client->rapid_commit)
+                        return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                                      "Received unexpected reply message, even we sent a solicit message without the rapid commit option, ignoring.");
+
                 r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit);
                 if (r < 0)
                         return r;
@@ -1311,13 +1367,10 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
 
         if (client->fd < 0) {
                 r = dhcp6_network_bind_udp_socket(client->ifindex, &client->local_address);
-                if (r < 0) {
-                        _cleanup_free_ char *p = NULL;
-
-                        (void) in6_addr_to_string(&client->local_address, &p);
+                if (r < 0)
                         return log_dhcp6_client_errno(client, r,
-                                                      "Failed to bind to UDP socket at address %s: %m", strna(p));
-                }
+                                                      "Failed to bind to UDP socket at address %s: %m",
+                                                      IN6_ADDR_TO_STRING(&client->local_address));
 
                 client->fd = r;
         }
@@ -1351,7 +1404,7 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
         }
 
         log_dhcp6_client(client, "Starting in %s mode",
-                         client->information_request ? "Information request" : "Managed");
+                         client->information_request ? "Information request" : "Solicit");
 
         return client_start_transaction(client, state);
 }
@@ -1423,18 +1476,9 @@ DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_client, sd_dhcp6_client, dhcp6_client_fre
 
 int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
         _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
-        _cleanup_free_ be16_t *req_opts = NULL;
-        size_t t;
 
         assert_return(ret, -EINVAL);
 
-        req_opts = new(be16_t, ELEMENTSOF(default_req_opts));
-        if (!req_opts)
-                return -ENOMEM;
-
-        for (t = 0; t < ELEMENTSOF(default_req_opts); t++)
-                req_opts[t] = htobe16(default_req_opts[t]);
-
         client = new(sd_dhcp6_client, 1);
         if (!client)
                 return -ENOMEM;
@@ -1446,8 +1490,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
                 .ifindex = -1,
                 .request_ia = DHCP6_REQUEST_IA_NA | DHCP6_REQUEST_IA_PD,
                 .fd = -1,
-                .req_opts_len = ELEMENTSOF(default_req_opts),
-                .req_opts = TAKE_PTR(req_opts),
+                .rapid_commit = true,
         };
 
         *ret = TAKE_PTR(client);
diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c
index fd47cb73..55c7d627 100644
--- a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c
@@ -469,7 +469,9 @@ static int dhcp6_lease_parse_message(
 
                 r = dhcp6_option_parse(message->options, len, &offset, &optcode, &optlen, &optval);
                 if (r < 0)
-                        return r;
+                        return log_dhcp6_client_errno(client, r,
+                                                      "Failed to parse option header at offset %zu of total length %zu: %m",
+                                                      offset, len);
 
                 switch (optcode) {
                 case SD_DHCP6_OPTION_CLIENTID:
@@ -479,7 +481,7 @@ static int dhcp6_lease_parse_message(
 
                         r = dhcp6_lease_set_clientid(lease, optval, optlen);
                         if (r < 0)
-                                return r;
+                                return log_dhcp6_client_errno(client, r, "Failed to set client ID: %m");
 
                         break;
 
@@ -490,17 +492,17 @@ static int dhcp6_lease_parse_message(
 
                         r = dhcp6_lease_set_serverid(lease, optval, optlen);
                         if (r < 0)
-                                return r;
+                                return log_dhcp6_client_errno(client, r, "Failed to set server ID: %m");
 
                         break;
 
                 case SD_DHCP6_OPTION_PREFERENCE:
                         if (optlen != 1)
-                                return -EINVAL;
+                                return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Received invalid length for preference.");
 
                         r = dhcp6_lease_set_preference(lease, optval[0]);
                         if (r < 0)
-                                return r;
+                                return log_dhcp6_client_errno(client, r, "Failed to set preference: %m");
 
                         break;
 
@@ -509,7 +511,7 @@ static int dhcp6_lease_parse_message(
 
                         r = dhcp6_option_parse_status(optval, optlen, &msg);
                         if (r < 0)
-                                return r;
+                                return log_dhcp6_client_errno(client, r, "Failed to parse status code: %m");
 
                         if (r > 0)
                                 return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
@@ -529,9 +531,11 @@ static int dhcp6_lease_parse_message(
 
                         r = dhcp6_option_parse_ia(client, client->ia_na.header.id, optcode, optlen, optval, &ia);
                         if (r == -ENOMEM)
-                                return r;
-                        if (r < 0)
+                                return log_oom_debug();
+                        if (r < 0) {
+                                log_dhcp6_client_errno(client, r, "Failed to parse IA_NA option, ignoring: %m");
                                 continue;
+                        }
 
                         if (lease->ia_na) {
                                 log_dhcp6_client(client, "Received duplicate matching IA_NA option, ignoring.");
@@ -552,9 +556,11 @@ static int dhcp6_lease_parse_message(
 
                         r = dhcp6_option_parse_ia(client, client->ia_pd.header.id, optcode, optlen, optval, &ia);
                         if (r == -ENOMEM)
-                                return r;
-                        if (r < 0)
+                                return log_oom_debug();
+                        if (r < 0) {
+                                log_dhcp6_client_errno(client, r, "Failed to parse IA_PD option, ignoring: %m");
                                 continue;
+                        }
 
                         if (lease->ia_pd) {
                                 log_dhcp6_client(client, "Received duplicate matching IA_PD option, ignoring.");
@@ -566,20 +572,23 @@ static int dhcp6_lease_parse_message(
                         break;
                 }
                 case SD_DHCP6_OPTION_RAPID_COMMIT:
+                        if (optlen != 0)
+                                log_dhcp6_client(client, "Received rapid commit option with an invalid length (%zu), ignoring.", optlen);
+
                         r = dhcp6_lease_set_rapid_commit(lease);
                         if (r < 0)
-                                return r;
+                                return log_dhcp6_client_errno(client, r, "Failed to set rapid commit flag: %m");
 
                         break;
 
-                case SD_DHCP6_OPTION_DNS_SERVERS:
+                case SD_DHCP6_OPTION_DNS_SERVER:
                         r = dhcp6_lease_add_dns(lease, optval, optlen);
                         if (r < 0)
                                 log_dhcp6_client_errno(client, r, "Failed to parse DNS server option, ignoring: %m");
 
                         break;
 
-                case SD_DHCP6_OPTION_DOMAIN_LIST:
+                case SD_DHCP6_OPTION_DOMAIN:
                         r = dhcp6_lease_add_domains(lease, optval, optlen);
                         if (r < 0)
                                 log_dhcp6_client_errno(client, r, "Failed to parse domain list option, ignoring: %m");
@@ -593,7 +602,7 @@ static int dhcp6_lease_parse_message(
 
                         break;
 
-                case SD_DHCP6_OPTION_SNTP_SERVERS:
+                case SD_DHCP6_OPTION_SNTP_SERVER:
                         r = dhcp6_lease_add_sntp(lease, optval, optlen);
                         if (r < 0)
                                 log_dhcp6_client_errno(client, r, "Failed to parse SNTP server option, ignoring: %m");
@@ -609,7 +618,8 @@ static int dhcp6_lease_parse_message(
 
                 case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
                         if (optlen != 4)
-                                return -EINVAL;
+                                return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
+                                                              "Received information refresh time option with an invalid length (%zu).", optlen);
 
                         irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC;
                         break;
diff --git a/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c b/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c
index 6e3c2ce9..ebbd4422 100644
--- a/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c
+++ b/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c
@@ -111,20 +111,6 @@ int event_reset_time_relative(
         return event_reset_time(e, s, clock, usec_add(usec_now, usec), accuracy, callback, userdata, priority, description, force_reset);
 }
 
-int event_source_disable(sd_event_source *s) {
-        if (!s)
-                return 0;
-
-        return sd_event_source_set_enabled(s, SD_EVENT_OFF);
-}
-
-int event_source_is_enabled(sd_event_source *s) {
-        if (!s)
-                return false;
-
-        return sd_event_source_get_enabled(s, NULL);
-}
-
 #if 0 /* NM_IGNORED */
 int event_add_time_change(sd_event *e, sd_event_source **ret, sd_event_io_handler_t callback, void *userdata) {
         _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
diff --git a/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h b/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h
index abd043bd..c1855844 100644
--- a/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h
+++ b/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h
@@ -27,7 +27,8 @@ int event_reset_time_relative(
                 int64_t priority,
                 const char *description,
                 bool force_reset);
-int event_source_disable(sd_event_source *s);
-int event_source_is_enabled(sd_event_source *s);
+static inline int event_source_disable(sd_event_source *s) {
+        return sd_event_source_set_enabled(s, SD_EVENT_OFF);
+}
 
 int event_add_time_change(sd_event *e, sd_event_source **ret, sd_event_io_handler_t callback, void *userdata);
diff --git a/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c b/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c
index 240476e6..8b2c554c 100644
--- a/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c
+++ b/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c
@@ -15,6 +15,7 @@
 #include "event-source.h"
 #include "fd-util.h"
 #include "fs-util.h"
+#include "glyph-util.h"
 #include "hashmap.h"
 #include "list.h"
 #include "macro.h"
@@ -50,19 +51,19 @@ static bool event_source_is_offline(sd_event_source *s) {
 }
 
 static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = {
-        [SOURCE_IO] = "io",
-        [SOURCE_TIME_REALTIME] = "realtime",
-        [SOURCE_TIME_BOOTTIME] = "bootime",
-        [SOURCE_TIME_MONOTONIC] = "monotonic",
+        [SOURCE_IO]                  = "io",
+        [SOURCE_TIME_REALTIME]       = "realtime",
+        [SOURCE_TIME_BOOTTIME]       = "bootime",
+        [SOURCE_TIME_MONOTONIC]      = "monotonic",
         [SOURCE_TIME_REALTIME_ALARM] = "realtime-alarm",
         [SOURCE_TIME_BOOTTIME_ALARM] = "boottime-alarm",
-        [SOURCE_SIGNAL] = "signal",
-        [SOURCE_CHILD] = "child",
-        [SOURCE_DEFER] = "defer",
-        [SOURCE_POST] = "post",
-        [SOURCE_EXIT] = "exit",
-        [SOURCE_WATCHDOG] = "watchdog",
-        [SOURCE_INOTIFY] = "inotify",
+        [SOURCE_SIGNAL]              = "signal",
+        [SOURCE_CHILD]               = "child",
+        [SOURCE_DEFER]               = "defer",
+        [SOURCE_POST]                = "post",
+        [SOURCE_EXIT]                = "exit",
+        [SOURCE_WATCHDOG]            = "watchdog",
+        [SOURCE_INOTIFY]             = "inotify",
 };
 
 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int);
@@ -125,10 +126,10 @@ struct sd_event {
         Hashmap *inotify_data; /* indexed by priority */
 
         /* A list of inode structures that still have an fd open, that we need to close before the next loop iteration */
-        LIST_HEAD(struct inode_data, inode_data_to_close);
+        LIST_HEAD(struct inode_data, inode_data_to_close_list);
 
         /* A list of inotify objects that already have events buffered which aren't processed yet */
-        LIST_HEAD(struct inotify_data, inotify_data_buffered);
+        LIST_HEAD(struct inotify_data, buffered_inotify_data_list);
 
         pid_t original_pid;
 
@@ -407,7 +408,8 @@ _public_ int sd_event_new(sd_event** ret) {
         e->epoll_fd = fd_move_above_stdio(e->epoll_fd);
 
         if (secure_getenv("SD_EVENT_PROFILE_DELAYS")) {
-                log_debug("Event loop profiling enabled. Logarithmic histogram of event loop iterations in the range 2^0 … 2^63 us will be logged every 5s.");
+                log_debug("Event loop profiling enabled. Logarithmic histogram of event loop iterations in the range 2^0 %s 2^63 us will be logged every 5s.",
+                          special_glyph(SPECIAL_GLYPH_ELLIPSIS));
                 e->profile_delays = true;
         }
 
@@ -420,6 +422,8 @@ fail:
 }
 
 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
+#define PROTECT_EVENT(e)                                                \
+        _unused_ _cleanup_(sd_event_unrefp) sd_event *_ref = sd_event_ref(e);
 
 _public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
         if (s)
@@ -708,6 +712,9 @@ static void event_unmask_signal_data(sd_event *e, struct signal_data *d, int sig
                 return;
         }
 
+        if (event_pid_changed(e))
+                return;
+
         assert(d->fd >= 0);
 
         if (signalfd(d->fd, &d->sigset, SFD_NONBLOCK|SFD_CLOEXEC) < 0)
@@ -853,6 +860,9 @@ static void source_disconnect(sd_event_source *s) {
                 break;
 
         case SOURCE_CHILD:
+                if (event_pid_changed(s->event))
+                        s->child.process_owned = false;
+
                 if (s->child.pid > 0) {
                         if (event_source_is_online(s)) {
                                 assert(s->event->n_online_child_sources > 0);
@@ -1429,7 +1439,6 @@ _public_ int sd_event_add_child(
                 return -ENOMEM;
 
         s->wakeup = WAKEUP_EVENT_SOURCE;
-        s->child.pid = pid;
         s->child.options = options;
         s->child.callback = callback;
         s->userdata = userdata;
@@ -1439,7 +1448,7 @@ _public_ int sd_event_add_child(
          * pin the PID, and make regular waitid() handling race-free. */
 
         if (shall_use_pidfd()) {
-                s->child.pidfd = pidfd_open(s->child.pid, 0);
+                s->child.pidfd = pidfd_open(pid, 0);
                 if (s->child.pidfd < 0) {
                         /* Propagate errors unless the syscall is not supported or blocked */
                         if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
@@ -1449,10 +1458,6 @@ _public_ int sd_event_add_child(
         } else
                 s->child.pidfd = -1;
 
-        r = hashmap_put(e->child_sources, PID_TO_PTR(pid), s);
-        if (r < 0)
-                return r;
-
         if (EVENT_SOURCE_WATCH_PIDFD(s)) {
                 /* We have a pidfd and we only want to watch for exit */
                 r = source_child_pidfd_register(s, s->enabled);
@@ -1468,6 +1473,12 @@ _public_ int sd_event_add_child(
                 e->need_process_child = true;
         }
 
+        r = hashmap_put(e->child_sources, PID_TO_PTR(pid), s);
+        if (r < 0)
+                return r;
+
+        /* These must be done after everything succeeds. */
+        s->child.pid = pid;
         e->n_online_child_sources++;
 
         if (ret)
@@ -1687,7 +1698,7 @@ static void event_free_inotify_data(sd_event *e, struct inotify_data *d) {
         assert(hashmap_isempty(d->wd));
 
         if (d->buffer_filled > 0)
-                LIST_REMOVE(buffered, e->inotify_data_buffered, d);
+                LIST_REMOVE(buffered, e->buffered_inotify_data_list, d);
 
         hashmap_free(d->inodes);
         hashmap_free(d->wd);
@@ -1695,7 +1706,8 @@ static void event_free_inotify_data(sd_event *e, struct inotify_data *d) {
         assert_se(hashmap_remove(e->inotify_data, &d->priority) == d);
 
         if (d->fd >= 0) {
-                if (epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, d->fd, NULL) < 0)
+                if (!event_pid_changed(e) &&
+                    epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, d->fd, NULL) < 0)
                         log_debug_errno(errno, "Failed to remove inotify fd from epoll, ignoring: %m");
 
                 safe_close(d->fd);
@@ -1798,14 +1810,14 @@ static void event_free_inode_data(
         assert(!d->event_sources);
 
         if (d->fd >= 0) {
-                LIST_REMOVE(to_close, e->inode_data_to_close, d);
+                LIST_REMOVE(to_close, e->inode_data_to_close_list, d);
                 safe_close(d->fd);
         }
 
         if (d->inotify_data) {
 
                 if (d->wd >= 0) {
-                        if (d->inotify_data->fd >= 0) {
+                        if (d->inotify_data->fd >= 0 && !event_pid_changed(e)) {
                                 /* So here's a problem. At the time this runs the watch descriptor might already be
                                  * invalidated, because an IN_IGNORED event might be queued right the moment we enter
                                  * the syscall. Hence, whenever we get EINVAL, ignore it entirely, since it's a very
@@ -2060,7 +2072,7 @@ static int event_add_inotify_fd_internal(
                         }
                 }
 
-                LIST_PREPEND(to_close, e->inode_data_to_close, inode_data);
+                LIST_PREPEND(to_close, e->inode_data_to_close_list, inode_data);
         }
 
         /* Link our event source to the inode data object */
@@ -2133,12 +2145,9 @@ static sd_event_source* event_source_free(sd_event_source *s) {
          * we still retain a valid event source object after
          * the callback. */
 
-        if (s->dispatching) {
-                if (s->type == SOURCE_IO)
-                        source_io_unregister(s);
-
+        if (s->dispatching)
                 source_disconnect(s);
-        } else
+        else
                 source_free(s);
 
         return NULL;
@@ -2347,7 +2356,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
                                 goto fail;
                         }
 
-                        LIST_PREPEND(to_close, s->event->inode_data_to_close, new_inode_data);
+                        LIST_PREPEND(to_close, s->event->inode_data_to_close_list, new_inode_data);
                 }
 
                 /* Move the event source to the new inode data structure */
@@ -2407,6 +2416,10 @@ fail:
 }
 
 _public_ int sd_event_source_get_enabled(sd_event_source *s, int *ret) {
+        /* Quick mode: the event source doesn't exist and we only want to query boolean enablement state. */
+        if (!s && !ret)
+                return false;
+
         assert_return(s, -EINVAL);
         assert_return(!event_pid_changed(s->event), -ECHILD);
 
@@ -2584,8 +2597,13 @@ static int event_source_online(
 _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) {
         int r;
 
-        assert_return(s, -EINVAL);
         assert_return(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL);
+
+        /* Quick mode: if the source doesn't exist, SD_EVENT_OFF is a noop. */
+        if (m == SD_EVENT_OFF && !s)
+                return 0;
+
+        assert_return(s, -EINVAL);
         assert_return(!event_pid_changed(s->event), -ECHILD);
 
         /* If we are dead anyway, we are fine with turning off sources, but everything else needs to fail. */
@@ -3222,23 +3240,16 @@ static int process_child(sd_event *e, int64_t threshold, int64_t *ret_min_priori
 
         e->need_process_child = false;
 
-        /*
-           So, this is ugly. We iteratively invoke waitid() with P_PID
-           + WNOHANG for each PID we wait for, instead of using
-           P_ALL. This is because we only want to get child
-           information of very specific child processes, and not all
-           of them. We might not have processed the SIGCHLD even of a
-           previous invocation and we don't want to maintain a
-           unbounded *per-child* event queue, hence we really don't
-           want anything flushed out of the kernel's queue that we
-           don't care about. Since this is O(n) this means that if you
-           have a lot of processes you probably want to handle SIGCHLD
-           yourself.
-
-           We do not reap the children here (by using WNOWAIT), this
-           is only done after the event source is dispatched so that
-           the callback still sees the process as a zombie.
-        */
+        /* So, this is ugly. We iteratively invoke waitid() with P_PID + WNOHANG for each PID we wait
+         * for, instead of using P_ALL. This is because we only want to get child information of very
+         * specific child processes, and not all of them. We might not have processed the SIGCHLD event
+         * of a previous invocation and we don't want to maintain a unbounded *per-child* event queue,
+         * hence we really don't want anything flushed out of the kernel's queue that we don't care
+         * about. Since this is O(n) this means that if you have a lot of processes you probably want
+         * to handle SIGCHLD yourself.
+         *
+         * We do not reap the children here (by using WNOWAIT), this is only done after the event
+         * source is dispatched so that the callback still sees the process as a zombie. */
 
         HASHMAP_FOREACH(s, e->child_sources) {
                 assert(s->type == SOURCE_CHILD);
@@ -3255,7 +3266,9 @@ static int process_child(sd_event *e, int64_t threshold, int64_t *ret_min_priori
                 if (s->child.exited)
                         continue;
 
-                if (EVENT_SOURCE_WATCH_PIDFD(s)) /* There's a usable pidfd known for this event source? then don't waitid() for it here */
+                if (EVENT_SOURCE_WATCH_PIDFD(s))
+                        /* There's a usable pidfd known for this event source? Then don't waitid() for
+                         * it here */
                         continue;
 
                 zero(s->child.siginfo);
@@ -3270,10 +3283,9 @@ static int process_child(sd_event *e, int64_t threshold, int64_t *ret_min_priori
                                 s->child.exited = true;
 
                         if (!zombie && (s->child.options & WEXITED)) {
-                                /* If the child isn't dead then let's
-                                 * immediately remove the state change
-                                 * from the queue, since there's no
-                                 * benefit in leaving it queued */
+                                /* If the child isn't dead then let's immediately remove the state
+                                 * change from the queue, since there's no benefit in leaving it
+                                 * queued. */
 
                                 assert(s->child.options & (WSTOPPED|WCONTINUED));
                                 (void) waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED)));
@@ -3328,19 +3340,16 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events, i
         assert_return(events == EPOLLIN, -EIO);
         assert(min_priority);
 
-        /* If there's a signal queued on this priority and SIGCHLD is
-           on this priority too, then make sure to recheck the
-           children we watch. This is because we only ever dequeue
-           the first signal per priority, and if we dequeue one, and
-           SIGCHLD might be enqueued later we wouldn't know, but we
-           might have higher priority children we care about hence we
-           need to check that explicitly. */
+        /* If there's a signal queued on this priority and SIGCHLD is on this priority too, then make
+         * sure to recheck the children we watch. This is because we only ever dequeue the first signal
+         * per priority, and if we dequeue one, and SIGCHLD might be enqueued later we wouldn't know,
+         * but we might have higher priority children we care about hence we need to check that
+         * explicitly. */
 
         if (sigismember(&d->sigset, SIGCHLD))
                 e->need_process_child = true;
 
-        /* If there's already an event source pending for this
-         * priority we don't read another */
+        /* If there's already an event source pending for this priority we don't read another */
         if (d->current)
                 return 0;
 
@@ -3413,7 +3422,7 @@ static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t
 
         assert(n > 0);
         d->buffer_filled = (size_t) n;
-        LIST_PREPEND(buffered, e->inotify_data_buffered, d);
+        LIST_PREPEND(buffered, e->buffered_inotify_data_list, d);
 
         return 1;
 }
@@ -3431,7 +3440,7 @@ static void event_inotify_data_drop(sd_event *e, struct inotify_data *d, size_t
         d->buffer_filled -= sz;
 
         if (d->buffer_filled == 0)
-                LIST_REMOVE(buffered, e->inotify_data_buffered, d);
+                LIST_REMOVE(buffered, e->buffered_inotify_data_list, d);
 }
 
 static int event_inotify_data_process(sd_event *e, struct inotify_data *d) {
@@ -3524,7 +3533,7 @@ static int process_inotify(sd_event *e) {
 
         assert(e);
 
-        LIST_FOREACH(buffered, d, e->inotify_data_buffered) {
+        LIST_FOREACH(buffered, d, e->buffered_inotify_data_list) {
                 r = event_inotify_data_process(e, d);
                 if (r < 0)
                         return r;
@@ -3536,8 +3545,8 @@ static int process_inotify(sd_event *e) {
 }
 
 static int source_dispatch(sd_event_source *s) {
-        _cleanup_(sd_event_unrefp) sd_event *saved_event = NULL;
         EventSourceType saved_type;
+        sd_event *saved_event;
         int r = 0;
 
         assert(s);
@@ -3549,7 +3558,8 @@ static int source_dispatch(sd_event_source *s) {
 
         /* Similarly, store a reference to the event loop object, so that we can still access it after the
          * callback might have invalidated/disconnected the event source. */
-        saved_event = sd_event_ref(s->event);
+        saved_event = s->event;
+        PROTECT_EVENT(saved_event);
 
         /* Check if we hit the ratelimit for this event source, and if so, let's disable it. */
         assert(!s->ratelimited);
@@ -3750,7 +3760,7 @@ static int dispatch_exit(sd_event *e) {
                 return 0;
         }
 
-        _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
+        PROTECT_EVENT(e);
         e->iteration++;
         e->state = SD_EVENT_EXITING;
         r = source_dispatch(p);
@@ -3821,11 +3831,11 @@ static void event_close_inode_data_fds(sd_event *e) {
          * for the inode). Hence, let's close them when entering the first iteration after they were added, as a
          * compromise. */
 
-        while ((d = e->inode_data_to_close)) {
+        while ((d = e->inode_data_to_close_list)) {
                 assert(d->fd >= 0);
                 d->fd = safe_close(d->fd);
 
-                LIST_REMOVE(to_close, e->inode_data_to_close, d);
+                LIST_REMOVE(to_close, e->inode_data_to_close_list, d);
         }
 }
 
@@ -3844,7 +3854,7 @@ _public_ int sd_event_prepare(sd_event *e) {
         assert_return(!e->default_event_ptr || e->tid == gettid(), -EREMOTEIO);
 
         /* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
-        _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
+        PROTECT_EVENT(e);
 
         if (e->exit_requested)
                 goto pending;
@@ -3879,7 +3889,7 @@ _public_ int sd_event_prepare(sd_event *e) {
 
         event_close_inode_data_fds(e);
 
-        if (event_next_pending(e) || e->need_process_child)
+        if (event_next_pending(e) || e->need_process_child || e->buffered_inotify_data_list)
                 goto pending;
 
         e->state = SD_EVENT_ARMED;
@@ -3959,7 +3969,7 @@ static int process_epoll(sd_event *e, usec_t timeout, int64_t threshold, int64_t
         n_event_max = MALLOC_ELEMENTSOF(e->event_queue);
 
         /* If we still have inotify data buffered, then query the other fds, but don't wait on it */
-        if (e->inotify_data_buffered)
+        if (e->buffered_inotify_data_list)
                 timeout = 0;
 
         for (;;) {
@@ -4174,7 +4184,7 @@ _public_ int sd_event_dispatch(sd_event *e) {
 
         p = event_next_pending(e);
         if (p) {
-                _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
+                PROTECT_EVENT(e);
 
                 e->state = SD_EVENT_RUNNING;
                 r = source_dispatch(p);
@@ -4226,7 +4236,7 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
         }
 
         /* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
-        _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
+        PROTECT_EVENT(e);
 
         r = sd_event_prepare(e);
         if (r == 0)
@@ -4256,7 +4266,7 @@ _public_ int sd_event_loop(sd_event *e) {
         assert_return(!event_pid_changed(e), -ECHILD);
         assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
 
-        _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
+        PROTECT_EVENT(e);
 
         while (e->state != SD_EVENT_FINISHED) {
                 r = sd_event_run(e, UINT64_MAX);
diff --git a/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c b/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c
index f1a3a42e..66247fd1 100644
--- a/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c
+++ b/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c
@@ -28,9 +28,9 @@ bool id128_is_valid(const char *s) {
                 for (i = 0; i < l; i++) {
                         char c = s[i];
 
-                        if (!(c >= '0' && c <= '9') &&
-                            !(c >= 'a' && c <= 'z') &&
-                            !(c >= 'A' && c <= 'Z'))
+                        if (!ascii_isdigit(c) &&
+                            !(c >= 'a' && c <= 'f') &&
+                            !(c >= 'A' && c <= 'F'))
                                 return false;
                 }
 
@@ -45,9 +45,9 @@ bool id128_is_valid(const char *s) {
                                 if (c != '-')
                                         return false;
                         } else {
-                                if (!(c >= '0' && c <= '9') &&
-                                    !(c >= 'a' && c <= 'z') &&
-                                    !(c >= 'A' && c <= 'Z'))
+                                if (!ascii_isdigit(c) &&
+                                    !(c >= 'a' && c <= 'f') &&
+                                    !(c >= 'A' && c <= 'F'))
                                         return false;
                         }
                 }
@@ -211,20 +211,4 @@ int id128_get_product(sd_id128_t *ret) {
         *ret = uuid;
         return 0;
 }
-
-int id128_equal_string(const char *s, sd_id128_t id) {
-        sd_id128_t parsed;
-        int r;
-
-        if (!s)
-                return false;
-
-        /* Checks if the specified string matches a valid string representation of the specified 128 bit ID/uuid */
-
-        r = sd_id128_from_string(s, &parsed);
-        if (r < 0)
-                return r;
-
-        return sd_id128_equal(parsed, id);
-}
 #endif /* NM_IGNORED */
diff --git a/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.h b/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.h
index 65a278c8..17b180c1 100644
--- a/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.h
+++ b/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.h
@@ -34,5 +34,3 @@ extern const struct hash_ops id128_hash_ops;
 sd_id128_t id128_make_v4_uuid(sd_id128_t id);
 
 int id128_get_product(sd_id128_t *ret);
-
-int id128_equal_string(const char *s, sd_id128_t id);
diff --git a/src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c b/src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c
index 8e47e26e..b7d7788c 100644
--- a/src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c
+++ b/src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c
@@ -105,6 +105,22 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
         return 0;
 }
 
+_public_ int sd_id128_string_equal(const char *s, sd_id128_t id) {
+        sd_id128_t parsed;
+        int r;
+
+        if (!s)
+                return false;
+
+        /* Checks if the specified string matches a valid string representation of the specified 128 bit ID/uuid */
+
+        r = sd_id128_from_string(s, &parsed);
+        if (r < 0)
+                return r;
+
+        return sd_id128_equal(parsed, id);
+}
+
 _public_ int sd_id128_get_machine(sd_id128_t *ret) {
         static thread_local sd_id128_t saved_machine_id = {};
         int r;
@@ -261,7 +277,10 @@ _public_ int sd_id128_get_invocation(sd_id128_t *ret) {
                 /* We first check the environment. The environment variable is primarily relevant for user
                  * services, and sufficiently safe as long as no privilege boundary is involved. */
                 r = get_invocation_from_environment(&saved_invocation_id);
-                if (r < 0 && r != -ENXIO)
+                if (r >= 0) {
+                        *ret = saved_invocation_id;
+                        return 0;
+                } else if (r != -ENXIO)
                         return r;
 
                 /* The kernel keyring is relevant for system services (as for user services we don't store
@@ -277,13 +296,10 @@ _public_ int sd_id128_get_invocation(sd_id128_t *ret) {
 
 _public_ int sd_id128_randomize(sd_id128_t *ret) {
         sd_id128_t t;
-        int r;
 
         assert_return(ret, -EINVAL);
 
-        r = genuine_random_bytes(&t, sizeof(t), 0);
-        if (r < 0)
-                return r;
+        random_bytes(&t, sizeof(t));
 
         /* Turn this into a valid v4 UUID, to be nice. Note that we
          * only guarantee this for newly generated UUIDs, not for
diff --git a/src/libnm-systemd-core/src/systemd/_sd-common.h b/src/libnm-systemd-core/src/systemd/_sd-common.h
index e1214296..6f657c22 100644
--- a/src/libnm-systemd-core/src/systemd/_sd-common.h
+++ b/src/libnm-systemd-core/src/systemd/_sd-common.h
@@ -14,7 +14,7 @@
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <https://www.gnu.org/licenses/>.
 ***/
 
 /* This is a private header; never even think of including this directly! */
@@ -85,7 +85,7 @@ typedef void (*_sd_destroy_t)(void *userdata);
 #endif
 
 #ifndef _SD_ARRAY_STATIC
-#  if __STDC_VERSION__ >= 199901L
+#  if __STDC_VERSION__ >= 199901L && !defined(__cplusplus)
 #    define _SD_ARRAY_STATIC static
 #  else
 #    define _SD_ARRAY_STATIC
diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp-client.h b/src/libnm-systemd-core/src/systemd/sd-dhcp-client.h
deleted file mode 100644
index 834f80b4..00000000
--- a/src/libnm-systemd-core/src/systemd/sd-dhcp-client.h
+++ /dev/null
@@ -1,345 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#ifndef foosddhcpclienthfoo
-#define foosddhcpclienthfoo
-
-/***
-  Copyright © 2013 Intel Corporation. All rights reserved.
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <inttypes.h>
-#include <net/ethernet.h>
-#include <netinet/in.h>
-#include <sys/types.h>
-#include <stdbool.h>
-
-#include "sd-dhcp-lease.h"
-#include "sd-dhcp-option.h"
-#include "sd-event.h"
-
-#include "_sd-common.h"
-
-_SD_BEGIN_DECLARATIONS;
-
-enum {
-        SD_DHCP_CLIENT_EVENT_STOP               = 0,
-        SD_DHCP_CLIENT_EVENT_IP_ACQUIRE         = 1,
-        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,
-        SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE  = 6, /* Sent when we have not received a reply after the first few attempts.
-                                                      * The client may want to start acquiring link-local addresses. */
-};
-
-/* https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#options */
-enum {
-        SD_DHCP_OPTION_PAD                            = 0,   /* [RFC2132] */
-        SD_DHCP_OPTION_SUBNET_MASK                    = 1,   /* [RFC2132] */
-        SD_DHCP_OPTION_TIME_OFFSET                    = 2,   /* [RFC2132], deprecated by 100 and 101 */
-        SD_DHCP_OPTION_ROUTER                         = 3,   /* [RFC2132] */
-        SD_DHCP_OPTION_TIME_SERVER                    = 4,   /* [RFC2132] */
-        SD_DHCP_OPTION_NAME_SERVER                    = 5,   /* [RFC2132] */
-        SD_DHCP_OPTION_DOMAIN_NAME_SERVER             = 6,   /* [RFC2132] */
-        SD_DHCP_OPTION_LOG_SERVER                     = 7,   /* [RFC2132] */
-        SD_DHCP_OPTION_QUOTES_SERVER                  = 8,   /* [RFC2132] */
-        SD_DHCP_OPTION_LPR_SERVER                     = 9,   /* [RFC2132] */
-        SD_DHCP_OPTION_IMPRESS_SERVER                 = 10,  /* [RFC2132] */
-        SD_DHCP_OPTION_RLP_SERVER                     = 11,  /* [RFC2132] */
-        SD_DHCP_OPTION_HOST_NAME                      = 12,  /* [RFC2132] */
-        SD_DHCP_OPTION_BOOT_FILE_SIZE                 = 13,  /* [RFC2132] */
-        SD_DHCP_OPTION_MERIT_DUMP_FILE                = 14,  /* [RFC2132] */
-        SD_DHCP_OPTION_DOMAIN_NAME                    = 15,  /* [RFC2132] */
-        SD_DHCP_OPTION_SWAP_SERVER                    = 16,  /* [RFC2132] */
-        SD_DHCP_OPTION_ROOT_PATH                      = 17,  /* [RFC2132] */
-        SD_DHCP_OPTION_EXTENSION_FILE                 = 18,  /* [RFC2132] */
-        SD_DHCP_OPTION_FORWARD                        = 19,  /* [RFC2132] */
-        SD_DHCP_OPTION_SOURCE_ROUTE                   = 20,  /* [RFC2132] */
-        SD_DHCP_OPTION_POLICY_FILTER                  = 21,  /* [RFC2132] */
-        SD_DHCP_OPTION_MAX_DATAGRAM_ASSEMBLY          = 22,  /* [RFC2132] */
-        SD_DHCP_OPTION_DEFAULT_IP_TTL                 = 23,  /* [RFC2132] */
-        SD_DHCP_OPTION_MTU_TIMEOUT                    = 24,  /* [RFC2132] */
-        SD_DHCP_OPTION_MTU_PLATEAU                    = 25,  /* [RFC2132] */
-        SD_DHCP_OPTION_MTU_INTERFACE                  = 26,  /* [RFC2132] */
-        SD_DHCP_OPTION_MTU_SUBNET                     = 27,  /* [RFC2132] */
-        SD_DHCP_OPTION_BROADCAST                      = 28,  /* [RFC2132] */
-        SD_DHCP_OPTION_MASK_DISCOVERY                 = 29,  /* [RFC2132] */
-        SD_DHCP_OPTION_MASK_SUPPLIER                  = 30,  /* [RFC2132] */
-        SD_DHCP_OPTION_ROUTER_DISCOVERY               = 31,  /* [RFC2132] */
-        SD_DHCP_OPTION_ROUTER_REQUEST                 = 32,  /* [RFC2132] */
-        SD_DHCP_OPTION_STATIC_ROUTE                   = 33,  /* [RFC2132] */
-        SD_DHCP_OPTION_TRAILERS                       = 34,  /* [RFC2132] */
-        SD_DHCP_OPTION_ARP_TIMEOUT                    = 35,  /* [RFC2132] */
-        SD_DHCP_OPTION_ETHERNET                       = 36,  /* [RFC2132] */
-        SD_DHCP_OPTION_DEFAULT_TCP_TTL                = 37,  /* [RFC2132] */
-        SD_DHCP_OPTION_KEEPALIVE_TIME                 = 38,  /* [RFC2132] */
-        SD_DHCP_OPTION_KEEPALIVE_DATA                 = 39,  /* [RFC2132] */
-        SD_DHCP_OPTION_NIS_DOMAIN                     = 40,  /* [RFC2132] */
-        SD_DHCP_OPTION_NIS_SERVER                     = 41,  /* [RFC2132] */
-        SD_DHCP_OPTION_NTP_SERVER                     = 42,  /* [RFC2132] */
-        SD_DHCP_OPTION_VENDOR_SPECIFIC                = 43,  /* [RFC2132] */
-        SD_DHCP_OPTION_NETBIOS_NAME_SERVER            = 44,  /* [RFC2132] */
-        SD_DHCP_OPTION_NETBIOS_DIST_SERVER            = 45,  /* [RFC2132] */
-        SD_DHCP_OPTION_NETBIOS_NODE_TYPE              = 46,  /* [RFC2132] */
-        SD_DHCP_OPTION_NETBIOS_SCOPE                  = 47,  /* [RFC2132] */
-        SD_DHCP_OPTION_X_WINDOW_FONT                  = 48,  /* [RFC2132] */
-        SD_DHCP_OPTION_X_WINDOW_MANAGER               = 49,  /* [RFC2132] */
-        SD_DHCP_OPTION_REQUESTED_IP_ADDRESS           = 50,  /* [RFC2132] */
-        SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME          = 51,  /* [RFC2132] */
-        SD_DHCP_OPTION_OVERLOAD                       = 52,  /* [RFC2132] */
-        SD_DHCP_OPTION_MESSAGE_TYPE                   = 53,  /* [RFC2132] */
-        SD_DHCP_OPTION_SERVER_IDENTIFIER              = 54,  /* [RFC2132] */
-        SD_DHCP_OPTION_PARAMETER_REQUEST_LIST         = 55,  /* [RFC2132] */
-        SD_DHCP_OPTION_ERROR_MESSAGE                  = 56,  /* [RFC2132] */
-        SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE           = 57,  /* [RFC2132] */
-        SD_DHCP_OPTION_RENEWAL_TIME                   = 58,  /* [RFC2132] */
-        SD_DHCP_OPTION_REBINDING_TIME                 = 59,  /* [RFC2132] */
-        SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER        = 60,  /* [RFC2132] */
-        SD_DHCP_OPTION_CLIENT_IDENTIFIER              = 61,  /* [RFC2132] */
-        SD_DHCP_OPTION_NETWARE_IP_DOMAIN              = 62,  /* [RFC2242] */
-        SD_DHCP_OPTION_NETWARE_IP_OPTION              = 63,  /* [RFC2242] */
-        SD_DHCP_OPTION_NIS_DOMAIN_NAME                = 64,  /* [RFC2132] */
-        SD_DHCP_OPTION_NIS_SERVER_ADDR                = 65,  /* [RFC2132] */
-        SD_DHCP_OPTION_BOOT_SERVER_NAME               = 66,  /* [RFC2132] */
-        SD_DHCP_OPTION_BOOT_FILENAME                  = 67,  /* [RFC2132] */
-        SD_DHCP_OPTION_HOME_AGENT_ADDRESSES           = 68,  /* [RFC2132] */
-        SD_DHCP_OPTION_SMTP_SERVER                    = 69,  /* [RFC2132] */
-        SD_DHCP_OPTION_POP3_SERVER                    = 70,  /* [RFC2132] */
-        SD_DHCP_OPTION_NNTP_SERVER                    = 71,  /* [RFC2132] */
-        SD_DHCP_OPTION_WWW_SERVER                     = 72,  /* [RFC2132] */
-        SD_DHCP_OPTION_FINGER_SERVER                  = 73,  /* [RFC2132] */
-        SD_DHCP_OPTION_IRC_SERVER                     = 74,  /* [RFC2132] */
-        SD_DHCP_OPTION_STREETTALK_SERVER              = 75,  /* [RFC2132] */
-        SD_DHCP_OPTION_STDA_SERVER                    = 76,  /* [RFC2132] */
-        SD_DHCP_OPTION_USER_CLASS                     = 77,  /* [RFC3004] */
-        SD_DHCP_OPTION_DIRECTORY_AGENT                = 78,  /* [RFC2610] */
-        SD_DHCP_OPTION_SERVICE_SCOPE                  = 79,  /* [RFC2610] */
-        SD_DHCP_OPTION_RAPID_COMMIT                   = 80,  /* [RFC4039] */
-        SD_DHCP_OPTION_FQDN                           = 81,  /* [RFC4702] */
-        SD_DHCP_OPTION_RELAY_AGENT_INFORMATION        = 82,  /* [RFC3046] */
-        SD_DHCP_OPTION_ISNS                           = 83,  /* [RFC4174] */
-        /* option code 84 is unassigned [RFC3679] */
-        SD_DHCP_OPTION_NDS_SERVER                     = 85,  /* [RFC2241] */
-        SD_DHCP_OPTION_NDS_TREE_NAME                  = 86,  /* [RFC2241] */
-        SD_DHCP_OPTION_NDS_CONTEXT                    = 87,  /* [RFC2241] */
-        SD_DHCP_OPTION_BCMCS_CONTROLLER_DOMAIN_NAM    = 88,  /* [RFC4280] */
-        SD_DHCP_OPTION_BCMCS_CONTROLLER_ADDRESS       = 89,  /* [RFC4280] */
-        SD_DHCP_OPTION_AUTHENTICATION                 = 90,  /* [RFC3118] */
-        SD_DHCP_OPTION_CLIENT_LAST_TRANSACTION_TIME   = 91,  /* [RFC4388] */
-        SD_DHCP_OPTION_ASSOCIATED_IP                  = 92,  /* [RFC4388] */
-        SD_DHCP_OPTION_CLIENT_SYSTEM                  = 93,  /* [RFC4578] */
-        SD_DHCP_OPTION_CLIENT_NDI                     = 94,  /* [RFC4578] */
-        SD_DHCP_OPTION_LDAP                           = 95,  /* [RFC3679] */
-        /* option code 96 is unassigned [RFC3679] */
-        SD_DHCP_OPTION_UUID                           = 97,  /* [RFC4578] */
-        SD_DHCP_OPTION_USER_AUTHENTICATION            = 98,  /* [RFC2485] */
-        SD_DHCP_OPTION_GEOCONF_CIVIC                  = 99,  /* [RFC4776] */
-        SD_DHCP_OPTION_POSIX_TIMEZONE                 = 100, /* [RFC4833] */
-        SD_DHCP_OPTION_TZDB_TIMEZONE                  = 101, /* [RFC4833] */
-        /* option codes 102-107 are unassigned [RFC3679] */
-        SD_DHCP_OPTION_IPV6_ONLY_PREFERRED            = 108, /* [RFC8925] */
-        SD_DHCP_OPTION_DHCP4O6_SOURCE_ADDRESS         = 109, /* [RFC8539] */
-        /* option codes 110-111 are unassigned [RFC3679] */
-        SD_DHCP_OPTION_NETINFO_ADDRESS                = 112, /* [RFC3679] */
-        SD_DHCP_OPTION_NETINFO_TAG                    = 113, /* [RFC3679] */
-        SD_DHCP_OPTION_DHCP_CAPTIVE_PORTAL            = 114, /* [RFC8910] */
-        /* option code 115 is unassigned [RFC3679] */
-        SD_DHCP_OPTION_AUTO_CONFIG                    = 116, /* [RFC2563] */
-        SD_DHCP_OPTION_NAME_SERVICE_SEARCH            = 117, /* [RFC2937] */
-        SD_DHCP_OPTION_SUBNET_SELECTION               = 118, /* [RFC3011] */
-        SD_DHCP_OPTION_DOMAIN_SEARCH                  = 119, /* [RFC3397] */
-        SD_DHCP_OPTION_SIP_SERVER                     = 120, /* [RFC3361] */
-        SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE         = 121, /* [RFC3442] */
-        SD_DHCP_OPTION_CABLELABS_CLIENT_CONFIGURATION = 122, /* [RFC3495] */
-        SD_DHCP_OPTION_GEOCONF                        = 123, /* [RFC6225] */
-        SD_DHCP_OPTION_VENDOR_CLASS                   = 124, /* [RFC3925] */
-        SD_DHCP_OPTION_VENDOR_SPECIFIC_INFORMATION    = 125, /* [RFC3925] */
-        /* option codes 126-127 are unassigned [RFC3679] */
-        /* option codes 128-135 are assigned to use by PXE, but they are vendor specific [RFC4578] */
-        SD_DHCP_OPTION_PANA_AGENT                     = 136, /* [RFC5192] */
-        SD_DHCP_OPTION_LOST_SERVER_FQDN               = 137, /* [RFC5223] */
-        SD_DHCP_OPTION_CAPWAP_AC_ADDRESS              = 138, /* [RFC5417] */
-        SD_DHCP_OPTION_MOS_ADDRESS                    = 139, /* [RFC5678] */
-        SD_DHCP_OPTION_MOS_FQDN                       = 140, /* [RFC5678] */
-        SD_DHCP_OPTION_SIP_SERVICE_DOMAINS            = 141, /* [RFC6011] */
-        SD_DHCP_OPTION_ANDSF_ADDRESS                  = 142, /* [RFC6153] */
-        SD_DHCP_OPTION_SZTP_REDIRECT                  = 143, /* [RFC8572] */
-        SD_DHCP_OPTION_GEOLOC                         = 144, /* [RFC6225] */
-        SD_DHCP_OPTION_FORCERENEW_NONCE_CAPABLE       = 145, /* [RFC6704] */
-        SD_DHCP_OPTION_RDNSS_SELECTION                = 146, /* [RFC6731] */
-        SD_DHCP_OPTION_DOTS_RI                        = 147, /* [RFC8973] */
-        SD_DHCP_OPTION_DOTS_ADDRESS                   = 148, /* [RFC8973] */
-        /* option code 149 is unassigned [RFC3942] */
-        SD_DHCP_OPTION_TFTP_SERVER_ADDRESS            = 150, /* [RFC5859] */
-        SD_DHCP_OPTION_STATUS_CODE                    = 151, /* [RFC6926] */
-        SD_DHCP_OPTION_BASE_TIME                      = 152, /* [RFC6926] */
-        SD_DHCP_OPTION_START_TIME_OF_STATE            = 153, /* [RFC6926] */
-        SD_DHCP_OPTION_QUERY_START_TIME               = 154, /* [RFC6926] */
-        SD_DHCP_OPTION_QUERY_END_TIME                 = 155, /* [RFC6926] */
-        SD_DHCP_OPTION_DHCP_STATE                     = 156, /* [RFC6926] */
-        SD_DHCP_OPTION_DATA_SOURCE                    = 157, /* [RFC6926] */
-        SD_DHCP_OPTION_PCP_SERVER                     = 158, /* [RFC7291] */
-        SD_DHCP_OPTION_PORT_PARAMS                    = 159, /* [RFC7618] */
-        /* option code 160 is unassigned [RFC7710][RFC8910] */
-        SD_DHCP_OPTION_MUD_URL                        = 161, /* [RFC8520] */
-        /* option codes 162-174 are unassigned [RFC3942] */
-        /* option codes 175-177 are temporary assigned. */
-        /* option codes 178-207 are unassigned [RFC3942] */
-        SD_DHCP_OPTION_PXELINUX_MAGIC                 = 208, /* [RFC5071] Deprecated */
-        SD_DHCP_OPTION_CONFIGURATION_FILE             = 209, /* [RFC5071] */
-        SD_DHCP_OPTION_PATH_PREFIX                    = 210, /* [RFC5071] */
-        SD_DHCP_OPTION_REBOOT_TIME                    = 211, /* [RFC5071] */
-        SD_DHCP_OPTION_6RD                            = 212, /* [RFC5969] */
-        SD_DHCP_OPTION_ACCESS_DOMAIN                  = 213, /* [RFC5986] */
-        /* option codes 214-219 are unassigned */
-        SD_DHCP_OPTION_SUBNET_ALLOCATION              = 220, /* [RFC6656] */
-        SD_DHCP_OPTION_VIRTUAL_SUBNET_SELECTION       = 221, /* [RFC6607] */
-        /* option codes 222-223 are unassigned [RFC3942] */
-        /* option codes 224-254 are reserved for private use */
-        SD_DHCP_OPTION_PRIVATE_BASE                   = 224,
-        SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE = 249, /* [RFC7844] */
-        SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY    = 252, /* [RFC7844] */
-        SD_DHCP_OPTION_PRIVATE_LAST                   = 254,
-        SD_DHCP_OPTION_END                            = 255, /* [RFC2132] */
-};
-
-/* Suboptions for SD_DHCP_OPTION_RELAY_AGENT_INFORMATION option */
-enum {
-        SD_DHCP_RELAY_AGENT_CIRCUIT_ID             = 1,
-        SD_DHCP_RELAY_AGENT_REMOTE_ID              = 2,
-};
-
-typedef struct sd_dhcp_client sd_dhcp_client;
-
-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,
-                void *userdata);
-
-int sd_dhcp_client_set_request_option(
-                sd_dhcp_client *client,
-                uint8_t option);
-int sd_dhcp_client_set_request_address(
-                sd_dhcp_client *client,
-                const struct in_addr *last_address);
-int sd_dhcp_client_set_request_broadcast(
-                sd_dhcp_client *client,
-                int broadcast);
-int sd_dhcp_client_set_ifindex(
-                sd_dhcp_client *client,
-                int interface_index);
-int sd_dhcp_client_set_ifname(
-                sd_dhcp_client *client,
-                const char *interface_name);
-int sd_dhcp_client_get_ifname(sd_dhcp_client *client, const char **ret);
-int sd_dhcp_client_set_mac(
-                sd_dhcp_client *client,
-                const uint8_t *addr,
-                const uint8_t *bcast_addr,
-                size_t addr_len,
-                uint16_t arp_type);
-int sd_dhcp_client_set_client_id(
-                sd_dhcp_client *client,
-                uint8_t type,
-                const uint8_t *data,
-                size_t data_len);
-int sd_dhcp_client_set_iaid_duid(
-                sd_dhcp_client *client,
-                bool iaid_set,
-                uint32_t iaid,
-                uint16_t duid_type,
-                const void *duid,
-                size_t duid_len);
-int sd_dhcp_client_set_iaid_duid_llt(
-                sd_dhcp_client *client,
-                bool iaid_set,
-                uint32_t iaid,
-                uint64_t llt_time);
-int sd_dhcp_client_set_duid(
-                sd_dhcp_client *client,
-                uint16_t duid_type,
-                const void *duid,
-                size_t duid_len);
-int sd_dhcp_client_set_duid_llt(
-                sd_dhcp_client *client,
-                uint64_t llt_time);
-int sd_dhcp_client_get_client_id(
-                sd_dhcp_client *client,
-                uint8_t *type,
-                const uint8_t **data,
-                size_t *data_len);
-int sd_dhcp_client_set_mtu(
-                sd_dhcp_client *client,
-                uint32_t mtu);
-int sd_dhcp_client_set_max_attempts(
-                sd_dhcp_client *client,
-                uint64_t attempt);
-int sd_dhcp_client_set_client_port(
-                sd_dhcp_client *client,
-                uint16_t port);
-int sd_dhcp_client_set_hostname(
-                sd_dhcp_client *client,
-                const char *hostname);
-int sd_dhcp_client_set_vendor_class_identifier(
-                sd_dhcp_client *client,
-                const char *vci);
-int sd_dhcp_client_set_mud_url(
-                sd_dhcp_client *client,
-                const char *mudurl);
-int sd_dhcp_client_set_user_class(
-                sd_dhcp_client *client,
-                char * const *user_class);
-int sd_dhcp_client_get_lease(
-                sd_dhcp_client *client,
-                sd_dhcp_lease **ret);
-int sd_dhcp_client_set_service_type(
-                sd_dhcp_client *client,
-                int type);
-int sd_dhcp_client_set_fallback_lease_lifetime(
-                sd_dhcp_client *client,
-                uint32_t fallback_lease_lifetime);
-
-int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v);
-int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v);
-
-int sd_dhcp_client_is_running(sd_dhcp_client *client);
-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);
-int sd_dhcp_client_send_decline(sd_dhcp_client *client);
-int sd_dhcp_client_send_renew(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);
-
-/* NOTE: anonymize parameter is used to initialize PRL memory with different
- * options when using RFC7844 Anonymity Profiles */
-int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize);
-
-int sd_dhcp_client_id_to_string(const void *data, size_t len, char **ret);
-
-int sd_dhcp_client_attach_event(
-                sd_dhcp_client *client,
-                sd_event *event,
-                int64_t priority);
-int sd_dhcp_client_detach_event(sd_dhcp_client *client);
-sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client);
-
-_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_client, sd_dhcp_client_unref);
-
-_SD_END_DECLARATIONS;
-
-#endif
diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp-lease.h b/src/libnm-systemd-core/src/systemd/sd-dhcp-lease.h
deleted file mode 100644
index 578ac6d4..00000000
--- a/src/libnm-systemd-core/src/systemd/sd-dhcp-lease.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#ifndef foosddhcpleasehfoo
-#define foosddhcpleasehfoo
-
-/***
-  Copyright © 2013 Intel Corporation. All rights reserved.
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <inttypes.h>
-#include <net/ethernet.h>
-#include <netinet/in.h>
-#include <sys/types.h>
-
-#include "_sd-common.h"
-
-_SD_BEGIN_DECLARATIONS;
-
-typedef struct sd_dhcp_lease sd_dhcp_lease;
-typedef struct sd_dhcp_route sd_dhcp_route;
-
-sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease);
-sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease);
-
-typedef enum sd_dhcp_lease_server_type_t {
-        SD_DHCP_LEASE_DNS,
-        SD_DHCP_LEASE_NTP,
-        SD_DHCP_LEASE_SIP,
-        SD_DHCP_LEASE_POP3,
-        SD_DHCP_LEASE_SMTP,
-        SD_DHCP_LEASE_LPR,
-        _SD_DHCP_LEASE_SERVER_TYPE_MAX,
-        _SD_DHCP_LEASE_SERVER_TYPE_INVALID = -EINVAL,
-        _SD_ENUM_FORCE_S64(DHCP_LEASE_SERVER_TYPE),
-} sd_dhcp_lease_server_type_t;
-
-int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr);
-int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime);
-int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1);
-int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2);
-int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr);
-int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr);
-int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr);
-int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr);
-int sd_dhcp_lease_get_servers(sd_dhcp_lease *lease, sd_dhcp_lease_server_type_t what, const struct in_addr **addr);
-int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_pop3(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_smtp(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_lpr(sd_dhcp_lease *lease, const struct in_addr **addr);
-int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu);
-int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
-int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains);
-int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname);
-int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path);
-int sd_dhcp_lease_get_static_routes(sd_dhcp_lease *lease, sd_dhcp_route ***ret);
-int sd_dhcp_lease_get_classless_routes(sd_dhcp_lease *lease, sd_dhcp_route ***ret);
-int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len);
-int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len);
-int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone);
-int sd_dhcp_lease_get_6rd(
-                sd_dhcp_lease *lease,
-                uint8_t *ret_ipv4masklen,
-                uint8_t *ret_prefixlen,
-                struct in6_addr *ret_prefix,
-                const struct in_addr **ret_br_addresses,
-                size_t *ret_n_br_addresses);
-
-int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination);
-int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length);
-int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway);
-
-_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_lease, sd_dhcp_lease_unref);
-
-_SD_END_DECLARATIONS;
-
-#endif
diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp-option.h b/src/libnm-systemd-core/src/systemd/sd-dhcp-option.h
deleted file mode 100644
index 71aa479b..00000000
--- a/src/libnm-systemd-core/src/systemd/sd-dhcp-option.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#ifndef foosddhcpoptionhfoo
-#define foosddhcpoptionhfoo
-
-/***
-  Copyright © 2013 Intel Corporation. All rights reserved.
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <inttypes.h>
-#include <sys/types.h>
-
-#include "_sd-common.h"
-
-_SD_BEGIN_DECLARATIONS;
-
-typedef struct sd_dhcp_option sd_dhcp_option;
-
-int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret);
-sd_dhcp_option *sd_dhcp_option_ref(sd_dhcp_option *ra);
-sd_dhcp_option *sd_dhcp_option_unref(sd_dhcp_option *ra);
-
-_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_option, sd_dhcp_option_unref);
-
-_SD_END_DECLARATIONS;
-
-#endif
diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h b/src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h
index d89b7d1c..2c66c51b 100644
--- a/src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h
+++ b/src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h
@@ -16,7 +16,7 @@
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <https://www.gnu.org/licenses/>.
 ***/
 
 #include <inttypes.h>
@@ -36,7 +36,7 @@ enum {
         SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE             = 10,
         SD_DHCP6_CLIENT_EVENT_RETRANS_MAX               = 11,
         SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE                = 12,
-        SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST       = 13,
+        SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST       = 13
 };
 
 /* https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#dhcpv6-parameters-2 */
@@ -63,15 +63,15 @@ enum {
         SD_DHCP6_OPTION_RECONF_ACCEPT              = 20,  /* RFC 8415 */
         SD_DHCP6_OPTION_SIP_SERVER_DOMAIN_NAME     = 21,  /* RFC 3319 */
         SD_DHCP6_OPTION_SIP_SERVER_ADDRESS         = 22,  /* RFC 3319 */
-        SD_DHCP6_OPTION_DNS_SERVERS                = 23,  /* RFC 3646 */
-        SD_DHCP6_OPTION_DOMAIN_LIST                = 24,  /* RFC 3646 */
+        SD_DHCP6_OPTION_DNS_SERVER                 = 23,  /* RFC 3646 */
+        SD_DHCP6_OPTION_DOMAIN                     = 24,  /* RFC 3646 */
         SD_DHCP6_OPTION_IA_PD                      = 25,  /* RFC 3633, RFC 8415 */
         SD_DHCP6_OPTION_IA_PD_PREFIX               = 26,  /* RFC 3633, RFC 8415 */
-        SD_DHCP6_OPTION_NIS_SERVERS                = 27,  /* RFC 3898 */
-        SD_DHCP6_OPTION_NISP_SERVERS               = 28,  /* RFC 3898 */
+        SD_DHCP6_OPTION_NIS_SERVER                 = 27,  /* RFC 3898 */
+        SD_DHCP6_OPTION_NISP_SERVER                = 28,  /* RFC 3898 */
         SD_DHCP6_OPTION_NIS_DOMAIN_NAME            = 29,  /* RFC 3898 */
         SD_DHCP6_OPTION_NISP_DOMAIN_NAME           = 30,  /* RFC 3898 */
-        SD_DHCP6_OPTION_SNTP_SERVERS               = 31,  /* RFC 4075, deprecated */
+        SD_DHCP6_OPTION_SNTP_SERVER                = 31,  /* RFC 4075, deprecated */
         SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME   = 32,  /* RFC 4242, 8415, sec. 21.23 */
         SD_DHCP6_OPTION_BCMCS_SERVER_D             = 33,  /* RFC 4280 */
         SD_DHCP6_OPTION_BCMCS_SERVER_A             = 34,  /* RFC 4280 */
@@ -183,7 +183,7 @@ enum {
         SD_DHCP6_OPTION_SLAP_QUAD                  = 140, /* RFC 8948 */
         SD_DHCP6_OPTION_V6_DOTS_RI                 = 141, /* RFC 8973 */
         SD_DHCP6_OPTION_V6_DOTS_ADDRESS            = 142, /* RFC 8973 */
-        SD_DHCP6_OPTION_IPV6_ADDRESS_ANDSF         = 143, /* RFC 6153 */
+        SD_DHCP6_OPTION_IPV6_ADDRESS_ANDSF         = 143 /* RFC 6153 */
         /* option codes 144-65535 are unassigned */
 };
 
@@ -262,6 +262,7 @@ int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client,
                                         int request);
 int sd_dhcp6_client_add_vendor_option(sd_dhcp6_client *client,
                                       sd_dhcp6_option *v);
+int sd_dhcp6_client_set_rapid_commit(sd_dhcp6_client *client, int enable);
 
 int sd_dhcp6_client_get_lease(
                 sd_dhcp6_client *client,
diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h b/src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h
index 472276de..716f6fc1 100644
--- a/src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h
+++ b/src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h
@@ -16,7 +16,7 @@
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <https://www.gnu.org/licenses/>.
 ***/
 
 #include <inttypes.h>
diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp6-option.h b/src/libnm-systemd-core/src/systemd/sd-dhcp6-option.h
index ddb2c7ce..b4b4671e 100644
--- a/src/libnm-systemd-core/src/systemd/sd-dhcp6-option.h
+++ b/src/libnm-systemd-core/src/systemd/sd-dhcp6-option.h
@@ -14,7 +14,7 @@
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <https://www.gnu.org/licenses/>.
 ***/
 
 #include <inttypes.h>
diff --git a/src/libnm-systemd-core/src/systemd/sd-event.h b/src/libnm-systemd-core/src/systemd/sd-event.h
index 63984eef..e782339c 100644
--- a/src/libnm-systemd-core/src/systemd/sd-event.h
+++ b/src/libnm-systemd-core/src/systemd/sd-event.h
@@ -14,7 +14,7 @@
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <https://www.gnu.org/licenses/>.
 ***/
 
 #include <inttypes.h>
diff --git a/src/libnm-systemd-core/src/systemd/sd-id128.h b/src/libnm-systemd-core/src/systemd/sd-id128.h
index f7d3244b..3303c374 100644
--- a/src/libnm-systemd-core/src/systemd/sd-id128.h
+++ b/src/libnm-systemd-core/src/systemd/sd-id128.h
@@ -14,7 +14,7 @@
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <https://www.gnu.org/licenses/>.
 ***/
 
 #include <inttypes.h>
@@ -116,9 +116,11 @@ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret);
         #a #b #c #d "-" #e #f "-" #g #h "-" #i #j "-" #k #l #m #n #o #p
 
 _sd_pure_ static __inline__ int sd_id128_equal(sd_id128_t a, sd_id128_t b) {
-        return memcmp(&a, &b, 16) == 0;
+        return a.qwords[0] == b.qwords[0] && a.qwords[1] == b.qwords[1];
 }
 
+int sd_id128_string_equal(const char *s, sd_id128_t id);
+
 _sd_pure_ static __inline__ int sd_id128_is_null(sd_id128_t a) {
         return a.qwords[0] == 0 && a.qwords[1] == 0;
 }
diff --git a/src/libnm-systemd-core/src/systemd/sd-lldp-rx.h b/src/libnm-systemd-core/src/systemd/sd-lldp-rx.h
index bfeac14c..504d7f59 100644
--- a/src/libnm-systemd-core/src/systemd/sd-lldp-rx.h
+++ b/src/libnm-systemd-core/src/systemd/sd-lldp-rx.h
@@ -14,7 +14,7 @@
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <https://www.gnu.org/licenses/>.
 ***/
 
 #include <errno.h>
@@ -32,14 +32,14 @@ _SD_BEGIN_DECLARATIONS;
 typedef struct sd_lldp_rx sd_lldp_rx;
 typedef struct sd_lldp_neighbor sd_lldp_neighbor;
 
-typedef enum sd_lldp_rx_event_t {
+__extension__ typedef enum sd_lldp_rx_event_t {
         SD_LLDP_RX_EVENT_ADDED,
         SD_LLDP_RX_EVENT_REMOVED,
         SD_LLDP_RX_EVENT_UPDATED,
         SD_LLDP_RX_EVENT_REFRESHED,
         _SD_LLDP_RX_EVENT_MAX,
         _SD_LLDP_RX_EVENT_INVALID = -EINVAL,
-        _SD_ENUM_FORCE_S64(LLDP_RX_EVENT),
+        _SD_ENUM_FORCE_S64(LLDP_RX_EVENT)
 } sd_lldp_rx_event_t;
 
 typedef void (*sd_lldp_rx_callback_t)(sd_lldp_rx *lldp_rx, sd_lldp_rx_event_t event, sd_lldp_neighbor *n, void *userdata);
diff --git a/src/libnm-systemd-core/src/systemd/sd-lldp.h b/src/libnm-systemd-core/src/systemd/sd-lldp.h
index c32d7894..4069c5b2 100644
--- a/src/libnm-systemd-core/src/systemd/sd-lldp.h
+++ b/src/libnm-systemd-core/src/systemd/sd-lldp.h
@@ -14,7 +14,7 @@
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <https://www.gnu.org/licenses/>.
 ***/
 
 #include <inttypes.h>
@@ -34,7 +34,7 @@ enum {
         SD_LLDP_TYPE_SYSTEM_DESCRIPTION  = 6,
         SD_LLDP_TYPE_SYSTEM_CAPABILITIES = 7,
         SD_LLDP_TYPE_MGMT_ADDRESS        = 8,
-        SD_LLDP_TYPE_PRIVATE             = 127,
+        SD_LLDP_TYPE_PRIVATE             = 127
 };
 
 /* IEEE 802.1AB-2009 Clause 8.5.2: Chassis subtypes */
@@ -46,7 +46,7 @@ enum {
         SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS         = 4,
         SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS     = 5,
         SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME      = 6,
-        SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED    = 7,
+        SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED    = 7
 };
 
 /* IEEE 802.1AB-2009 Clause 8.5.3: Port subtype */
@@ -58,7 +58,7 @@ enum {
         SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS  = 4,
         SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME   = 5,
         SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6,
-        SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7,
+        SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7
 };
 
 /* IEEE 802.1AB-2009 Clause 8.5.8: System capabilities */
@@ -73,7 +73,7 @@ enum {
         SD_LLDP_SYSTEM_CAPABILITIES_STATION  = 1 << 7,
         SD_LLDP_SYSTEM_CAPABILITIES_CVLAN    = 1 << 8,
         SD_LLDP_SYSTEM_CAPABILITIES_SVLAN    = 1 << 9,
-        SD_LLDP_SYSTEM_CAPABILITIES_TPMR     = 1 << 10,
+        SD_LLDP_SYSTEM_CAPABILITIES_TPMR     = 1 << 10
 };
 
 #define SD_LLDP_SYSTEM_CAPABILITIES_ALL UINT16_MAX
@@ -107,7 +107,7 @@ enum {
         SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY     = 4,
         SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST      = 5,
         SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID        = 6,
-        SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION      = 7,
+        SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION      = 7
 };
 
 /* IEEE 802.1AB-2009 Annex F */
@@ -115,7 +115,7 @@ enum {
         SD_LLDP_OUI_802_3_SUBTYPE_MAC_PHY_CONFIG_STATUS = 1,
         SD_LLDP_OUI_802_3_SUBTYPE_POWER_VIA_MDI         = 2,
         SD_LLDP_OUI_802_3_SUBTYPE_LINK_AGGREGATION      = 3,
-        SD_LLDP_OUI_802_3_SUBTYPE_MAXIMUM_FRAME_SIZE    = 4,
+        SD_LLDP_OUI_802_3_SUBTYPE_MAXIMUM_FRAME_SIZE    = 4
 };
 
 _SD_END_DECLARATIONS;
diff --git a/src/libnm-systemd-core/src/systemd/sd-ndisc.h b/src/libnm-systemd-core/src/systemd/sd-ndisc.h
index ab9ff55d..ee309a42 100644
--- a/src/libnm-systemd-core/src/systemd/sd-ndisc.h
+++ b/src/libnm-systemd-core/src/systemd/sd-ndisc.h
@@ -16,7 +16,7 @@
   Lesser General Public License for more details.
 
   You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <https://www.gnu.org/licenses/>.
 ***/
 
 #include <errno.h>
@@ -42,25 +42,25 @@ enum {
         SD_NDISC_OPTION_RDNSS              = 25,
         SD_NDISC_OPTION_FLAGS_EXTENSION    = 26,
         SD_NDISC_OPTION_DNSSL              = 31,
-        SD_NDISC_OPTION_CAPTIVE_PORTAL     = 37,
+        SD_NDISC_OPTION_CAPTIVE_PORTAL     = 37
 };
 
 /* Route preference, RFC 4191, Section 2.1 */
 enum {
         SD_NDISC_PREFERENCE_LOW    = 3U,
         SD_NDISC_PREFERENCE_MEDIUM = 0U,
-        SD_NDISC_PREFERENCE_HIGH   = 1U,
+        SD_NDISC_PREFERENCE_HIGH   = 1U
 };
 
 typedef struct sd_ndisc sd_ndisc;
 typedef struct sd_ndisc_router sd_ndisc_router;
 
-typedef enum sd_ndisc_event_t {
+__extension__ typedef enum sd_ndisc_event_t {
         SD_NDISC_EVENT_TIMEOUT,
         SD_NDISC_EVENT_ROUTER,
         _SD_NDISC_EVENT_MAX,
         _SD_NDISC_EVENT_INVALID = -EINVAL,
-        _SD_ENUM_FORCE_S64(NDISC_EVENT),
+        _SD_ENUM_FORCE_S64(NDISC_EVENT)
 } sd_ndisc_event_t;
 
 typedef void (*sd_ndisc_callback_t)(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router *rt, void *userdata);
@@ -82,7 +82,6 @@ int sd_ndisc_set_ifname(sd_ndisc *nd, const char *interface_name);
 int sd_ndisc_get_ifname(sd_ndisc *nd, const char **ret);
 int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr);
 
-int sd_ndisc_router_from_raw(sd_ndisc_router **ret, const void *raw, size_t raw_size);
 sd_ndisc_router *sd_ndisc_router_ref(sd_ndisc_router *rt);
 sd_ndisc_router *sd_ndisc_router_unref(sd_ndisc_router *rt);