]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp6-client: introduce sd_dhcp6_lease_get_server_address()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 1 Nov 2021 01:31:31 +0000 (10:31 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 1 Nov 2021 09:22:49 +0000 (18:22 +0900)
src/libsystemd-network/dhcp6-lease-internal.h
src/libsystemd-network/sd-dhcp6-client.c
src/libsystemd-network/sd-dhcp6-lease.c
src/systemd/sd-dhcp6-lease.h

index 66af241df5339754bb4d0620f8fe786b901c8439..673afe18d6fab5a8a5cbef81060b002001c64432 100644 (file)
@@ -19,6 +19,7 @@ struct sd_dhcp6_lease {
         uint8_t preference;
         bool rapid_commit;
         triple_timestamp timestamp;
+        struct in6_addr server_address;
 
         DHCP6IA ia;
         DHCP6IA pd;
index 9a6be6478970bae0a1684bb74131ecf7af0970ef..010ddd8bd908f160f1ef49c03bd85120e524a6be 100644 (file)
@@ -1342,7 +1342,13 @@ static int client_parse_message(
         return 0;
 }
 
-static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len, const triple_timestamp *t) {
+static int client_receive_reply(
+                sd_dhcp6_client *client,
+                DHCP6Message *reply,
+                size_t len,
+                const triple_timestamp *t,
+                const struct in6_addr *server_address) {
+
         _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
         bool rapid_commit;
         int r;
@@ -1359,6 +1365,8 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, si
                 return -ENOMEM;
 
         lease->timestamp = *t;
+        if (server_address)
+                lease->server_address = *server_address;
 
         r = client_parse_message(client, reply, len, lease);
         if (r < 0)
@@ -1379,7 +1387,13 @@ 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, const triple_timestamp *t) {
+static int client_receive_advertise(
+                sd_dhcp6_client *client,
+                DHCP6Message *advertise,
+                size_t len,
+                const triple_timestamp *t,
+                const struct in6_addr *server_address) {
+
         _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
         uint8_t pref_advertise = 0, pref_lease = 0;
         int r;
@@ -1396,6 +1410,8 @@ static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *adver
                 return r;
 
         lease->timestamp = *t;
+        if (server_address)
+                lease->server_address = *server_address;
 
         r = client_parse_message(client, advertise, len, lease);
         if (r < 0)
@@ -1430,7 +1446,10 @@ static int client_receive_message(
         /* This needs to be initialized with zero. See #20741. */
         CMSG_BUFFER_TYPE(CMSG_SPACE_TIMEVAL) control = {};
         struct iovec iov;
+        union sockaddr_union sa = {};
         struct msghdr msg = {
+                .msg_name = &sa.sa,
+                .msg_namelen = sizeof(sa),
                 .msg_iov = &iov,
                 .msg_iovlen = 1,
                 .msg_control = &control,
@@ -1439,6 +1458,7 @@ static int client_receive_message(
         struct cmsghdr *cmsg;
         triple_timestamp t = {};
         _cleanup_free_ DHCP6Message *message = NULL;
+        struct in6_addr *server_address = NULL;
         ssize_t buflen, len;
         int r = 0;
 
@@ -1474,6 +1494,16 @@ static int client_receive_message(
                 return 0;
         }
 
+        /* msg_namelen == 0 happens when running the test-suite over a socketpair */
+        if (msg.msg_namelen > 0) {
+                if (msg.msg_namelen != sizeof(struct sockaddr_in6) || sa.in6.sin6_family != AF_INET6) {
+                        log_dhcp6_client(client, "Received message from invalid source, ignoring.");
+                        return 0;
+                }
+
+                server_address = &sa.in6.sin6_addr;
+        }
+
         CMSG_FOREACH(cmsg, &msg) {
                 if (cmsg->cmsg_level == SOL_SOCKET &&
                     cmsg->cmsg_type == SO_TIMESTAMP &&
@@ -1498,7 +1528,7 @@ static int client_receive_message(
 
         switch (client->state) {
         case DHCP6_STATE_INFORMATION_REQUEST:
-                r = client_receive_reply(client, message, len, &t);
+                r = client_receive_reply(client, message, len, &t, server_address);
                 if (r < 0) {
                         log_dhcp6_client_errno(client, r, "Failed to process received reply message, ignoring: %m");
                         return 0;
@@ -1511,7 +1541,7 @@ static int client_receive_message(
                 break;
 
         case DHCP6_STATE_SOLICITATION:
-                r = client_receive_advertise(client, message, len, &t);
+                r = client_receive_advertise(client, message, len, &t, server_address);
                 if (r < 0) {
                         log_dhcp6_client_errno(client, r, "Failed to process received advertise message, ignoring: %m");
                         return 0;
@@ -1527,7 +1557,7 @@ static int client_receive_message(
         case DHCP6_STATE_RENEW:
         case DHCP6_STATE_REBIND:
 
-                r = client_receive_reply(client, message, len, &t);
+                r = client_receive_reply(client, message, len, &t, server_address);
                 if (r < 0) {
                         log_dhcp6_client_errno(client, r, "Failed to process received reply message, ignoring: %m");
                         return 0;
index 6c7ffc7999c655ce7cc4e57621f7fe6f8d30c4a6..7e433c4efae56ca9a2584b01c06af14e69dfa48d 100644 (file)
@@ -24,6 +24,14 @@ int sd_dhcp6_lease_get_timestamp(sd_dhcp6_lease *lease, clockid_t clock, uint64_
         return 0;
 }
 
+int sd_dhcp6_lease_get_server_address(sd_dhcp6_lease *lease, struct in6_addr *ret) {
+        assert_return(lease, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        *ret = lease->server_address;
+        return 0;
+}
+
 int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) {
         DHCP6Address *addr;
         uint32_t valid = 0, t;
index 04c6383051f473bee0f5c80147e40e0ad0ad8a6d..472276def1ba4906afcabaaf0ba6a1f7bdd25221 100644 (file)
@@ -30,6 +30,7 @@ _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);
+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,