]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
d41bd96f LP |
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 { | |
9807fdc1 LP |
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 */ | |
d41bd96f | 48 | |
9807fdc1 | 49 | _VARLINK_SERVER_FLAGS_ALL = (1 << 4) - 1, |
d41bd96f LP |
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); | |
6d4d6002 | 55 | typedef void (*VarlinkDisconnect)(VarlinkServer *server, Varlink *link, void *userdata); |
d41bd96f LP |
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); | |
9652d740 | 78 | Varlink* varlink_close_unref(Varlink *v); |
d41bd96f LP |
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 | ||
45a6c965 LP |
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 | ||
d41bd96f LP |
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); | |
7466e94f | 104 | int varlink_error_errno(Varlink *v, int error); |
d41bd96f LP |
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); | |
6d4d6002 | 140 | int varlink_server_bind_disconnect(VarlinkServer *s, VarlinkDisconnect disconnect); |
d41bd96f LP |
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 | ||
c4f601f2 LP |
157 | unsigned varlink_server_current_connections(VarlinkServer *s); |
158 | ||
d41bd96f LP |
159 | int varlink_server_set_description(VarlinkServer *s, const char *description); |
160 | ||
161 | DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_unref); | |
9652d740 | 162 | DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_close_unref); |
d41bd96f LP |
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" | |
e30bbc90 | 175 | #define VARLINK_ERROR_SUBSCRIPTION_TAKEN "org.varlink.service.SubscriptionTaken" |