]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp6-client: set lease expiration timer in client_enter_bound_state()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 6 Feb 2022 17:36:55 +0000 (02:36 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 14 Feb 2022 05:45:14 +0000 (14:45 +0900)
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.

src/libsystemd-network/dhcp6-internal.h
src/libsystemd-network/dhcp6-lease-internal.h
src/libsystemd-network/sd-dhcp6-client.c
src/libsystemd-network/sd-dhcp6-lease.c

index 7f03ce1e07e475d7dc15bf172480a2eae2296af2..c2655827b82bd9c5be4e31460ffdc181a9493a23 100644 (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;
index 589274c23bfab6ec40b649a4669576966cf8201a..a82e9fd06ba0fb3b5691ef8c9d03fa476d48a866 100644 (file)
@@ -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);
index 81b78a016f0c5383cdcae7835240ceb7df4e313c..0ebe9f503be911e812fa95607e6efe270d49ca44 100644 (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);
 
index 9cc7e2b642831aca71f4b902a9f93076523f8558..90c3373bd50f0e9cf9f6e185c5687d89e7bb9c81 100644 (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;
 }