sd-dhcp6-client: set lease expiration timer in client_enter_bound_state()

The timer must be active until the client get re-enter bound state,
and the timeout must be determined by the lease acquired when entering
the bound state.
This commit is contained in:
Yu Watanabe
2022-02-14 14:45:14 +09:00
parent 30b31359b0
commit 3bb18e707c
4 changed files with 64 additions and 78 deletions
+3 -3
View File
@@ -98,8 +98,6 @@ typedef struct sd_dhcp6_client {
uint16_t arp_type;
DHCP6IA ia_na;
DHCP6IA ia_pd;
sd_event_source *timeout_t1;
sd_event_source *timeout_t2;
DHCP6RequestIA request_ia;
be32_t transaction_id;
usec_t transaction_start;
@@ -117,7 +115,9 @@ typedef struct sd_dhcp6_client {
usec_t retransmit_time;
uint8_t retransmit_count;
sd_event_source *timeout_resend;
sd_event_source *timeout_resend_expire;
sd_event_source *timeout_expire;
sd_event_source *timeout_t1;
sd_event_source *timeout_t2;
sd_dhcp6_client_callback_t callback;
void *userdata;
struct duid duid;
@@ -25,7 +25,7 @@ struct sd_dhcp6_lease {
triple_timestamp timestamp;
usec_t lifetime_t1;
usec_t lifetime_t2;
usec_t max_retransmit_duration;
usec_t lifetime_valid;
struct in6_addr server_address;
DHCP6IA *ia_na;
@@ -49,8 +49,7 @@ void dhcp6_ia_clear_addresses(DHCP6IA *ia);
DHCP6IA *dhcp6_ia_free(DHCP6IA *ia);
DEFINE_TRIVIAL_CLEANUP_FUNC(DHCP6IA*, dhcp6_ia_free);
int dhcp6_lease_get_lifetime(sd_dhcp6_lease *lease, usec_t *ret_t1, usec_t *ret_t2);
int dhcp6_lease_get_max_retransmit_duration(sd_dhcp6_lease *lease, usec_t *ret);
int dhcp6_lease_get_lifetime(sd_dhcp6_lease *lease, usec_t *ret_t1, usec_t *ret_t2, usec_t *ret_valid);
int dhcp6_lease_set_clientid(sd_dhcp6_lease *lease, const uint8_t *id, size_t len);
int dhcp6_lease_get_clientid(sd_dhcp6_lease *lease, uint8_t **ret_id, size_t *ret_len);
+49 -55
View File
@@ -597,7 +597,7 @@ static void client_reset(sd_dhcp6_client *client) {
(void) event_source_disable(client->receive_message);
(void) event_source_disable(client->timeout_resend);
(void) event_source_disable(client->timeout_resend_expire);
(void) event_source_disable(client->timeout_expire);
(void) event_source_disable(client->timeout_t1);
(void) event_source_disable(client->timeout_t2);
@@ -811,6 +811,31 @@ static usec_t client_timeout_compute_random(usec_t val) {
return usec_sub_unsigned(val, random_u64_range(val / 10));
}
static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) {
sd_dhcp6_client *client = userdata;
DHCP6_CLIENT_DONT_DESTROY(client);
DHCP6State state;
assert(s);
assert(client);
assert(client->event);
(void) event_source_disable(client->timeout_expire);
(void) event_source_disable(client->timeout_t2);
(void) event_source_disable(client->timeout_t1);
state = client->state;
client_stop(client, SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE);
/* RFC 3315, section 18.1.4., says that "...the client may choose to
use a Solicit message to locate a new DHCP server..." */
if (state == DHCP6_STATE_REBIND)
client_set_state(client, DHCP6_STATE_SOLICITATION);
return 0;
}
static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) {
sd_dhcp6_client *client = userdata;
@@ -845,7 +870,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata)
}
static int client_enter_bound_state(sd_dhcp6_client *client) {
usec_t lifetime_t1, lifetime_t2;
usec_t lifetime_t1, lifetime_t2, lifetime_valid;
int r;
assert(client);
@@ -856,10 +881,9 @@ static int client_enter_bound_state(sd_dhcp6_client *client) {
DHCP6_STATE_RENEW,
DHCP6_STATE_REBIND));
(void) event_source_disable(client->timeout_resend_expire);
(void) event_source_disable(client->timeout_resend);
r = dhcp6_lease_get_lifetime(client->lease, &lifetime_t1, &lifetime_t2);
r = dhcp6_lease_get_lifetime(client->lease, &lifetime_t1, &lifetime_t2, &lifetime_valid);
if (r < 0)
goto error;
@@ -894,6 +918,21 @@ static int client_enter_bound_state(sd_dhcp6_client *client) {
goto error;
}
if (lifetime_valid == USEC_INFINITY) {
log_dhcp6_client(client, "Infinite valid lifetime");
event_source_disable(client->timeout_expire);
} else {
log_dhcp6_client(client, "Valid lifetime expires in %s", FORMAT_TIMESPAN(lifetime_valid, USEC_PER_SEC));
r = event_reset_time_relative(client->event, &client->timeout_expire,
clock_boottime_or_monotonic(),
lifetime_valid, USEC_PER_SEC,
client_timeout_expire, client,
client->event_priority, "dhcp6-lease-expire", true);
if (r < 0)
goto error;
}
client->state = DHCP6_STATE_BOUND;
client_notify(client, SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE);
return 0;
@@ -903,36 +942,13 @@ error:
return r;
}
static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec, void *userdata) {
sd_dhcp6_client *client = userdata;
DHCP6_CLIENT_DONT_DESTROY(client);
DHCP6State state;
assert(s);
assert(client);
assert(client->event);
state = client->state;
client_stop(client, SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE);
/* RFC 3315, section 18.1.4., says that "...the client may choose to
use a Solicit message to locate a new DHCP server..." */
if (state == DHCP6_STATE_REBIND)
client_set_state(client, DHCP6_STATE_SOLICITATION);
return 0;
}
static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userdata) {
int r = 0;
sd_dhcp6_client *client = userdata;
sd_dhcp6_client *client = ASSERT_PTR(userdata);
usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0;
usec_t max_retransmit_duration = 0;
uint8_t max_retransmit_count = 0;
int r;
assert(s);
assert(client);
assert(client->event);
(void) event_source_disable(client->timeout_resend);
@@ -977,14 +993,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userda
init_retransmit_time = DHCP6_REB_TIMEOUT;
max_retransmit_time = DHCP6_REB_MAX_RT;
if (event_source_is_enabled(client->timeout_resend_expire) <= 0) {
r = dhcp6_lease_get_max_retransmit_duration(client->lease, &max_retransmit_duration);
if (r < 0) {
client_stop(client, r);
return 0;
}
}
/* Also, instead of setting MRD, the expire timer is already set in client_enter_bound_state(). */
break;
case DHCP6_STATE_STOPPED:
@@ -1034,24 +1043,10 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userda
if (r < 0)
goto error;
if (max_retransmit_duration > 0 && event_source_is_enabled(client->timeout_resend_expire) <= 0) {
log_dhcp6_client(client, "Max retransmission duration %"PRIu64" secs",
max_retransmit_duration / USEC_PER_SEC);
r = event_reset_time(client->event, &client->timeout_resend_expire,
clock_boottime_or_monotonic(),
time_now + max_retransmit_duration, USEC_PER_SEC,
client_timeout_resend_expire, client,
client->event_priority, "dhcp6-resend-expire-timer", true);
if (r < 0)
goto error;
}
return 0;
error:
if (r < 0)
client_stop(client, r);
client_stop(client, r);
return 0;
}
@@ -1347,7 +1342,6 @@ static int client_set_state(sd_dhcp6_client *client, DHCP6State state) {
assert_not_reached();
}
(void) event_source_disable(client->timeout_resend_expire);
(void) event_source_disable(client->timeout_resend);
client->retransmit_time = 0;
client->retransmit_count = 0;
@@ -1508,7 +1502,7 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
sd_event_source_disable_unref(client->receive_message);
sd_event_source_disable_unref(client->timeout_resend);
sd_event_source_disable_unref(client->timeout_resend_expire);
sd_event_source_disable_unref(client->timeout_expire);
sd_event_source_disable_unref(client->timeout_t1);
sd_event_source_disable_unref(client->timeout_t2);
+10 -17
View File
@@ -36,6 +36,10 @@ int sd_dhcp6_lease_get_timestamp(sd_dhcp6_lease *lease, clockid_t clock, uint64_
return 0;
}
static usec_t sec2usec(uint32_t sec) {
return sec == UINT32_MAX ? USEC_INFINITY : sec * USEC_PER_SEC;
}
static void dhcp6_lease_set_lifetime(sd_dhcp6_lease *lease) {
uint32_t t1 = UINT32_MAX, t2 = UINT32_MAX, min_valid_lt = UINT32_MAX;
DHCP6Address *a;
@@ -66,14 +70,12 @@ static void dhcp6_lease_set_lifetime(sd_dhcp6_lease *lease) {
t2 = min_valid_lt / 10 * 8;
}
assert(t2 <= min_valid_lt);
lease->max_retransmit_duration = (min_valid_lt - t2) * USEC_PER_SEC;
lease->lifetime_t1 = t1 == UINT32_MAX ? USEC_INFINITY : t1 * USEC_PER_SEC;
lease->lifetime_t2 = t2 == UINT32_MAX ? USEC_INFINITY : t2 * USEC_PER_SEC;
lease->lifetime_valid = sec2usec(min_valid_lt);
lease->lifetime_t1 = sec2usec(t1);
lease->lifetime_t2 = sec2usec(t2);
}
int dhcp6_lease_get_lifetime(sd_dhcp6_lease *lease, usec_t *ret_t1, usec_t *ret_t2) {
int dhcp6_lease_get_lifetime(sd_dhcp6_lease *lease, usec_t *ret_t1, usec_t *ret_t2, usec_t *ret_valid) {
assert(lease);
if (!lease->ia_na && !lease->ia_pd)
@@ -83,17 +85,8 @@ int dhcp6_lease_get_lifetime(sd_dhcp6_lease *lease, usec_t *ret_t1, usec_t *ret_
*ret_t1 = lease->lifetime_t1;
if (ret_t2)
*ret_t2 = lease->lifetime_t2;
return 0;
}
int dhcp6_lease_get_max_retransmit_duration(sd_dhcp6_lease *lease, usec_t *ret) {
assert(lease);
if (!lease->ia_na && !lease->ia_pd)
return -ENODATA;
if (ret)
*ret = lease->max_retransmit_duration;
if (ret_valid)
*ret_valid = lease->lifetime_valid;
return 0;
}