From 6ed69be98aa1e1bb7f431cfdb0852b82b126f96b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 22 Aug 2023 14:12:10 +0900 Subject: [PATCH 1/6] Revert "network: DHCP6 client- Allow to send manual DUID" This reverts commits 89e73ce86fb115c2e319bf9f28b63efad2975495 and 543d2a4d45ba199a62c87b3bf69dfd4ff55abf0c. The commit assign "custom" to fixed DUID type 5. When making DUID fully configurable, the type number should be also configurable. Also, the fully custom DUID should be acceptable for DHCPv4. --- man/networkd.conf.xml | 7 ---- src/libsystemd-network/dhcp-identifier.c | 9 +++-- src/libsystemd-network/dhcp-identifier.h | 1 - src/libsystemd-network/sd-dhcp6-client.c | 12 +++---- src/network/networkd-dhcp-common.c | 9 +++-- src/network/networkd-dhcp6.c | 5 --- ...ipv6-only-custom-client-identifier.network | 15 -------- test/test-network/systemd-networkd-tests.py | 35 ------------------- 8 files changed, 12 insertions(+), 81 deletions(-) delete mode 100644 test/test-network/conf/25-dhcp-client-ipv6-only-custom-client-identifier.network diff --git a/man/networkd.conf.xml b/man/networkd.conf.xml index 9fa925e85c..bf597cac2e 100644 --- a/man/networkd.conf.xml +++ b/man/networkd.conf.xml @@ -138,13 +138,6 @@ - - - If DUIDType=custom, then the DUIDRawData= value will - used be as custom identifier. If DUIDType=custom is specified then the - DUIDRawData= key is mandatory. Note it applies only on DHCPv6 clients. - - If DUIDType=uuid, and DUIDRawData= is not set, diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c index 83fb6ce340..a27d67a315 100644 --- a/src/libsystemd-network/dhcp-identifier.c +++ b/src/libsystemd-network/dhcp-identifier.c @@ -15,11 +15,10 @@ #define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */ static const char * const duid_type_table[_DUID_TYPE_MAX] = { - [DUID_TYPE_LLT] = "DUID-LLT", - [DUID_TYPE_EN] = "DUID-EN/Vendor", - [DUID_TYPE_LL] = "DUID-LL", - [DUID_TYPE_UUID] = "UUID", - [DUID_TYPE_CUSTOM] = "Custom", + [DUID_TYPE_LLT] = "DUID-LLT", + [DUID_TYPE_EN] = "DUID-EN/Vendor", + [DUID_TYPE_LL] = "DUID-LL", + [DUID_TYPE_UUID] = "UUID", }; DEFINE_STRING_TABLE_LOOKUP_TO_STRING(duid_type, DUIDType); diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h index 1ac3476157..523dfc4a71 100644 --- a/src/libsystemd-network/dhcp-identifier.h +++ b/src/libsystemd-network/dhcp-identifier.h @@ -17,7 +17,6 @@ typedef enum DUIDType { DUID_TYPE_EN = 2, DUID_TYPE_LL = 3, DUID_TYPE_UUID = 4, - DUID_TYPE_CUSTOM = 5, _DUID_TYPE_MAX, _DUID_TYPE_INVALID = -EINVAL, } DUIDType; diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index e8d99718b3..2f4053caad 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -212,14 +212,10 @@ static int dhcp6_client_set_duid_internal( log_dhcp6_client(client, "Using DUID of type %i of incorrect length, proceeding.", duid_type); } - if (duid_type == DUID_TYPE_CUSTOM) { - memcpy(&client->duid, duid, duid_len); - client->duid_len = duid_len; - } else { - client->duid.type = htobe16(duid_type); - memcpy(&client->duid.raw.data, duid, duid_len); - client->duid_len = sizeof(client->duid.type) + duid_len; - } + client->duid.type = htobe16(duid_type); + memcpy(&client->duid.raw.data, duid, duid_len); + client->duid_len = sizeof(client->duid.type) + duid_len; + } else { r = dhcp_identifier_set_duid(duid_type, &client->hw_addr, client->arp_type, llt_time, client->test_mode, &client->duid, &client->duid_len); diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index baf80cb644..5f9ef80e3e 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -1106,11 +1106,10 @@ static const char * const dhcp_option_data_type_table[_DHCP_OPTION_DATA_MAX] = { DEFINE_STRING_TABLE_LOOKUP(dhcp_option_data_type, DHCPOptionDataType); static const char* const duid_type_table[_DUID_TYPE_MAX] = { - [DUID_TYPE_LLT] = "link-layer-time", - [DUID_TYPE_EN] = "vendor", - [DUID_TYPE_LL] = "link-layer", - [DUID_TYPE_UUID] = "uuid", - [DUID_TYPE_CUSTOM] = "custom", + [DUID_TYPE_LLT] = "link-layer-time", + [DUID_TYPE_EN] = "vendor", + [DUID_TYPE_LL] = "link-layer", + [DUID_TYPE_UUID] = "uuid", }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(duid_type, DUIDType); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index e0f0850898..00c767e1fb 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -555,11 +555,6 @@ static int dhcp6_set_identifier(Link *link, sd_dhcp6_client *client) { } duid = link_get_dhcp6_duid(link); - - if (duid->type == DUID_TYPE_CUSTOM && duid->raw_data_len == 0) - return log_link_debug_errno(link, SYNTHETIC_ERRNO(EINVAL), - "DHCPv6 CLIENT: Missing DUID Raw Data as duid type set to 'custom': %m"); - if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0) r = sd_dhcp6_client_set_duid_llt(client, duid->llt_time); else diff --git a/test/test-network/conf/25-dhcp-client-ipv6-only-custom-client-identifier.network b/test/test-network/conf/25-dhcp-client-ipv6-only-custom-client-identifier.network deleted file mode 100644 index edd5b7f501..0000000000 --- a/test/test-network/conf/25-dhcp-client-ipv6-only-custom-client-identifier.network +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -[Match] -Name=veth99 - -[Network] -DHCP=ipv6 -IPv6Token=::1a:2b:3c:4d - -[Route] -Gateway=_ipv6ra -Destination=2001:1234:5:9fff:ff:ff:ff:ff/128 - -[DHCPv6] -DUIDType=custom -DUIDRawData=00:00:ab:11:f9:2a:c2:77:29:f9:5c:00 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 5910d0d8da..bd1a10507b 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -5020,41 +5020,6 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.assertIn('DHCPREPLY(veth-peer)', output) self.assertNotIn('rapid-commit', output) - def test_dhcp_client_ipv6_only_with_custom_client_identifier(self): - copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv6-only-custom-client-identifier.network') - - start_networkd() - self.wait_online(['veth-peer:carrier']) - start_dnsmasq() - self.wait_online(['veth99:routable', 'veth-peer:routable']) - - # checking address - output = check_output('ip address show dev veth99 scope global') - print(output) - self.assertRegex(output, r'inet6 2600::[0-9a-f:]*/128 scope global dynamic noprefixroute') - self.assertNotIn('192.168.5', output) - - # checking semi-static route - output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff') - print(output) - self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd') - - # Confirm that ipv6 token is not set in the kernel - output = check_output('ip token show dev veth99') - print(output) - self.assertRegex(output, 'token :: dev veth99') - - print('## dnsmasq log') - output = read_dnsmasq_log_file() - print(output) - self.assertIn('DHCPSOLICIT(veth-peer) 00:00:ab:11:f9:2a:c2:77:29:f9:5c:00', output) - self.assertNotIn('DHCPADVERTISE(veth-peer)', output) - self.assertNotIn('DHCPREQUEST(veth-peer)', output) - self.assertIn('DHCPREPLY(veth-peer)', output) - self.assertIn('sent size: 0 option: 14 rapid-commit', output) - - stop_dnsmasq() - def test_dhcp_client_ipv4_only(self): copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv4-only.network') From 53488ea352b658e37eef06f958c3f8ca062a64d9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 22 Aug 2023 14:22:03 +0900 Subject: [PATCH 2/6] network: introduce per DUID type setters No functional change, just refactoring. --- src/libsystemd-network/dhcp-identifier.c | 75 +++------ src/libsystemd-network/dhcp-identifier.h | 20 ++- src/libsystemd-network/sd-dhcp-client.c | 180 ++++++++++++++------- src/libsystemd-network/sd-dhcp6-client.c | 96 ++++++----- src/libsystemd-network/test-dhcp6-client.c | 4 +- src/network/networkd-dhcp4.c | 44 +++-- src/network/networkd-dhcp6.c | 25 ++- src/systemd/sd-dhcp-client.h | 26 ++- src/systemd/sd-dhcp6-client.h | 13 +- 9 files changed, 287 insertions(+), 196 deletions(-) diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c index a27d67a315..93aadd1e4f 100644 --- a/src/libsystemd-network/dhcp-identifier.c +++ b/src/libsystemd-network/dhcp-identifier.c @@ -23,43 +23,7 @@ static const char * const duid_type_table[_DUID_TYPE_MAX] = { DEFINE_STRING_TABLE_LOOKUP_TO_STRING(duid_type, DUIDType); -int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict) { - struct duid d; - - assert_cc(sizeof(d.raw) >= MAX_DUID_LEN); - if (duid_len > MAX_DUID_LEN) - return -EINVAL; - - if (!strict) - /* Strict validation is not requested. We only ensure that the - * DUID is not too long. */ - return 0; - - 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; -} - -static int dhcp_identifier_set_duid_llt( +int dhcp_identifier_set_duid_llt( const struct hw_addr_data *hw_addr, uint16_t arp_type, usec_t t, @@ -97,7 +61,7 @@ static int dhcp_identifier_set_duid_llt( return 0; } -static int dhcp_identifier_set_duid_ll( +int dhcp_identifier_set_duid_ll( const struct hw_addr_data *hw_addr, uint16_t arp_type, struct duid *ret_duid, @@ -160,7 +124,7 @@ int dhcp_identifier_set_duid_en(bool test_mode, struct duid *ret_duid, size_t *r return 0; } -static int dhcp_identifier_set_duid_uuid(struct duid *ret_duid, size_t *ret_len) { +int dhcp_identifier_set_duid_uuid(struct duid *ret_duid, size_t *ret_len) { sd_id128_t machine_id; int r; @@ -179,27 +143,28 @@ static int dhcp_identifier_set_duid_uuid(struct duid *ret_duid, size_t *ret_len) return 0; } -int dhcp_identifier_set_duid( +int dhcp_identifier_set_duid_raw( DUIDType duid_type, - const struct hw_addr_data *hw_addr, - uint16_t arp_type, - usec_t llt_time, - bool test_mode, + const uint8_t *buf, + size_t buf_len, struct duid *ret_duid, size_t *ret_len) { - switch (duid_type) { - case DUID_TYPE_LLT: - 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(hw_addr, arp_type, ret_duid, ret_len); - case DUID_TYPE_UUID: - return dhcp_identifier_set_duid_uuid(ret_duid, ret_len); - default: + assert(buf || buf_len == 0); + assert(ret_duid); + assert(ret_len); + + if (duid_type < 0 || duid_type > UINT16_MAX) return -EINVAL; - } + + if (buf_len > MAX_DUID_LEN) + return -EINVAL; + + unaligned_write_be16(&ret_duid->type, duid_type); + memcpy_safe(ret_duid->raw.data, buf, buf_len); + + *ret_len = offsetof(struct duid, raw.data) + buf_len; + return 0; } int dhcp_identifier_set_iaid( diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h index 523dfc4a71..3830b5952c 100644 --- a/src/libsystemd-network/dhcp-identifier.h +++ b/src/libsystemd-network/dhcp-identifier.h @@ -57,13 +57,23 @@ struct duid { } _packed_; 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, +int dhcp_identifier_set_duid_llt( const struct hw_addr_data *hw_addr, uint16_t arp_type, - usec_t llt_time, - bool test_mode, + usec_t t, + struct duid *ret_duid, + size_t *ret_len); +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); +int dhcp_identifier_set_duid_en(bool test_mode, struct duid *ret_duid, size_t *ret_len); +int dhcp_identifier_set_duid_uuid(struct duid *ret_duid, size_t *ret_len); +int dhcp_identifier_set_duid_raw( + DUIDType duid_type, + const uint8_t *buf, + size_t buf_len, struct duid *ret_duid, size_t *ret_len); int dhcp_identifier_set_iaid( diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 272201abfd..8f330c8f14 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -402,27 +402,15 @@ int sd_dhcp_client_set_client_id( * 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( +static int dhcp_client_set_iaid( sd_dhcp_client *client, bool iaid_set, - uint32_t iaid, - DUIDType duid_type, - const void *duid, - size_t duid_len, - usec_t llt_time) { + uint32_t iaid) { - size_t len; int r; assert_return(client, -EINVAL); assert_return(!sd_dhcp_client_is_running(client), -EBUSY); - 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; @@ -437,46 +425,132 @@ static int dhcp_client_set_iaid_duid_internal( 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->hw_addr, - 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) + sizeof(client->client_id.ns.iaid) + len; - 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, 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, iaid_set, iaid, DUID_TYPE_LLT, NULL, 0, llt_time); + + size_t len; + int r; + + assert_return(client, -EINVAL); + assert_return(!sd_dhcp_client_is_running(client), -EBUSY); + + r = dhcp_client_set_iaid(client, iaid_set, iaid); + if (r < 0) + return r; + + r = dhcp_identifier_set_duid_llt(&client->hw_addr, client->arp_type, llt_time, &client->client_id.ns.duid, &len); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to set DUID-LLT: %m"); + + client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + len; + + return 0; +} + +int sd_dhcp_client_set_iaid_duid_ll( + sd_dhcp_client *client, + bool iaid_set, + uint32_t iaid) { + + size_t len; + int r; + + assert_return(client, -EINVAL); + assert_return(!sd_dhcp_client_is_running(client), -EBUSY); + + r = dhcp_client_set_iaid(client, iaid_set, iaid); + if (r < 0) + return r; + + r = dhcp_identifier_set_duid_ll(&client->hw_addr, client->arp_type, &client->client_id.ns.duid, &len); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to set DUID-LL: %m"); + + client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + len; + + return 0; +} + +int sd_dhcp_client_set_iaid_duid_en( + sd_dhcp_client *client, + bool iaid_set, + uint32_t iaid) { + + size_t len; + int r; + + assert_return(client, -EINVAL); + assert_return(!sd_dhcp_client_is_running(client), -EBUSY); + + r = dhcp_client_set_iaid(client, iaid_set, iaid); + if (r < 0) + return r; + + r = dhcp_identifier_set_duid_en(client->test_mode, &client->client_id.ns.duid, &len); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to set DUID-EN: %m"); + + client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + len; + + return 0; +} + +int sd_dhcp_client_set_iaid_duid_uuid( + sd_dhcp_client *client, + bool iaid_set, + uint32_t iaid) { + + size_t len; + int r; + + assert_return(client, -EINVAL); + assert_return(!sd_dhcp_client_is_running(client), -EBUSY); + + r = dhcp_client_set_iaid(client, iaid_set, iaid); + if (r < 0) + return r; + + r = dhcp_identifier_set_duid_uuid(&client->client_id.ns.duid, &len); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to set DUID-UUID: %m"); + + client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + len; + + return 0; +} + +int sd_dhcp_client_set_iaid_duid_raw( + sd_dhcp_client *client, + bool iaid_set, + uint32_t iaid, + uint16_t duid_type, + const uint8_t *duid, + size_t duid_len) { + + size_t len; + int r; + + assert_return(client, -EINVAL); + assert_return(!sd_dhcp_client_is_running(client), -EBUSY); + assert_return(duid || duid_len == 0, -EINVAL); + + r = dhcp_client_set_iaid(client, iaid_set, iaid); + if (r < 0) + return r; + + r = dhcp_identifier_set_duid_raw(duid_type, duid, duid_len, &client->client_id.ns.duid, &len); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to set DUID: %m"); + + client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + len; + + return 0; } void dhcp_client_set_test_mode(sd_dhcp_client *client, bool test_mode) { @@ -798,21 +872,9 @@ static int client_message_init( /* 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->dev, &client->hw_addr, - /* legacy_unstable_byteorder = */ true, - &client->client_id.ns.iaid); + r = sd_dhcp_client_set_iaid_duid_en(client, /* iaid_set = */ false, /* iaid = */ 0); 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 diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 2f4053caad..8957e1cf4b 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -190,60 +190,70 @@ static int client_ensure_duid(sd_dhcp6_client *client) { * without further modification. Otherwise, if duid_type is supported, DUID * is set based on that type. Otherwise, an error is returned. */ -static int dhcp6_client_set_duid_internal( - sd_dhcp6_client *client, - DUIDType duid_type, - const void *duid, - size_t duid_len, - usec_t llt_time) { +int sd_dhcp6_client_set_duid_llt(sd_dhcp6_client *client, uint64_t llt_time) { int r; assert_return(client, -EINVAL); assert_return(!sd_dhcp6_client_is_running(client), -EBUSY); - assert_return(duid_len == 0 || duid, -EINVAL); - if (duid) { - r = dhcp_validate_duid_len(duid_type, duid_len, true); - if (r < 0) { - r = dhcp_validate_duid_len(duid_type, duid_len, false); - if (r < 0) - return log_dhcp6_client_errno(client, r, "Failed to validate length of DUID: %m"); - - log_dhcp6_client(client, "Using DUID of type %i of incorrect length, proceeding.", duid_type); - } - - client->duid.type = htobe16(duid_type); - memcpy(&client->duid.raw.data, duid, duid_len); - client->duid_len = sizeof(client->duid.type) + duid_len; - - } else { - 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 " - "interface type is not supported.", - duid_type_to_string(duid_type)); - if (r < 0) - return log_dhcp6_client_errno(client, r, "Failed to set %s: %m", - duid_type_to_string(duid_type)); - } + r = dhcp_identifier_set_duid_llt(&client->hw_addr, client->arp_type, llt_time, &client->duid, &client->duid_len); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Failed to set DUID-LLT: %m"); return 0; } -int sd_dhcp6_client_set_duid( - sd_dhcp6_client *client, - uint16_t duid_type, - const void *duid, - size_t duid_len) { - return dhcp6_client_set_duid_internal(client, duid_type, duid, duid_len, 0); +int sd_dhcp6_client_set_duid_ll(sd_dhcp6_client *client) { + int r; + + assert_return(client, -EINVAL); + assert_return(!sd_dhcp6_client_is_running(client), -EBUSY); + + r = dhcp_identifier_set_duid_ll(&client->hw_addr, client->arp_type, &client->duid, &client->duid_len); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Failed to set DUID-LL: %m"); + + return 0; } -int sd_dhcp6_client_set_duid_llt( - sd_dhcp6_client *client, - usec_t llt_time) { - return dhcp6_client_set_duid_internal(client, DUID_TYPE_LLT, NULL, 0, llt_time); +int sd_dhcp6_client_set_duid_en(sd_dhcp6_client *client) { + int r; + + assert_return(client, -EINVAL); + assert_return(!sd_dhcp6_client_is_running(client), -EBUSY); + + r = dhcp_identifier_set_duid_en(client->test_mode, &client->duid, &client->duid_len); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Failed to set DUID-EN: %m"); + + return 0; +} + +int sd_dhcp6_client_set_duid_uuid(sd_dhcp6_client *client) { + int r; + + assert_return(client, -EINVAL); + assert_return(!sd_dhcp6_client_is_running(client), -EBUSY); + + r = dhcp_identifier_set_duid_uuid(&client->duid, &client->duid_len); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Failed to set DUID-UUID: %m"); + + return 0; +} + +int sd_dhcp6_client_set_duid_raw(sd_dhcp6_client *client, uint16_t duid_type, const uint8_t *duid, size_t duid_len) { + int r; + + assert_return(client, -EINVAL); + assert_return(!sd_dhcp6_client_is_running(client), -EBUSY); + assert_return(duid || duid_len == 0, -EINVAL); + + r = dhcp_identifier_set_duid_raw(duid_type, duid, duid_len, &client->duid, &client->duid_len); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Failed to set DUID: %m"); + + return 0; } int sd_dhcp6_client_duid_as_string( diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c index 6b1842f1f8..ccf9208d43 100644 --- a/src/libsystemd-network/test-dhcp6-client.c +++ b/src/libsystemd-network/test-dhcp6-client.c @@ -428,7 +428,7 @@ TEST(client_parse_message_issue_22099) { assert_se(sd_dhcp6_client_new(&client) >= 0); assert_se(sd_dhcp6_client_set_iaid(client, 0xcc59117b) >= 0); - assert_se(sd_dhcp6_client_set_duid(client, 2, duid, sizeof(duid)) >= 0); + assert_se(sd_dhcp6_client_set_duid_raw(client, 2, duid, sizeof(duid)) >= 0); assert_se(dhcp6_lease_new_from_message(client, (const DHCP6Message*) msg, sizeof(msg), NULL, NULL, &lease) >= 0); } @@ -472,7 +472,7 @@ TEST(client_parse_message_issue_24002) { assert_se(sd_dhcp6_client_new(&client) >= 0); assert_se(sd_dhcp6_client_set_iaid(client, 0xaabbccdd) >= 0); - assert_se(sd_dhcp6_client_set_duid(client, 2, duid, sizeof(duid)) >= 0); + assert_se(sd_dhcp6_client_set_duid_raw(client, 2, duid, sizeof(duid)) >= 0); assert_se(dhcp6_lease_new_from_message(client, (const DHCP6Message*) msg, sizeof(msg), NULL, NULL, &lease) >= 0); } diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index eeb3585f29..9dcd37e11c 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1326,20 +1326,42 @@ static int dhcp4_set_client_identifier(Link *link) { /* If configured, apply user specified DUID and IAID */ const DUID *duid = link_get_dhcp4_duid(link); - if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0) - r = sd_dhcp_client_set_iaid_duid_llt(link->dhcp_client, + if (duid->raw_data_len == 0) + switch (duid->type) { + case DUID_TYPE_LLT: + r = sd_dhcp_client_set_iaid_duid_llt(link->dhcp_client, + link->network->dhcp_iaid_set, + link->network->dhcp_iaid, + duid->llt_time); + break; + case DUID_TYPE_LL: + r = sd_dhcp_client_set_iaid_duid_ll(link->dhcp_client, + link->network->dhcp_iaid_set, + link->network->dhcp_iaid); + break; + case DUID_TYPE_EN: + r = sd_dhcp_client_set_iaid_duid_en(link->dhcp_client, + link->network->dhcp_iaid_set, + link->network->dhcp_iaid); + break; + case DUID_TYPE_UUID: + r = sd_dhcp_client_set_iaid_duid_uuid(link->dhcp_client, + link->network->dhcp_iaid_set, + link->network->dhcp_iaid); + break; + default: + r = sd_dhcp_client_set_iaid_duid_raw(link->dhcp_client, + link->network->dhcp_iaid_set, + link->network->dhcp_iaid, + duid->type, NULL, 0); + } + else + r = sd_dhcp_client_set_iaid_duid_raw(link->dhcp_client, link->network->dhcp_iaid_set, link->network->dhcp_iaid, - duid->llt_time); - else - r = sd_dhcp_client_set_iaid_duid(link->dhcp_client, - link->network->dhcp_iaid_set, - link->network->dhcp_iaid, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); + duid->type, duid->raw_data, duid->raw_data_len); if (r < 0) - return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set IAID+DUID: %m"); + return r; break; } case DHCP_CLIENT_ID_MAC: { diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 00c767e1fb..95b13ca93c 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -555,13 +555,26 @@ static int dhcp6_set_identifier(Link *link, sd_dhcp6_client *client) { } duid = link_get_dhcp6_duid(link); - if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0) - r = sd_dhcp6_client_set_duid_llt(client, duid->llt_time); + + if (duid->raw_data_len == 0) + switch (duid->type) { + case DUID_TYPE_LLT: + r = sd_dhcp6_client_set_duid_llt(client, duid->llt_time); + break; + case DUID_TYPE_LL: + r = sd_dhcp6_client_set_duid_ll(client); + break; + case DUID_TYPE_EN: + r = sd_dhcp6_client_set_duid_en(client); + break; + case DUID_TYPE_UUID: + r = sd_dhcp6_client_set_duid_uuid(client); + break; + default: + r = sd_dhcp6_client_set_duid_raw(client, duid->type, NULL, 0); + } else - r = sd_dhcp6_client_set_duid(client, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); + r = sd_dhcp6_client_set_duid_raw(client, duid->type, duid->raw_data, duid->raw_data_len); if (r < 0) return r; diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h index 7339bb6872..ddd445c9f0 100644 --- a/src/systemd/sd-dhcp-client.h +++ b/src/systemd/sd-dhcp-client.h @@ -257,18 +257,30 @@ int sd_dhcp_client_set_client_id( uint8_t type, const uint8_t *data, size_t data_len); -__extension__ 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); __extension__ int sd_dhcp_client_set_iaid_duid_llt( sd_dhcp_client *client, bool iaid_set, uint32_t iaid, uint64_t llt_time); +__extension__ int sd_dhcp_client_set_iaid_duid_ll( + sd_dhcp_client *client, + bool iaid_set, + uint32_t iaid); +__extension__ int sd_dhcp_client_set_iaid_duid_en( + sd_dhcp_client *client, + bool iaid_set, + uint32_t iaid); +__extension__ int sd_dhcp_client_set_iaid_duid_uuid( + sd_dhcp_client *client, + bool iaid_set, + uint32_t iaid); +__extension__ int sd_dhcp_client_set_iaid_duid_raw( + sd_dhcp_client *client, + bool iaid_set, + uint32_t iaid, + uint16_t duid_type, + const uint8_t *duid, + size_t duid_len); int sd_dhcp_client_get_client_id( sd_dhcp_client *client, uint8_t *ret_type, diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h index a9fa78569d..c85c5652c4 100644 --- a/src/systemd/sd-dhcp6-client.h +++ b/src/systemd/sd-dhcp6-client.h @@ -211,14 +211,11 @@ int sd_dhcp6_client_set_mac( const uint8_t *addr, size_t addr_len, uint16_t arp_type); -int sd_dhcp6_client_set_duid( - sd_dhcp6_client *client, - uint16_t duid_type, - const void *duid, - size_t duid_len); -int sd_dhcp6_client_set_duid_llt( - sd_dhcp6_client *client, - uint64_t llt_time); +int sd_dhcp6_client_set_duid_llt(sd_dhcp6_client *client, uint64_t llt_time); +int sd_dhcp6_client_set_duid_ll(sd_dhcp6_client *client); +int sd_dhcp6_client_set_duid_en(sd_dhcp6_client *client); +int sd_dhcp6_client_set_duid_uuid(sd_dhcp6_client *client); +int sd_dhcp6_client_set_duid_raw(sd_dhcp6_client *client, uint16_t duid_type, const uint8_t *duid, size_t duid_len); int sd_dhcp6_client_set_iaid( sd_dhcp6_client *client, uint32_t iaid); From 92914960113b9ed21570f4329e2b2b2bf3e84629 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 22 Aug 2023 14:26:06 +0900 Subject: [PATCH 3/6] network/dhcp: fix maximal DUID data size The maximum DUID size is 128, but that includes type specified. Hence, the maximal data size is 126. --- src/libsystemd-network/dhcp-identifier.c | 2 +- src/libsystemd-network/dhcp-identifier.h | 3 ++- src/network/networkd-dhcp-common.c | 4 ++-- src/network/networkd-dhcp-common.h | 2 +- src/network/test-networkd-conf.c | 25 ++++++++++++++++++++---- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c index 93aadd1e4f..b0572585e6 100644 --- a/src/libsystemd-network/dhcp-identifier.c +++ b/src/libsystemd-network/dhcp-identifier.c @@ -157,7 +157,7 @@ int dhcp_identifier_set_duid_raw( if (duid_type < 0 || duid_type > UINT16_MAX) return -EINVAL; - if (buf_len > MAX_DUID_LEN) + if (buf_len > MAX_DUID_DATA_LEN) return -EINVAL; unaligned_write_be16(&ret_duid->type, duid_type); diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h index 3830b5952c..28acb2ca56 100644 --- a/src/libsystemd-network/dhcp-identifier.h +++ b/src/libsystemd-network/dhcp-identifier.h @@ -25,6 +25,7 @@ typedef enum DUIDType { * A DUID can be no more than 128 octets long (not including the type code). */ #define MAX_DUID_LEN 128 +#define MAX_DUID_DATA_LEN (MAX_DUID_LEN - sizeof(be16_t)) /* https://tools.ietf.org/html/rfc3315#section-9.1 */ struct duid { @@ -51,7 +52,7 @@ struct duid { sd_id128_t uuid; } _packed_ uuid; struct { - uint8_t data[MAX_DUID_LEN]; + uint8_t data[MAX_DUID_DATA_LEN]; } _packed_ raw; }; } _packed_; diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index 5f9ef80e3e..8bd20ea21c 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -1243,7 +1243,7 @@ int config_parse_duid_rawdata( void *data, void *userdata) { - uint8_t raw_data[MAX_DUID_LEN]; + uint8_t raw_data[MAX_DUID_DATA_LEN]; unsigned count = 0; bool force = ltype; DUID *duid = ASSERT_PTR(data); @@ -1271,7 +1271,7 @@ int config_parse_duid_rawdata( if (r == 0) break; - if (count >= MAX_DUID_LEN) { + if (count >= MAX_DUID_DATA_LEN) { log_syntax(unit, LOG_WARNING, filename, line, 0, "Max DUID length exceeded, ignoring assignment: %s.", rvalue); return 0; } diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h index 07367d4d24..ea942af721 100644 --- a/src/network/networkd-dhcp-common.h +++ b/src/network/networkd-dhcp-common.h @@ -48,7 +48,7 @@ typedef struct DUID { DUIDType type; uint8_t raw_data_len; - uint8_t raw_data[MAX_DUID_LEN]; + uint8_t raw_data[MAX_DUID_DATA_LEN]; usec_t llt_time; bool set; } DUID; diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c index f6f068706a..22dd991fb0 100644 --- a/src/network/test-networkd-conf.c +++ b/src/network/test-networkd-conf.c @@ -83,9 +83,26 @@ static void test_config_parse_ether_addrs_one(const char *rvalue, const struct e assert_se(set_size(s) == 0); } -#define BYTES_0_128 "0:1:2:3:4:5:6:7:8:9:a:b:c:d:e:f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f:20:21:22:23:24:25:26:27:28:29:2a:2b:2c:2d:2e:2f:30:31:32:33:34:35:36:37:38:39:3a:3b:3c:3d:3e:3f:40:41:42:43:44:45:46:47:48:49:4a:4b:4c:4d:4e:4f:50:51:52:53:54:55:56:57:58:59:5a:5b:5c:5d:5e:5f:60:61:62:63:64:65:66:67:68:69:6a:6b:6c:6d:6e:6f:70:71:72:73:74:75:76:77:78:79:7a:7b:7c:7d:7e:7f:80" +#define BYTES_0_126 \ + "00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:" \ + "10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f:" \ + "20:21:22:23:24:25:26:27:28:29:2a:2b:2c:2d:2e:2f:" \ + "30:31:32:33:34:35:36:37:38:39:3a:3b:3c:3d:3e:3f:" \ + "40:41:42:43:44:45:46:47:48:49:4a:4b:4c:4d:4e:4f:" \ + "50:51:52:53:54:55:56:57:58:59:5a:5b:5c:5d:5e:5f:" \ + "60:61:62:63:64:65:66:67:68:69:6a:6b:6c:6d:6e:6f:" \ + "70:71:72:73:74:75:76:77:78:79:7a:7b:7c:7d:7e" -#define BYTES_1_128 {0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80} +#define BYTES_1_126 { \ + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, \ + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, \ + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, \ + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, \ + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, \ + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, \ + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, \ + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e \ +} TEST(config_parse_duid_rawdata) { test_config_parse_duid_rawdata_one("", 0, &(DUID){}); @@ -99,8 +116,8 @@ TEST(config_parse_duid_rawdata) { &(DUID){0, 8, {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}}); test_config_parse_duid_rawdata_one("11::", 0, &(DUID){0, 1, {0x11}}); /* FIXME: should this be an error? */ test_config_parse_duid_rawdata_one("abcdef", 0, &(DUID){}); - test_config_parse_duid_rawdata_one(BYTES_0_128, 0, &(DUID){}); - test_config_parse_duid_rawdata_one(&BYTES_0_128[2], 0, &(DUID){0, 128, BYTES_1_128}); + test_config_parse_duid_rawdata_one(BYTES_0_126, 0, &(DUID){}); + test_config_parse_duid_rawdata_one(&BYTES_0_126[3], 0, &(DUID){0, 126, BYTES_1_126}); } TEST(config_parse_ether_addr) { From 2da796cabb3becf57b98ef1522e1cd8857c906d2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 22 Aug 2023 14:44:13 +0900 Subject: [PATCH 4/6] dhcp: DUID-EN identifier has variable length Also make `array[0]` -> `array[]`. See RFC 8415, section 11.3. --- src/libsystemd-network/dhcp-identifier.c | 4 ++-- src/libsystemd-network/dhcp-identifier.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c index b0572585e6..c905704ab5 100644 --- a/src/libsystemd-network/dhcp-identifier.c +++ b/src/libsystemd-network/dhcp-identifier.c @@ -114,9 +114,9 @@ int dhcp_identifier_set_duid_en(bool test_mode, struct duid *ret_duid, size_t *r /* a bit of snake-oil perhaps, but no need to expose the machine-id * directly; duid->en.id might not be aligned, so we need to copy */ hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes)); - memcpy(ret_duid->en.id, &hash, sizeof(ret_duid->en.id)); + memcpy(ret_duid->en.id, &hash, sizeof(hash)); - *ret_len = offsetof(struct duid, en.id) + sizeof(ret_duid->en.id); + *ret_len = offsetof(struct duid, en.id) + sizeof(hash); if (test_mode) assert_se(memcmp(ret_duid, (const uint8_t[]) { 0x00, 0x02, 0x00, 0x00, 0xab, 0x11, 0x61, 0x77, 0x40, 0xde, 0x13, 0x42, 0xc3, 0xa2 }, *ret_len) == 0); diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h index 28acb2ca56..efb266ef80 100644 --- a/src/libsystemd-network/dhcp-identifier.h +++ b/src/libsystemd-network/dhcp-identifier.h @@ -35,17 +35,17 @@ struct duid { /* DUID_TYPE_LLT */ be16_t htype; be32_t time; - uint8_t haddr[0]; + uint8_t haddr[]; } _packed_ llt; struct { /* DUID_TYPE_EN */ be32_t pen; - uint8_t id[8]; + uint8_t id[]; } _packed_ en; struct { /* DUID_TYPE_LL */ be16_t htype; - uint8_t haddr[0]; + uint8_t haddr[]; } _packed_ ll; struct { /* DUID_TYPE_UUID */ From 80500bb5d4eebf682c0f94d0bfeaf8cd44e19626 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 22 Aug 2023 14:32:07 +0900 Subject: [PATCH 5/6] network/dhcp: make DUIDType= take an arbitrary integer Closes #26745. --- man/networkd.conf.xml | 2 +- src/libsystemd-network/dhcp-identifier.h | 1 + src/network/networkd-dhcp-common.c | 14 +++++++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/man/networkd.conf.xml b/man/networkd.conf.xml index bf597cac2e..f25083cc69 100644 --- a/man/networkd.conf.xml +++ b/man/networkd.conf.xml @@ -127,7 +127,7 @@ RFC 3315 for a description of all the options. - The following values are understood: + This takes an integer in the range 0…65535, or one of the following string values: diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h index efb266ef80..7b36f92e7f 100644 --- a/src/libsystemd-network/dhcp-identifier.h +++ b/src/libsystemd-network/dhcp-identifier.h @@ -19,6 +19,7 @@ typedef enum DUIDType { DUID_TYPE_UUID = 4, _DUID_TYPE_MAX, _DUID_TYPE_INVALID = -EINVAL, + _DUID_TYPE_FORCE_U16 = UINT16_MAX, } DUIDType; /* RFC 3315 section 9.1: diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c index 8bd20ea21c..5b5b251e61 100644 --- a/src/network/networkd-dhcp-common.c +++ b/src/network/networkd-dhcp-common.c @@ -1154,9 +1154,17 @@ int config_parse_duid_type( type = duid_type_from_string(type_string); if (type < 0) { - log_syntax(unit, LOG_WARNING, filename, line, type, - "Failed to parse DUID type '%s', ignoring.", type_string); - return 0; + uint16_t t; + + r = safe_atou16(type_string, &t); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse DUID type '%s', ignoring.", type_string); + return 0; + } + + type = t; + assert(type == t); /* Check if type can store uint16_t. */ } if (!isempty(p)) { From e448fcd01a35c2c932a7da17441f1522e332e714 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Tue, 22 Aug 2023 15:00:29 +0900 Subject: [PATCH 6/6] test-network: re-add test for custom client identifier --- ...ipv6-only-custom-client-identifier.network | 15 +++++++++++ test/test-network/systemd-networkd-tests.py | 25 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 test/test-network/conf/25-dhcp-client-ipv6-only-custom-client-identifier.network diff --git a/test/test-network/conf/25-dhcp-client-ipv6-only-custom-client-identifier.network b/test/test-network/conf/25-dhcp-client-ipv6-only-custom-client-identifier.network new file mode 100644 index 0000000000..1b1a56cd70 --- /dev/null +++ b/test/test-network/conf/25-dhcp-client-ipv6-only-custom-client-identifier.network @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=veth99 + +[Network] +DHCP=ipv6 +IPv6Token=::1a:2b:3c:4d + +[Route] +Gateway=_ipv6ra +Destination=2001:1234:5:9fff:ff:ff:ff:ff/128 + +[DHCPv6] +DUIDType=0x42 +DUIDRawData=00:00:ab:11:f9:2a:c2:77:29:f9:5c:00 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index bd1a10507b..171152040b 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -5020,6 +5020,31 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): self.assertIn('DHCPREPLY(veth-peer)', output) self.assertNotIn('rapid-commit', output) + def test_dhcp_client_ipv6_only_with_custom_client_identifier(self): + copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv6-only-custom-client-identifier.network') + + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + # checking address + output = check_output('ip address show dev veth99 scope global') + print(output) + self.assertRegex(output, r'inet6 2600::[0-9a-f:]*/128 scope global dynamic noprefixroute') + self.assertNotIn('192.168.5', output) + + print('## dnsmasq log') + output = read_dnsmasq_log_file() + print(output) + self.assertIn('DHCPSOLICIT(veth-peer) 00:42:00:00:ab:11:f9:2a:c2:77:29:f9:5c:00', output) + self.assertNotIn('DHCPADVERTISE(veth-peer)', output) + self.assertNotIn('DHCPREQUEST(veth-peer)', output) + self.assertIn('DHCPREPLY(veth-peer)', output) + self.assertIn('sent size: 0 option: 14 rapid-commit', output) + + stop_dnsmasq() + def test_dhcp_client_ipv4_only(self): copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv4-only.network')