]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp6-client: introduce sd_dhcp6_lease_get_timestamp()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Oct 2021 19:19:59 +0000 (04:19 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 19 Oct 2021 17:36:20 +0000 (02:36 +0900)
src/libsystemd-network/dhcp6-lease-internal.h
src/libsystemd-network/dhcp6-network.c
src/libsystemd-network/sd-dhcp6-client.c
src/libsystemd-network/sd-dhcp6-lease.c
src/systemd/sd-dhcp6-lease.h

index 8801497b722a20f124a9df7e03fa27c5458e0531..66af241df5339754bb4d0620f8fe786b901c8439 100644 (file)
@@ -18,6 +18,7 @@ struct sd_dhcp6_lease {
         size_t serverid_len;
         uint8_t preference;
         bool rapid_commit;
+        triple_timestamp timestamp;
 
         DHCP6IA ia;
         DHCP6IA pd;
index 4f7bd53de4ed86ebe59fba1f850caaf2b216b9da..eedd92d3c2422e578876abdde2c5040b9a4c78ad 100644 (file)
@@ -47,6 +47,10 @@ int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *local_address) {
         if (r < 0)
                 return r;
 
+        r = setsockopt_int(s, SOL_SOCKET, SO_TIMESTAMP, true);
+        if (r < 0)
+                return r;
+
         r = bind(s, &src.sa, sizeof(src.in6));
         if (r < 0)
                 return -errno;
index aacdf0698079d6c1e4ac7aa565abb63a2137f11e..9a6be6478970bae0a1684bb74131ecf7af0970ef 100644 (file)
@@ -21,6 +21,7 @@
 #include "hexdecoct.h"
 #include "hostname-util.h"
 #include "in-addr-util.h"
+#include "io-util.h"
 #include "network-common.h"
 #include "random-util.h"
 #include "socket-util.h"
@@ -1341,13 +1342,14 @@ static int client_parse_message(
         return 0;
 }
 
-static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) {
+static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len, const triple_timestamp *t) {
         _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
         bool rapid_commit;
         int r;
 
         assert(client);
         assert(reply);
+        assert(t);
 
         if (reply->type != DHCP6_MESSAGE_REPLY)
                 return 0;
@@ -1356,6 +1358,8 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, si
         if (r < 0)
                 return -ENOMEM;
 
+        lease->timestamp = *t;
+
         r = client_parse_message(client, reply, len, lease);
         if (r < 0)
                 return r;
@@ -1375,11 +1379,15 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, si
         return DHCP6_STATE_BOUND;
 }
 
-static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) {
+static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len, const triple_timestamp *t) {
         _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
         uint8_t pref_advertise = 0, pref_lease = 0;
         int r;
 
+        assert(client);
+        assert(advertise);
+        assert(t);
+
         if (advertise->type != DHCP6_MESSAGE_ADVERTISE)
                 return 0;
 
@@ -1387,6 +1395,8 @@ static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *adver
         if (r < 0)
                 return r;
 
+        lease->timestamp = *t;
+
         r = client_parse_message(client, advertise, len, lease);
         if (r < 0)
                 return r;
@@ -1417,6 +1427,17 @@ static int client_receive_message(
 
         sd_dhcp6_client *client = userdata;
         DHCP6_CLIENT_DONT_DESTROY(client);
+        /* This needs to be initialized with zero. See #20741. */
+        CMSG_BUFFER_TYPE(CMSG_SPACE_TIMEVAL) control = {};
+        struct iovec iov;
+        struct msghdr msg = {
+                .msg_iov = &iov,
+                .msg_iovlen = 1,
+                .msg_control = &control,
+                .msg_controllen = sizeof(control),
+        };
+        struct cmsghdr *cmsg;
+        triple_timestamp t = {};
         _cleanup_free_ DHCP6Message *message = NULL;
         ssize_t buflen, len;
         int r = 0;
@@ -1427,9 +1448,8 @@ static int client_receive_message(
 
         buflen = next_datagram_size_fd(fd);
         if (buflen == -ENETDOWN)
-                /* the link is down. Don't return an error or the I/O event
-                   source will be disconnected and we won't be able to receive
-                   packets again when the link comes back. */
+                /* the link is down. Don't return an error or the I/O event source will be disconnected
+                 * and we won't be able to receive packets again when the link comes back. */
                 return 0;
         if (buflen < 0)
                 return buflen;
@@ -1438,7 +1458,9 @@ static int client_receive_message(
         if (!message)
                 return -ENOMEM;
 
-        len = recv(fd, message, buflen, 0);
+        iov = IOVEC_MAKE(message, buflen);
+
+        len = recvmsg_safe(fd, &msg, MSG_DONTWAIT);
         if (len < 0) {
                 /* see comment above for why we shouldn't error out on ENETDOWN. */
                 if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN))
@@ -1452,6 +1474,16 @@ static int client_receive_message(
                 return 0;
         }
 
+        CMSG_FOREACH(cmsg, &msg) {
+                if (cmsg->cmsg_level == SOL_SOCKET &&
+                    cmsg->cmsg_type == SO_TIMESTAMP &&
+                    cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
+                        triple_timestamp_from_realtime(&t, timeval_load((struct timeval*) CMSG_DATA(cmsg)));
+        }
+
+        if (!triple_timestamp_is_set(&t))
+                triple_timestamp_get(&t);
+
         if (!IN_SET(message->type, DHCP6_MESSAGE_ADVERTISE, DHCP6_MESSAGE_REPLY, DHCP6_MESSAGE_RECONFIGURE)) {
                 const char *type_str = dhcp6_message_type_to_string(message->type);
                 if (type_str)
@@ -1466,7 +1498,7 @@ static int client_receive_message(
 
         switch (client->state) {
         case DHCP6_STATE_INFORMATION_REQUEST:
-                r = client_receive_reply(client, message, len);
+                r = client_receive_reply(client, message, len, &t);
                 if (r < 0) {
                         log_dhcp6_client_errno(client, r, "Failed to process received reply message, ignoring: %m");
                         return 0;
@@ -1479,7 +1511,7 @@ static int client_receive_message(
                 break;
 
         case DHCP6_STATE_SOLICITATION:
-                r = client_receive_advertise(client, message, len);
+                r = client_receive_advertise(client, message, len, &t);
                 if (r < 0) {
                         log_dhcp6_client_errno(client, r, "Failed to process received advertise message, ignoring: %m");
                         return 0;
@@ -1495,7 +1527,7 @@ static int client_receive_message(
         case DHCP6_STATE_RENEW:
         case DHCP6_STATE_REBIND:
 
-                r = client_receive_reply(client, message, len);
+                r = client_receive_reply(client, message, len, &t);
                 if (r < 0) {
                         log_dhcp6_client_errno(client, r, "Failed to process received reply message, ignoring: %m");
                         return 0;
index c55b06d2f75e41bab2253a0c430bd427d4f1be29..6c7ffc7999c655ce7cc4e57621f7fe6f8d30c4a6 100644 (file)
 #include "strv.h"
 #include "util.h"
 
+int sd_dhcp6_lease_get_timestamp(sd_dhcp6_lease *lease, clockid_t clock, uint64_t *ret) {
+        assert_return(lease, -EINVAL);
+        assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP);
+        assert_return(clock_supported(clock), -EOPNOTSUPP);
+        assert_return(ret, -EINVAL);
+
+        if (!triple_timestamp_is_set(&lease->timestamp))
+                return -ENODATA;
+
+        *ret = triple_timestamp_by_clock(&lease->timestamp, clock);
+        return 0;
+}
+
 int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) {
         DHCP6Address *addr;
         uint32_t valid = 0, t;
index a10901e5cb98fb8c30870bdc2bea8df351aaf131..04c6383051f473bee0f5c80147e40e0ad0ad8a6d 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <inttypes.h>
 #include <netinet/in.h>
+#include <sys/types.h>
 
 #include "_sd-common.h"
 
@@ -28,6 +29,8 @@ _SD_BEGIN_DECLARATIONS;
 
 typedef struct sd_dhcp6_lease sd_dhcp6_lease;
 
+int sd_dhcp6_lease_get_timestamp(sd_dhcp6_lease *lease, clockid_t clock, uint64_t *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,