about summary refs log tree commit diff
path: root/src/systemd
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemd')
-rw-r--r--src/systemd/src/basic/utf8.h1
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.c2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.h41
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-protocol.h7
-rw-r--r--src/systemd/src/libsystemd-network/lldp-neighbor.c47
-rw-r--r--src/systemd/src/libsystemd-network/lldp.h102
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.c29
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.h4
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c50
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-client.c50
-rw-r--r--src/systemd/src/systemd/sd-dhcp-client.h2
-rw-r--r--src/systemd/src/systemd/sd-dhcp6-client.h5
-rw-r--r--src/systemd/src/systemd/sd-lldp.h81
13 files changed, 253 insertions, 168 deletions
diff --git a/src/systemd/src/basic/utf8.h b/src/systemd/src/basic/utf8.h
index a3c8558e..1bc23dc1 100644
--- a/src/systemd/src/basic/utf8.h
+++ b/src/systemd/src/basic/utf8.h
@@ -32,6 +32,7 @@
 #endif /* NM_IGNORED */
 
 #define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
+#define UTF8_BYTE_ORDER_MARK "\xef\xbb\xbf"
 
 bool unichar_is_valid(char32_t c);
 
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c
index 0cbce155..c7a3eac5 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.c
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c
@@ -51,7 +51,7 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
         if (r < 0)
                 return r;
 
-        unaligned_write_be16(&duid->type, DHCP6_DUID_EN);
+        unaligned_write_be16(&duid->type, DUID_TYPE_EN);
         unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
 
         *len = sizeof(duid->type) + sizeof(duid->en);
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.h b/src/systemd/src/libsystemd-network/dhcp-identifier.h
index 93f06f59..babae15c 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.h
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.h
@@ -25,13 +25,23 @@
 #include "sparse-endian.h"
 #include "unaligned.h"
 
+typedef enum DUIDType {
+        DUID_TYPE_RAW       = 0,
+        DUID_TYPE_LLT       = 1,
+        DUID_TYPE_EN        = 2,
+        DUID_TYPE_LL        = 3,
+        DUID_TYPE_UUID      = 4,
+        _DUID_TYPE_MAX,
+        _DUID_TYPE_INVALID  = -1,
+} DUIDType;
+
 /* RFC 3315 section 9.1:
  *      A DUID can be no more than 128 octets long (not including the type code).
  */
 #define MAX_DUID_LEN 128
 
 struct duid {
-        uint16_t type;
+        be16_t type;
         union {
                 struct {
                         /* DHCP6_DUID_LLT */
@@ -61,3 +71,32 @@ struct duid {
 
 int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
 int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);
+
+static inline int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
+        struct duid d;
+
+        assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
+
+        switch (duid_type) {
+        case DUID_TYPE_LLT:
+                if (duid_len <= sizeof(d.llt))
+                        return -EINVAL;
+                break;
+        case DUID_TYPE_EN:
+                if (duid_len != sizeof(d.en))
+                        return -EINVAL;
+                break;
+        case DUID_TYPE_LL:
+                if (duid_len <= sizeof(d.ll))
+                        return -EINVAL;
+                break;
+        case DUID_TYPE_UUID:
+                if (duid_len != sizeof(d.uuid))
+                        return -EINVAL;
+                break;
+        default:
+                /* accept unknown type in order to be forward compatible */
+                break;
+        }
+        return 0;
+}
diff --git a/src/systemd/src/libsystemd-network/dhcp6-protocol.h b/src/systemd/src/libsystemd-network/dhcp6-protocol.h
index ee4bdfb0..2487c470 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-protocol.h
@@ -62,13 +62,6 @@ enum {
 #define DHCP6_REB_TIMEOUT                       10 * USEC_PER_SEC
 #define DHCP6_REB_MAX_RT                        600 * USEC_PER_SEC
 
-enum {
-        DHCP6_DUID_LLT                          = 1,
-        DHCP6_DUID_EN                           = 2,
-        DHCP6_DUID_LL                           = 3,
-        DHCP6_DUID_UUID                         = 4,
-};
-
 enum DHCP6State {
         DHCP6_STATE_STOPPED                     = 0,
         DHCP6_STATE_INFORMATION_REQUEST         = 1,
diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/systemd/src/libsystemd-network/lldp-neighbor.c
index 0515ce1e..ce1d89b6 100644
--- a/src/systemd/src/libsystemd-network/lldp-neighbor.c
+++ b/src/systemd/src/libsystemd-network/lldp-neighbor.c
@@ -26,7 +26,6 @@
 #include "in-addr-util.h"
 #include "lldp-internal.h"
 #include "lldp-neighbor.h"
-#include "lldp.h"
 #include "unaligned.h"
 
 static void lldp_neighbor_id_hash_func(const void *p, struct siphash *state) {
@@ -247,7 +246,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
 
                 switch (type) {
 
-                case LLDP_TYPE_END:
+                case SD_LLDP_TYPE_END:
                         if (length != 0) {
                                 log_lldp("End marker TLV not zero-sized, ignoring datagram.");
                                 return -EBADMSG;
@@ -259,7 +258,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
 
                         goto end_marker;
 
-                case LLDP_TYPE_CHASSIS_ID:
+                case SD_LLDP_TYPE_CHASSIS_ID:
                         if (length < 2 || length > 256) { /* includes the chassis subtype, hence one extra byte */
                                 log_lldp("Chassis ID field size out of range, ignoring datagram.");
                                 return -EBADMSG;
@@ -276,7 +275,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
                         n->id.chassis_id_size = length;
                         break;
 
-                case LLDP_TYPE_PORT_ID:
+                case SD_LLDP_TYPE_PORT_ID:
                         if (length < 2 || length > 256) { /* includes the port subtype, hence one extra byte */
                                 log_lldp("Port ID field size out of range, ignoring datagram.");
                                 return -EBADMSG;
@@ -293,7 +292,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
                         n->id.port_id_size = length;
                         break;
 
-                case LLDP_TYPE_TTL:
+                case SD_LLDP_TYPE_TTL:
                         if (length != 2) {
                                 log_lldp("TTL field has wrong size, ignoring datagram.");
                                 return -EBADMSG;
@@ -308,25 +307,25 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
                         n->has_ttl = true;
                         break;
 
-                case LLDP_TYPE_PORT_DESCRIPTION:
+                case SD_LLDP_TYPE_PORT_DESCRIPTION:
                         r = parse_string(&n->port_description, p, length);
                         if (r < 0)
                                 return r;
                         break;
 
-                case LLDP_TYPE_SYSTEM_NAME:
+                case SD_LLDP_TYPE_SYSTEM_NAME:
                         r = parse_string(&n->system_name, p, length);
                         if (r < 0)
                                 return r;
                         break;
 
-                case LLDP_TYPE_SYSTEM_DESCRIPTION:
+                case SD_LLDP_TYPE_SYSTEM_DESCRIPTION:
                         r = parse_string(&n->system_description, p, length);
                         if (r < 0)
                                 return r;
                         break;
 
-                case LLDP_TYPE_SYSTEM_CAPABILITIES:
+                case SD_LLDP_TYPE_SYSTEM_CAPABILITIES:
                         if (length != 4)
                                 log_lldp("System capabilities field has wrong size, ignoring.");
                         else {
@@ -337,7 +336,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
 
                         break;
 
-                case LLDP_TYPE_PRIVATE:
+                case SD_LLDP_TYPE_PRIVATE:
                         if (length < 4)
                                 log_lldp("Found private TLV that is too short, ignoring.");
 
@@ -481,18 +480,18 @@ _public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, cons
 
         switch (*(uint8_t*) n->id.chassis_id) {
 
-        case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT:
-        case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS:
-        case LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT:
-        case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME:
-        case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED:
+        case SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT:
+        case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS:
+        case SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT:
+        case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME:
+        case SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED:
                 k = cescape_length((char*) n->id.chassis_id + 1, n->id.chassis_id_size - 1);
                 if (!k)
                         return -ENOMEM;
 
                 goto done;
 
-        case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
+        case SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
                 r = format_mac_address(n->id.chassis_id, n->id.chassis_id_size, &k);
                 if (r < 0)
                         return r;
@@ -501,7 +500,7 @@ _public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, cons
 
                 break;
 
-        case LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS:
+        case SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS:
                 r = format_network_address(n->id.chassis_id, n->id.chassis_id_size, &k);
                 if (r < 0)
                         return r;
@@ -552,17 +551,17 @@ _public_ int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const c
 
         switch (*(uint8_t*) n->id.port_id) {
 
-        case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS:
-        case LLDP_PORT_SUBTYPE_PORT_COMPONENT:
-        case LLDP_PORT_SUBTYPE_INTERFACE_NAME:
-        case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED:
+        case SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS:
+        case SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT:
+        case SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME:
+        case SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED:
                 k = cescape_length((char*) n->id.port_id + 1, n->id.port_id_size - 1);
                 if (!k)
                         return -ENOMEM;
 
                 goto done;
 
-        case LLDP_PORT_SUBTYPE_MAC_ADDRESS:
+        case SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS:
                 r = format_mac_address(n->id.port_id, n->id.port_id_size, &k);
                 if (r < 0)
                         return r;
@@ -571,7 +570,7 @@ _public_ int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const c
 
                 break;
 
-        case LLDP_PORT_SUBTYPE_NETWORK_ADDRESS:
+        case SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS:
                 r = format_network_address(n->id.port_id, n->id.port_id_size, &k);
                 if (r < 0)
                         return r;
@@ -740,7 +739,7 @@ _public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[3], u
         assert_return(oui, -EINVAL);
         assert_return(subtype, -EINVAL);
 
-        r = sd_lldp_neighbor_tlv_is_type(n, LLDP_TYPE_PRIVATE);
+        r = sd_lldp_neighbor_tlv_is_type(n, SD_LLDP_TYPE_PRIVATE);
         if (r < 0)
                 return r;
         if (r == 0)
diff --git a/src/systemd/src/libsystemd-network/lldp.h b/src/systemd/src/libsystemd-network/lldp.h
deleted file mode 100644
index d61ecabc..00000000
--- a/src/systemd/src/libsystemd-network/lldp.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#pragma once
-
-/***
-  This file is part of systemd.
-
-  Copyright (C) 2014 Tom Gundersen
-  Copyright (C) 2014 Susant Sahani
-
-  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/>.
-***/
-
-#define LLDP_MULTICAST_ADDR     { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
-
-/* IEEE 802.3AB Clause 9: TLV Types */
-enum {
-        LLDP_TYPE_END                  =   0,
-        LLDP_TYPE_CHASSIS_ID           =   1,
-        LLDP_TYPE_PORT_ID              =   2,
-        LLDP_TYPE_TTL                  =   3,
-        LLDP_TYPE_PORT_DESCRIPTION     =   4,
-        LLDP_TYPE_SYSTEM_NAME          =   5,
-        LLDP_TYPE_SYSTEM_DESCRIPTION   =   6,
-        LLDP_TYPE_SYSTEM_CAPABILITIES  =   7,
-        LLDP_TYPE_MGMT_ADDRESS         =   8,
-        LLDP_TYPE_PRIVATE              =   127,
-};
-
-/* IEEE 802.3AB Clause 9.5.2: Chassis subtypes */
-enum {
-        LLDP_CHASSIS_SUBTYPE_RESERVED            = 0,
-        LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT   = 1,
-        LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS     = 2,
-        LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT      = 3,
-        LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS         = 4,
-        LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS     = 5,
-        LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME      = 6,
-        LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED    = 7,
-};
-
-/* IEEE 802.3AB Clause 9.5.3: Port subtype */
-enum {
-        LLDP_PORT_SUBTYPE_RESERVED           = 0,
-        LLDP_PORT_SUBTYPE_INTERFACE_ALIAS    = 1,
-        LLDP_PORT_SUBTYPE_PORT_COMPONENT     = 2,
-        LLDP_PORT_SUBTYPE_MAC_ADDRESS        = 3,
-        LLDP_PORT_SUBTYPE_NETWORK_ADDRESS    = 4,
-        LLDP_PORT_SUBTYPE_INTERFACE_NAME     = 5,
-        LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID   = 6,
-        LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED   = 7,
-};
-
-enum {
-        LLDP_SYSTEM_CAPABILITIES_OTHER        = 1 << 0,
-        LLDP_SYSTEM_CAPABILITIES_REPEATER     = 1 << 1,
-        LLDP_SYSTEM_CAPABILITIES_BRIDGE       = 1 << 2,
-        LLDP_SYSTEM_CAPABILITIES_WLAN_AP      = 1 << 3,
-        LLDP_SYSTEM_CAPABILITIES_ROUTER       = 1 << 4,
-        LLDP_SYSTEM_CAPABILITIES_PHONE        = 1 << 5,
-        LLDP_SYSTEM_CAPABILITIES_DOCSIS       = 1 << 6,
-        LLDP_SYSTEM_CAPABILITIES_STATION      = 1 << 7,
-        LLDP_SYSTEM_CAPABILITIES_CVLAN        = 1 << 8,
-        LLDP_SYSTEM_CAPABILITIES_SVLAN        = 1 << 9,
-        LLDP_SYSTEM_CAPABILITIES_TPMR         = 1 << 10,
-};
-
-#define _LLDP_SYSTEM_CAPABILITIES_ALL ((uint16_t) -1)
-
-#define _LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS                           \
-        ((uint16_t)                                                     \
-         (LLDP_SYSTEM_CAPABILITIES_REPEATER|                            \
-          LLDP_SYSTEM_CAPABILITIES_BRIDGE|                              \
-          LLDP_SYSTEM_CAPABILITIES_WLAN_AP|                             \
-          LLDP_SYSTEM_CAPABILITIES_ROUTER|                              \
-          LLDP_SYSTEM_CAPABILITIES_DOCSIS|                              \
-          LLDP_SYSTEM_CAPABILITIES_CVLAN|                               \
-          LLDP_SYSTEM_CAPABILITIES_SVLAN|                               \
-          LLDP_SYSTEM_CAPABILITIES_TPMR))
-
-
-#define LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
-#define LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }
-
-enum {
-        LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID            = 1,
-        LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID   = 2,
-        LLDP_OUI_802_1_SUBTYPE_VLAN_NAME               = 3,
-        LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY       = 4,
-        LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST        = 5,
-        LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID          = 6,
-        LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION        = 7,
-};
diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c
index 4e61c4fa..55fcc1da 100644
--- a/src/systemd/src/libsystemd-network/network-internal.c
+++ b/src/systemd/src/libsystemd-network/network-internal.c
@@ -339,6 +339,35 @@ int config_parse_hwaddr(const char *unit,
 
         return 0;
 }
+
+int config_parse_iaid(const char *unit,
+                      const char *filename,
+                      unsigned line,
+                      const char *section,
+                      unsigned section_line,
+                      const char *lvalue,
+                      int ltype,
+                      const char *rvalue,
+                      void *data,
+                      void *userdata) {
+        uint32_t iaid;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = safe_atou32(rvalue, &iaid);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Unable to read IAID: %s", rvalue);
+                return r;
+        }
+
+        *((uint32_t *)data) = iaid;
+
+        return 0;
+}
 #endif /* NM_IGNORED */
 
 void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h
index fd161056..955cc898 100644
--- a/src/systemd/src/libsystemd-network/network-internal.h
+++ b/src/systemd/src/libsystemd-network/network-internal.h
@@ -63,6 +63,10 @@ int config_parse_ifalias(const char *unit, const char *filename, unsigned line,
                          const char *section, unsigned section_line, const char *lvalue,
                          int ltype, const char *rvalue, void *data, void *userdata);
 
+int config_parse_iaid(const char *unit, const char *filename, unsigned line,
+                      const char *section, unsigned section_line, const char *lvalue,
+                      int ltype, const char *rvalue, void *data, void *userdata);
+
 int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
 const char *net_get_name(struct udev_device *device);
 #endif /* NM_IGNORED */
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index 40f3c8e9..758dba4b 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -84,7 +84,7 @@ struct sd_dhcp_client {
                         } _packed_ ll;
                         struct {
                                 /* 255: Node-specific (RFC 4361) */
-                                uint32_t iaid;
+                                be32_t iaid;
                                 struct duid duid;
                         } _packed_ ns;
                         struct {
@@ -300,6 +300,54 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
         return 0;
 }
 
+#if 0 /* NM_IGNORED */
+int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
+                                 uint16_t duid_type, uint8_t *duid, size_t duid_len) {
+        DHCP_CLIENT_DONT_DESTROY(client);
+        int r;
+        assert_return(client, -EINVAL);
+        zero(client->client_id);
+
+        client->client_id.type = 255;
+
+        /* If IAID is not configured, generate it. */
+        if (iaid == 0) {
+                r = dhcp_identifier_set_iaid(client->index, client->mac_addr,
+                                             client->mac_addr_len,
+                                             &client->client_id.ns.iaid);
+                if (r < 0)
+                        return r;
+        } else
+                client->client_id.ns.iaid = htobe32(iaid);
+
+        /* If DUID is not configured, generate DUID-EN. */
+        if (duid_len == 0) {
+                r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid,
+                                                &duid_len);
+                if (r < 0)
+                        return r;
+        } else {
+                r = dhcp_validate_duid_len(client->client_id.type, duid_len);
+                if (r < 0)
+                        return r;
+                client->client_id.ns.duid.type = htobe16(duid_type);
+                memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
+                duid_len += sizeof(client->client_id.ns.duid.type);
+        }
+
+        client->client_id_len = sizeof(client->client_id.type) + duid_len +
+                                sizeof(client->client_id.ns.iaid);
+
+        if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
+                log_dhcp_client(client, "Configured IAID+DUID, restarting.");
+                client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
+                sd_dhcp_client_start(client);
+        }
+
+        return 0;
+}
+#endif /* NM_IGNORED */
+
 int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
                                 const char *hostname) {
         char *new_hostname = NULL;
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
index ebec1f12..8fa1822f 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
@@ -182,44 +182,34 @@ static int client_ensure_duid(sd_dhcp6_client *client) {
         return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
 }
 
-int sd_dhcp6_client_set_duid(
-                sd_dhcp6_client *client,
-                uint16_t type,
-                uint8_t *duid, size_t duid_len) {
+int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type,
+                             uint8_t *duid, size_t duid_len) {
+        int r;
         assert_return(client, -EINVAL);
-        assert_return(duid, -EINVAL);
-        assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
-
         assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
 
-        switch (type) {
-        case DHCP6_DUID_LLT:
-                if (duid_len <= sizeof(client->duid.llt))
-                        return -EINVAL;
-                break;
-        case DHCP6_DUID_EN:
-                if (duid_len != sizeof(client->duid.en))
-                        return -EINVAL;
-                break;
-        case DHCP6_DUID_LL:
-                if (duid_len <= sizeof(client->duid.ll))
-                        return -EINVAL;
-                break;
-        case DHCP6_DUID_UUID:
-                if (duid_len != sizeof(client->duid.uuid))
-                        return -EINVAL;
-                break;
-        default:
-                /* accept unknown type in order to be forward compatible */
-                break;
+        if (duid_len > 0) {
+                r = dhcp_validate_duid_len(duid_type, duid_len);
+                if (r < 0)
+                        return r;
+                client->duid.type = htobe16(duid_type);
+                memcpy(&client->duid.raw.data, duid, duid_len);
+                client->duid_len = duid_len + sizeof(client->duid.type);
         }
 
-        client->duid.type = htobe16(type);
-        memcpy(&client->duid.raw.data, duid, duid_len);
-        client->duid_len = duid_len + sizeof(client->duid.type);
+        return 0;
+}
+
+#if 0 /* NM_IGNORED */
+int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) {
+        assert_return(client, -EINVAL);
+        assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
+
+        client->ia_na.id = htobe32(iaid);
 
         return 0;
 }
+#endif /* NM_IGNORED */
 
 int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled) {
         assert_return(client, -EINVAL);
diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h
index ef453705..374ff877 100644
--- a/src/systemd/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/src/systemd/sd-dhcp-client.h
@@ -98,6 +98,8 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
                            size_t addr_len, uint16_t arp_type);
 int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
                                  const uint8_t *data, size_t data_len);
+int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid,
+                                 uint16_t duid_type, uint8_t *duid, size_t duid_len);
 int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
                                  const uint8_t **data, size_t *data_len);
 int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu);
diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h
index 1bedc941..4604cb63 100644
--- a/src/systemd/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/src/systemd/sd-dhcp6-client.h
@@ -85,8 +85,9 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index);
 int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address);
 int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
                             size_t addr_len, uint16_t arp_type);
-int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *duid,
-                             size_t duid_len);
+int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type,
+                             uint8_t *duid, size_t duid_len);
+int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid);
 int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled);
 int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled);
 int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
diff --git a/src/systemd/src/systemd/sd-lldp.h b/src/systemd/src/systemd/sd-lldp.h
index f7eff587..4f2a3b50 100644
--- a/src/systemd/src/systemd/sd-lldp.h
+++ b/src/systemd/src/systemd/sd-lldp.h
@@ -33,6 +33,87 @@ _SD_BEGIN_DECLARATIONS;
 typedef struct sd_lldp sd_lldp;
 typedef struct sd_lldp_neighbor sd_lldp_neighbor;
 
+#define SD_LLDP_MULTICAST_ADDR     { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
+
+/* IEEE 802.3AB Clause 9: TLV Types */
+enum {
+        SD_LLDP_TYPE_END                  =   0,
+        SD_LLDP_TYPE_CHASSIS_ID           =   1,
+        SD_LLDP_TYPE_PORT_ID              =   2,
+        SD_LLDP_TYPE_TTL                  =   3,
+        SD_LLDP_TYPE_PORT_DESCRIPTION     =   4,
+        SD_LLDP_TYPE_SYSTEM_NAME          =   5,
+        SD_LLDP_TYPE_SYSTEM_DESCRIPTION   =   6,
+        SD_LLDP_TYPE_SYSTEM_CAPABILITIES  =   7,
+        SD_LLDP_TYPE_MGMT_ADDRESS         =   8,
+        SD_LLDP_TYPE_PRIVATE              =   127,
+};
+
+/* IEEE 802.3AB Clause 9.5.2: Chassis subtypes */
+enum {
+        SD_LLDP_CHASSIS_SUBTYPE_RESERVED            = 0,
+        SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT   = 1,
+        SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS     = 2,
+        SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT      = 3,
+        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,
+};
+
+/* IEEE 802.3AB Clause 9.5.3: Port subtype */
+enum {
+        SD_LLDP_PORT_SUBTYPE_RESERVED           = 0,
+        SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS    = 1,
+        SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT     = 2,
+        SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS        = 3,
+        SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS    = 4,
+        SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME     = 5,
+        SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID   = 6,
+        SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED   = 7,
+};
+
+enum {
+        SD_LLDP_SYSTEM_CAPABILITIES_OTHER        = 1 << 0,
+        SD_LLDP_SYSTEM_CAPABILITIES_REPEATER     = 1 << 1,
+        SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE       = 1 << 2,
+        SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP      = 1 << 3,
+        SD_LLDP_SYSTEM_CAPABILITIES_ROUTER       = 1 << 4,
+        SD_LLDP_SYSTEM_CAPABILITIES_PHONE        = 1 << 5,
+        SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS       = 1 << 6,
+        SD_LLDP_SYSTEM_CAPABILITIES_STATION      = 1 << 7,
+        SD_LLDP_SYSTEM_CAPABILITIES_CVLAN        = 1 << 8,
+        SD_LLDP_SYSTEM_CAPABILITIES_SVLAN        = 1 << 9,
+        SD_LLDP_SYSTEM_CAPABILITIES_TPMR         = 1 << 10,
+};
+
+#define SD_LLDP_SYSTEM_CAPABILITIES_ALL ((uint16_t) -1)
+
+#define SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS                         \
+        ((uint16_t)                                                     \
+         (SD_LLDP_SYSTEM_CAPABILITIES_REPEATER|                         \
+          SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|                           \
+          SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP|                          \
+          SD_LLDP_SYSTEM_CAPABILITIES_ROUTER|                           \
+          SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS|                           \
+          SD_LLDP_SYSTEM_CAPABILITIES_CVLAN|                            \
+          SD_LLDP_SYSTEM_CAPABILITIES_SVLAN|                            \
+          SD_LLDP_SYSTEM_CAPABILITIES_TPMR))
+
+
+#define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
+#define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }
+
+enum {
+        SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID            = 1,
+        SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID   = 2,
+        SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME               = 3,
+        SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY       = 4,
+        SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST        = 5,
+        SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID          = 6,
+        SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION        = 7,
+};
+
 typedef enum sd_lldp_event {
         SD_LLDP_EVENT_ADDED     = 'a',
         SD_LLDP_EVENT_REMOVED   = 'r',