diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h index cb5b359cbe..9bff5c2dcd 100644 --- a/src/libsystemd-network/dhcp6-internal.h +++ b/src/libsystemd-network/dhcp6-internal.h @@ -41,13 +41,24 @@ struct DHCP6Address { } iaaddr _packed_; }; +/* Non-temporary Address option */ +struct ia_na { + be32_t id; + be32_t lifetime_t1; + be32_t lifetime_t2; +} _packed_; + +/* Temporary Address option */ +struct ia_ta { + be32_t id; +} _packed_; + struct DHCP6IA { uint16_t type; - struct { - be32_t id; - be32_t lifetime_t1; - be32_t lifetime_t2; - } _packed_; + union { + struct ia_na ia_na; + struct ia_ta ia_ta; + }; sd_event_source *timeout_t1; sd_event_source *timeout_t2; diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c index f346bda5fc..139b7a4c5c 100644 --- a/src/libsystemd-network/dhcp6-option.c +++ b/src/libsystemd-network/dhcp6-option.c @@ -82,6 +82,7 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) { uint16_t len; + be32_t *iaid; uint8_t *ia_hdr; size_t ia_buflen, ia_addrlen = 0; DHCP6Address *addr; @@ -92,10 +93,12 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) { switch (ia->type) { case SD_DHCP6_OPTION_IA_NA: len = DHCP6_OPTION_IA_NA_LEN; + iaid = &ia->ia_na.id; break; case SD_DHCP6_OPTION_IA_TA: len = DHCP6_OPTION_IA_TA_LEN; + iaid = &ia->ia_ta.id; break; default: @@ -111,7 +114,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) { *buf += sizeof(DHCP6Option); *buflen -= sizeof(DHCP6Option); - memcpy(*buf, &ia->id, len); + memcpy(*buf, iaid, len); *buf += len; *buflen -= len; @@ -232,10 +235,10 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype, } iaaddr_offset = DHCP6_OPTION_IA_NA_LEN; - memcpy(&ia->id, *buf, iaaddr_offset); + memcpy(&ia->ia_na, *buf, sizeof(ia->ia_na)); - lt_t1 = be32toh(ia->lifetime_t1); - lt_t2 = be32toh(ia->lifetime_t2); + lt_t1 = be32toh(ia->ia_na.lifetime_t1); + lt_t2 = be32toh(ia->ia_na.lifetime_t2); if (lt_t1 && lt_t2 && lt_t1 > lt_t2) { log_dhcp6_client(client, "IA T1 %ds > T2 %ds", @@ -254,10 +257,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype, } iaaddr_offset = DHCP6_OPTION_IA_TA_LEN; - memcpy(&ia->id, *buf, iaaddr_offset); - - ia->lifetime_t1 = 0; - ia->lifetime_t2 = 0; + memcpy(&ia->ia_ta.id, *buf, sizeof(ia->ia_ta)); break; @@ -327,19 +327,19 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype, if (r == -ENOMSG) r = 0; - if (!ia->lifetime_t1 && !ia->lifetime_t2) { + if (*buflen) + r = -ENOMSG; + + if (!ia->ia_na.lifetime_t1 && !ia->ia_na.lifetime_t2) { lt_t1 = lt_min / 2; lt_t2 = lt_min / 10 * 8; - ia->lifetime_t1 = htobe32(lt_t1); - ia->lifetime_t2 = htobe32(lt_t2); + ia->ia_na.lifetime_t1 = htobe32(lt_t1); + ia->ia_na.lifetime_t2 = htobe32(lt_t2); log_dhcp6_client(client, "Computed IA T1 %ds and T2 %ds as both were zero", lt_t1, lt_t2); } - if (*buflen) - r = -ENOMSG; - error: *buf += *buflen; *buflen = 0; diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 074a409cbf..87f37dc0d4 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -230,7 +230,7 @@ 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); + client->ia_na.ia_na.id = htobe32(iaid); return 0; } @@ -710,10 +710,10 @@ static int client_ensure_iaid(sd_dhcp6_client *client) { assert(client); - if (client->ia_na.id) + if (client->ia_na.ia_na.id) return 0; - r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, &client->ia_na.id); + r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, &client->ia_na.ia_na.id); if (r < 0) return r; @@ -815,7 +815,7 @@ static int client_parse_message( if (r < 0) return r; - if (client->ia_na.id != iaid_lease) { + if (client->ia_na.ia_na.id != iaid_lease) { log_dhcp6_client(client, "%s has wrong IAID", dhcp6_message_type_to_string(message->type)); return -EINVAL; @@ -1133,17 +1133,17 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { case DHCP6_STATE_BOUND: - if (client->lease->ia.lifetime_t1 == 0xffffffff || - client->lease->ia.lifetime_t2 == 0xffffffff) { + if (client->lease->ia.ia_na.lifetime_t1 == 0xffffffff || + client->lease->ia.ia_na.lifetime_t2 == 0xffffffff) { log_dhcp6_client(client, "Infinite T1 0x%08x or T2 0x%08x", - be32toh(client->lease->ia.lifetime_t1), - be32toh(client->lease->ia.lifetime_t2)); + be32toh(client->lease->ia.ia_na.lifetime_t1), + be32toh(client->lease->ia.ia_na.lifetime_t2)); return 0; } - timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t1) * USEC_PER_SEC); + timeout = client_timeout_compute_random(be32toh(client->lease->ia.ia_na.lifetime_t1) * USEC_PER_SEC); log_dhcp6_client(client, "T1 expires in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC)); @@ -1165,7 +1165,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { if (r < 0) goto error; - timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t2) * USEC_PER_SEC); + timeout = client_timeout_compute_random(be32toh(client->lease->ia.ia_na.lifetime_t2) * USEC_PER_SEC); log_dhcp6_client(client, "T2 expires in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC)); diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index 6f604e072f..c0819b7383 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -49,7 +49,7 @@ int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) { valid = t; } - t = be32toh(ia->lifetime_t2); + t = be32toh(ia->ia_na.lifetime_t2); if (t > valid) return -EINVAL; @@ -144,7 +144,7 @@ int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) { assert_return(lease, -EINVAL); assert_return(iaid, -EINVAL); - *iaid = lease->ia.id; + *iaid = lease->ia.ia_na.id; return 0; }