1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 /* A minimal Varlink implementation. We only implement the minimal, obvious bits here though. No validation,
10 * no introspection, no name service, just the stuff actually needed.
12 * You might wonder why we aren't using libvarlink here? Varlink is a very simple protocol, which allows us
13 * to write our own implementation relatively easily. However, the main reasons are these:
15 * • We want to use our own JSON subsystem, with all the benefits that brings (i.e. accurate unsigned+signed
16 * 64bit integers, full fuzzing, logging during parsing and so on). If we'd want to use that with
17 * libvarlink we'd have to serialize and deserialize all the time from its own representation which is
18 * inefficient and nasty.
20 * • We want integration into sd-event, but also synchronous event-loop-less operation
22 * • We need proper per-UID accounting and access control, since we want to allow communication between
23 * unprivileged clients and privileged servers.
25 * • And of course, we don't want the name service and introspection stuff for now (though that might
29 typedef struct Varlink Varlink
;
30 typedef struct VarlinkServer VarlinkServer
;
32 typedef enum VarlinkReplyFlags
{
33 VARLINK_REPLY_ERROR
= 1 << 0,
34 VARLINK_REPLY_CONTINUES
= 1 << 1,
35 VARLINK_REPLY_LOCAL
= 1 << 2,
38 typedef enum VarlinkMethodFlags
{
39 VARLINK_METHOD_ONEWAY
= 1 << 0,
40 VARLINK_METHOD_MORE
= 2 << 1,
43 typedef enum VarlinkServerFlags
{
44 VARLINK_SERVER_ROOT_ONLY
= 1 << 0, /* Only accessible by root */
45 VARLINK_SERVER_MYSELF_ONLY
= 1 << 1, /* Only accessible by our own UID */
46 VARLINK_SERVER_ACCOUNT_UID
= 1 << 2, /* Do per user accounting */
47 VARLINK_SERVER_INHERIT_USERDATA
= 1 << 3, /* Initialize Varlink connection userdata from VarlinkServer userdata */
49 _VARLINK_SERVER_FLAGS_ALL
= (1 << 4) - 1,
52 typedef int (*VarlinkMethod
)(Varlink
*link
, JsonVariant
*parameters
, VarlinkMethodFlags flags
, void *userdata
);
53 typedef int (*VarlinkReply
)(Varlink
*link
, JsonVariant
*parameters
, const char *error_id
, VarlinkReplyFlags flags
, void *userdata
);
54 typedef int (*VarlinkConnect
)(VarlinkServer
*server
, Varlink
*link
, void *userdata
);
55 typedef void (*VarlinkDisconnect
)(VarlinkServer
*server
, Varlink
*link
, void *userdata
);
57 int varlink_connect_address(Varlink
**ret
, const char *address
);
58 int varlink_connect_fd(Varlink
**ret
, int fd
);
60 Varlink
* varlink_ref(Varlink
*link
);
61 Varlink
* varlink_unref(Varlink
*v
);
63 int varlink_get_fd(Varlink
*v
);
64 int varlink_get_events(Varlink
*v
);
65 int varlink_get_timeout(Varlink
*v
, usec_t
*ret
);
67 int varlink_attach_event(Varlink
*v
, sd_event
*e
, int64_t priority
);
68 void varlink_detach_event(Varlink
*v
);
69 sd_event
*varlink_get_event(Varlink
*v
);
71 int varlink_process(Varlink
*v
);
72 int varlink_wait(Varlink
*v
, usec_t timeout
);
74 int varlink_flush(Varlink
*v
);
75 int varlink_close(Varlink
*v
);
77 Varlink
* varlink_flush_close_unref(Varlink
*v
);
78 Varlink
* varlink_close_unref(Varlink
*v
);
80 /* Enqueue method call, not expecting a reply */
81 int varlink_send(Varlink
*v
, const char *method
, JsonVariant
*parameters
);
82 int varlink_sendb(Varlink
*v
, const char *method
, ...);
84 /* Send method call and wait for reply */
85 int varlink_call(Varlink
*v
, const char *method
, JsonVariant
*parameters
, JsonVariant
**ret_parameters
, const char **ret_error_id
, VarlinkReplyFlags
*ret_flags
);
86 int varlink_callb(Varlink
*v
, const char *method
, JsonVariant
**ret_parameters
, const char **ret_error_id
, VarlinkReplyFlags
*ret_flags
, ...);
88 /* Enqueue method call, expect a reply, which is eventually delivered to the reply callback */
89 int varlink_invoke(Varlink
*v
, const char *method
, JsonVariant
*parameters
);
90 int varlink_invokeb(Varlink
*v
, const char *method
, ...);
92 /* Enqueue method call, expect a reply now, and possibly more later, which are all delivered to the reply callback */
93 int varlink_observe(Varlink
*v
, const char *method
, JsonVariant
*parameters
);
94 int varlink_observeb(Varlink
*v
, const char *method
, ...);
96 /* Enqueue a final reply */
97 int varlink_reply(Varlink
*v
, JsonVariant
*parameters
);
98 int varlink_replyb(Varlink
*v
, ...);
100 /* Enqueue a (final) error */
101 int varlink_error(Varlink
*v
, const char *error_id
, JsonVariant
*parameters
);
102 int varlink_errorb(Varlink
*v
, const char *error_id
, ...);
103 int varlink_error_invalid_parameter(Varlink
*v
, JsonVariant
*parameters
);
104 int varlink_error_errno(Varlink
*v
, int error
);
106 /* Enqueue a "more" reply */
107 int varlink_notify(Varlink
*v
, JsonVariant
*parameters
);
108 int varlink_notifyb(Varlink
*v
, ...);
110 /* Write outgoing fds into the socket (to be associated with the next enqueued message) */
111 int varlink_push_fd(Varlink
*v
, int fd
);
112 int varlink_dup_fd(Varlink
*v
, int fd
);
113 int varlink_reset_fds(Varlink
*v
);
115 /* Read incoming fds from the socket (associated with the currently handled message) */
116 int varlink_peek_fd(Varlink
*v
, size_t i
);
117 int varlink_take_fd(Varlink
*v
, size_t i
);
119 int varlink_set_allow_fd_passing_input(Varlink
*v
, bool b
);
120 int varlink_set_allow_fd_passing_output(Varlink
*v
, bool b
);
122 /* Bind a disconnect, reply or timeout callback */
123 int varlink_bind_reply(Varlink
*v
, VarlinkReply reply
);
125 void* varlink_set_userdata(Varlink
*v
, void *userdata
);
126 void* varlink_get_userdata(Varlink
*v
);
128 int varlink_get_peer_uid(Varlink
*v
, uid_t
*ret
);
129 int varlink_get_peer_pid(Varlink
*v
, pid_t
*ret
);
131 int varlink_set_relative_timeout(Varlink
*v
, usec_t usec
);
133 VarlinkServer
* varlink_get_server(Varlink
*v
);
135 int varlink_set_description(Varlink
*v
, const char *d
);
137 /* Create a varlink server */
138 int varlink_server_new(VarlinkServer
**ret
, VarlinkServerFlags flags
);
139 VarlinkServer
*varlink_server_ref(VarlinkServer
*s
);
140 VarlinkServer
*varlink_server_unref(VarlinkServer
*s
);
142 /* Add addresses or fds to listen on */
143 int varlink_server_listen_address(VarlinkServer
*s
, const char *address
, mode_t mode
);
144 int varlink_server_listen_fd(VarlinkServer
*s
, int fd
);
145 int varlink_server_add_connection(VarlinkServer
*s
, int fd
, Varlink
**ret
);
148 int varlink_server_bind_method(VarlinkServer
*s
, const char *method
, VarlinkMethod callback
);
149 int varlink_server_bind_method_many_internal(VarlinkServer
*s
, ...);
150 #define varlink_server_bind_method_many(s, ...) varlink_server_bind_method_many_internal(s, __VA_ARGS__, NULL)
151 int varlink_server_bind_connect(VarlinkServer
*s
, VarlinkConnect connect
);
152 int varlink_server_bind_disconnect(VarlinkServer
*s
, VarlinkDisconnect disconnect
);
154 void* varlink_server_set_userdata(VarlinkServer
*s
, void *userdata
);
155 void* varlink_server_get_userdata(VarlinkServer
*s
);
157 int varlink_server_attach_event(VarlinkServer
*v
, sd_event
*e
, int64_t priority
);
158 int varlink_server_detach_event(VarlinkServer
*v
);
159 sd_event
*varlink_server_get_event(VarlinkServer
*v
);
161 int varlink_server_shutdown(VarlinkServer
*server
);
163 unsigned varlink_server_connections_max(VarlinkServer
*s
);
164 unsigned varlink_server_connections_per_uid_max(VarlinkServer
*s
);
166 int varlink_server_set_connections_per_uid_max(VarlinkServer
*s
, unsigned m
);
167 int varlink_server_set_connections_max(VarlinkServer
*s
, unsigned m
);
169 unsigned varlink_server_current_connections(VarlinkServer
*s
);
171 int varlink_server_set_description(VarlinkServer
*s
, const char *description
);
173 DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink
*, varlink_unref
);
174 DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink
*, varlink_close_unref
);
175 DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink
*, varlink_flush_close_unref
);
176 DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServer
*, varlink_server_unref
);
178 /* These are local errors that never cross the wire, and are our own invention */
179 #define VARLINK_ERROR_DISCONNECTED "io.systemd.Disconnected"
180 #define VARLINK_ERROR_TIMEOUT "io.systemd.TimedOut"
181 #define VARLINK_ERROR_PROTOCOL "io.systemd.Protocol"
182 #define VARLINK_ERROR_SYSTEM "io.systemd.System"
184 /* These are errors defined in the Varlink spec */
185 #define VARLINK_ERROR_INTERFACE_NOT_FOUND "org.varlink.service.InterfaceNotFound"
186 #define VARLINK_ERROR_METHOD_NOT_FOUND "org.varlink.service.MethodNotFound"
187 #define VARLINK_ERROR_METHOD_NOT_IMPLEMENTED "org.varlink.service.MethodNotImplemented"
188 #define VARLINK_ERROR_INVALID_PARAMETER "org.varlink.service.InvalidParameter"
190 /* These are errors we came up with and squatted the namespace with */
191 #define VARLINK_ERROR_SUBSCRIPTION_TAKEN "org.varlink.service.SubscriptionTaken"
192 #define VARLINK_ERROR_PERMISSION_DENIED "org.varlink.service.PermissionDenied"