diff --git a/man/rules/meson.build b/man/rules/meson.build
index 8c21e90090..486f565815 100644
--- a/man/rules/meson.build
+++ b/man/rules/meson.build
@@ -968,6 +968,10 @@ manpages = [
'sd_uid_get_sessions',
'sd_uid_is_on_seat'],
'HAVE_PAM'],
+ ['sd_varlink_call_and_upgrade',
+ '3',
+ ['sd_varlink_call_and_upgradeb', 'sd_varlink_call_and_upgradebo'],
+ ''],
['sd_varlink_connect_address',
'3',
['sd_varlink_connect_exec',
diff --git a/man/sd_varlink_call_and_upgrade.xml b/man/sd_varlink_call_and_upgrade.xml
new file mode 100644
index 0000000000..48eb9de93f
--- /dev/null
+++ b/man/sd_varlink_call_and_upgrade.xml
@@ -0,0 +1,177 @@
+
+
+
+
+
+
+
+ sd_varlink_call_and_upgrade
+ systemd
+
+
+
+ sd_varlink_call_and_upgrade
+ 3
+
+
+
+ sd_varlink_call_and_upgrade
+ sd_varlink_call_and_upgradeb
+ sd_varlink_call_and_upgradebo
+
+ Invoke a Varlink method and take over the connection for a raw protocol
+
+
+
+
+ #include <systemd/sd-varlink.h>
+
+
+ int sd_varlink_call_and_upgrade
+ sd_varlink *link
+ const char *method
+ sd_json_variant *parameters
+ sd_json_variant **ret_parameters
+ const char **ret_error_id
+ int *ret_input_fd
+ int *ret_output_fd
+
+
+
+ int sd_varlink_call_and_upgradeb
+ sd_varlink *link
+ const char *method
+ sd_json_variant **ret_parameters
+ const char **ret_error_id
+ int *ret_input_fd
+ int *ret_output_fd
+ …
+
+
+
+ int sd_varlink_call_and_upgradebo
+ sd_varlink *link
+ const char *method
+ sd_json_variant **ret_parameters
+ const char **ret_error_id
+ int *ret_input_fd
+ int *ret_output_fd
+ …
+
+
+
+
+
+ Description
+
+ These functions implement the client side of a Varlink protocol upgrade. They
+ are the counterpart of the server-side
+ sd_varlink_reply_and_upgrade3
+ family. If a method call is issued this way, the connection may switch, after the reply, from the Varlink
+ protocol to an arbitrary, non-Varlink ("raw") protocol spoken over the underlying socket or pipe file
+ descriptors, in a manner similar to the Upgrade: mechanism of HTTP.
+
+ sd_varlink_call_and_upgrade() synchronously invokes the method
+ method on the connection link, requesting a protocol upgrade,
+ and waits for the reply. It takes the Varlink connection object, the method name, a JSON object with the
+ method call parameters (which may be NULL), two output pointers for the reply
+ parameters and a possible error identifier, and two output pointers for the file descriptors. The reply
+ parameters returned in ret_parameters and the error identifier returned in
+ ret_error_id are borrowed references that remain valid only until the connection is
+ closed or unreffed. Either of the two may be passed as NULL if the information is not
+ needed.
+
+ If the server replies with a regular reply (rather than a Varlink error) the connection is upgraded:
+ it is disconnected from the Varlink protocol, and ownership of the underlying file descriptors is
+ transferred to the caller via ret_input_fd and ret_output_fd,
+ which is responsible for eventually closing them with
+ close2.
+ If the server replies with a Varlink error instead, the connection is not upgraded and
+ no file descriptors are returned; the error identifier is reported in ret_error_id
+ (if non-NULL), otherwise a negative errno-style error derived from it is returned.
+
+ The returned file descriptors are switched to blocking mode. For bidirectional sockets a single
+ underlying file descriptor carries both directions; in this case ret_input_fd and
+ ret_output_fd are returned as two independent (duplicated) descriptors referring to
+ the same socket, so they may be closed separately. For transports backed by a pair of pipes the two
+ descriptors differ and refer to the distinct read and write ends. At least one of
+ ret_input_fd or ret_output_fd must be
+ non-NULL.
+
+ sd_varlink_call_and_upgradeb() is similar to
+ sd_varlink_call_and_upgrade(), but instead of expecting a fully constructed
+ sd_json_variant object carrying the method call parameters, this object is constructed
+ on-the-fly from the variadic argument list, in a style identical to
+ sd_json_build3.
+ sd_varlink_call_and_upgradebo() is identical to
+ sd_varlink_call_and_upgradeb(), but an enclosing JSON object is added implicitly, so
+ that the argument list is expected to consist of object field pairs only, in a style identical to
+ sd_json_buildo3. This
+ relationship mirrors that of
+ sd_varlink_call3 and its
+ sd_varlink_callb()/sd_varlink_callbo() variants.
+
+
+
+ Return Value
+
+ On success, these functions return a positive integer if the connection was upgraded, or zero if the
+ server returned a Varlink error and ret_error_id was set to it. On failure, they
+ return a negative errno-style error code.
+
+
+ Errors
+
+ Returned errors may indicate the following problems:
+
+
+
+ -EINVAL
+
+ An argument is invalid.
+
+
+
+ -ENOTCONN
+
+ The Varlink connection object is not connected.
+
+
+
+ -EPROTO
+
+ A protocol error occurred, for example the server sent unexpected raw protocol data
+ before the upgrade completed.
+
+
+
+ -ENOMEM
+
+ Memory allocation failed.
+
+
+
+
+
+
+
+
+ History
+ sd_varlink_call_and_upgrade() was added in version 261.
+ sd_varlink_call_and_upgradeb() and
+ sd_varlink_call_and_upgradebo() were added in version 262.
+
+
+
+ See Also
+
+
+ systemd1
+ sd-varlink3
+ sd_varlink_call3
+ sd_varlink_reply_and_upgrade3
+ sd_json_build3
+
+
+
diff --git a/man/sd_varlink_reply_and_upgrade.xml b/man/sd_varlink_reply_and_upgrade.xml
index f51dee3779..b2a8f6752f 100644
--- a/man/sd_varlink_reply_and_upgrade.xml
+++ b/man/sd_varlink_reply_and_upgrade.xml
@@ -219,6 +219,7 @@
sd-varlink3
sd_varlink_reply3
sd_varlink_call3
+ sd_varlink_call_and_upgrade3
sd_varlink_process3
sd_varlink_set_userdata3
sd_json_build3
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 317c51b4c3..83fb8c92b3 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -1108,6 +1108,7 @@ global:
LIBSYSTEMD_262 {
global:
sd_varlink_bind_upgrade;
+ sd_varlink_call_and_upgradeb;
sd_varlink_respond_and_upgrade;
sd_varlink_respond_and_upgradeb;
} LIBSYSTEMD_261;
diff --git a/src/libsystemd/sd-varlink/sd-varlink.c b/src/libsystemd/sd-varlink/sd-varlink.c
index 198883d754..a86e523a47 100644
--- a/src/libsystemd/sd-varlink/sd-varlink.c
+++ b/src/libsystemd/sd-varlink/sd-varlink.c
@@ -2183,6 +2183,31 @@ finish:
return r;
}
+_public_ int sd_varlink_call_and_upgradeb(
+ sd_varlink *v,
+ const char *method,
+ sd_json_variant **ret_parameters,
+ const char **ret_error_id,
+ int *ret_input_fd,
+ int *ret_output_fd,
+ ...) {
+
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *parameters = NULL;
+ va_list ap;
+ int r;
+
+ assert_return(v, -EINVAL);
+ assert_return(method, -EINVAL);
+
+ va_start(ap, ret_output_fd);
+ r = sd_json_buildv(¶meters, ap);
+ va_end(ap);
+ if (r < 0)
+ return varlink_log_errno(v, r, "Failed to build json message: %m");
+
+ return sd_varlink_call_and_upgrade(v, method, parameters, ret_parameters, ret_error_id, ret_input_fd, ret_output_fd);
+}
+
_public_ int sd_varlink_callb_ap(
sd_varlink *v,
const char *method,
diff --git a/src/systemd/sd-varlink.h b/src/systemd/sd-varlink.h
index 7480594d74..3dbb443fa3 100644
--- a/src/systemd/sd-varlink.h
+++ b/src/systemd/sd-varlink.h
@@ -145,6 +145,9 @@ int sd_varlink_callb(sd_varlink *v, const char *method, sd_json_variant **ret_pa
* Returns > 0 if the connection was upgraded, 0 if a Varlink error occurred (and ret_error_id was set),
* or < 0 on local failure. */
int sd_varlink_call_and_upgrade(sd_varlink *v, const char *method, sd_json_variant *parameters, sd_json_variant **ret_parameters, const char **ret_error_id, int *ret_input_fd, int *ret_output_fd);
+int sd_varlink_call_and_upgradeb(sd_varlink *v, const char *method, sd_json_variant **ret_parameters, const char **ret_error_id, int *ret_input_fd, int *ret_output_fd, ...);
+#define sd_varlink_call_and_upgradebo(v, method, ret_parameters, ret_error_id, ret_input_fd, ret_output_fd, ...) \
+ sd_varlink_call_and_upgradeb((v), (method), (ret_parameters), (ret_error_id), (ret_input_fd), (ret_output_fd), SD_JSON_BUILD_OBJECT(__VA_ARGS__))
/* Send method call and begin collecting all 'more' replies into an array, finishing when a final reply is sent */
int sd_varlink_collect_full(sd_varlink *v, const char *method, sd_json_variant *parameters, sd_json_variant **ret_parameters, const char **ret_error_id, sd_varlink_reply_flags_t *ret_flags);