From: Yu Watanabe Date: Mon, 7 Feb 2022 06:10:25 +0000 (+0900) Subject: dhcp-identifier: introduce dhcp_identifier_set_duid() X-Git-Tag: v251-rc1~291^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e1618fafa5fbaca85a5a0a0ccf58458cafeb022;p=thirdparty%2Fsystemd.git dhcp-identifier: introduce dhcp_identifier_set_duid() --- diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c index 313d0a43f1f..f9769300d52 100644 --- a/src/libsystemd-network/dhcp-identifier.c +++ b/src/libsystemd-network/dhcp-identifier.c @@ -28,7 +28,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(uint16_t duid_type, size_t duid_len, bool strict) { +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); @@ -64,62 +64,68 @@ int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict) { return 0; } -int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) { +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) { uint16_t time_from_2000y; - assert(duid); - assert(len); assert(addr); + assert(ret_duid); + assert(ret_len); + + if (addr_len == 0) + return -EOPNOTSUPP; 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; + return -EOPNOTSUPP; if (t < USEC_2000) time_from_2000y = 0; else time_from_2000y = (uint16_t) (((t - USEC_2000) / USEC_PER_SEC) & 0xffffffff); - unaligned_write_be16(&duid->type, DUID_TYPE_LLT); - unaligned_write_be16(&duid->llt.htype, arp_type); - unaligned_write_be32(&duid->llt.time, time_from_2000y); - memcpy(duid->llt.haddr, addr, addr_len); + 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); - *len = sizeof(duid->type) + sizeof(duid->llt.htype) + sizeof(duid->llt.time) + addr_len; + *ret_len = sizeof(ret_duid->type) + sizeof(ret_duid->llt.htype) + sizeof(ret_duid->llt.time) + addr_len; return 0; } -int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) { - assert(duid); - assert(len); +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); + assert(ret_duid); + assert(ret_len); + + if (addr_len == 0) + return -EOPNOTSUPP; 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; + return -EOPNOTSUPP; - unaligned_write_be16(&duid->type, DUID_TYPE_LL); - unaligned_write_be16(&duid->ll.htype, arp_type); - memcpy(duid->ll.haddr, addr, addr_len); + 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); - *len = sizeof(duid->type) + sizeof(duid->ll.htype) + addr_len; + *ret_len = sizeof(ret_duid->type) + sizeof(ret_duid->ll.htype) + addr_len; return 0; } -int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) { +int dhcp_identifier_set_duid_en(struct duid *ret_duid, size_t *ret_len) { sd_id128_t machine_id; uint64_t hash; - assert(duid); - assert(len); + assert(ret_duid); + assert(ret_len); #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION int r = sd_id128_get_machine(&machine_id); @@ -129,45 +135,68 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) { machine_id = SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10); #endif - unaligned_write_be16(&duid->type, DUID_TYPE_EN); - unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN); - - *len = sizeof(duid->type) + sizeof(duid->en); + unaligned_write_be16(&ret_duid->type, DUID_TYPE_EN); + unaligned_write_be32(&ret_duid->en.pen, SYSTEMD_PEN); /* 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(duid->en.id, &hash, sizeof(duid->en.id)); + memcpy(ret_duid->en.id, &hash, sizeof(ret_duid->en.id)); + + *ret_len = sizeof(ret_duid->type) + sizeof(ret_duid->en); return 0; } -int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len) { +static int dhcp_identifier_set_duid_uuid(struct duid *ret_duid, size_t *ret_len) { sd_id128_t machine_id; int r; - assert(duid); - assert(len); + assert(ret_duid); + assert(ret_len); r = sd_id128_get_machine_app_specific(APPLICATION_ID, &machine_id); if (r < 0) return r; - unaligned_write_be16(&duid->type, DUID_TYPE_UUID); - memcpy(&duid->raw.data, &machine_id, sizeof(machine_id)); + unaligned_write_be16(&ret_duid->type, DUID_TYPE_UUID); + memcpy(ret_duid->raw.data, &machine_id, sizeof(machine_id)); - *len = sizeof(duid->type) + sizeof(machine_id); + *ret_len = sizeof(ret_duid->type) + sizeof(machine_id); return 0; } +int dhcp_identifier_set_duid( + DUIDType duid_type, + const uint8_t *addr, + size_t addr_len, + uint16_t arp_type, + usec_t llt_time, + struct duid *ret_duid, + size_t *ret_len) { + + switch (duid_type) { + case DUID_TYPE_LLT: + return dhcp_identifier_set_duid_llt(addr, addr_len, arp_type, llt_time, ret_duid, ret_len); + case DUID_TYPE_EN: + return dhcp_identifier_set_duid_en(ret_duid, ret_len); + case DUID_TYPE_LL: + return dhcp_identifier_set_duid_ll(addr, addr_len, arp_type, ret_duid, ret_len); + case DUID_TYPE_UUID: + return dhcp_identifier_set_duid_uuid(ret_duid, ret_len); + default: + return -EINVAL; + } +} + int dhcp_identifier_set_iaid( int ifindex, const uint8_t *mac, size_t mac_len, bool legacy_unstable_byteorder, bool use_mac, - void *_id) { + void *ret) { /* name is a pointer to memory in the sd_device struct, so must * have the same scope */ @@ -219,6 +248,6 @@ int dhcp_identifier_set_iaid( * behavior. */ id32 = be32toh(id32); - unaligned_write_ne32(_id, id32); + unaligned_write_ne32(ret, id32); return 0; } diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h index 31a96b20b39..acf203c057d 100644 --- a/src/libsystemd-network/dhcp-identifier.h +++ b/src/libsystemd-network/dhcp-identifier.h @@ -54,11 +54,22 @@ struct duid { }; } _packed_; -int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict); -int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len); -int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len); -int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len); -int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len); -int dhcp_identifier_set_iaid(int ifindex, const uint8_t *mac, size_t mac_len, bool legacy_unstable_byteorder, bool use_mac, void *_id); +int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict); +int dhcp_identifier_set_duid_en(struct duid *ret_duid, size_t *ret_len); +int dhcp_identifier_set_duid( + DUIDType duid_type, + const uint8_t *addr, + size_t addr_len, + uint16_t arp_type, + usec_t llt_time, + struct duid *ret_duid, + size_t *ret_len); +int dhcp_identifier_set_iaid( + int ifindex, + const uint8_t *mac, + size_t mac_len, + bool legacy_unstable_byteorder, + bool use_mac, + void *ret); const char *duid_type_to_string(DUIDType t) _const_; diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 7b296ae4a04..2106fa8a2c0 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -450,7 +450,7 @@ static int dhcp_client_set_iaid_duid_internal( bool iaid_append, bool iaid_set, uint32_t iaid, - uint16_t duid_type, + DUIDType duid_type, const void *duid, size_t duid_len, usec_t llt_time) { @@ -489,37 +489,19 @@ static int dhcp_client_set_iaid_duid_internal( 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 - switch (duid_type) { - case DUID_TYPE_LLT: - if (client->mac_addr_len == 0) - return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LLT, MAC address is not set."); - r = dhcp_identifier_set_duid_llt(&client->client_id.ns.duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &len); - if (r < 0) - return log_dhcp_client_errno(client, r, "Failed to set DUID-LLT: %m"); - break; - case DUID_TYPE_EN: - r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len); - if (r < 0) - return log_dhcp_client_errno(client, r, "Failed to set DUID-EN: %m"); - break; - case DUID_TYPE_LL: - if (client->mac_addr_len == 0) - return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LL, MAC address is not set."); - - r = dhcp_identifier_set_duid_ll(&client->client_id.ns.duid, client->mac_addr, client->mac_addr_len, client->arp_type, &len); - if (r < 0) - return log_dhcp_client_errno(client, r, "Failed to set DUID-LL: %m"); - break; - case DUID_TYPE_UUID: - 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"); - break; - default: - return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Invalid DUID type"); - } + } else { + r = dhcp_identifier_set_duid(duid_type, client->mac_addr, client->mac_addr_len, + client->arp_type, llt_time, &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); diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 1ae7a037283..ce543b7dfb5 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -281,7 +281,7 @@ static int client_ensure_duid(sd_dhcp6_client *client) { */ static int dhcp6_client_set_duid_internal( sd_dhcp6_client *client, - uint16_t duid_type, + DUIDType duid_type, const void *duid, size_t duid_len, usec_t llt_time) { @@ -304,37 +304,19 @@ static int dhcp6_client_set_duid_internal( client->duid.type = htobe16(duid_type); memcpy(&client->duid.raw.data, duid, duid_len); client->duid_len = sizeof(client->duid.type) + duid_len; - } else - switch (duid_type) { - case DUID_TYPE_LLT: - if (client->hw_addr.length == 0) - return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LLT, MAC address is not set."); - - r = dhcp_identifier_set_duid_llt(&client->duid, llt_time, client->hw_addr.bytes, client->hw_addr.length, client->arp_type, &client->duid_len); - if (r < 0) - return log_dhcp6_client_errno(client, r, "Failed to set DUID-LLT: %m"); - break; - case DUID_TYPE_EN: - r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); - if (r < 0) - return log_dhcp6_client_errno(client, r, "Failed to set DUID-EN: %m"); - break; - case DUID_TYPE_LL: - if (client->hw_addr.length == 0) - return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LL, MAC address is not set."); - r = dhcp_identifier_set_duid_ll(&client->duid, client->hw_addr.bytes, client->hw_addr.length, client->arp_type, &client->duid_len); - if (r < 0) - return log_dhcp6_client_errno(client, r, "Failed to set DUID-LL: %m"); - break; - case DUID_TYPE_UUID: - 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"); - break; - default: - return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Invalid DUID type"); - } + } else { + r = dhcp_identifier_set_duid(duid_type, client->hw_addr.bytes, client->hw_addr.length, + client->arp_type, llt_time, &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)); + } return 0; }