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.
This commit is contained in:
Lennart Poettering 2023-09-25 16:00:00 +02:00
parent 2e5edb93b7
commit 02b0d24d1e
2 changed files with 44 additions and 1 deletions

View file

@ -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;
}

View file

@ -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);