From: Lennart Poettering Date: Mon, 25 Sep 2023 14:00:00 +0000 (+0200) Subject: varlink: add varlink_invocation() call X-Git-Tag: v255-rc1~305^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=02b0d24d1e30331004ee15a4aaccc20ac1d87553;p=thirdparty%2Fsystemd.git varlink: add varlink_invocation() call This call checks if we are invoked in a socket-activation Varlink server context. It's useful for commands that can be run from the command line or as Varlink service and then either serve commands from the cmdline or those from Varlink. --- diff --git a/src/shared/varlink.c b/src/shared/varlink.c index e97127838a2..f061024785c 100644 --- a/src/shared/varlink.c +++ b/src/shared/varlink.c @@ -3540,3 +3540,38 @@ int varlink_server_deserialize_one(VarlinkServer *s, const char *value, FDSet *f LIST_PREPEND(sockets, s->sockets, TAKE_PTR(ss)); return 0; } + +int varlink_invocation(VarlinkInvocationFlags flags) { + _cleanup_strv_free_ char **names = NULL; + int r, b; + socklen_t l = sizeof(b); + + /* Returns true if this is a "pure" varlink server invocation, i.e. with one fd passed. */ + + r = sd_listen_fds_with_names(/* unset_environment= */ false, &names); + if (r < 0) + return r; + if (r == 0) + return false; + if (r > 1) + return -ETOOMANYREFS; + + if (!strv_equal(names, STRV_MAKE("varlink"))) + return false; + + if (FLAGS_SET(flags, VARLINK_ALLOW_LISTEN|VARLINK_ALLOW_ACCEPT)) /* Both flags set? Then allow everything */ + return true; + + if ((flags & (VARLINK_ALLOW_LISTEN|VARLINK_ALLOW_ACCEPT)) == 0) /* Neither is set, then fail */ + return -EISCONN; + + if (getsockopt(SD_LISTEN_FDS_START, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0) + return -errno; + + assert(l == sizeof(b)); + + if (!FLAGS_SET(flags, b ? VARLINK_ALLOW_LISTEN : VARLINK_ALLOW_ACCEPT)) + return -EISCONN; + + return true; +} diff --git a/src/shared/varlink.h b/src/shared/varlink.h index cfb7f7ed8be..5fe529c8532 100644 --- a/src/shared/varlink.h +++ b/src/shared/varlink.h @@ -46,7 +46,6 @@ typedef enum VarlinkServerFlags { VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */ VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */ VARLINK_SERVER_INHERIT_USERDATA = 1 << 3, /* Initialize Varlink connection userdata from VarlinkServer userdata */ - _VARLINK_SERVER_FLAGS_ALL = (1 << 4) - 1, } VarlinkServerFlags; @@ -185,6 +184,15 @@ unsigned varlink_server_current_connections(VarlinkServer *s); int varlink_server_set_description(VarlinkServer *s, const char *description); +typedef enum VarlinkInvocationFlags { + VARLINK_ALLOW_LISTEN = 1 << 0, + VARLINK_ALLOW_ACCEPT = 1 << 1, + _VARLINK_SERVER_INVOCATION_FLAGS_MAX = (1 << 2) - 1, + _VARLINK_SERVER_INVOCATION_FLAGS_INVALID = -EINVAL, +} VarlinkInvocationFlags; + +int varlink_invocation(VarlinkInvocationFlags flags); + DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_close_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_flush_close_unref);