]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/varlink.h
Merge pull request #31648 from neighbourhoodie/review-content
[thirdparty/systemd.git] / src / shared / varlink.h
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3
4 #include "sd-event.h"
5
6 #include "json.h"
7 #include "pidref.h"
8 #include "time-util.h"
9 #include "varlink-idl.h"
10
11 /* A minimal Varlink implementation. We only implement the minimal, obvious bits here though. No validation,
12 * no introspection, no name service, just the stuff actually needed.
13 *
14 * You might wonder why we aren't using libvarlink here? Varlink is a very simple protocol, which allows us
15 * to write our own implementation relatively easily. However, the main reasons are these:
16 *
17 * • We want to use our own JSON subsystem, with all the benefits that brings (i.e. accurate unsigned+signed
18 * 64-bit integers, full fuzzing, logging during parsing and so on). If we'd want to use that with
19 * libvarlink we'd have to serialize and deserialize all the time from its own representation which is
20 * inefficient and nasty.
21 *
22 * • We want integration into sd-event, but also synchronous event-loop-less operation
23 *
24 * • We need proper per-UID accounting and access control, since we want to allow communication between
25 * unprivileged clients and privileged servers.
26 *
27 * • And of course, we don't want the name service and introspection stuff for now (though that might
28 * change).
29 */
30
31 typedef struct Varlink Varlink;
32 typedef struct VarlinkServer VarlinkServer;
33
34 typedef enum VarlinkReplyFlags {
35 VARLINK_REPLY_ERROR = 1 << 0,
36 VARLINK_REPLY_CONTINUES = 1 << 1,
37 VARLINK_REPLY_LOCAL = 1 << 2,
38 } VarlinkReplyFlags;
39
40 typedef enum VarlinkMethodFlags {
41 VARLINK_METHOD_ONEWAY = 1 << 0,
42 VARLINK_METHOD_MORE = 2 << 1,
43 } VarlinkMethodFlags;
44
45 typedef enum VarlinkServerFlags {
46 VARLINK_SERVER_ROOT_ONLY = 1 << 0, /* Only accessible by root */
47 VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */
48 VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */
49 VARLINK_SERVER_INHERIT_USERDATA = 1 << 3, /* Initialize Varlink connection userdata from VarlinkServer userdata */
50 VARLINK_SERVER_INPUT_SENSITIVE = 1 << 4, /* Automatically mark al connection input as sensitive */
51 _VARLINK_SERVER_FLAGS_ALL = (1 << 5) - 1,
52 } VarlinkServerFlags;
53
54 typedef int (*VarlinkMethod)(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata);
55 typedef int (*VarlinkReply)(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata);
56 typedef int (*VarlinkConnect)(VarlinkServer *server, Varlink *link, void *userdata);
57 typedef void (*VarlinkDisconnect)(VarlinkServer *server, Varlink *link, void *userdata);
58
59 int varlink_connect_address(Varlink **ret, const char *address);
60 int varlink_connect_exec(Varlink **ret, const char *command, char **argv);
61 int varlink_connect_url(Varlink **ret, const char *url);
62 int varlink_connect_fd(Varlink **ret, int fd);
63
64 Varlink* varlink_ref(Varlink *link);
65 Varlink* varlink_unref(Varlink *v);
66
67 int varlink_get_fd(Varlink *v);
68 int varlink_get_events(Varlink *v);
69 int varlink_get_timeout(Varlink *v, usec_t *ret);
70
71 int varlink_attach_event(Varlink *v, sd_event *e, int64_t priority);
72 void varlink_detach_event(Varlink *v);
73 sd_event *varlink_get_event(Varlink *v);
74
75 int varlink_process(Varlink *v);
76 int varlink_wait(Varlink *v, usec_t timeout);
77
78 int varlink_is_idle(Varlink *v);
79
80 int varlink_flush(Varlink *v);
81 int varlink_close(Varlink *v);
82
83 Varlink* varlink_flush_close_unref(Varlink *v);
84 Varlink* varlink_close_unref(Varlink *v);
85
86 /* Enqueue method call, not expecting a reply */
87 int varlink_send(Varlink *v, const char *method, JsonVariant *parameters);
88 int varlink_sendb(Varlink *v, const char *method, ...);
89
90 /* Send method call and wait for reply */
91 int varlink_call_full(Varlink *v, const char *method, JsonVariant *parameters, JsonVariant **ret_parameters, const char **ret_error_id, VarlinkReplyFlags *ret_flags);
92 static inline int varlink_call(Varlink *v, const char *method, JsonVariant *parameters, JsonVariant **ret_parameters, const char **ret_error_id) {
93 return varlink_call_full(v, method, parameters, ret_parameters, ret_error_id, NULL);
94 }
95 int varlink_call_and_log(Varlink *v, const char *method, JsonVariant *parameters, JsonVariant **ret_parameters);
96
97 int varlink_callb_ap(Varlink *v, const char *method, JsonVariant **ret_parameters, const char **ret_error_id, VarlinkReplyFlags *ret_flags, va_list ap);
98 static inline int varlink_callb_full(Varlink *v, const char *method, JsonVariant **ret_parameters, const char **ret_error_id, VarlinkReplyFlags *ret_flags, ...) {
99 va_list ap;
100 int r;
101
102 va_start(ap, ret_flags);
103 r = varlink_callb_ap(v, method, ret_parameters, ret_error_id, ret_flags, ap);
104 va_end(ap);
105 return r;
106 }
107 static inline int varlink_callb(Varlink *v, const char *method, JsonVariant **ret_parameters, const char **ret_error_id, ...) {
108 va_list ap;
109 int r;
110
111 va_start(ap, ret_error_id);
112 r = varlink_callb_ap(v, method, ret_parameters, ret_error_id, NULL, ap);
113 va_end(ap);
114 return r;
115 }
116 int varlink_callb_and_log(Varlink *v, const char *method, JsonVariant **ret_parameters, ...);
117
118 /* Send method call and begin collecting all 'more' replies into an array, finishing when a final reply is sent */
119 int varlink_collect_full(Varlink *v, const char *method, JsonVariant *parameters, JsonVariant **ret_parameters, const char **ret_error_id, VarlinkReplyFlags *ret_flags);
120 static inline int varlink_collect(Varlink *v, const char *method, JsonVariant *parameters, JsonVariant **ret_parameters, const char **ret_error_id) {
121 return varlink_collect_full(v, method, parameters, ret_parameters, ret_error_id, NULL);
122 }
123 int varlink_collectb(Varlink *v, const char *method, JsonVariant **ret_parameters, const char **ret_error_id, ...);
124
125 /* Enqueue method call, expect a reply, which is eventually delivered to the reply callback */
126 int varlink_invoke(Varlink *v, const char *method, JsonVariant *parameters);
127 int varlink_invokeb(Varlink *v, const char *method, ...);
128
129 /* Enqueue method call, expect a reply now, and possibly more later, which are all delivered to the reply callback */
130 int varlink_observe(Varlink *v, const char *method, JsonVariant *parameters);
131 int varlink_observeb(Varlink *v, const char *method, ...);
132
133 /* Enqueue a final reply */
134 int varlink_reply(Varlink *v, JsonVariant *parameters);
135 int varlink_replyb(Varlink *v, ...);
136
137 /* Enqueue a (final) error */
138 int varlink_error(Varlink *v, const char *error_id, JsonVariant *parameters);
139 int varlink_errorb(Varlink *v, const char *error_id, ...);
140 int varlink_error_invalid_parameter(Varlink *v, JsonVariant *parameters);
141 int varlink_error_invalid_parameter_name(Varlink *v, const char *name);
142 int varlink_error_errno(Varlink *v, int error);
143
144 /* Enqueue a "more" reply */
145 int varlink_notify(Varlink *v, JsonVariant *parameters);
146 int varlink_notifyb(Varlink *v, ...);
147
148 /* Ask for the current message to be dispatched again */
149 int varlink_dispatch_again(Varlink *v);
150
151 /* Get the currently processed incoming message */
152 int varlink_get_current_parameters(Varlink *v, JsonVariant **ret);
153
154 /* Parsing incoming data via json_dispatch() and generate a nice error on parse errors */
155 int varlink_dispatch(Varlink *v, JsonVariant *parameters, const JsonDispatch table[], void *userdata);
156
157 /* Write outgoing fds into the socket (to be associated with the next enqueued message) */
158 int varlink_push_fd(Varlink *v, int fd);
159 int varlink_push_dup_fd(Varlink *v, int fd);
160 int varlink_reset_fds(Varlink *v);
161
162 /* Read incoming fds from the socket (associated with the currently handled message) */
163 int varlink_peek_fd(Varlink *v, size_t i);
164 int varlink_peek_dup_fd(Varlink *v, size_t i);
165 int varlink_take_fd(Varlink *v, size_t i);
166
167 int varlink_set_allow_fd_passing_input(Varlink *v, bool b);
168 int varlink_set_allow_fd_passing_output(Varlink *v, bool b);
169
170 /* Bind a disconnect, reply or timeout callback */
171 int varlink_bind_reply(Varlink *v, VarlinkReply reply);
172
173 void* varlink_set_userdata(Varlink *v, void *userdata);
174 void* varlink_get_userdata(Varlink *v);
175
176 int varlink_get_peer_uid(Varlink *v, uid_t *ret);
177 int varlink_get_peer_gid(Varlink *v, gid_t *ret);
178 int varlink_get_peer_pid(Varlink *v, pid_t *ret);
179 int varlink_get_peer_pidref(Varlink *v, PidRef *ret);
180
181 int varlink_set_relative_timeout(Varlink *v, usec_t usec);
182
183 VarlinkServer* varlink_get_server(Varlink *v);
184
185 int varlink_set_description(Varlink *v, const char *d);
186
187 /* Automatically mark the parameters part of incoming messages as security sensitive */
188 int varlink_set_input_sensitive(Varlink *v);
189
190 /* Create a varlink server */
191 int varlink_server_new(VarlinkServer **ret, VarlinkServerFlags flags);
192 VarlinkServer *varlink_server_ref(VarlinkServer *s);
193 VarlinkServer *varlink_server_unref(VarlinkServer *s);
194
195 /* Add addresses or fds to listen on */
196 int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t mode);
197 int varlink_server_listen_fd(VarlinkServer *s, int fd);
198 int varlink_server_listen_auto(VarlinkServer *s);
199 int varlink_server_add_connection(VarlinkServer *s, int fd, Varlink **ret);
200
201 /* Bind callbacks */
202 int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMethod callback);
203 int varlink_server_bind_method_many_internal(VarlinkServer *s, ...);
204 #define varlink_server_bind_method_many(s, ...) varlink_server_bind_method_many_internal(s, __VA_ARGS__, NULL)
205 int varlink_server_bind_connect(VarlinkServer *s, VarlinkConnect connect);
206 int varlink_server_bind_disconnect(VarlinkServer *s, VarlinkDisconnect disconnect);
207
208 /* Add interface definition */
209 int varlink_server_add_interface(VarlinkServer *s, const VarlinkInterface *interface);
210 int varlink_server_add_interface_many_internal(VarlinkServer *s, ...);
211 #define varlink_server_add_interface_many(s, ...) varlink_server_add_interface_many_internal(s, __VA_ARGS__, NULL)
212
213 void* varlink_server_set_userdata(VarlinkServer *s, void *userdata);
214 void* varlink_server_get_userdata(VarlinkServer *s);
215
216 int varlink_server_attach_event(VarlinkServer *v, sd_event *e, int64_t priority);
217 int varlink_server_detach_event(VarlinkServer *v);
218 sd_event *varlink_server_get_event(VarlinkServer *v);
219
220 int varlink_server_loop_auto(VarlinkServer *server);
221
222 int varlink_server_shutdown(VarlinkServer *server);
223
224 int varlink_server_set_exit_on_idle(VarlinkServer *s, bool b);
225
226 unsigned varlink_server_connections_max(VarlinkServer *s);
227 unsigned varlink_server_connections_per_uid_max(VarlinkServer *s);
228
229 int varlink_server_set_connections_per_uid_max(VarlinkServer *s, unsigned m);
230 int varlink_server_set_connections_max(VarlinkServer *s, unsigned m);
231
232 unsigned varlink_server_current_connections(VarlinkServer *s);
233
234 int varlink_server_set_description(VarlinkServer *s, const char *description);
235
236 typedef enum VarlinkInvocationFlags {
237 VARLINK_ALLOW_LISTEN = 1 << 0,
238 VARLINK_ALLOW_ACCEPT = 1 << 1,
239 _VARLINK_SERVER_INVOCATION_FLAGS_MAX = (1 << 2) - 1,
240 _VARLINK_SERVER_INVOCATION_FLAGS_INVALID = -EINVAL,
241 } VarlinkInvocationFlags;
242
243 int varlink_invocation(VarlinkInvocationFlags flags);
244
245 int varlink_error_to_errno(const char *error, JsonVariant *parameters);
246
247 DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_unref);
248 DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_close_unref);
249 DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_flush_close_unref);
250 DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServer *, varlink_server_unref);
251
252 /* These are local errors that never cross the wire, and are our own invention */
253 #define VARLINK_ERROR_DISCONNECTED "io.systemd.Disconnected"
254 #define VARLINK_ERROR_TIMEOUT "io.systemd.TimedOut"
255 #define VARLINK_ERROR_PROTOCOL "io.systemd.Protocol"
256
257 /* This one we invented, and use for generically propagating system errors (errno) to clients */
258 #define VARLINK_ERROR_SYSTEM "io.systemd.System"
259
260 /* This one we invented and is a weaker version of "org.varlink.service.PermissionDenied", and indicates that if user would allow interactive auth, we might allow access */
261 #define VARLINK_ERROR_INTERACTIVE_AUTHENTICATION_REQUIRED "io.systemd.InteractiveAuthenticationRequired"
262
263 /* These are errors defined in the Varlink spec */
264 #define VARLINK_ERROR_INTERFACE_NOT_FOUND "org.varlink.service.InterfaceNotFound"
265 #define VARLINK_ERROR_METHOD_NOT_FOUND "org.varlink.service.MethodNotFound"
266 #define VARLINK_ERROR_METHOD_NOT_IMPLEMENTED "org.varlink.service.MethodNotImplemented"
267 #define VARLINK_ERROR_INVALID_PARAMETER "org.varlink.service.InvalidParameter"
268 #define VARLINK_ERROR_PERMISSION_DENIED "org.varlink.service.PermissionDenied"
269 #define VARLINK_ERROR_EXPECTED_MORE "org.varlink.service.ExpectedMore"