Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
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 : :
48 : : _VARLINK_SERVER_FLAGS_ALL = (1 << 3) - 1,
49 : : } VarlinkServerFlags;
50 : :
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 : :
55 : : int varlink_connect_address(Varlink **ret, const char *address);
56 : : int varlink_connect_fd(Varlink **ret, int fd);
57 : :
58 : : Varlink* varlink_ref(Varlink *link);
59 : : Varlink* varlink_unref(Varlink *v);
60 : :
61 : : int varlink_get_fd(Varlink *v);
62 : : int varlink_get_events(Varlink *v);
63 : : int varlink_get_timeout(Varlink *v, usec_t *ret);
64 : :
65 : : int varlink_attach_event(Varlink *v, sd_event *e, int64_t priority);
66 : : void varlink_detach_event(Varlink *v);
67 : : sd_event *varlink_get_event(Varlink *v);
68 : :
69 : : int varlink_process(Varlink *v);
70 : : int varlink_wait(Varlink *v, usec_t timeout);
71 : :
72 : : int varlink_flush(Varlink *v);
73 : : int varlink_close(Varlink *v);
74 : :
75 : : Varlink* varlink_flush_close_unref(Varlink *v);
76 : :
77 : : /* Enqueue method call, not expecting a reply */
78 : : int varlink_send(Varlink *v, const char *method, JsonVariant *parameters);
79 : : int varlink_sendb(Varlink *v, const char *method, ...);
80 : :
81 : : /* Send method call and wait for reply */
82 : : int varlink_call(Varlink *v, const char *method, JsonVariant *parameters, JsonVariant **ret_parameters, const char **ret_error_id, VarlinkReplyFlags *ret_flags);
83 : : int varlink_callb(Varlink *v, const char *method, JsonVariant **ret_parameters, const char **ret_error_id, VarlinkReplyFlags *ret_flags, ...);
84 : :
85 : : /* Enqueue method call, expect a reply, which is eventually delivered to the reply callback */
86 : : int varlink_invoke(Varlink *v, const char *method, JsonVariant *parameters);
87 : : int varlink_invokeb(Varlink *v, const char *method, ...);
88 : :
89 : : /* Enqueue a final reply */
90 : : int varlink_reply(Varlink *v, JsonVariant *parameters);
91 : : int varlink_replyb(Varlink *v, ...);
92 : :
93 : : /* Enqueue a (final) error */
94 : : int varlink_error(Varlink *v, const char *error_id, JsonVariant *parameters);
95 : : int varlink_errorb(Varlink *v, const char *error_id, ...);
96 : : int varlink_error_invalid_parameter(Varlink *v, JsonVariant *parameters);
97 : :
98 : : /* Enqueue a "more" reply */
99 : : int varlink_notify(Varlink *v, JsonVariant *parameters);
100 : : int varlink_notifyb(Varlink *v, ...);
101 : :
102 : : /* Bind a disconnect, reply or timeout callback */
103 : : int varlink_bind_reply(Varlink *v, VarlinkReply reply);
104 : :
105 : : void* varlink_set_userdata(Varlink *v, void *userdata);
106 : : void* varlink_get_userdata(Varlink *v);
107 : :
108 : : int varlink_get_peer_uid(Varlink *v, uid_t *ret);
109 : : int varlink_get_peer_pid(Varlink *v, pid_t *ret);
110 : :
111 : : int varlink_set_relative_timeout(Varlink *v, usec_t usec);
112 : :
113 : : VarlinkServer* varlink_get_server(Varlink *v);
114 : :
115 : : int varlink_set_description(Varlink *v, const char *d);
116 : :
117 : : /* Create a varlink server */
118 : : int varlink_server_new(VarlinkServer **ret, VarlinkServerFlags flags);
119 : : VarlinkServer *varlink_server_ref(VarlinkServer *s);
120 : : VarlinkServer *varlink_server_unref(VarlinkServer *s);
121 : :
122 : : /* Add addresses or fds to listen on */
123 : : int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t mode);
124 : : int varlink_server_listen_fd(VarlinkServer *s, int fd);
125 : : int varlink_server_add_connection(VarlinkServer *s, int fd, Varlink **ret);
126 : :
127 : : /* Bind callbacks */
128 : : int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMethod callback);
129 : : int varlink_server_bind_method_many_internal(VarlinkServer *s, ...);
130 : : #define varlink_server_bind_method_many(s, ...) varlink_server_bind_method_many_internal(s, __VA_ARGS__, NULL)
131 : : int varlink_server_bind_connect(VarlinkServer *s, VarlinkConnect connect);
132 : :
133 : : void* varlink_server_set_userdata(VarlinkServer *s, void *userdata);
134 : : void* varlink_server_get_userdata(VarlinkServer *s);
135 : :
136 : : int varlink_server_attach_event(VarlinkServer *v, sd_event *e, int64_t priority);
137 : : int varlink_server_detach_event(VarlinkServer *v);
138 : : sd_event *varlink_server_get_event(VarlinkServer *v);
139 : :
140 : : int varlink_server_shutdown(VarlinkServer *server);
141 : :
142 : : unsigned varlink_server_connections_max(VarlinkServer *s);
143 : : unsigned varlink_server_connections_per_uid_max(VarlinkServer *s);
144 : :
145 : : int varlink_server_set_connections_per_uid_max(VarlinkServer *s, unsigned m);
146 : : int varlink_server_set_connections_max(VarlinkServer *s, unsigned m);
147 : :
148 : : int varlink_server_set_description(VarlinkServer *s, const char *description);
149 : :
150 [ + + ]: 1868 : DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_unref);
151 [ + - ]: 12 : DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_flush_close_unref);
152 [ + - ]: 4 : DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServer *, varlink_server_unref);
153 : :
154 : : #define VARLINK_ERROR_DISCONNECTED "io.systemd.Disconnected"
155 : : #define VARLINK_ERROR_TIMEOUT "io.systemd.TimedOut"
156 : : #define VARLINK_ERROR_PROTOCOL "io.systemd.Protocol"
157 : : #define VARLINK_ERROR_SYSTEM "io.systemd.System"
158 : :
159 : : #define VARLINK_ERROR_INTERFACE_NOT_FOUND "org.varlink.service.InterfaceNotFound"
160 : : #define VARLINK_ERROR_METHOD_NOT_FOUND "org.varlink.service.MethodNotFound"
161 : : #define VARLINK_ERROR_METHOD_NOT_IMPLEMENTED "org.varlink.service.MethodNotImplemented"
162 : : #define VARLINK_ERROR_INVALID_PARAMETER "org.varlink.service.InvalidParameter"
|