From: Yu Watanabe Date: Mon, 1 Nov 2021 01:31:31 +0000 (+0900) Subject: sd-dhcp6-client: introduce sd_dhcp6_lease_get_server_address() X-Git-Tag: v250-rc1~373^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ef4edc1546ef1470e0a64a618a095dd2734a0d93;p=thirdparty%2Fsystemd.git sd-dhcp6-client: introduce sd_dhcp6_lease_get_server_address() --- diff --git a/src/libsystemd-network/dhcp6-lease-internal.h b/src/libsystemd-network/dhcp6-lease-internal.h index 66af241df53..673afe18d6f 100644 --- a/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/libsystemd-network/dhcp6-lease-internal.h @@ -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; diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 9a6be647897..010ddd8bd90 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -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; diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index 6c7ffc7999c..7e433c4efae 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -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; diff --git a/src/systemd/sd-dhcp6-lease.h b/src/systemd/sd-dhcp6-lease.h index 04c6383051f..472276def1b 100644 --- a/src/systemd/sd-dhcp6-lease.h +++ b/src/systemd/sd-dhcp6-lease.h @@ -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,