1 /* SPDX-License-Identifier: LGPL-2.1+ */
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 */
48 _VARLINK_SERVER_FLAGS_ALL
= (1 << 3) - 1,
51 typedef int (*VarlinkMethod
)(Varlink
*link
, JsonVariant
*parameters
, VarlinkMethodFlags flags
, void *userdata
);
52 typedef int (*VarlinkReply
)(Varlink
*link
, JsonVariant
*parameters
, const char *error_id
, VarlinkReplyFlags flags
, void *userdata
);
53 typedef int (*VarlinkConnect
)(VarlinkServer
*server
, Varlink
*link
, void *userdata
);
54 typedef void (*VarlinkDisconnect
)(VarlinkServer
*server
, Varlink
*link
, void *userdata
);
56 int varlink_connect_address(Varlink
**ret
, const char *address
);
57 int varlink_connect_fd(Varlink
**ret
, int fd
);
59 Varlink
* varlink_ref(Varlink
*link
);
60 Varlink
* varlink_unref(Varlink
*v
);
62 int varlink_get_fd(Varlink
*v
);
63 int varlink_get_events(Varlink
*v
);
64 int varlink_get_timeout(Varlink
*v
, usec_t
*ret
);
66 int varlink_attach_event(Varlink
*v
, sd_event
*e
, int64_t priority
);
67 void varlink_detach_event(Varlink
*v
);
68 sd_event
*varlink_get_event(Varlink
*v
);
70 int varlink_process(Varlink
*v
);
71 int varlink_wait(Varlink
*v
, usec_t timeout
);
73 int varlink_flush(Varlink
*v
);
74 int varlink_close(Varlink
*v
);
76 Varlink
* varlink_flush_close_unref(Varlink
*v
);
77 Varlink
* varlink_close_unref(Varlink
*v
);
79 /* Enqueue method call, not expecting a reply */
80 int varlink_send(Varlink
*v
, const char *method
, JsonVariant
*parameters
);
81 int varlink_sendb(Varlink
*v
, const char *method
, ...);
83 /* Send method call and wait for reply */
84 int varlink_call(Varlink
*v
, const char *method
, JsonVariant
*parameters
, JsonVariant
**ret_parameters
, const char **ret_error_id
, VarlinkReplyFlags
*ret_flags
);
85 int varlink_callb(Varlink
*v
, const char *method
, JsonVariant
**ret_parameters
, const char **ret_error_id
, VarlinkReplyFlags
*ret_flags
, ...);
87 /* Enqueue method call, expect a reply, which is eventually delivered to the reply callback */
88 int varlink_invoke(Varlink
*v
, const char *method
, JsonVariant
*parameters
);
89 int varlink_invokeb(Varlink
*v
, const char *method
, ...);
91 /* Enqueue method call, expect a reply now, and possibly more later, which are all delivered to the reply callback */
92 int varlink_observe(Varlink
*v
, const char *method
, JsonVariant
*parameters
);
93 int varlink_observeb(Varlink
*v
, const char *method
, ...);
95 /* Enqueue a final reply */
96 int varlink_reply(Varlink
*v
, JsonVariant
*parameters
);
97 int varlink_replyb(Varlink
*v
, ...);
99 /* Enqueue a (final) error */
100 int varlink_error(Varlink
*v
, const char *error_id
, JsonVariant
*parameters
);
101 int varlink_errorb(Varlink
*v
, const char *error_id
, ...);
102 int varlink_error_invalid_parameter(Varlink
*v
, JsonVariant
*parameters
);
103 int varlink_error_errno(Varlink
*v
, int error
);
105 /* Enqueue a "more" reply */
106 int varlink_notify(Varlink
*v
, JsonVariant
*parameters
);
107 int varlink_notifyb(Varlink
*v
, ...);
109 /* Bind a disconnect, reply or timeout callback */
110 int varlink_bind_reply(Varlink
*v
, VarlinkReply reply
);
112 void* varlink_set_userdata(Varlink
*v
, void *userdata
);
113 void* varlink_get_userdata(Varlink
*v
);
115 int varlink_get_peer_uid(Varlink
*v
, uid_t
*ret
);
116 int varlink_get_peer_pid(Varlink
*v
, pid_t
*ret
);
118 int varlink_set_relative_timeout(Varlink
*v
, usec_t usec
);
120 VarlinkServer
* varlink_get_server(Varlink
*v
);
122 int varlink_set_description(Varlink
*v
, const char *d
);
124 /* Create a varlink server */
125 int varlink_server_new(VarlinkServer
**ret
, VarlinkServerFlags flags
);
126 VarlinkServer
*varlink_server_ref(VarlinkServer
*s
);
127 VarlinkServer
*varlink_server_unref(VarlinkServer
*s
);
129 /* Add addresses or fds to listen on */
130 int varlink_server_listen_address(VarlinkServer
*s
, const char *address
, mode_t mode
);
131 int varlink_server_listen_fd(VarlinkServer
*s
, int fd
);
132 int varlink_server_add_connection(VarlinkServer
*s
, int fd
, Varlink
**ret
);
135 int varlink_server_bind_method(VarlinkServer
*s
, const char *method
, VarlinkMethod callback
);
136 int varlink_server_bind_method_many_internal(VarlinkServer
*s
, ...);
137 #define varlink_server_bind_method_many(s, ...) varlink_server_bind_method_many_internal(s, __VA_ARGS__, NULL)
138 int varlink_server_bind_connect(VarlinkServer
*s
, VarlinkConnect connect
);
139 int varlink_server_bind_disconnect(VarlinkServer
*s
, VarlinkDisconnect disconnect
);
141 void* varlink_server_set_userdata(VarlinkServer
*s
, void *userdata
);
142 void* varlink_server_get_userdata(VarlinkServer
*s
);
144 int varlink_server_attach_event(VarlinkServer
*v
, sd_event
*e
, int64_t priority
);
145 int varlink_server_detach_event(VarlinkServer
*v
);
146 sd_event
*varlink_server_get_event(VarlinkServer
*v
);
148 int varlink_server_shutdown(VarlinkServer
*server
);
150 unsigned varlink_server_connections_max(VarlinkServer
*s
);
151 unsigned varlink_server_connections_per_uid_max(VarlinkServer
*s
);
153 int varlink_server_set_connections_per_uid_max(VarlinkServer
*s
, unsigned m
);
154 int varlink_server_set_connections_max(VarlinkServer
*s
, unsigned m
);
156 unsigned varlink_server_current_connections(VarlinkServer
*s
);
158 int varlink_server_set_description(VarlinkServer
*s
, const char *description
);
160 DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink
*, varlink_unref
);
161 DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink
*, varlink_close_unref
);
162 DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink
*, varlink_flush_close_unref
);
163 DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServer
*, varlink_server_unref
);
165 #define VARLINK_ERROR_DISCONNECTED "io.systemd.Disconnected"
166 #define VARLINK_ERROR_TIMEOUT "io.systemd.TimedOut"
167 #define VARLINK_ERROR_PROTOCOL "io.systemd.Protocol"
168 #define VARLINK_ERROR_SYSTEM "io.systemd.System"
170 #define VARLINK_ERROR_INTERFACE_NOT_FOUND "org.varlink.service.InterfaceNotFound"
171 #define VARLINK_ERROR_METHOD_NOT_FOUND "org.varlink.service.MethodNotFound"
172 #define VARLINK_ERROR_METHOD_NOT_IMPLEMENTED "org.varlink.service.MethodNotImplemented"
173 #define VARLINK_ERROR_INVALID_PARAMETER "org.varlink.service.InvalidParameter"
174 #define VARLINK_ERROR_SUBSCRIPTION_TAKEN "org.varlink.service.SubscriptionTaken"