} 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;
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;
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:
*buf += sizeof(DHCP6Option);
*buflen -= sizeof(DHCP6Option);
- memcpy(*buf, &ia->id, len);
+ memcpy(*buf, iaid, len);
*buf += len;
*buflen -= len;
}
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",
}
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;
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;
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;
}
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;
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;
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));
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));
valid = t;
}
- t = be32toh(ia->lifetime_t2);
+ t = be32toh(ia->ia_na.lifetime_t2);
if (t > valid)
return -EINVAL;
assert_return(lease, -EINVAL);
assert_return(iaid, -EINVAL);
- *iaid = lease->ia.id;
+ *iaid = lease->ia.ia_na.id;
return 0;
}