# SPDX-License-Identifier: LGPL-2.1-or-later
#
-# Make sure unix/* and vsock/* can be used to connect to AF_UNIX and AF_VSOCK paths
+# Allow connecting to the local host directly via ".host"
+Host .host machine/.host
+ ProxyCommand {{LIBEXECDIR}}/systemd-ssh-proxy unix/run/ssh-unix-local/socket %p
+ ProxyUseFdpass yes
+ CheckHostIP no
+
+# Make sure unix/* and vsock/* can be used to connect to AF_UNIX and AF_VSOCK paths.
+# Make sure machine/* can be used to connect to local machines registered in machined.
#
-Host unix/* vsock/*
+Host unix/* vsock/* machine/*
ProxyCommand {{LIBEXECDIR}}/systemd-ssh-proxy %h %p
ProxyUseFdpass yes
CheckHostIP no
# Disable all kinds of host identity checks, since these addresses are generally ephemeral.
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
-
-# Allow connecting to the local host directly via ".host"
-Host .host
- ProxyCommand {{LIBEXECDIR}}/systemd-ssh-proxy unix/run/ssh-unix-local/socket %p
- ProxyUseFdpass yes
- CheckHostIP no
#include "socket-util.h"
#include "string-util.h"
#include "strv.h"
+#include "varlink.h"
-static int process_vsock(const char *host, const char *port) {
+static int process_vsock_cid(unsigned cid, const char *port) {
int r;
- assert(host);
+ assert(cid != VMADDR_CID_ANY);
assert(port);
union sockaddr_union sa = {
+ .vm.svm_cid = cid,
.vm.svm_family = AF_VSOCK,
};
- r = vsock_parse_cid(host, &sa.vm.svm_cid);
- if (r < 0)
- return log_error_errno(r, "Failed to parse vsock cid: %s", host);
-
r = vsock_parse_port(port, &sa.vm.svm_port);
if (r < 0)
return log_error_errno(r, "Failed to parse vsock port: %s", port);
log_debug("Successfully sent AF_VSOCK socket via STDOUT.");
return 0;
+
+}
+
+static int process_vsock_string(const char *host, const char *port) {
+ unsigned cid;
+ int r;
+
+ assert(host);
+ assert(port);
+
+ r = vsock_parse_cid(host, &cid);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse vsock cid: %s", host);
+
+ return process_vsock_cid(cid, port);
}
static int process_unix(const char *path) {
return 0;
}
+static int process_machine(const char *machine, const char *port) {
+ _cleanup_(varlink_unrefp) Varlink *vl = NULL;
+ int r;
+
+ assert(machine);
+ assert(port);
+
+ r = varlink_connect_address(&vl, "/run/systemd/machine/io.systemd.Machine");
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect to machined on /run/systemd/machine/io.systemd.Machine: %m");
+
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *result = NULL;
+ r = varlink_callbo_and_log(
+ vl,
+ "io.systemd.Machine.List",
+ &result,
+ SD_JSON_BUILD_PAIR("name", SD_JSON_BUILD_STRING(machine)));
+ if (r < 0)
+ return r;
+
+ uint32_t cid = VMADDR_CID_ANY;
+
+ const sd_json_dispatch_field dispatch_table[] = {
+ { "vSockCid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint32, PTR_TO_SIZE(&cid), 0 },
+ {}
+ };
+
+ r = sd_json_dispatch(result, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse Varlink reply: %m");
+
+ if (cid == VMADDR_CID_ANY)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Machine has no AF_VSOCK CID assigned.");
+
+ return process_vsock_cid(cid, port);
+}
+
static int run(int argc, char* argv[]) {
log_setup();
const char *p = startswith(host, "vsock/");
if (p)
- return process_vsock(p, port);
+ return process_vsock_string(p, port);
p = startswith(host, "unix/");
if (p)
if (p)
return process_vsock_mux(p, port);
+ p = startswith(host, "machine/");
+ if (p)
+ return process_machine(p, port);
+
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Don't know how to parse host name specification: %s", host);
}