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