struct ether_addr mac_addr;
DHCP6IA ia_na;
be32_t transaction_id;
+ usec_t transaction_start;
struct sd_dhcp6_lease *lease;
int fd;
be16_t *req_opts;
client->fd = safe_close(client->fd);
client->transaction_id = 0;
+ client->transaction_start = 0;
client->ia_na.timeout_t1 =
sd_event_source_unref(client->ia_na.timeout_t1);
client_reset(client);
}
-static int client_send_message(sd_dhcp6_client *client) {
+static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
_cleanup_free_ DHCP6Message *message = NULL;
struct in6_addr all_servers =
IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
size_t len, optlen = 512;
uint8_t *opt;
int r;
+ usec_t elapsed_usec;
+ be16_t elapsed_time;
len = sizeof(DHCP6Message) + optlen;
if (r < 0)
return r;
+ elapsed_usec = time_now - client->transaction_start;
+ if (elapsed_usec < 0xffff * USEC_PER_MSEC * 10)
+ elapsed_time = htobe16(elapsed_usec / USEC_PER_MSEC / 10);
+ else
+ elapsed_time = 0xffff;
+
+ r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ELAPSED_TIME,
+ sizeof(elapsed_time), &elapsed_time);
+ if (r < 0)
+ return r;
+
r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message,
len - optlen);
if (r < 0)
return 0;
}
- r = client_send_message(client);
- if (r >= 0)
- client->retransmit_count++;
-
-
r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
if (r < 0)
goto error;
+ r = client_send_message(client, time_now);
+ if (r >= 0)
+ client->retransmit_count++;
+
if (!client->retransmit_time) {
client->retransmit_time =
client_timeout_compute_random(init_retransmit_time);
if (r < 0)
goto error;
+ r = sd_event_source_set_name(client->timeout_resend,
+ "dhcp6-resend-timer");
+ if (r < 0)
+ goto error;
+
if (max_retransmit_duration && !client->timeout_resend_expire) {
log_dhcp6_client(client, "Max retransmission duration %"PRIu64" secs",
client->event_priority);
if (r < 0)
goto error;
+
+ r = sd_event_source_set_name(client->timeout_resend_expire,
+ "dhcp6-resend-expire-timer");
+ if (r < 0)
+ goto error;
}
error:
DHCP6Message *message, size_t len,
sd_dhcp6_lease *lease) {
int r;
- uint8_t *optval, *option = (uint8_t *)(message + 1), *id = NULL;
+ uint8_t *optval, *option, *id = NULL;
uint16_t optcode, status;
size_t optlen, id_len;
bool clientid = false;
be32_t iaid_lease;
+ option = (uint8_t *)message + sizeof(DHCP6Message);
+ len -= sizeof(DHCP6Message);
+
while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen,
&optval)) >= 0) {
switch (optcode) {
client->retransmit_time = 0;
client->retransmit_count = 0;
+ if (client->state == DHCP6_STATE_STOPPED) {
+ time_now = now(clock_boottime_or_monotonic());
+ } else {
+ r = sd_event_now(client->event, clock_boottime_or_monotonic(),
+ &time_now);
+ if (r < 0)
+ return r;
+ }
+
switch (state) {
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_SOLICITATION:
if (r < 0)
return r;
+ r = sd_event_source_set_name(client->receive_message,
+ "dhcp6-receive-message");
+ if (r < 0)
+ return r;
+
client->state = DHCP6_STATE_SOLICITATION;
break;
case DHCP6_STATE_BOUND:
- r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
- if (r < 0)
- return r;
-
if (client->lease->ia.lifetime_t1 == 0xffffffff ||
client->lease->ia.lifetime_t2 == 0xffffffff) {
if (r < 0)
return r;
+ r = sd_event_source_set_name(client->lease->ia.timeout_t1,
+ "dhcp6-t1-timeout");
+ if (r < 0)
+ return r;
+
timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t2) * USEC_PER_SEC);
log_dhcp6_client(client, "T2 expires in %s",
if (r < 0)
return r;
+ r = sd_event_source_set_name(client->lease->ia.timeout_t2,
+ "dhcp6-t2-timeout");
+ if (r < 0)
+ return r;
+
client->state = state;
return 0;
}
client->transaction_id = random_u32() & htobe32(0x00ffffff);
+ client->transaction_start = time_now;
r = sd_event_add_time(client->event, &client->timeout_resend,
clock_boottime_or_monotonic(), 0, 0, client_timeout_resend,
if (r < 0)
return r;
+ r = sd_event_source_set_name(client->timeout_resend,
+ "dhcp6-resend-timeout");
+ if (r < 0)
+ return r;
+
return 0;
}