From: Yu Watanabe Date: Sun, 6 Feb 2022 17:36:55 +0000 (+0900) Subject: sd-dhcp6-client: set lease expiration timer in client_enter_bound_state() X-Git-Tag: v251-rc1~291^2~32 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3bb18e707c5209d7f051fa22682c10136d22a33e;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h index 7f03ce1e07e..c2655827b82 100644 --- a/src/libsystemd-network/dhcp6-internal.h +++ b/src/libsystemd-network/dhcp6-internal.h @@ -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; diff --git a/src/libsystemd-network/dhcp6-lease-internal.h b/src/libsystemd-network/dhcp6-lease-internal.h index 589274c23bf..a82e9fd06ba 100644 --- a/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/libsystemd-network/dhcp6-lease-internal.h @@ -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); diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 81b78a016f0..0ebe9f503be 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -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); diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index 9cc7e2b6428..90c3373bd50 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -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; }