From: Ivan Kruglov Date: Tue, 24 Sep 2024 12:56:16 +0000 (+0200) Subject: machine: generalise logic GetMachineAddresses to later use it in varlink interface X-Git-Tag: v257-rc1~341^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f1daf9fb74b6041f3ab31e130441682669c404ef;p=thirdparty%2Fsystemd.git machine: generalise logic GetMachineAddresses to later use it in varlink interface --- diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index 783463896f6..a8c376dee97 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -19,7 +19,6 @@ #include "format-util.h" #include "fs-util.h" #include "in-addr-util.h" -#include "iovec-util.h" #include "local-addresses.h" #include "machine-dbus.h" #include "machine.h" @@ -169,6 +168,7 @@ int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_erro int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ struct local_address *addresses = NULL; Machine *m = ASSERT_PTR(userdata); int r; @@ -182,154 +182,30 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd if (r < 0) return r; - switch (m->class) { - - case MACHINE_HOST: { - _cleanup_free_ struct local_address *addresses = NULL; - int n; - - n = local_addresses(NULL, 0, AF_UNSPEC, &addresses); - if (n < 0) - return n; - - for (int i = 0; i < n; i++) { - r = sd_bus_message_open_container(reply, 'r', "iay"); - if (r < 0) - return r; - - r = sd_bus_message_append(reply, "i", addresses[i].family); - if (r < 0) - return r; - - r = sd_bus_message_append_array(reply, 'y', &addresses[i].address, FAMILY_ADDRESS_SIZE(addresses[i].family)); - if (r < 0) - return r; - - r = sd_bus_message_close_container(reply); - if (r < 0) - return r; - } - - break; - } - - case MACHINE_CONTAINER: { - _cleanup_close_pair_ int pair[2] = EBADF_PAIR; - _cleanup_close_ int netns_fd = -EBADF; - pid_t child; + int n = machine_get_addresses(m, &addresses); + if (n == -ENONET) + return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name); + if (ERRNO_IS_NEG_NOT_SUPPORTED(n)) + return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting IP address data is only supported on container machines."); + if (n < 0) + return sd_bus_error_set_errnof(error, n, "Failed to get addresses: %m"); - r = in_same_namespace(0, m->leader.pid, NAMESPACE_NET); + for (int i = 0; i < n; i++) { + r = sd_bus_message_open_container(reply, 'r', "iay"); if (r < 0) return r; - if (r > 0) - return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name); - r = pidref_namespace_open(&m->leader, - /* ret_pidns_fd = */ NULL, - /* ret_mntns_fd = */ NULL, - &netns_fd, - /* ret_userns_fd = */ NULL, - /* ret_root_fd = */ NULL); + r = sd_bus_message_append(reply, "i", addresses[i].family); if (r < 0) return r; - if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0) - return -errno; - - r = namespace_fork("(sd-addrns)", "(sd-addr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, - -1, -1, netns_fd, -1, -1, &child); + r = sd_bus_message_append_array(reply, 'y', &addresses[i].address, FAMILY_ADDRESS_SIZE(addresses[i].family)); if (r < 0) - return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); - if (r == 0) { - _cleanup_free_ struct local_address *addresses = NULL; - struct local_address *a; - int i, n; - - pair[0] = safe_close(pair[0]); - - n = local_addresses(NULL, 0, AF_UNSPEC, &addresses); - if (n < 0) - _exit(EXIT_FAILURE); - - for (a = addresses, i = 0; i < n; a++, i++) { - struct iovec iov[2] = { - { .iov_base = &a->family, .iov_len = sizeof(a->family) }, - { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) }, - }; - - r = writev(pair[1], iov, 2); - if (r < 0) - _exit(EXIT_FAILURE); - } - - pair[1] = safe_close(pair[1]); - - _exit(EXIT_SUCCESS); - } - - pair[1] = safe_close(pair[1]); - - for (;;) { - int family; - ssize_t n; - union in_addr_union in_addr; - struct iovec iov[2]; - struct msghdr mh = { - .msg_iov = iov, - .msg_iovlen = 2, - }; - - iov[0] = IOVEC_MAKE(&family, sizeof(family)); - iov[1] = IOVEC_MAKE(&in_addr, sizeof(in_addr)); - - n = recvmsg_safe(pair[0], &mh, 0); - if (n < 0) - return n; - if ((size_t) n < sizeof(family)) - break; - - r = sd_bus_message_open_container(reply, 'r', "iay"); - if (r < 0) - return r; - - r = sd_bus_message_append(reply, "i", family); - if (r < 0) - return r; - - switch (family) { - - case AF_INET: - if (n != sizeof(struct in_addr) + sizeof(family)) - return -EIO; - - r = sd_bus_message_append_array(reply, 'y', &in_addr.in, sizeof(in_addr.in)); - break; - - case AF_INET6: - if (n != sizeof(struct in6_addr) + sizeof(family)) - return -EIO; - - r = sd_bus_message_append_array(reply, 'y', &in_addr.in6, sizeof(in_addr.in6)); - break; - } - if (r < 0) - return r; - - r = sd_bus_message_close_container(reply); - if (r < 0) - return r; - } + return r; - r = wait_for_terminate_and_check("(sd-addrns)", child, 0); + r = sd_bus_message_close_container(reply); if (r < 0) - return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m"); - if (r != EXIT_SUCCESS) - return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Child died abnormally."); - break; - } - - default: - return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting IP address data is only supported on container machines."); + return r; } r = sd_bus_message_close_container(reply); diff --git a/src/machine/machined-core.c b/src/machine/machined-core.c index 1a840a6a37c..df6e4378350 100644 --- a/src/machine/machined-core.c +++ b/src/machine/machined-core.c @@ -1,8 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "cgroup-util.h" +#include "fd-util.h" +#include "iovec-util.h" #include "machined.h" #include "process-util.h" +#include "socket-util.h" #include "strv.h" #include "user-util.h" @@ -175,3 +178,124 @@ void manager_enqueue_gc(Manager *m) { (void) sd_event_source_set_description(m->deferred_gc_event_source, "deferred-gc"); } + +int machine_get_addresses(Machine* machine, struct local_address **ret_addresses) { + assert(machine); + assert(ret_addresses); + + switch (machine->class) { + + case MACHINE_HOST: { + _cleanup_free_ struct local_address *addresses = NULL; + int n; + + n = local_addresses(/* rtnl = */ NULL, /* ifindex = */ 0, AF_UNSPEC, &addresses); + if (n < 0) + return log_debug_errno(n, "Failed to get local addresses: %m"); + + *ret_addresses = TAKE_PTR(addresses); + return n; + } + + case MACHINE_CONTAINER: { + _cleanup_close_pair_ int pair[2] = EBADF_PAIR; + _cleanup_close_ int netns_fd = -EBADF; + pid_t child; + int r; + + r = in_same_namespace(/* pid1 = */ 0, machine->leader.pid, NAMESPACE_NET); + if (r < 0) + return log_debug_errno(r, "Failed to check if container has private network: %m"); + if (r > 0) + return -ENONET; + + r = pidref_namespace_open(&machine->leader, + /* ret_pidns_fd = */ NULL, + /* ret_mntns_fd = */ NULL, + &netns_fd, + /* ret_userns_fd = */ NULL, + /* ret_root_fd = */ NULL); + if (r < 0) + return log_debug_errno(r, "Failed to open namespace: %m"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0) + return log_debug_errno(errno, "Failed to call socketpair(): %m"); + + r = namespace_fork("(sd-addrns)", + "(sd-addr)", + /* except_fds = */ NULL, + /* n_except_fds = */ 0, + FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, + /* pidns_fd = */ -1, + /* mntns_fd = */ -1, + netns_fd, + /* userns_fd = */ -1, + /* root_fd = */ -1, + &child); + if (r < 0) + return log_debug_errno(r, "Failed to fork(): %m"); + if (r == 0) { + _cleanup_free_ struct local_address *addresses = NULL; + + pair[0] = safe_close(pair[0]); + + int n = local_addresses(/* rtnl = */ NULL, /* ifindex = */ 0, AF_UNSPEC, &addresses); + if (n < 0) { + log_debug_errno(n, "Failed to get local addresses: %m"); + _exit(EXIT_FAILURE); + } + + FOREACH_ARRAY(a, addresses, n) { + r = write(pair[1], a, sizeof(*a)); + if (r < 0) { + log_debug_errno(errno, "Failed to write to socket: %m"); + _exit(EXIT_FAILURE); + } + } + + pair[1] = safe_close(pair[1]); + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + + _cleanup_free_ struct local_address *list = NULL; + size_t n_list = 0; + + for (;;) { + ssize_t n; + struct local_address la; + + n = read(pair[0], &la, sizeof(la)); + if (n < 0) + return log_debug_errno(errno, "Failed to read from socket(): %m"); + if (n == 0) + break; + if ((size_t) n < sizeof(la)) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Received unexpectedly short message"); + + r = add_local_address(&list, + &n_list, + la.ifindex, + la.scope, + la.family, + &la.address); + if (r < 0) + return log_debug_errno(r, "Failed to add local address: %m"); + } + + r = wait_for_terminate_and_check("(sd-addrns)", child, /* flags = */ 0); + if (r < 0) + return log_debug_errno(r, "Failed to wait for child: %m"); + if (r != EXIT_SUCCESS) + return log_debug_errno(SYNTHETIC_ERRNO(ESHUTDOWN), "Child died abnormally"); + + *ret_addresses = TAKE_PTR(list); + return (int) n_list; + } + + default: + return -EOPNOTSUPP; + } +} diff --git a/src/machine/machined.h b/src/machine/machined.h index 4ba54ebe201..f1d0d157c88 100644 --- a/src/machine/machined.h +++ b/src/machine/machined.h @@ -12,6 +12,7 @@ typedef struct Manager Manager; #include "hashmap.h" #include "image-dbus.h" #include "list.h" +#include "local-addresses.h" #include "machine-dbus.h" #include "machine.h" #include "operation.h" @@ -63,3 +64,5 @@ int manager_find_machine_for_gid(Manager *m, gid_t host_gid, Machine **ret_machi void manager_gc(Manager *m, bool drop_not_started); void manager_enqueue_gc(Manager *m); + +int machine_get_addresses(Machine* machine, struct local_address **ret_addresses); diff --git a/src/shared/local-addresses.c b/src/shared/local-addresses.c index 5d5435f54b5..10550fca206 100644 --- a/src/shared/local-addresses.c +++ b/src/shared/local-addresses.c @@ -104,7 +104,7 @@ static int add_local_address_full( return 1; } -static int add_local_address( +int add_local_address( struct local_address **list, size_t *n_list, int ifindex, diff --git a/src/shared/local-addresses.h b/src/shared/local-addresses.h index 399d0c6fb80..42abca78381 100644 --- a/src/shared/local-addresses.h +++ b/src/shared/local-addresses.h @@ -16,6 +16,8 @@ struct local_address { bool has_local_address(const struct local_address *addresses, size_t n_addresses, const struct local_address *needle); +int add_local_address(struct local_address **list, size_t *n_list, int ifindex, unsigned char scope, int family, const union in_addr_union *address); + int local_addresses(sd_netlink *rtnl, int ifindex, int af, struct local_address **ret); int local_gateways(sd_netlink *rtnl, int ifindex, int af, struct local_address **ret);