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 "time-util.h"
8 
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.
11  *
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:
14  *
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.
19  *
20  * • We want integration into sd-event, but also synchronous event-loop-less operation
21  *
22  * • We need proper per-UID accounting and access control, since we want to allow communication between
23  *   unprivileged clients and privileged servers.
24  *
25  * • And of course, we don't want the name service and introspection stuff for now (though that might
26  *   change).
27  */
28 
29 typedef struct Varlink Varlink;
30 typedef struct VarlinkServer VarlinkServer;
31 
32 typedef enum VarlinkReplyFlags {
33         VARLINK_REPLY_ERROR     = 1 << 0,
34         VARLINK_REPLY_CONTINUES = 1 << 1,
35         VARLINK_REPLY_LOCAL     = 1 << 2,
36 } VarlinkReplyFlags;
37 
38 typedef enum VarlinkMethodFlags {
39         VARLINK_METHOD_ONEWAY = 1 << 0,
40         VARLINK_METHOD_MORE   = 2 << 1,
41 } VarlinkMethodFlags;
42 
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 */
48 
49         _VARLINK_SERVER_FLAGS_ALL = (1 << 4) - 1,
50 } VarlinkServerFlags;
51 
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);
56 
57 int varlink_connect_address(Varlink **ret, const char *address);
58 int varlink_connect_fd(Varlink **ret, int fd);
59 
60 Varlink* varlink_ref(Varlink *link);
61 Varlink* varlink_unref(Varlink *v);
62 
63 int varlink_get_fd(Varlink *v);
64 int varlink_get_events(Varlink *v);
65 int varlink_get_timeout(Varlink *v, usec_t *ret);
66 
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);
70 
71 int varlink_process(Varlink *v);
72 int varlink_wait(Varlink *v, usec_t timeout);
73 
74 int varlink_flush(Varlink *v);
75 int varlink_close(Varlink *v);
76 
77 Varlink* varlink_flush_close_unref(Varlink *v);
78 Varlink* varlink_close_unref(Varlink *v);
79 
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, ...);
83 
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, ...);
87 
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, ...);
91 
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, ...);
95 
96 /* Enqueue a final reply */
97 int varlink_reply(Varlink *v, JsonVariant *parameters);
98 int varlink_replyb(Varlink *v, ...);
99 
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);
105 
106 /* Enqueue a "more" reply */
107 int varlink_notify(Varlink *v, JsonVariant *parameters);
108 int varlink_notifyb(Varlink *v, ...);
109 
110 /* Bind a disconnect, reply or timeout callback */
111 int varlink_bind_reply(Varlink *v, VarlinkReply reply);
112 
113 void* varlink_set_userdata(Varlink *v, void *userdata);
114 void* varlink_get_userdata(Varlink *v);
115 
116 int varlink_get_peer_uid(Varlink *v, uid_t *ret);
117 int varlink_get_peer_pid(Varlink *v, pid_t *ret);
118 
119 int varlink_set_relative_timeout(Varlink *v, usec_t usec);
120 
121 VarlinkServer* varlink_get_server(Varlink *v);
122 
123 int varlink_set_description(Varlink *v, const char *d);
124 
125 /* Create a varlink server */
126 int varlink_server_new(VarlinkServer **ret, VarlinkServerFlags flags);
127 VarlinkServer *varlink_server_ref(VarlinkServer *s);
128 VarlinkServer *varlink_server_unref(VarlinkServer *s);
129 
130 /* Add addresses or fds to listen on */
131 int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t mode);
132 int varlink_server_listen_fd(VarlinkServer *s, int fd);
133 int varlink_server_add_connection(VarlinkServer *s, int fd, Varlink **ret);
134 
135 /* Bind callbacks */
136 int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMethod callback);
137 int varlink_server_bind_method_many_internal(VarlinkServer *s, ...);
138 #define varlink_server_bind_method_many(s, ...) varlink_server_bind_method_many_internal(s, __VA_ARGS__, NULL)
139 int varlink_server_bind_connect(VarlinkServer *s, VarlinkConnect connect);
140 int varlink_server_bind_disconnect(VarlinkServer *s, VarlinkDisconnect disconnect);
141 
142 void* varlink_server_set_userdata(VarlinkServer *s, void *userdata);
143 void* varlink_server_get_userdata(VarlinkServer *s);
144 
145 int varlink_server_attach_event(VarlinkServer *v, sd_event *e, int64_t priority);
146 int varlink_server_detach_event(VarlinkServer *v);
147 sd_event *varlink_server_get_event(VarlinkServer *v);
148 
149 int varlink_server_shutdown(VarlinkServer *server);
150 
151 unsigned varlink_server_connections_max(VarlinkServer *s);
152 unsigned varlink_server_connections_per_uid_max(VarlinkServer *s);
153 
154 int varlink_server_set_connections_per_uid_max(VarlinkServer *s, unsigned m);
155 int varlink_server_set_connections_max(VarlinkServer *s, unsigned m);
156 
157 unsigned varlink_server_current_connections(VarlinkServer *s);
158 
159 int varlink_server_set_description(VarlinkServer *s, const char *description);
160 
161 DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_unref);
162 DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_close_unref);
163 DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_flush_close_unref);
164 DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServer *, varlink_server_unref);
165 
166 #define VARLINK_ERROR_DISCONNECTED "io.systemd.Disconnected"
167 #define VARLINK_ERROR_TIMEOUT "io.systemd.TimedOut"
168 #define VARLINK_ERROR_PROTOCOL "io.systemd.Protocol"
169 #define VARLINK_ERROR_SYSTEM "io.systemd.System"
170 
171 #define VARLINK_ERROR_INTERFACE_NOT_FOUND "org.varlink.service.InterfaceNotFound"
172 #define VARLINK_ERROR_METHOD_NOT_FOUND "org.varlink.service.MethodNotFound"
173 #define VARLINK_ERROR_METHOD_NOT_IMPLEMENTED "org.varlink.service.MethodNotImplemented"
174 #define VARLINK_ERROR_INVALID_PARAMETER "org.varlink.service.InvalidParameter"
175 #define VARLINK_ERROR_SUBSCRIPTION_TAKEN "org.varlink.service.SubscriptionTaken"
176