]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp6-client: rework IA_NA or IA_PD getters
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 4 Sep 2023 18:12:46 +0000 (03:12 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 20 Sep 2023 18:59:00 +0000 (03:59 +0900)
This splits sd_dhcp6_lease_get_address() into small pieces,
and introduce FOREACH_DHCP6_ADDRESS() macro.
Also, the lifetimes provided by _get_address_lifetime() are now in usec,
and _get_address_lifetime_timestamp() provides timestamp.

The same change is also applied for IA_PD.

src/libsystemd-network/dhcp6-lease-internal.h
src/libsystemd-network/sd-dhcp6-lease.c
src/libsystemd-network/test-dhcp6-client.c
src/network/networkd-dhcp-prefix-delegation.c
src/network/networkd-dhcp6.c
src/network/networkd-json.c
src/systemd/sd-dhcp6-lease.h

index 470fc798709f0cace42fa755afefbfe809e7e09c..c1eb23eba1a67222a36da2d940405b252a8ed607 100644 (file)
@@ -72,3 +72,17 @@ int dhcp6_lease_new_from_message(
                 const triple_timestamp *timestamp,
                 const struct in6_addr *server_address,
                 sd_dhcp6_lease **ret);
+
+#define _FOREACH_DHCP6_ADDRESS(lease, it)                               \
+        for (int it = sd_dhcp6_lease_address_iterator_reset(lease);     \
+             it > 0;                                                    \
+             it = sd_dhcp6_lease_address_iterator_next(lease))
+#define FOREACH_DHCP6_ADDRESS(lease)                                    \
+        _FOREACH_DHCP6_ADDRESS(lease, UNIQ_T(i, UNIQ))
+
+#define _FOREACH_DHCP6_PD_PREFIX(lease, it)                             \
+        for (int it = sd_dhcp6_lease_pd_iterator_reset(lease);          \
+             it > 0;                                                    \
+             it = sd_dhcp6_lease_pd_iterator_next(lease))
+#define FOREACH_DHCP6_PD_PREFIX(lease)                                  \
+        _FOREACH_DHCP6_PD_PREFIX(lease, UNIQ_T(i, UNIQ))
index 9d1c69ed3f02002696d08f581f7a8fdbdfb2f549..2be084d45cdbac9eb298114cfa471026e2ee7882 100644 (file)
@@ -8,6 +8,7 @@
 #include "alloc-util.h"
 #include "dhcp6-internal.h"
 #include "dhcp6-lease-internal.h"
+#include "network-common.h"
 #include "strv.h"
 
 #define IRT_DEFAULT (1 * USEC_PER_DAY)
@@ -216,67 +217,149 @@ int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *ret) {
         return 0;
 }
 
-int sd_dhcp6_lease_get_address(
+int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *ret) {
+        assert_return(lease, -EINVAL);
+
+        if (!lease->addr_iter)
+                return -ENODATA;
+
+        if (ret)
+                *ret = lease->addr_iter->iaaddr.address;
+        return 0;
+}
+
+int sd_dhcp6_lease_get_address_lifetime(
                 sd_dhcp6_lease *lease,
-                struct in6_addr *ret_addr,
-                uint32_t *ret_lifetime_preferred,
-                uint32_t *ret_lifetime_valid) {
+                usec_t *ret_lifetime_preferred,
+                usec_t *ret_lifetime_valid) {
+
+        const struct iaaddr *a;
 
         assert_return(lease, -EINVAL);
 
         if (!lease->addr_iter)
                 return -ENODATA;
 
-        if (ret_addr)
-                *ret_addr = lease->addr_iter->iaaddr.address;
+        a = &lease->addr_iter->iaaddr;
+
         if (ret_lifetime_preferred)
-                *ret_lifetime_preferred = be32toh(lease->addr_iter->iaaddr.lifetime_preferred);
+                *ret_lifetime_preferred = be32_sec_to_usec(a->lifetime_preferred, /* max_as_infinity = */ true);
         if (ret_lifetime_valid)
-                *ret_lifetime_valid = be32toh(lease->addr_iter->iaaddr.lifetime_valid);
-
-        lease->addr_iter = lease->addr_iter->addresses_next;
+                *ret_lifetime_valid = be32_sec_to_usec(a->lifetime_valid, /* max_as_infinity = */ true);
         return 0;
 }
 
-void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease) {
-        if (lease)
-                lease->addr_iter = lease->ia_na ? lease->ia_na->addresses : NULL;
+int sd_dhcp6_lease_address_iterator_reset(sd_dhcp6_lease *lease) {
+        if (!lease)
+                return false;
+
+        lease->addr_iter = lease->ia_na ? lease->ia_na->addresses : NULL;
+        return !!lease->addr_iter;
+}
+
+int sd_dhcp6_lease_address_iterator_next(sd_dhcp6_lease *lease) {
+        if (!lease || !lease->addr_iter)
+                return false;
+
+        lease->addr_iter = lease->addr_iter->addresses_next;
+        return !!lease->addr_iter;
 }
 
 int sd_dhcp6_lease_has_address(sd_dhcp6_lease *lease) {
         return lease && lease->ia_na;
 }
 
-int sd_dhcp6_lease_get_pd(
+int sd_dhcp6_lease_get_pd_prefix(
                 sd_dhcp6_lease *lease,
                 struct in6_addr *ret_prefix,
-                uint8_t *ret_prefix_len,
-                uint32_t *ret_lifetime_preferred,
-                uint32_t *ret_lifetime_valid) {
+                uint8_t *ret_prefix_len) {
+
+        const struct iapdprefix *a;
 
         assert_return(lease, -EINVAL);
 
         if (!lease->prefix_iter)
                 return -ENODATA;
 
+        a = &lease->prefix_iter->iapdprefix;
+
         if (ret_prefix)
-                *ret_prefix = lease->prefix_iter->iapdprefix.address;
+                *ret_prefix = a->address;
         if (ret_prefix_len)
-                *ret_prefix_len = lease->prefix_iter->iapdprefix.prefixlen;
+                *ret_prefix_len = a->prefixlen;
+        return 0;
+}
+
+int sd_dhcp6_lease_get_pd_lifetime(
+                sd_dhcp6_lease *lease,
+                uint64_t *ret_lifetime_preferred,
+                uint64_t *ret_lifetime_valid) {
+
+        const struct iapdprefix *a;
+
+        assert_return(lease, -EINVAL);
+
+        if (!lease->prefix_iter)
+                return -ENODATA;
+
+        a = &lease->prefix_iter->iapdprefix;
+
         if (ret_lifetime_preferred)
-                *ret_lifetime_preferred = be32toh(lease->prefix_iter->iapdprefix.lifetime_preferred);
+                *ret_lifetime_preferred = be32_sec_to_usec(a->lifetime_preferred, /* max_as_infinity = */ true);
         if (ret_lifetime_valid)
-                *ret_lifetime_valid = be32toh(lease->prefix_iter->iapdprefix.lifetime_valid);
-
-        lease->prefix_iter = lease->prefix_iter->addresses_next;
+                *ret_lifetime_valid = be32_sec_to_usec(a->lifetime_valid, /* max_as_infinity = */ true);
         return 0;
 }
 
-void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease *lease) {
-        if (lease)
-                lease->prefix_iter = lease->ia_pd ? lease->ia_pd->addresses : NULL;
+int sd_dhcp6_lease_pd_iterator_reset(sd_dhcp6_lease *lease) {
+        if (!lease)
+                return false;
+
+        lease->prefix_iter = lease->ia_pd ? lease->ia_pd->addresses : NULL;
+        return !!lease->prefix_iter;
 }
 
+int sd_dhcp6_lease_pd_iterator_next(sd_dhcp6_lease *lease) {
+        if (!lease || !lease->prefix_iter)
+                return false;
+
+        lease->prefix_iter = lease->prefix_iter->addresses_next;
+        return !!lease->prefix_iter;
+}
+
+#define DEFINE_GET_TIMESTAMP2(name)                                     \
+        int sd_dhcp6_lease_get_##name##_lifetime_timestamp(             \
+                        sd_dhcp6_lease *lease,                          \
+                        clockid_t clock,                                \
+                        uint64_t *ret_lifetime_preferred,               \
+                        uint64_t *ret_lifetime_valid) {                 \
+                                                                        \
+                usec_t t, p, v;                                         \
+                int r;                                                  \
+                                                                        \
+                assert_return(lease, -EINVAL);                          \
+                                                                        \
+                r = sd_dhcp6_lease_get_##name##_lifetime(               \
+                                lease,                                  \
+                                ret_lifetime_preferred ? &p : NULL,     \
+                                ret_lifetime_valid ? &v : NULL);        \
+                if (r < 0)                                              \
+                        return r;                                       \
+                                                                        \
+                r = sd_dhcp6_lease_get_timestamp(lease, clock, &t);     \
+                if (r < 0)                                              \
+                        return r;                                       \
+                                                                        \
+                if (ret_lifetime_preferred)                             \
+                        *ret_lifetime_preferred = time_span_to_stamp(p, t); \
+                if (ret_lifetime_valid)                                 \
+                        *ret_lifetime_valid = time_span_to_stamp(v, t); \
+                return 0;                                               \
+        }
+
+DEFINE_GET_TIMESTAMP2(address);
+DEFINE_GET_TIMESTAMP2(pd);
+
 int sd_dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) {
         return lease && lease->ia_pd;
 }
index a954bfb6668be44f08f071955201687c1d4fa210..7c253b5e5f74091c60e80eabc8bf70a19de0b93e 100644 (file)
@@ -893,7 +893,7 @@ static void test_lease_common(sd_dhcp6_client *client) {
 static void test_lease_managed(sd_dhcp6_client *client) {
         sd_dhcp6_lease *lease;
         struct in6_addr addr;
-        uint32_t lt_pref, lt_valid;
+        usec_t lt_pref, lt_valid;
         uint8_t *id, prefixlen;
         size_t len;
 
@@ -905,53 +905,37 @@ static void test_lease_managed(sd_dhcp6_client *client) {
         assert_se(sd_dhcp6_lease_has_address(lease));
         assert_se(sd_dhcp6_lease_has_pd_prefix(lease));
 
-        sd_dhcp6_lease_reset_address_iter(lease);
-        assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref, &lt_valid) >= 0);
-        assert_se(in6_addr_equal(&addr, &ia_na_address1));
-        assert_se(lt_pref == 150);
-        assert_se(lt_valid == 180);
-        assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref, &lt_valid) >= 0);
-        assert_se(in6_addr_equal(&addr, &ia_na_address2));
-        assert_se(lt_pref == 150);
-        assert_se(lt_valid == 180);
-        assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref, &lt_valid) == -ENODATA);
-
-        sd_dhcp6_lease_reset_address_iter(lease);
-        assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref, &lt_valid) >= 0);
-        assert_se(in6_addr_equal(&addr, &ia_na_address1));
-        assert_se(lt_pref == 150);
-        assert_se(lt_valid == 180);
-        assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref, &lt_valid) >= 0);
-        assert_se(in6_addr_equal(&addr, &ia_na_address2));
-        assert_se(lt_pref == 150);
-        assert_se(lt_valid == 180);
-        assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref, &lt_valid) == -ENODATA);
-
-        sd_dhcp6_lease_reset_pd_prefix_iter(lease);
-        assert_se(sd_dhcp6_lease_get_pd(lease, &addr, &prefixlen, &lt_pref, &lt_valid) >= 0);
-        assert_se(in6_addr_equal(&addr, &ia_pd_prefix1));
-        assert_se(prefixlen == 64);
-        assert_se(lt_pref == 150);
-        assert_se(lt_valid == 180);
-        assert_se(sd_dhcp6_lease_get_pd(lease, &addr, &prefixlen, &lt_pref, &lt_valid) >= 0);
-        assert_se(in6_addr_equal(&addr, &ia_pd_prefix2));
-        assert_se(prefixlen == 64);
-        assert_se(lt_pref == 150);
-        assert_se(lt_valid == 180);
-        assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref, &lt_valid) == -ENODATA);
-
-        sd_dhcp6_lease_reset_pd_prefix_iter(lease);
-        assert_se(sd_dhcp6_lease_get_pd(lease, &addr, &prefixlen, &lt_pref, &lt_valid) >= 0);
-        assert_se(in6_addr_equal(&addr, &ia_pd_prefix1));
-        assert_se(prefixlen == 64);
-        assert_se(lt_pref == 150);
-        assert_se(lt_valid == 180);
-        assert_se(sd_dhcp6_lease_get_pd(lease, &addr, &prefixlen, &lt_pref, &lt_valid) >= 0);
-        assert_se(in6_addr_equal(&addr, &ia_pd_prefix2));
-        assert_se(prefixlen == 64);
-        assert_se(lt_pref == 150);
-        assert_se(lt_valid == 180);
-        assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref, &lt_valid) == -ENODATA);
+        for (unsigned i = 0; i < 2; i++) {
+                assert_se(sd_dhcp6_lease_address_iterator_reset(lease));
+                assert_se(sd_dhcp6_lease_get_address(lease, &addr) >= 0);
+                assert_se(sd_dhcp6_lease_get_address_lifetime(lease, &lt_pref, &lt_valid) >= 0);
+                assert_se(in6_addr_equal(&addr, &ia_na_address1));
+                assert_se(lt_pref == 150 * USEC_PER_SEC);
+                assert_se(lt_valid == 180 * USEC_PER_SEC);
+                assert_se(sd_dhcp6_lease_address_iterator_next(lease));
+                assert_se(sd_dhcp6_lease_get_address(lease, &addr) >= 0);
+                assert_se(sd_dhcp6_lease_get_address_lifetime(lease, &lt_pref, &lt_valid) >= 0);
+                assert_se(in6_addr_equal(&addr, &ia_na_address2));
+                assert_se(lt_pref == 150 * USEC_PER_SEC);
+                assert_se(lt_valid == 180 * USEC_PER_SEC);
+                assert_se(!sd_dhcp6_lease_address_iterator_next(lease));
+
+                assert_se(sd_dhcp6_lease_pd_iterator_reset(lease));
+                assert_se(sd_dhcp6_lease_get_pd_prefix(lease, &addr, &prefixlen) >= 0);
+                assert_se(sd_dhcp6_lease_get_pd_lifetime(lease, &lt_pref, &lt_valid) >= 0);
+                assert_se(in6_addr_equal(&addr, &ia_pd_prefix1));
+                assert_se(prefixlen == 64);
+                assert_se(lt_pref == 150 * USEC_PER_SEC);
+                assert_se(lt_valid == 180 * USEC_PER_SEC);
+                assert_se(sd_dhcp6_lease_pd_iterator_next(lease));
+                assert_se(sd_dhcp6_lease_get_pd_prefix(lease, &addr, &prefixlen) >= 0);
+                assert_se(sd_dhcp6_lease_get_pd_lifetime(lease, &lt_pref, &lt_valid) >= 0);
+                assert_se(in6_addr_equal(&addr, &ia_pd_prefix2));
+                assert_se(prefixlen == 64);
+                assert_se(lt_pref == 150 * USEC_PER_SEC);
+                assert_se(lt_valid == 180 * USEC_PER_SEC);
+                assert_se(!sd_dhcp6_lease_pd_iterator_next(lease));
+        }
 
         test_lease_common(client);
 }
index 0051a7ee44b0b05977f028e019d584e9c94b923a..56bbc4acc54570bafb28f9fdbb41848272d99b04 100644 (file)
@@ -2,8 +2,7 @@
 
 #include <linux/ipv6_route.h>
 
-#include "sd-dhcp6-client.h"
-
+#include "dhcp6-lease-internal.h"
 #include "hashmap.h"
 #include "in-addr-prefix-util.h"
 #include "networkd-address-generation.h"
@@ -993,7 +992,6 @@ int dhcp4_pd_prefix_acquired(Link *uplink) {
 }
 
 static int dhcp6_pd_assign_subnet_prefixes(Link *link, Link *uplink) {
-        usec_t timestamp_usec;
         int r;
 
         assert(link);
@@ -1004,19 +1002,14 @@ static int dhcp6_pd_assign_subnet_prefixes(Link *link, Link *uplink) {
         if (r <= 0)
                 return r;
 
-        r = sd_dhcp6_lease_get_timestamp(uplink->dhcp6_lease, CLOCK_BOOTTIME, &timestamp_usec);
-        if (r < 0)
-                return r;
-
-        for (sd_dhcp6_lease_reset_pd_prefix_iter(uplink->dhcp6_lease);;) {
-                uint32_t lifetime_preferred_sec, lifetime_valid_sec;
+        FOREACH_DHCP6_PD_PREFIX(uplink->dhcp6_lease) {
+                usec_t lifetime_preferred_usec, lifetime_valid_usec;
                 struct in6_addr pd_prefix;
                 uint8_t pd_prefix_len;
 
-                r = sd_dhcp6_lease_get_pd(uplink->dhcp6_lease, &pd_prefix, &pd_prefix_len,
-                                          &lifetime_preferred_sec, &lifetime_valid_sec);
+                r = sd_dhcp6_lease_get_pd_prefix(uplink->dhcp6_lease, &pd_prefix, &pd_prefix_len);
                 if (r < 0)
-                        break;
+                        return r;
 
                 if (pd_prefix_len > 64)
                         continue;
@@ -1026,9 +1019,13 @@ static int dhcp6_pd_assign_subnet_prefixes(Link *link, Link *uplink) {
                 if (r < 0)
                         return r;
 
+                r = sd_dhcp6_lease_get_pd_lifetime_timestamp(uplink->dhcp6_lease, CLOCK_BOOTTIME,
+                                                             &lifetime_preferred_usec, &lifetime_valid_usec);
+                if (r < 0)
+                        return r;
+
                 r = dhcp_pd_assign_subnet_prefix(link, &pd_prefix, pd_prefix_len,
-                                                 sec_to_usec(lifetime_preferred_sec, timestamp_usec),
-                                                 sec_to_usec(lifetime_valid_sec, timestamp_usec),
+                                                 lifetime_preferred_usec, lifetime_valid_usec,
                                                  /* is_uplink = */ link == uplink);
                 if (r < 0)
                         return r;
@@ -1039,7 +1036,6 @@ static int dhcp6_pd_assign_subnet_prefixes(Link *link, Link *uplink) {
 
 int dhcp6_pd_prefix_acquired(Link *uplink) {
         union in_addr_union server_address;
-        usec_t timestamp_usec;
         Link *link;
         int r;
 
@@ -1050,20 +1046,15 @@ int dhcp6_pd_prefix_acquired(Link *uplink) {
         if (r < 0)
                 return log_link_warning_errno(uplink, r, "Failed to get server address of DHCPv6 lease: %m");
 
-        r = sd_dhcp6_lease_get_timestamp(uplink->dhcp6_lease, CLOCK_BOOTTIME, &timestamp_usec);
-        if (r < 0)
-                return log_link_warning_errno(uplink, r, "Failed to get timestamp of DHCPv6 lease: %m");
-
         /* First, logs acquired prefixes and request unreachable routes. */
-        for (sd_dhcp6_lease_reset_pd_prefix_iter(uplink->dhcp6_lease);;) {
-                uint32_t lifetime_preferred_sec, lifetime_valid_sec;
+        FOREACH_DHCP6_PD_PREFIX(uplink->dhcp6_lease) {
+                usec_t lifetime_valid_usec;
                 struct in6_addr pd_prefix;
                 uint8_t pd_prefix_len;
 
-                r = sd_dhcp6_lease_get_pd(uplink->dhcp6_lease, &pd_prefix, &pd_prefix_len,
-                                          &lifetime_preferred_sec, &lifetime_valid_sec);
+                r = sd_dhcp6_lease_get_pd_prefix(uplink->dhcp6_lease, &pd_prefix, &pd_prefix_len);
                 if (r < 0)
-                        break;
+                        return r;
 
                 /* Mask prefix for safety. */
                 r = in6_addr_mask(&pd_prefix, pd_prefix_len);
@@ -1074,9 +1065,13 @@ int dhcp6_pd_prefix_acquired(Link *uplink) {
                 if (r < 0)
                         return r;
 
+                r = sd_dhcp6_lease_get_pd_lifetime_timestamp(uplink->dhcp6_lease, CLOCK_BOOTTIME,
+                                                             NULL, &lifetime_valid_usec);
+                if (r < 0)
+                        return r;
+
                 r = dhcp6_request_unreachable_route(uplink, &pd_prefix, pd_prefix_len,
-                                                    sec_to_usec(lifetime_valid_sec, timestamp_usec),
-                                                    &server_address);
+                                                    lifetime_valid_usec, &server_address);
                 if (r < 0)
                         return r;
         }
index e30344fb4fe663063b8760ac6f8cec1dcf06f7aa..5c5dff9413d721bb015e288931f2e7a126607ab1 100644 (file)
@@ -3,9 +3,8 @@
   Copyright © 2014 Intel Corporation. All rights reserved.
 ***/
 
-#include "sd-dhcp6-client.h"
-
 #include "dhcp6-client-internal.h"
+#include "dhcp6-lease-internal.h"
 #include "hashmap.h"
 #include "hostname-setup.h"
 #include "hostname-util.h"
@@ -242,7 +241,6 @@ static int dhcp6_request_address(
 
 static int dhcp6_address_acquired(Link *link) {
         struct in6_addr server_address;
-        usec_t timestamp_usec;
         int r;
 
         assert(link);
@@ -256,21 +254,22 @@ static int dhcp6_address_acquired(Link *link) {
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to get server address of DHCPv6 lease: %m");
 
-        r = sd_dhcp6_lease_get_timestamp(link->dhcp6_lease, CLOCK_BOOTTIME, &timestamp_usec);
-        if (r < 0)
-                return log_link_warning_errno(link, r, "Failed to get timestamp of DHCPv6 lease: %m");
-
-        for (sd_dhcp6_lease_reset_address_iter(link->dhcp6_lease);;) {
-                uint32_t lifetime_preferred_sec, lifetime_valid_sec;
+        FOREACH_DHCP6_ADDRESS(link->dhcp6_lease) {
+                usec_t lifetime_preferred_usec, lifetime_valid_usec;
                 struct in6_addr ip6_addr;
 
-                r = sd_dhcp6_lease_get_address(link->dhcp6_lease, &ip6_addr, &lifetime_preferred_sec, &lifetime_valid_sec);
+                r = sd_dhcp6_lease_get_address(link->dhcp6_lease, &ip6_addr);
                 if (r < 0)
-                        break;
+                        return r;
+
+                r = sd_dhcp6_lease_get_address_lifetime_timestamp(link->dhcp6_lease, CLOCK_BOOTTIME,
+                                                                  &lifetime_preferred_usec, &lifetime_valid_usec);
+                if (r < 0)
+                        return r;
 
                 r = dhcp6_request_address(link, &server_address, &ip6_addr,
-                                          sec_to_usec(lifetime_preferred_sec, timestamp_usec),
-                                          sec_to_usec(lifetime_valid_sec, timestamp_usec));
+                                          lifetime_preferred_usec,
+                                          lifetime_valid_usec);
                 if (r < 0)
                         return r;
         }
index e4db7ef75d7fa3078cea2bea343ed625d46af6ae..0b2f6e68b81cf37127cc67b24dbd30cadd8df092 100644 (file)
@@ -9,7 +9,6 @@
 #include "netif-util.h"
 #include "networkd-address.h"
 #include "networkd-dhcp-common.h"
-#include "networkd-dhcp-prefix-delegation.h"
 #include "networkd-json.h"
 #include "networkd-link.h"
 #include "networkd-manager.h"
@@ -1046,7 +1045,7 @@ static int dhcp_server_append_json(Link *link, JsonVariant **v) {
 
 static int dhcp6_client_lease_append_json(Link *link, JsonVariant **v) {
         _cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
-        uint64_t lease_timestamp_usec;
+        usec_t lease_timestamp_usec;
         int r;
 
         assert(link);
@@ -1061,9 +1060,9 @@ static int dhcp6_client_lease_append_json(Link *link, JsonVariant **v) {
 
         r = json_build(&w, JSON_BUILD_OBJECT(
                                 JSON_BUILD_PAIR_FINITE_USEC("Timeout1USec",
-                                        link->dhcp6_lease->lifetime_t1 + lease_timestamp_usec),
+                                        usec_add(link->dhcp6_lease->lifetime_t1, lease_timestamp_usec)),
                                 JSON_BUILD_PAIR_FINITE_USEC("Timeout2USec",
-                                        link->dhcp6_lease->lifetime_t2 + lease_timestamp_usec),
+                                        usec_add(link->dhcp6_lease->lifetime_t2, lease_timestamp_usec)),
                                 JSON_BUILD_PAIR_FINITE_USEC("LeaseTimestampUSec",
                                         lease_timestamp_usec)));
         if (r < 0)
@@ -1074,10 +1073,6 @@ static int dhcp6_client_lease_append_json(Link *link, JsonVariant **v) {
 
 static int dhcp6_client_pd_append_json(Link *link, JsonVariant **v) {
         _cleanup_(json_variant_unrefp) JsonVariant *array = NULL;
-        struct in6_addr prefix;
-        uint32_t lifetime_preferred, lifetime_valid;
-        uint8_t prefix_len;
-        uint64_t lease_timestamp_usec;
         int r;
 
         assert(link);
@@ -1088,20 +1083,25 @@ static int dhcp6_client_pd_append_json(Link *link, JsonVariant **v) {
             !sd_dhcp6_lease_has_pd_prefix(link->dhcp6_lease))
                 return 0;
 
-        sd_dhcp6_lease_reset_pd_prefix_iter(link->dhcp6_lease);
+        FOREACH_DHCP6_PD_PREFIX(link->dhcp6_lease) {
+                usec_t lifetime_preferred_usec, lifetime_valid_usec;
+                struct in6_addr prefix;
+                uint8_t prefix_len;
 
-        r = sd_dhcp6_lease_get_timestamp(link->dhcp6_lease, CLOCK_BOOTTIME, &lease_timestamp_usec);
-        if (r < 0)
-                return 0;
+                r = sd_dhcp6_lease_get_pd_prefix(link->dhcp6_lease, &prefix, &prefix_len);
+                if (r < 0)
+                        return r;
+
+                r = sd_dhcp6_lease_get_pd_lifetime_timestamp(link->dhcp6_lease, CLOCK_BOOTTIME,
+                                                             &lifetime_preferred_usec, &lifetime_valid_usec);
+                if (r < 0)
+                        return r;
 
-        while (sd_dhcp6_lease_get_pd(link->dhcp6_lease, &prefix, &prefix_len, &lifetime_preferred, &lifetime_valid) >= 0) {
                 r = json_variant_append_arrayb(&array, JSON_BUILD_OBJECT(
                                                JSON_BUILD_PAIR_IN6_ADDR("Prefix", &prefix),
                                                JSON_BUILD_PAIR_UNSIGNED("PrefixLength", prefix_len),
-                                               JSON_BUILD_PAIR_FINITE_USEC("PreferredLifetimeUSec",
-                                                                           sec_to_usec(lifetime_preferred, lease_timestamp_usec)),
-                                               JSON_BUILD_PAIR_FINITE_USEC("ValidLifetimeUSec",
-                                                                           sec_to_usec(lifetime_valid, lease_timestamp_usec))));
+                                               JSON_BUILD_PAIR_FINITE_USEC("PreferredLifetimeUSec", lifetime_preferred_usec),
+                                               JSON_BUILD_PAIR_FINITE_USEC("ValidLifetimeUSec", lifetime_valid_usec)));
                 if (r < 0)
                         return r;
         }
index dc226ebc997ab17d6fd09d465e246b3aee0ec849..607f85428d48a8b2840bdde16997a0a9d0505548 100644 (file)
@@ -32,17 +32,37 @@ typedef struct sd_dhcp6_lease sd_dhcp6_lease;
 int sd_dhcp6_lease_get_timestamp(sd_dhcp6_lease *lease, clockid_t clock, uint64_t *ret);
 int sd_dhcp6_lease_get_server_address(sd_dhcp6_lease *lease, struct in6_addr *ret);
 
-void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease);
-int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease,
-                               struct in6_addr *addr,
-                               uint32_t *lifetime_preferred,
-                               uint32_t *lifetime_valid);
+int sd_dhcp6_lease_address_iterator_reset(sd_dhcp6_lease *lease);
+int sd_dhcp6_lease_address_iterator_next(sd_dhcp6_lease *lease);
+int sd_dhcp6_lease_get_address(
+                sd_dhcp6_lease *lease,
+                struct in6_addr *ret);
+int sd_dhcp6_lease_get_address_lifetime(
+                sd_dhcp6_lease *lease,
+                uint64_t *ret_lifetime_preferred,
+                uint64_t *ret_lifetime_valid);
+int sd_dhcp6_lease_get_address_lifetime_timestamp(
+                sd_dhcp6_lease *lease,
+                clockid_t clock,
+                uint64_t *ret_lifetime_preferred,
+                uint64_t *ret_lifetime_valid);
 int sd_dhcp6_lease_has_address(sd_dhcp6_lease *lease);
-void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease *lease);
-int sd_dhcp6_lease_get_pd(sd_dhcp6_lease *lease, struct in6_addr *prefix,
-                          uint8_t *prefix_len,
-                          uint32_t *lifetime_preferred,
-                          uint32_t *lifetime_valid);
+
+int sd_dhcp6_lease_pd_iterator_reset(sd_dhcp6_lease *lease);
+int sd_dhcp6_lease_pd_iterator_next(sd_dhcp6_lease *lease);
+int sd_dhcp6_lease_get_pd_prefix(
+                sd_dhcp6_lease *lease,
+                struct in6_addr *ret_prefix,
+                uint8_t *ret_prefix_length);
+int sd_dhcp6_lease_get_pd_lifetime(
+                sd_dhcp6_lease *lease,
+                uint64_t *ret_lifetime_preferred,
+                uint64_t *ret_lifetime_valid);
+int sd_dhcp6_lease_get_pd_lifetime_timestamp(
+                sd_dhcp6_lease *lease,
+                clockid_t clock,
+                uint64_t *ret_lifetime_preferred,
+                uint64_t *ret_lifetime_valid);
 int sd_dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease);
 
 int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, const struct in6_addr **ret);