1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "alloc-util.h"
7 #include "errno-util.h"
9 #include "glyph-util.h"
13 #include "process-util.h"
14 #include "selinux-util.h"
15 #include "serialize.h"
17 #include "socket-util.h"
18 #include "string-table.h"
19 #include "string-util.h"
21 #include "time-util.h"
22 #include "umask-util.h"
23 #include "user-util.h"
25 #include "varlink-internal.h"
27 #define VARLINK_DEFAULT_CONNECTIONS_MAX 4096U
28 #define VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX 1024U
30 #define VARLINK_DEFAULT_TIMEOUT_USEC (45U*USEC_PER_SEC)
31 #define VARLINK_BUFFER_MAX (16U*1024U*1024U)
32 #define VARLINK_READ_SIZE (64U*1024U)
34 typedef enum VarlinkState
{
35 /* Client side states */
37 VARLINK_AWAITING_REPLY
,
38 VARLINK_AWAITING_REPLY_MORE
,
41 VARLINK_PROCESSING_REPLY
,
43 /* Server side states */
45 VARLINK_PROCESSING_METHOD
,
46 VARLINK_PROCESSING_METHOD_MORE
,
47 VARLINK_PROCESSING_METHOD_ONEWAY
,
48 VARLINK_PROCESSED_METHOD
,
49 VARLINK_PENDING_METHOD
,
50 VARLINK_PENDING_METHOD_MORE
,
52 /* Common states (only during shutdown) */
53 VARLINK_PENDING_DISCONNECT
,
54 VARLINK_PENDING_TIMEOUT
,
55 VARLINK_PROCESSING_DISCONNECT
,
56 VARLINK_PROCESSING_TIMEOUT
,
57 VARLINK_PROCESSING_FAILURE
,
61 _VARLINK_STATE_INVALID
= -EINVAL
,
64 /* Tests whether we are not yet disconnected. Note that this is true during all states where the connection
65 * is still good for something, and false only when it's dead for good. This means: when we are
66 * asynchronously connecting to a peer and the connect() is still pending, then this will return 'true', as
67 * the connection is still good, and we are likely to be able to properly operate on it soon. */
68 #define VARLINK_STATE_IS_ALIVE(state) \
70 VARLINK_IDLE_CLIENT, \
71 VARLINK_AWAITING_REPLY, \
72 VARLINK_AWAITING_REPLY_MORE, \
75 VARLINK_PROCESSING_REPLY, \
76 VARLINK_IDLE_SERVER, \
77 VARLINK_PROCESSING_METHOD, \
78 VARLINK_PROCESSING_METHOD_MORE, \
79 VARLINK_PROCESSING_METHOD_ONEWAY, \
80 VARLINK_PROCESSED_METHOD, \
81 VARLINK_PENDING_METHOD, \
82 VARLINK_PENDING_METHOD_MORE)
87 VarlinkServer
*server
;
90 bool connecting
; /* This boolean indicates whether the socket fd we are operating on is currently
91 * processing an asynchronous connect(). In that state we watch the socket for
92 * EPOLLOUT, but we refrain from calling read() or write() on the socket as that
93 * will trigger ENOTCONN. Note that this boolean is kept separate from the
94 * VarlinkState above on purpose: while the connect() is still not complete we
95 * already want to allow queuing of messages and similar. Thus it's nice to keep
96 * these two state concepts separate: the VarlinkState encodes what our own view of
97 * the connection is, i.e. whether we think it's a server, a client, and has
98 * something queued already, while 'connecting' tells us a detail about the
99 * transport used below, that should have no effect on how we otherwise accept and
100 * process operations from the user.
102 * Or to say this differently: VARLINK_STATE_IS_ALIVE(state) tells you whether the
103 * connection is good to use, even if it might not be fully connected
104 * yet. connecting=true then informs you that actually we are still connecting, and
105 * the connection is actually not established yet and thus any requests you enqueue
106 * now will still work fine but will be queued only, not sent yet, but that
107 * shouldn't stop you from using the connection, since eventually whatever you queue
110 * Or to say this even differently: 'state' is a high-level ("application layer"
111 * high, if you so will) state, while 'conecting' is a low-level ("transport layer"
112 * low, if you so will) state, and while they are not entirely unrelated and
113 * sometimes propagate effects to each other they are only asynchronously connected
119 char *input_buffer
; /* valid data starts at input_buffer_index, ends at input_buffer_index+input_buffer_size */
120 size_t input_buffer_index
;
121 size_t input_buffer_size
;
122 size_t input_buffer_unscanned
;
124 char *output_buffer
; /* valid data starts at output_buffer_index, ends at output_buffer_index+output_buffer_size */
125 size_t output_buffer_index
;
126 size_t output_buffer_size
;
128 VarlinkReply reply_callback
;
130 JsonVariant
*current
;
134 bool ucred_acquired
:1;
136 bool write_disconnected
:1;
137 bool read_disconnected
:1;
138 bool prefer_read_write
:1;
148 sd_event_source
*io_event_source
;
149 sd_event_source
*time_event_source
;
150 sd_event_source
*quit_event_source
;
151 sd_event_source
*defer_event_source
;
154 typedef struct VarlinkServerSocket VarlinkServerSocket
;
156 struct VarlinkServerSocket
{
157 VarlinkServer
*server
;
162 sd_event_source
*event_source
;
164 LIST_FIELDS(VarlinkServerSocket
, sockets
);
167 struct VarlinkServer
{
169 VarlinkServerFlags flags
;
171 LIST_HEAD(VarlinkServerSocket
, sockets
);
174 VarlinkConnect connect_callback
;
175 VarlinkDisconnect disconnect_callback
;
178 int64_t event_priority
;
180 unsigned n_connections
;
186 unsigned connections_max
;
187 unsigned connections_per_uid_max
;
190 static const char* const varlink_state_table
[_VARLINK_STATE_MAX
] = {
191 [VARLINK_IDLE_CLIENT
] = "idle-client",
192 [VARLINK_AWAITING_REPLY
] = "awaiting-reply",
193 [VARLINK_AWAITING_REPLY_MORE
] = "awaiting-reply-more",
194 [VARLINK_CALLING
] = "calling",
195 [VARLINK_CALLED
] = "called",
196 [VARLINK_PROCESSING_REPLY
] = "processing-reply",
197 [VARLINK_IDLE_SERVER
] = "idle-server",
198 [VARLINK_PROCESSING_METHOD
] = "processing-method",
199 [VARLINK_PROCESSING_METHOD_MORE
] = "processing-method-more",
200 [VARLINK_PROCESSING_METHOD_ONEWAY
] = "processing-method-oneway",
201 [VARLINK_PROCESSED_METHOD
] = "processed-method",
202 [VARLINK_PENDING_METHOD
] = "pending-method",
203 [VARLINK_PENDING_METHOD_MORE
] = "pending-method-more",
204 [VARLINK_PENDING_DISCONNECT
] = "pending-disconnect",
205 [VARLINK_PENDING_TIMEOUT
] = "pending-timeout",
206 [VARLINK_PROCESSING_DISCONNECT
] = "processing-disconnect",
207 [VARLINK_PROCESSING_TIMEOUT
] = "processing-timeout",
208 [VARLINK_PROCESSING_FAILURE
] = "processing-failure",
209 [VARLINK_DISCONNECTED
] = "disconnected",
212 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(varlink_state
, VarlinkState
);
214 #define varlink_log_errno(v, error, fmt, ...) \
215 log_debug_errno(error, "%s: " fmt, varlink_description(v), ##__VA_ARGS__)
217 #define varlink_log(v, fmt, ...) \
218 log_debug("%s: " fmt, varlink_description(v), ##__VA_ARGS__)
220 #define varlink_server_log_errno(s, error, fmt, ...) \
221 log_debug_errno(error, "%s: " fmt, varlink_server_description(s), ##__VA_ARGS__)
223 #define varlink_server_log(s, fmt, ...) \
224 log_debug("%s: " fmt, varlink_server_description(s), ##__VA_ARGS__)
226 static inline const char *varlink_description(Varlink
*v
) {
227 return (v
? v
->description
: NULL
) ?: "varlink";
230 static inline const char *varlink_server_description(VarlinkServer
*s
) {
231 return (s
? s
->description
: NULL
) ?: "varlink";
234 static void varlink_set_state(Varlink
*v
, VarlinkState state
) {
236 assert(state
>= 0 && state
< _VARLINK_STATE_MAX
);
239 varlink_log(v
, "Setting state %s",
240 varlink_state_to_string(state
));
242 varlink_log(v
, "Changing state %s %s %s",
243 varlink_state_to_string(v
->state
),
244 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
),
245 varlink_state_to_string(state
));
250 static int varlink_new(Varlink
**ret
) {
263 .state
= _VARLINK_STATE_INVALID
,
265 .ucred
= UCRED_INVALID
,
267 .timestamp
= USEC_INFINITY
,
268 .timeout
= VARLINK_DEFAULT_TIMEOUT_USEC
275 int varlink_connect_address(Varlink
**ret
, const char *address
) {
276 _cleanup_(varlink_unrefp
) Varlink
*v
= NULL
;
277 union sockaddr_union sockaddr
;
280 assert_return(ret
, -EINVAL
);
281 assert_return(address
, -EINVAL
);
285 return log_debug_errno(r
, "Failed to create varlink object: %m");
287 v
->fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
289 return log_debug_errno(errno
, "Failed to create AF_UNIX socket: %m");
291 v
->fd
= fd_move_above_stdio(v
->fd
);
293 r
= sockaddr_un_set_path(&sockaddr
.un
, address
);
295 if (r
!= -ENAMETOOLONG
)
296 return log_debug_errno(r
, "Failed to set socket address '%s': %m", address
);
298 /* This is a file system path, and too long to fit into sockaddr_un. Let's connect via O_PATH
301 r
= connect_unix_path(v
->fd
, AT_FDCWD
, address
);
303 r
= RET_NERRNO(connect(v
->fd
, &sockaddr
.sa
, r
));
306 if (!IN_SET(r
, -EAGAIN
, -EINPROGRESS
))
307 return log_debug_errno(r
, "Failed to connect to %s: %m", address
);
309 v
->connecting
= true; /* We are asynchronously connecting, i.e. the connect() is being
310 * processed in the background. As long as that's the case the socket
311 * is in a special state: it's there, we can poll it for EPOLLOUT, but
312 * if we attempt to write() to it before we see EPOLLOUT we'll get
313 * ENOTCONN (and not EAGAIN, like we would for a normal connected
314 * socket that isn't writable at the moment). Since ENOTCONN on write()
315 * hence can mean two different things (i.e. connection not complete
316 * yet vs. already disconnected again), we store as a boolean whether
317 * we are still in connect(). */
320 varlink_set_state(v
, VARLINK_IDLE_CLIENT
);
326 int varlink_connect_fd(Varlink
**ret
, int fd
) {
330 assert_return(ret
, -EINVAL
);
331 assert_return(fd
>= 0, -EBADF
);
333 r
= fd_nonblock(fd
, true);
335 return log_debug_errno(r
, "Failed to make fd %d nonblocking: %m", fd
);
339 return log_debug_errno(r
, "Failed to create varlink object: %m");
342 varlink_set_state(v
, VARLINK_IDLE_CLIENT
);
344 /* Note that if this function is called we assume the passed socket (if it is one) is already
345 * properly connected, i.e. any asynchronous connect() done on it already completed. Because of that
346 * we'll not set the 'connecting' boolean here, i.e. we don't need to avoid write()ing to the socket
347 * until the connection is fully set up. Behaviour here is hence a bit different from
348 * varlink_connect_address() above, as there we do handle asynchronous connections ourselves and
349 * avoid doing write() on it before we saw EPOLLOUT for the first time. */
355 static void varlink_detach_event_sources(Varlink
*v
) {
358 v
->io_event_source
= sd_event_source_disable_unref(v
->io_event_source
);
359 v
->time_event_source
= sd_event_source_disable_unref(v
->time_event_source
);
360 v
->quit_event_source
= sd_event_source_disable_unref(v
->quit_event_source
);
361 v
->defer_event_source
= sd_event_source_disable_unref(v
->defer_event_source
);
364 static void varlink_clear(Varlink
*v
) {
367 varlink_detach_event_sources(v
);
369 v
->fd
= safe_close(v
->fd
);
371 v
->input_buffer
= mfree(v
->input_buffer
);
372 v
->output_buffer
= mfree(v
->output_buffer
);
374 v
->current
= json_variant_unref(v
->current
);
375 v
->reply
= json_variant_unref(v
->reply
);
377 v
->event
= sd_event_unref(v
->event
);
380 static Varlink
* varlink_destroy(Varlink
*v
) {
384 /* If this is called the server object must already been unreffed here. Why that? because when we
385 * linked up the varlink connection with the server object we took one ref in each direction */
390 free(v
->description
);
394 DEFINE_TRIVIAL_REF_UNREF_FUNC(Varlink
, varlink
, varlink_destroy
);
396 static int varlink_test_disconnect(Varlink
*v
) {
399 /* Tests whether we the connection has been terminated. We are careful to not stop processing it
400 * prematurely, since we want to handle half-open connections as well as possible and want to flush
401 * out and read data before we close down if we can. */
403 /* Already disconnected? */
404 if (!VARLINK_STATE_IS_ALIVE(v
->state
))
407 /* Wait until connection setup is complete, i.e. until asynchronous connect() completes */
411 /* Still something to write and we can write? Stay around */
412 if (v
->output_buffer_size
> 0 && !v
->write_disconnected
)
415 /* Both sides gone already? Then there's no need to stick around */
416 if (v
->read_disconnected
&& v
->write_disconnected
)
419 /* If we are waiting for incoming data but the read side is shut down, disconnect. */
420 if (IN_SET(v
->state
, VARLINK_AWAITING_REPLY
, VARLINK_AWAITING_REPLY_MORE
, VARLINK_CALLING
, VARLINK_IDLE_SERVER
) && v
->read_disconnected
)
423 /* Similar, if are a client that hasn't written anything yet but the write side is dead, also
424 * disconnect. We also explicitly check for POLLHUP here since we likely won't notice the write side
425 * being down if we never wrote anything. */
426 if (v
->state
== VARLINK_IDLE_CLIENT
&& (v
->write_disconnected
|| v
->got_pollhup
))
429 /* We are on the server side and still want to send out more replies, but we saw POLLHUP already, and
430 * either got no buffered bytes to write anymore or already saw a write error. In that case we should
431 * shut down the varlink link. */
432 if (IN_SET(v
->state
, VARLINK_PENDING_METHOD
, VARLINK_PENDING_METHOD_MORE
) && (v
->write_disconnected
|| v
->output_buffer_size
== 0) && v
->got_pollhup
)
438 varlink_set_state(v
, VARLINK_PENDING_DISCONNECT
);
442 static int varlink_write(Varlink
*v
) {
447 if (!VARLINK_STATE_IS_ALIVE(v
->state
))
449 if (v
->connecting
) /* Writing while we are still wait for a non-blocking connect() to complete will
450 * result in ENOTCONN, hence exit early here */
452 if (v
->output_buffer_size
== 0)
454 if (v
->write_disconnected
)
459 /* We generally prefer recv()/send() (mostly because of MSG_NOSIGNAL) but also want to be compatible
460 * with non-socket IO, hence fall back automatically.
462 * Use a local variable to help gcc figure out that we set 'n' in all cases. */
463 bool prefer_write
= v
->prefer_read_write
;
465 n
= send(v
->fd
, v
->output_buffer
+ v
->output_buffer_index
, v
->output_buffer_size
, MSG_DONTWAIT
|MSG_NOSIGNAL
);
466 if (n
< 0 && errno
== ENOTSOCK
)
467 prefer_write
= v
->prefer_read_write
= true;
470 n
= write(v
->fd
, v
->output_buffer
+ v
->output_buffer_index
, v
->output_buffer_size
);
475 if (ERRNO_IS_DISCONNECT(errno
)) {
476 /* If we get informed about a disconnect on write, then let's remember that, but not
477 * act on it just yet. Let's wait for read() to report the issue first. */
478 v
->write_disconnected
= true;
485 v
->output_buffer_size
-= n
;
487 if (v
->output_buffer_size
== 0)
488 v
->output_buffer_index
= 0;
490 v
->output_buffer_index
+= n
;
492 v
->timestamp
= now(CLOCK_MONOTONIC
);
496 static int varlink_read(Varlink
*v
) {
502 if (!IN_SET(v
->state
, VARLINK_AWAITING_REPLY
, VARLINK_AWAITING_REPLY_MORE
, VARLINK_CALLING
, VARLINK_IDLE_SERVER
))
504 if (v
->connecting
) /* read() on a socket while we are in connect() will fail with EINVAL, hence exit early here */
508 if (v
->input_buffer_unscanned
> 0)
510 if (v
->read_disconnected
)
513 if (v
->input_buffer_size
>= VARLINK_BUFFER_MAX
)
518 if (MALLOC_SIZEOF_SAFE(v
->input_buffer
) <= v
->input_buffer_index
+ v
->input_buffer_size
) {
521 add
= MIN(VARLINK_BUFFER_MAX
- v
->input_buffer_size
, VARLINK_READ_SIZE
);
523 if (v
->input_buffer_index
== 0) {
525 if (!GREEDY_REALLOC(v
->input_buffer
, v
->input_buffer_size
+ add
))
531 b
= new(char, v
->input_buffer_size
+ add
);
535 memcpy(b
, v
->input_buffer
+ v
->input_buffer_index
, v
->input_buffer_size
);
537 free_and_replace(v
->input_buffer
, b
);
538 v
->input_buffer_index
= 0;
542 rs
= MALLOC_SIZEOF_SAFE(v
->input_buffer
) - (v
->input_buffer_index
+ v
->input_buffer_size
);
544 bool prefer_read
= v
->prefer_read_write
;
546 n
= recv(v
->fd
, v
->input_buffer
+ v
->input_buffer_index
+ v
->input_buffer_size
, rs
, MSG_DONTWAIT
);
547 if (n
< 0 && errno
== ENOTSOCK
)
548 prefer_read
= v
->prefer_read_write
= true;
551 n
= read(v
->fd
, v
->input_buffer
+ v
->input_buffer_index
+ v
->input_buffer_size
, rs
);
556 if (ERRNO_IS_DISCONNECT(errno
)) {
557 v
->read_disconnected
= true;
563 if (n
== 0) { /* EOF */
564 v
->read_disconnected
= true;
568 v
->input_buffer_size
+= n
;
569 v
->input_buffer_unscanned
+= n
;
574 static int varlink_parse_message(Varlink
*v
) {
575 const char *e
, *begin
;
583 if (v
->input_buffer_unscanned
<= 0)
586 assert(v
->input_buffer_unscanned
<= v
->input_buffer_size
);
587 assert(v
->input_buffer_index
+ v
->input_buffer_size
<= MALLOC_SIZEOF_SAFE(v
->input_buffer
));
589 begin
= v
->input_buffer
+ v
->input_buffer_index
;
591 e
= memchr(begin
+ v
->input_buffer_size
- v
->input_buffer_unscanned
, 0, v
->input_buffer_unscanned
);
593 v
->input_buffer_unscanned
= 0;
599 varlink_log(v
, "New incoming message: %s", begin
); /* FIXME: should we output the whole message here before validation?
600 * This may produce a non-printable journal entry if the message
601 * is invalid. We may also expose privileged information. */
603 r
= json_parse(begin
, 0, &v
->current
, NULL
, NULL
);
605 /* If we encounter a parse failure flush all data. We cannot possibly recover from this,
606 * hence drop all buffered data now. */
607 v
->input_buffer_index
= v
->input_buffer_size
= v
->input_buffer_unscanned
= 0;
608 return varlink_log_errno(v
, r
, "Failed to parse JSON: %m");
611 v
->input_buffer_size
-= sz
;
613 if (v
->input_buffer_size
== 0)
614 v
->input_buffer_index
= 0;
616 v
->input_buffer_index
+= sz
;
618 v
->input_buffer_unscanned
= v
->input_buffer_size
;
622 static int varlink_test_timeout(Varlink
*v
) {
625 if (!IN_SET(v
->state
, VARLINK_AWAITING_REPLY
, VARLINK_AWAITING_REPLY_MORE
, VARLINK_CALLING
))
627 if (v
->timeout
== USEC_INFINITY
)
630 if (now(CLOCK_MONOTONIC
) < usec_add(v
->timestamp
, v
->timeout
))
633 varlink_set_state(v
, VARLINK_PENDING_TIMEOUT
);
638 static int varlink_dispatch_local_error(Varlink
*v
, const char *error
) {
644 if (!v
->reply_callback
)
647 r
= v
->reply_callback(v
, NULL
, error
, VARLINK_REPLY_ERROR
|VARLINK_REPLY_LOCAL
, v
->userdata
);
649 log_debug_errno(r
, "Reply callback returned error, ignoring: %m");
654 static int varlink_dispatch_timeout(Varlink
*v
) {
657 if (v
->state
!= VARLINK_PENDING_TIMEOUT
)
660 varlink_set_state(v
, VARLINK_PROCESSING_TIMEOUT
);
661 varlink_dispatch_local_error(v
, VARLINK_ERROR_TIMEOUT
);
667 static int varlink_dispatch_disconnect(Varlink
*v
) {
670 if (v
->state
!= VARLINK_PENDING_DISCONNECT
)
673 varlink_set_state(v
, VARLINK_PROCESSING_DISCONNECT
);
674 varlink_dispatch_local_error(v
, VARLINK_ERROR_DISCONNECTED
);
680 static int varlink_sanitize_parameters(JsonVariant
**v
) {
683 /* Varlink always wants a parameters list, hence make one if the caller doesn't want any */
685 return json_variant_new_object(v
, NULL
, 0);
686 else if (!json_variant_is_object(*v
))
692 static int varlink_dispatch_reply(Varlink
*v
) {
693 _cleanup_(json_variant_unrefp
) JsonVariant
*parameters
= NULL
;
694 VarlinkReplyFlags flags
= 0;
695 const char *error
= NULL
;
702 if (!IN_SET(v
->state
, VARLINK_AWAITING_REPLY
, VARLINK_AWAITING_REPLY_MORE
, VARLINK_CALLING
))
707 assert(v
->n_pending
> 0);
709 if (!json_variant_is_object(v
->current
))
712 JSON_VARIANT_OBJECT_FOREACH(k
, e
, v
->current
) {
714 if (streq(k
, "error")) {
717 if (!json_variant_is_string(e
))
720 error
= json_variant_string(e
);
721 flags
|= VARLINK_REPLY_ERROR
;
723 } else if (streq(k
, "parameters")) {
726 if (!json_variant_is_object(e
))
729 parameters
= json_variant_ref(e
);
731 } else if (streq(k
, "continues")) {
732 if (FLAGS_SET(flags
, VARLINK_REPLY_CONTINUES
))
735 if (!json_variant_is_boolean(e
))
738 if (json_variant_boolean(e
))
739 flags
|= VARLINK_REPLY_CONTINUES
;
744 /* Replies with 'continue' set are only OK if we set 'more' when the method call was initiated */
745 if (v
->state
!= VARLINK_AWAITING_REPLY_MORE
&& FLAGS_SET(flags
, VARLINK_REPLY_CONTINUES
))
748 /* An error is final */
749 if (error
&& FLAGS_SET(flags
, VARLINK_REPLY_CONTINUES
))
752 r
= varlink_sanitize_parameters(¶meters
);
756 if (IN_SET(v
->state
, VARLINK_AWAITING_REPLY
, VARLINK_AWAITING_REPLY_MORE
)) {
757 varlink_set_state(v
, VARLINK_PROCESSING_REPLY
);
759 if (v
->reply_callback
) {
760 r
= v
->reply_callback(v
, parameters
, error
, flags
, v
->userdata
);
762 log_debug_errno(r
, "Reply callback returned error, ignoring: %m");
765 v
->current
= json_variant_unref(v
->current
);
767 if (v
->state
== VARLINK_PROCESSING_REPLY
) {
769 assert(v
->n_pending
> 0);
771 if (!FLAGS_SET(flags
, VARLINK_REPLY_CONTINUES
))
775 FLAGS_SET(flags
, VARLINK_REPLY_CONTINUES
) ? VARLINK_AWAITING_REPLY_MORE
:
776 v
->n_pending
== 0 ? VARLINK_IDLE_CLIENT
: VARLINK_AWAITING_REPLY
);
779 assert(v
->state
== VARLINK_CALLING
);
780 varlink_set_state(v
, VARLINK_CALLED
);
786 varlink_set_state(v
, VARLINK_PROCESSING_FAILURE
);
787 varlink_dispatch_local_error(v
, VARLINK_ERROR_PROTOCOL
);
793 static int varlink_dispatch_method(Varlink
*v
) {
794 _cleanup_(json_variant_unrefp
) JsonVariant
*parameters
= NULL
;
795 VarlinkMethodFlags flags
= 0;
796 const char *method
= NULL
, *error
;
798 VarlinkMethod callback
;
804 if (v
->state
!= VARLINK_IDLE_SERVER
)
809 if (!json_variant_is_object(v
->current
))
812 JSON_VARIANT_OBJECT_FOREACH(k
, e
, v
->current
) {
814 if (streq(k
, "method")) {
817 if (!json_variant_is_string(e
))
820 method
= json_variant_string(e
);
822 } else if (streq(k
, "parameters")) {
825 if (!json_variant_is_object(e
))
828 parameters
= json_variant_ref(e
);
830 } else if (streq(k
, "oneway")) {
832 if ((flags
& (VARLINK_METHOD_ONEWAY
|VARLINK_METHOD_MORE
)) != 0)
835 if (!json_variant_is_boolean(e
))
838 if (json_variant_boolean(e
))
839 flags
|= VARLINK_METHOD_ONEWAY
;
841 } else if (streq(k
, "more")) {
843 if ((flags
& (VARLINK_METHOD_ONEWAY
|VARLINK_METHOD_MORE
)) != 0)
846 if (!json_variant_is_boolean(e
))
849 if (json_variant_boolean(e
))
850 flags
|= VARLINK_METHOD_MORE
;
859 r
= varlink_sanitize_parameters(¶meters
);
863 varlink_set_state(v
, (flags
& VARLINK_METHOD_MORE
) ? VARLINK_PROCESSING_METHOD_MORE
:
864 (flags
& VARLINK_METHOD_ONEWAY
) ? VARLINK_PROCESSING_METHOD_ONEWAY
:
865 VARLINK_PROCESSING_METHOD
);
869 if (STR_IN_SET(method
, "org.varlink.service.GetInfo", "org.varlink.service.GetInterface")) {
870 /* For now, we don't implement a single of varlink's own methods */
872 error
= VARLINK_ERROR_METHOD_NOT_IMPLEMENTED
;
873 } else if (startswith(method
, "org.varlink.service.")) {
875 error
= VARLINK_ERROR_METHOD_NOT_FOUND
;
877 callback
= hashmap_get(v
->server
->methods
, method
);
878 error
= VARLINK_ERROR_METHOD_NOT_FOUND
;
882 r
= callback(v
, parameters
, flags
, v
->userdata
);
884 log_debug_errno(r
, "Callback for %s returned error: %m", method
);
886 /* We got an error back from the callback. Propagate it to the client if the method call remains unanswered. */
887 if (!FLAGS_SET(flags
, VARLINK_METHOD_ONEWAY
)) {
888 r
= varlink_error_errno(v
, r
);
893 } else if (!FLAGS_SET(flags
, VARLINK_METHOD_ONEWAY
)) {
896 r
= varlink_errorb(v
, error
, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method
))));
903 case VARLINK_PROCESSED_METHOD
: /* Method call is fully processed */
904 case VARLINK_PROCESSING_METHOD_ONEWAY
: /* ditto */
905 v
->current
= json_variant_unref(v
->current
);
906 varlink_set_state(v
, VARLINK_IDLE_SERVER
);
909 case VARLINK_PROCESSING_METHOD
: /* Method call wasn't replied to, will be replied to later */
910 varlink_set_state(v
, VARLINK_PENDING_METHOD
);
913 case VARLINK_PROCESSING_METHOD_MORE
: /* No reply for a "more" message was sent, more to come */
914 varlink_set_state(v
, VARLINK_PENDING_METHOD_MORE
);
918 assert_not_reached();
928 varlink_set_state(v
, VARLINK_PROCESSING_FAILURE
);
929 varlink_dispatch_local_error(v
, VARLINK_ERROR_PROTOCOL
);
935 int varlink_process(Varlink
*v
) {
938 assert_return(v
, -EINVAL
);
940 if (v
->state
== VARLINK_DISCONNECTED
)
941 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENOTCONN
), "Not connected.");
945 r
= varlink_write(v
);
947 varlink_log_errno(v
, r
, "Write failed: %m");
951 r
= varlink_dispatch_reply(v
);
953 varlink_log_errno(v
, r
, "Reply dispatch failed: %m");
957 r
= varlink_dispatch_method(v
);
959 varlink_log_errno(v
, r
, "Method dispatch failed: %m");
963 r
= varlink_parse_message(v
);
965 varlink_log_errno(v
, r
, "Message parsing failed: %m");
971 varlink_log_errno(v
, r
, "Read failed: %m");
975 r
= varlink_test_disconnect(v
);
980 r
= varlink_dispatch_disconnect(v
);
985 r
= varlink_test_timeout(v
);
990 r
= varlink_dispatch_timeout(v
);
996 if (r
>= 0 && v
->defer_event_source
) {
999 /* If we did some processing, make sure we are called again soon */
1000 q
= sd_event_source_set_enabled(v
->defer_event_source
, r
> 0 ? SD_EVENT_ON
: SD_EVENT_OFF
);
1002 r
= varlink_log_errno(v
, q
, "Failed to enable deferred event source: %m");
1006 if (VARLINK_STATE_IS_ALIVE(v
->state
))
1007 /* Initiate disconnection */
1008 varlink_set_state(v
, VARLINK_PENDING_DISCONNECT
);
1010 /* We failed while disconnecting, in that case close right away */
1018 static void handle_revents(Varlink
*v
, int revents
) {
1021 if (v
->connecting
) {
1022 /* If we have seen POLLOUT or POLLHUP on a socket we are asynchronously waiting a connect()
1023 * to complete on, we know we are ready. We don't read the connection error here though,
1024 * we'll get the error on the next read() or write(). */
1025 if ((revents
& (POLLOUT
|POLLHUP
)) == 0)
1028 varlink_log(v
, "Asynchronous connection completed.");
1029 v
->connecting
= false;
1031 /* Note that we don't care much about POLLIN/POLLOUT here, we'll just try reading and writing
1032 * what we can. However, we do care about POLLHUP to detect connection termination even if we
1033 * momentarily don't want to read nor write anything. */
1035 if (!FLAGS_SET(revents
, POLLHUP
))
1038 varlink_log(v
, "Got POLLHUP from socket.");
1039 v
->got_pollhup
= true;
1043 int varlink_wait(Varlink
*v
, usec_t timeout
) {
1047 assert_return(v
, -EINVAL
);
1049 if (v
->state
== VARLINK_DISCONNECTED
)
1050 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENOTCONN
), "Not connected.");
1052 r
= varlink_get_timeout(v
, &t
);
1055 if (t
!= USEC_INFINITY
) {
1058 n
= now(CLOCK_MONOTONIC
);
1062 t
= usec_sub_unsigned(t
, n
);
1065 if (timeout
!= USEC_INFINITY
&&
1066 (t
== USEC_INFINITY
|| timeout
< t
))
1069 fd
= varlink_get_fd(v
);
1073 events
= varlink_get_events(v
);
1077 r
= fd_wait_for_event(fd
, events
, t
);
1078 if (r
< 0 && ERRNO_IS_TRANSIENT(r
)) /* Treat EINTR as not a timeout, but also nothing happened, and
1079 * the caller gets a chance to call back into us */
1084 handle_revents(v
, r
);
1088 int varlink_get_fd(Varlink
*v
) {
1090 assert_return(v
, -EINVAL
);
1092 if (v
->state
== VARLINK_DISCONNECTED
)
1093 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENOTCONN
), "Not connected.");
1095 return varlink_log_errno(v
, SYNTHETIC_ERRNO(EBADF
), "No valid fd.");
1100 int varlink_get_events(Varlink
*v
) {
1103 assert_return(v
, -EINVAL
);
1105 if (v
->state
== VARLINK_DISCONNECTED
)
1106 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENOTCONN
), "Not connected.");
1108 if (v
->connecting
) /* When processing an asynchronous connect(), we only wait for EPOLLOUT, which
1109 * tells us that the connection is now complete. Before that we should neither
1110 * write() or read() from the fd. */
1113 if (!v
->read_disconnected
&&
1114 IN_SET(v
->state
, VARLINK_AWAITING_REPLY
, VARLINK_AWAITING_REPLY_MORE
, VARLINK_CALLING
, VARLINK_IDLE_SERVER
) &&
1116 v
->input_buffer_unscanned
<= 0)
1119 if (!v
->write_disconnected
&&
1120 v
->output_buffer_size
> 0)
1126 int varlink_get_timeout(Varlink
*v
, usec_t
*ret
) {
1127 assert_return(v
, -EINVAL
);
1129 if (v
->state
== VARLINK_DISCONNECTED
)
1130 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENOTCONN
), "Not connected.");
1132 if (IN_SET(v
->state
, VARLINK_AWAITING_REPLY
, VARLINK_AWAITING_REPLY_MORE
, VARLINK_CALLING
) &&
1133 v
->timeout
!= USEC_INFINITY
) {
1135 *ret
= usec_add(v
->timestamp
, v
->timeout
);
1139 *ret
= USEC_INFINITY
;
1144 int varlink_flush(Varlink
*v
) {
1147 assert_return(v
, -EINVAL
);
1149 if (v
->state
== VARLINK_DISCONNECTED
)
1150 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENOTCONN
), "Not connected.");
1153 if (v
->output_buffer_size
== 0)
1155 if (v
->write_disconnected
)
1158 r
= varlink_write(v
);
1166 r
= fd_wait_for_event(v
->fd
, POLLOUT
, USEC_INFINITY
);
1168 if (ERRNO_IS_TRANSIENT(r
))
1171 return varlink_log_errno(v
, r
, "Poll failed on fd: %m");
1176 handle_revents(v
, r
);
1182 static void varlink_detach_server(Varlink
*v
) {
1183 VarlinkServer
*saved_server
;
1189 if (v
->server
->by_uid
&&
1190 v
->ucred_acquired
&&
1191 uid_is_valid(v
->ucred
.uid
)) {
1194 c
= PTR_TO_UINT(hashmap_get(v
->server
->by_uid
, UID_TO_PTR(v
->ucred
.uid
)));
1198 (void) hashmap_remove(v
->server
->by_uid
, UID_TO_PTR(v
->ucred
.uid
));
1200 (void) hashmap_replace(v
->server
->by_uid
, UID_TO_PTR(v
->ucred
.uid
), UINT_TO_PTR(c
- 1));
1203 assert(v
->server
->n_connections
> 0);
1204 v
->server
->n_connections
--;
1206 /* If this is a connection associated to a server, then let's disconnect the server and the
1207 * connection from each other. This drops the dangling reference that connect_callback() set up. But
1208 * before we release the references, let's call the disconnection callback if it is defined. */
1210 saved_server
= TAKE_PTR(v
->server
);
1212 if (saved_server
->disconnect_callback
)
1213 saved_server
->disconnect_callback(saved_server
, v
, saved_server
->userdata
);
1215 varlink_server_unref(saved_server
);
1219 int varlink_close(Varlink
*v
) {
1220 assert_return(v
, -EINVAL
);
1222 if (v
->state
== VARLINK_DISCONNECTED
)
1225 varlink_set_state(v
, VARLINK_DISCONNECTED
);
1227 /* Let's take a reference first, since varlink_detach_server() might drop the final (dangling) ref
1228 * which would destroy us before we can call varlink_clear() */
1230 varlink_detach_server(v
);
1237 Varlink
* varlink_close_unref(Varlink
*v
) {
1241 (void) varlink_close(v
);
1242 return varlink_unref(v
);
1245 Varlink
* varlink_flush_close_unref(Varlink
*v
) {
1249 (void) varlink_flush(v
);
1250 return varlink_close_unref(v
);
1253 static int varlink_enqueue_json(Varlink
*v
, JsonVariant
*m
) {
1254 _cleanup_free_
char *text
= NULL
;
1260 r
= json_variant_format(m
, 0, &text
);
1263 assert(text
[r
] == '\0');
1265 if (v
->output_buffer_size
+ r
+ 1 > VARLINK_BUFFER_MAX
)
1268 varlink_log(v
, "Sending message: %s", text
);
1270 if (v
->output_buffer_size
== 0) {
1272 free_and_replace(v
->output_buffer
, text
);
1274 v
->output_buffer_size
= r
+ 1;
1275 v
->output_buffer_index
= 0;
1277 } else if (v
->output_buffer_index
== 0) {
1279 if (!GREEDY_REALLOC(v
->output_buffer
, v
->output_buffer_size
+ r
+ 1))
1282 memcpy(v
->output_buffer
+ v
->output_buffer_size
, text
, r
+ 1);
1283 v
->output_buffer_size
+= r
+ 1;
1287 const size_t new_size
= v
->output_buffer_size
+ r
+ 1;
1289 n
= new(char, new_size
);
1293 memcpy(mempcpy(n
, v
->output_buffer
+ v
->output_buffer_index
, v
->output_buffer_size
), text
, r
+ 1);
1295 free_and_replace(v
->output_buffer
, n
);
1296 v
->output_buffer_size
= new_size
;
1297 v
->output_buffer_index
= 0;
1303 int varlink_send(Varlink
*v
, const char *method
, JsonVariant
*parameters
) {
1304 _cleanup_(json_variant_unrefp
) JsonVariant
*m
= NULL
;
1307 assert_return(v
, -EINVAL
);
1308 assert_return(method
, -EINVAL
);
1310 if (v
->state
== VARLINK_DISCONNECTED
)
1311 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENOTCONN
), "Not connected.");
1313 /* We allow enqueuing multiple method calls at once! */
1314 if (!IN_SET(v
->state
, VARLINK_IDLE_CLIENT
, VARLINK_AWAITING_REPLY
))
1315 return varlink_log_errno(v
, SYNTHETIC_ERRNO(EBUSY
), "Connection busy.");
1317 r
= varlink_sanitize_parameters(¶meters
);
1319 return varlink_log_errno(v
, r
, "Failed to sanitize parameters: %m");
1321 r
= json_build(&m
, JSON_BUILD_OBJECT(
1322 JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method
)),
1323 JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters
)),
1324 JSON_BUILD_PAIR("oneway", JSON_BUILD_BOOLEAN(true))));
1326 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1328 r
= varlink_enqueue_json(v
, m
);
1330 return varlink_log_errno(v
, r
, "Failed to enqueue json message: %m");
1332 /* No state change here, this is one-way only after all */
1333 v
->timestamp
= now(CLOCK_MONOTONIC
);
1337 int varlink_sendb(Varlink
*v
, const char *method
, ...) {
1338 _cleanup_(json_variant_unrefp
) JsonVariant
*parameters
= NULL
;
1342 assert_return(v
, -EINVAL
);
1344 va_start(ap
, method
);
1345 r
= json_buildv(¶meters
, ap
);
1349 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1351 return varlink_send(v
, method
, parameters
);
1354 int varlink_invoke(Varlink
*v
, const char *method
, JsonVariant
*parameters
) {
1355 _cleanup_(json_variant_unrefp
) JsonVariant
*m
= NULL
;
1358 assert_return(v
, -EINVAL
);
1359 assert_return(method
, -EINVAL
);
1361 if (v
->state
== VARLINK_DISCONNECTED
)
1362 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENOTCONN
), "Not connected.");
1364 /* We allow enqueuing multiple method calls at once! */
1365 if (!IN_SET(v
->state
, VARLINK_IDLE_CLIENT
, VARLINK_AWAITING_REPLY
))
1366 return varlink_log_errno(v
, SYNTHETIC_ERRNO(EBUSY
), "Connection busy.");
1368 r
= varlink_sanitize_parameters(¶meters
);
1370 return varlink_log_errno(v
, r
, "Failed to sanitize parameters: %m");
1372 r
= json_build(&m
, JSON_BUILD_OBJECT(
1373 JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method
)),
1374 JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters
))));
1376 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1378 r
= varlink_enqueue_json(v
, m
);
1380 return varlink_log_errno(v
, r
, "Failed to enqueue json message: %m");
1382 varlink_set_state(v
, VARLINK_AWAITING_REPLY
);
1384 v
->timestamp
= now(CLOCK_MONOTONIC
);
1389 int varlink_invokeb(Varlink
*v
, const char *method
, ...) {
1390 _cleanup_(json_variant_unrefp
) JsonVariant
*parameters
= NULL
;
1394 assert_return(v
, -EINVAL
);
1396 va_start(ap
, method
);
1397 r
= json_buildv(¶meters
, ap
);
1401 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1403 return varlink_invoke(v
, method
, parameters
);
1406 int varlink_observe(Varlink
*v
, const char *method
, JsonVariant
*parameters
) {
1407 _cleanup_(json_variant_unrefp
) JsonVariant
*m
= NULL
;
1410 assert_return(v
, -EINVAL
);
1411 assert_return(method
, -EINVAL
);
1413 if (v
->state
== VARLINK_DISCONNECTED
)
1414 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENOTCONN
), "Not connected.");
1416 /* Note that we don't allow enqueuing multiple method calls when we are in more/continues mode! We
1417 * thus insist on an idle client here. */
1418 if (v
->state
!= VARLINK_IDLE_CLIENT
)
1419 return varlink_log_errno(v
, SYNTHETIC_ERRNO(EBUSY
), "Connection busy.");
1421 r
= varlink_sanitize_parameters(¶meters
);
1423 return varlink_log_errno(v
, r
, "Failed to sanitize parameters: %m");
1425 r
= json_build(&m
, JSON_BUILD_OBJECT(
1426 JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method
)),
1427 JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters
)),
1428 JSON_BUILD_PAIR("more", JSON_BUILD_BOOLEAN(true))));
1430 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1432 r
= varlink_enqueue_json(v
, m
);
1434 return varlink_log_errno(v
, r
, "Failed to enqueue json message: %m");
1436 varlink_set_state(v
, VARLINK_AWAITING_REPLY_MORE
);
1438 v
->timestamp
= now(CLOCK_MONOTONIC
);
1443 int varlink_observeb(Varlink
*v
, const char *method
, ...) {
1444 _cleanup_(json_variant_unrefp
) JsonVariant
*parameters
= NULL
;
1448 assert_return(v
, -EINVAL
);
1450 va_start(ap
, method
);
1451 r
= json_buildv(¶meters
, ap
);
1455 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1457 return varlink_observe(v
, method
, parameters
);
1463 JsonVariant
*parameters
,
1464 JsonVariant
**ret_parameters
,
1465 const char **ret_error_id
,
1466 VarlinkReplyFlags
*ret_flags
) {
1468 _cleanup_(json_variant_unrefp
) JsonVariant
*m
= NULL
;
1471 assert_return(v
, -EINVAL
);
1472 assert_return(method
, -EINVAL
);
1474 if (v
->state
== VARLINK_DISCONNECTED
)
1475 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENOTCONN
), "Not connected.");
1476 if (v
->state
!= VARLINK_IDLE_CLIENT
)
1477 return varlink_log_errno(v
, SYNTHETIC_ERRNO(EBUSY
), "Connection busy.");
1479 assert(v
->n_pending
== 0); /* n_pending can't be > 0 if we are in VARLINK_IDLE_CLIENT state */
1481 r
= varlink_sanitize_parameters(¶meters
);
1483 return varlink_log_errno(v
, r
, "Failed to sanitize parameters: %m");
1485 r
= json_build(&m
, JSON_BUILD_OBJECT(
1486 JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method
)),
1487 JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters
))));
1489 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1491 r
= varlink_enqueue_json(v
, m
);
1493 return varlink_log_errno(v
, r
, "Failed to enqueue json message: %m");
1495 varlink_set_state(v
, VARLINK_CALLING
);
1497 v
->timestamp
= now(CLOCK_MONOTONIC
);
1499 while (v
->state
== VARLINK_CALLING
) {
1501 r
= varlink_process(v
);
1507 r
= varlink_wait(v
, USEC_INFINITY
);
1514 case VARLINK_CALLED
:
1517 json_variant_unref(v
->reply
);
1518 v
->reply
= TAKE_PTR(v
->current
);
1520 varlink_set_state(v
, VARLINK_IDLE_CLIENT
);
1521 assert(v
->n_pending
== 1);
1525 *ret_parameters
= json_variant_by_key(v
->reply
, "parameters");
1527 *ret_error_id
= json_variant_string(json_variant_by_key(v
->reply
, "error"));
1533 case VARLINK_PENDING_DISCONNECT
:
1534 case VARLINK_DISCONNECTED
:
1535 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ECONNRESET
), "Connection was closed.");
1537 case VARLINK_PENDING_TIMEOUT
:
1538 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ETIME
), "Connection timed out.");
1541 assert_not_reached();
1548 JsonVariant
**ret_parameters
,
1549 const char **ret_error_id
,
1550 VarlinkReplyFlags
*ret_flags
, ...) {
1552 _cleanup_(json_variant_unrefp
) JsonVariant
*parameters
= NULL
;
1556 assert_return(v
, -EINVAL
);
1558 va_start(ap
, ret_flags
);
1559 r
= json_buildv(¶meters
, ap
);
1563 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1565 return varlink_call(v
, method
, parameters
, ret_parameters
, ret_error_id
, ret_flags
);
1568 int varlink_reply(Varlink
*v
, JsonVariant
*parameters
) {
1569 _cleanup_(json_variant_unrefp
) JsonVariant
*m
= NULL
;
1572 assert_return(v
, -EINVAL
);
1574 if (v
->state
== VARLINK_DISCONNECTED
)
1576 if (!IN_SET(v
->state
,
1577 VARLINK_PROCESSING_METHOD
, VARLINK_PROCESSING_METHOD_MORE
,
1578 VARLINK_PENDING_METHOD
, VARLINK_PENDING_METHOD_MORE
))
1581 r
= varlink_sanitize_parameters(¶meters
);
1583 return varlink_log_errno(v
, r
, "Failed to sanitize parameters: %m");
1585 r
= json_build(&m
, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters
))));
1587 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1589 r
= varlink_enqueue_json(v
, m
);
1591 return varlink_log_errno(v
, r
, "Failed to enqueue json message: %m");
1593 if (IN_SET(v
->state
, VARLINK_PENDING_METHOD
, VARLINK_PENDING_METHOD_MORE
)) {
1594 /* We just replied to a method call that was let hanging for a while (i.e. we were outside of
1595 * the varlink_dispatch_method() stack frame), which means with this reply we are ready to
1596 * process further messages. */
1597 v
->current
= json_variant_unref(v
->current
);
1598 varlink_set_state(v
, VARLINK_IDLE_SERVER
);
1600 /* We replied to a method call from within the varlink_dispatch_method() stack frame), which
1601 * means we should it handle the rest of the state engine. */
1602 varlink_set_state(v
, VARLINK_PROCESSED_METHOD
);
1607 int varlink_replyb(Varlink
*v
, ...) {
1608 _cleanup_(json_variant_unrefp
) JsonVariant
*parameters
= NULL
;
1612 assert_return(v
, -EINVAL
);
1615 r
= json_buildv(¶meters
, ap
);
1621 return varlink_reply(v
, parameters
);
1624 int varlink_error(Varlink
*v
, const char *error_id
, JsonVariant
*parameters
) {
1625 _cleanup_(json_variant_unrefp
) JsonVariant
*m
= NULL
;
1628 assert_return(v
, -EINVAL
);
1629 assert_return(error_id
, -EINVAL
);
1631 if (v
->state
== VARLINK_DISCONNECTED
)
1632 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENOTCONN
), "Not connected.");
1633 if (!IN_SET(v
->state
,
1634 VARLINK_PROCESSING_METHOD
, VARLINK_PROCESSING_METHOD_MORE
,
1635 VARLINK_PENDING_METHOD
, VARLINK_PENDING_METHOD_MORE
))
1636 return varlink_log_errno(v
, SYNTHETIC_ERRNO(EBUSY
), "Connection busy.");
1638 r
= varlink_sanitize_parameters(¶meters
);
1640 return varlink_log_errno(v
, r
, "Failed to sanitize parameters: %m");
1642 r
= json_build(&m
, JSON_BUILD_OBJECT(
1643 JSON_BUILD_PAIR("error", JSON_BUILD_STRING(error_id
)),
1644 JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters
))));
1646 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1648 r
= varlink_enqueue_json(v
, m
);
1650 return varlink_log_errno(v
, r
, "Failed to enqueue json message: %m");
1652 if (IN_SET(v
->state
, VARLINK_PENDING_METHOD
, VARLINK_PENDING_METHOD_MORE
)) {
1653 v
->current
= json_variant_unref(v
->current
);
1654 varlink_set_state(v
, VARLINK_IDLE_SERVER
);
1656 varlink_set_state(v
, VARLINK_PROCESSED_METHOD
);
1661 int varlink_errorb(Varlink
*v
, const char *error_id
, ...) {
1662 _cleanup_(json_variant_unrefp
) JsonVariant
*parameters
= NULL
;
1666 assert_return(v
, -EINVAL
);
1667 assert_return(error_id
, -EINVAL
);
1669 va_start(ap
, error_id
);
1670 r
= json_buildv(¶meters
, ap
);
1674 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1676 return varlink_error(v
, error_id
, parameters
);
1679 int varlink_error_invalid_parameter(Varlink
*v
, JsonVariant
*parameters
) {
1682 assert_return(v
, -EINVAL
);
1683 assert_return(parameters
, -EINVAL
);
1685 /* We expect to be called in one of two ways: the 'parameters' argument is a string variant in which
1686 * case it is the parameter key name that is invalid. Or the 'parameters' argument is an object
1687 * variant in which case we'll pull out the first key. The latter mode is useful in functions that
1688 * don't expect any arguments. */
1690 /* varlink_error(...) expects a json object as the third parameter. Passing a string variant causes
1691 * parameter sanitization to fail, and it returns -EINVAL. */
1693 if (json_variant_is_string(parameters
)) {
1694 _cleanup_(json_variant_unrefp
) JsonVariant
*parameters_obj
= NULL
;
1696 r
= json_build(¶meters_obj
,
1698 JSON_BUILD_PAIR("parameter", JSON_BUILD_VARIANT(parameters
))));
1702 return varlink_error(v
, VARLINK_ERROR_INVALID_PARAMETER
, parameters_obj
);
1705 if (json_variant_is_object(parameters
) &&
1706 json_variant_elements(parameters
) > 0) {
1707 _cleanup_(json_variant_unrefp
) JsonVariant
*parameters_obj
= NULL
;
1709 r
= json_build(¶meters_obj
,
1711 JSON_BUILD_PAIR("parameter", JSON_BUILD_VARIANT(json_variant_by_index(parameters
, 0)))));
1715 return varlink_error(v
, VARLINK_ERROR_INVALID_PARAMETER
, parameters_obj
);
1721 int varlink_error_errno(Varlink
*v
, int error
) {
1722 return varlink_errorb(
1724 VARLINK_ERROR_SYSTEM
,
1725 JSON_BUILD_OBJECT(JSON_BUILD_PAIR("errno", JSON_BUILD_INTEGER(abs(error
)))));
1728 int varlink_notify(Varlink
*v
, JsonVariant
*parameters
) {
1729 _cleanup_(json_variant_unrefp
) JsonVariant
*m
= NULL
;
1732 assert_return(v
, -EINVAL
);
1734 if (v
->state
== VARLINK_DISCONNECTED
)
1735 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENOTCONN
), "Not connected.");
1736 if (!IN_SET(v
->state
, VARLINK_PROCESSING_METHOD_MORE
, VARLINK_PENDING_METHOD_MORE
))
1737 return varlink_log_errno(v
, SYNTHETIC_ERRNO(EBUSY
), "Connection busy.");
1739 r
= varlink_sanitize_parameters(¶meters
);
1741 return varlink_log_errno(v
, r
, "Failed to sanitize parameters: %m");
1743 r
= json_build(&m
, JSON_BUILD_OBJECT(
1744 JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters
)),
1745 JSON_BUILD_PAIR("continues", JSON_BUILD_BOOLEAN(true))));
1747 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1749 r
= varlink_enqueue_json(v
, m
);
1751 return varlink_log_errno(v
, r
, "Failed to enqueue json message: %m");
1753 /* No state change, as more is coming */
1757 int varlink_notifyb(Varlink
*v
, ...) {
1758 _cleanup_(json_variant_unrefp
) JsonVariant
*parameters
= NULL
;
1762 assert_return(v
, -EINVAL
);
1765 r
= json_buildv(¶meters
, ap
);
1769 return varlink_log_errno(v
, r
, "Failed to build json message: %m");
1771 return varlink_notify(v
, parameters
);
1774 int varlink_bind_reply(Varlink
*v
, VarlinkReply callback
) {
1775 assert_return(v
, -EINVAL
);
1777 if (callback
&& v
->reply_callback
&& callback
!= v
->reply_callback
)
1778 return varlink_log_errno(v
, SYNTHETIC_ERRNO(EBUSY
), "A different callback was already set.");
1780 v
->reply_callback
= callback
;
1785 void* varlink_set_userdata(Varlink
*v
, void *userdata
) {
1788 assert_return(v
, NULL
);
1791 v
->userdata
= userdata
;
1796 void* varlink_get_userdata(Varlink
*v
) {
1797 assert_return(v
, NULL
);
1802 static int varlink_acquire_ucred(Varlink
*v
) {
1807 if (v
->ucred_acquired
)
1810 r
= getpeercred(v
->fd
, &v
->ucred
);
1814 v
->ucred_acquired
= true;
1818 int varlink_get_peer_uid(Varlink
*v
, uid_t
*ret
) {
1821 assert_return(v
, -EINVAL
);
1822 assert_return(ret
, -EINVAL
);
1824 r
= varlink_acquire_ucred(v
);
1826 return varlink_log_errno(v
, r
, "Failed to acquire credentials: %m");
1828 if (!uid_is_valid(v
->ucred
.uid
))
1829 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENODATA
), "Peer uid is invalid.");
1831 *ret
= v
->ucred
.uid
;
1835 int varlink_get_peer_pid(Varlink
*v
, pid_t
*ret
) {
1838 assert_return(v
, -EINVAL
);
1839 assert_return(ret
, -EINVAL
);
1841 r
= varlink_acquire_ucred(v
);
1843 return varlink_log_errno(v
, r
, "Failed to acquire credentials: %m");
1845 if (!pid_is_valid(v
->ucred
.pid
))
1846 return varlink_log_errno(v
, SYNTHETIC_ERRNO(ENODATA
), "Peer uid is invalid.");
1848 *ret
= v
->ucred
.pid
;
1852 int varlink_set_relative_timeout(Varlink
*v
, usec_t timeout
) {
1853 assert_return(v
, -EINVAL
);
1854 assert_return(timeout
> 0, -EINVAL
);
1856 v
->timeout
= timeout
;
1860 VarlinkServer
*varlink_get_server(Varlink
*v
) {
1861 assert_return(v
, NULL
);
1866 int varlink_set_description(Varlink
*v
, const char *description
) {
1867 assert_return(v
, -EINVAL
);
1869 return free_and_strdup(&v
->description
, description
);
1872 static int io_callback(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
1873 Varlink
*v
= ASSERT_PTR(userdata
);
1877 handle_revents(v
, revents
);
1878 (void) varlink_process(v
);
1883 static int time_callback(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
1884 Varlink
*v
= ASSERT_PTR(userdata
);
1888 (void) varlink_process(v
);
1892 static int defer_callback(sd_event_source
*s
, void *userdata
) {
1893 Varlink
*v
= ASSERT_PTR(userdata
);
1897 (void) varlink_process(v
);
1901 static int prepare_callback(sd_event_source
*s
, void *userdata
) {
1902 Varlink
*v
= ASSERT_PTR(userdata
);
1909 e
= varlink_get_events(v
);
1913 r
= sd_event_source_set_io_events(v
->io_event_source
, e
);
1915 return varlink_log_errno(v
, r
, "Failed to set source events: %m");
1917 r
= varlink_get_timeout(v
, &until
);
1920 have_timeout
= r
> 0;
1923 r
= sd_event_source_set_time(v
->time_event_source
, until
);
1925 return varlink_log_errno(v
, r
, "Failed to set source time: %m");
1928 r
= sd_event_source_set_enabled(v
->time_event_source
, have_timeout
? SD_EVENT_ON
: SD_EVENT_OFF
);
1930 return varlink_log_errno(v
, r
, "Failed to enable event source: %m");
1935 static int quit_callback(sd_event_source
*event
, void *userdata
) {
1936 Varlink
*v
= ASSERT_PTR(userdata
);
1946 int varlink_attach_event(Varlink
*v
, sd_event
*e
, int64_t priority
) {
1949 assert_return(v
, -EINVAL
);
1950 assert_return(!v
->event
, -EBUSY
);
1953 v
->event
= sd_event_ref(e
);
1955 r
= sd_event_default(&v
->event
);
1957 return varlink_log_errno(v
, r
, "Failed to create event source: %m");
1960 r
= sd_event_add_time(v
->event
, &v
->time_event_source
, CLOCK_MONOTONIC
, 0, 0, time_callback
, v
);
1964 r
= sd_event_source_set_priority(v
->time_event_source
, priority
);
1968 (void) sd_event_source_set_description(v
->time_event_source
, "varlink-time");
1970 r
= sd_event_add_exit(v
->event
, &v
->quit_event_source
, quit_callback
, v
);
1974 r
= sd_event_source_set_priority(v
->quit_event_source
, priority
);
1978 (void) sd_event_source_set_description(v
->quit_event_source
, "varlink-quit");
1980 r
= sd_event_add_io(v
->event
, &v
->io_event_source
, v
->fd
, 0, io_callback
, v
);
1984 r
= sd_event_source_set_prepare(v
->io_event_source
, prepare_callback
);
1988 r
= sd_event_source_set_priority(v
->io_event_source
, priority
);
1992 (void) sd_event_source_set_description(v
->io_event_source
, "varlink-io");
1994 r
= sd_event_add_defer(v
->event
, &v
->defer_event_source
, defer_callback
, v
);
1998 r
= sd_event_source_set_priority(v
->defer_event_source
, priority
);
2002 (void) sd_event_source_set_description(v
->defer_event_source
, "varlink-defer");
2007 varlink_log_errno(v
, r
, "Failed to setup event source: %m");
2008 varlink_detach_event(v
);
2012 void varlink_detach_event(Varlink
*v
) {
2016 varlink_detach_event_sources(v
);
2018 v
->event
= sd_event_unref(v
->event
);
2021 sd_event
*varlink_get_event(Varlink
*v
) {
2022 assert_return(v
, NULL
);
2027 int varlink_server_new(VarlinkServer
**ret
, VarlinkServerFlags flags
) {
2030 assert_return(ret
, -EINVAL
);
2031 assert_return((flags
& ~_VARLINK_SERVER_FLAGS_ALL
) == 0, -EINVAL
);
2033 s
= new(VarlinkServer
, 1);
2035 return log_oom_debug();
2037 *s
= (VarlinkServer
) {
2040 .connections_max
= varlink_server_connections_max(NULL
),
2041 .connections_per_uid_max
= varlink_server_connections_per_uid_max(NULL
),
2048 static VarlinkServer
* varlink_server_destroy(VarlinkServer
*s
) {
2054 varlink_server_shutdown(s
);
2056 while ((m
= hashmap_steal_first_key(s
->methods
)))
2059 hashmap_free(s
->methods
);
2060 hashmap_free(s
->by_uid
);
2062 sd_event_unref(s
->event
);
2064 free(s
->description
);
2069 DEFINE_TRIVIAL_REF_UNREF_FUNC(VarlinkServer
, varlink_server
, varlink_server_destroy
);
2071 static int validate_connection(VarlinkServer
*server
, const struct ucred
*ucred
) {
2077 if (FLAGS_SET(server
->flags
, VARLINK_SERVER_ROOT_ONLY
))
2078 allowed
= ucred
->uid
== 0;
2080 if (FLAGS_SET(server
->flags
, VARLINK_SERVER_MYSELF_ONLY
))
2081 allowed
= allowed
> 0 || ucred
->uid
== getuid();
2083 if (allowed
== 0) { /* Allow access when it is explicitly allowed or when neither
2084 * VARLINK_SERVER_ROOT_ONLY nor VARLINK_SERVER_MYSELF_ONLY are specified. */
2085 varlink_server_log(server
, "Unprivileged client attempted connection, refusing.");
2089 if (server
->n_connections
>= server
->connections_max
) {
2090 varlink_server_log(server
, "Connection limit of %u reached, refusing.", server
->connections_max
);
2094 if (FLAGS_SET(server
->flags
, VARLINK_SERVER_ACCOUNT_UID
)) {
2097 if (!uid_is_valid(ucred
->uid
)) {
2098 varlink_server_log(server
, "Client with invalid UID attempted connection, refusing.");
2102 c
= PTR_TO_UINT(hashmap_get(server
->by_uid
, UID_TO_PTR(ucred
->uid
)));
2103 if (c
>= server
->connections_per_uid_max
) {
2104 varlink_server_log(server
, "Per-UID connection limit of %u reached, refusing.",
2105 server
->connections_per_uid_max
);
2113 static int count_connection(VarlinkServer
*server
, const struct ucred
*ucred
) {
2120 server
->n_connections
++;
2122 if (FLAGS_SET(server
->flags
, VARLINK_SERVER_ACCOUNT_UID
)) {
2123 r
= hashmap_ensure_allocated(&server
->by_uid
, NULL
);
2125 return log_debug_errno(r
, "Failed to allocate UID hash table: %m");
2127 c
= PTR_TO_UINT(hashmap_get(server
->by_uid
, UID_TO_PTR(ucred
->uid
)));
2129 varlink_server_log(server
, "Connections of user " UID_FMT
": %u (of %u max)",
2130 ucred
->uid
, c
, server
->connections_per_uid_max
);
2132 r
= hashmap_replace(server
->by_uid
, UID_TO_PTR(ucred
->uid
), UINT_TO_PTR(c
+ 1));
2134 return log_debug_errno(r
, "Failed to increment counter in UID hash table: %m");
2140 int varlink_server_add_connection(VarlinkServer
*server
, int fd
, Varlink
**ret
) {
2141 _cleanup_(varlink_unrefp
) Varlink
*v
= NULL
;
2142 struct ucred ucred
= UCRED_INVALID
;
2143 bool ucred_acquired
;
2146 assert_return(server
, -EINVAL
);
2147 assert_return(fd
>= 0, -EBADF
);
2149 if ((server
->flags
& (VARLINK_SERVER_ROOT_ONLY
|VARLINK_SERVER_ACCOUNT_UID
)) != 0) {
2150 r
= getpeercred(fd
, &ucred
);
2152 return varlink_server_log_errno(server
, r
, "Failed to acquire peer credentials of incoming socket, refusing: %m");
2154 ucred_acquired
= true;
2156 r
= validate_connection(server
, &ucred
);
2162 ucred_acquired
= false;
2164 r
= varlink_new(&v
);
2166 return varlink_server_log_errno(server
, r
, "Failed to allocate connection object: %m");
2168 r
= count_connection(server
, &ucred
);
2173 if (server
->flags
& VARLINK_SERVER_INHERIT_USERDATA
)
2174 v
->userdata
= server
->userdata
;
2176 if (ucred_acquired
) {
2178 v
->ucred_acquired
= true;
2181 _cleanup_free_
char *desc
= NULL
;
2182 if (asprintf(&desc
, "%s-%i", server
->description
?: "varlink", v
->fd
) >= 0)
2183 v
->description
= TAKE_PTR(desc
);
2185 /* Link up the server and the connection, and take reference in both directions. Note that the
2186 * reference on the connection is left dangling. It will be dropped when the connection is closed,
2187 * which happens in varlink_close(), including in the event loop quit callback. */
2188 v
->server
= varlink_server_ref(server
);
2191 varlink_set_state(v
, VARLINK_IDLE_SERVER
);
2193 if (server
->event
) {
2194 r
= varlink_attach_event(v
, server
->event
, server
->event_priority
);
2196 varlink_log_errno(v
, r
, "Failed to attach new connection: %m");
2197 v
->fd
= -EBADF
; /* take the fd out of the connection again */
2209 static VarlinkServerSocket
*varlink_server_socket_free(VarlinkServerSocket
*ss
) {
2217 DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServerSocket
*, varlink_server_socket_free
);
2219 static int connect_callback(sd_event_source
*source
, int fd
, uint32_t revents
, void *userdata
) {
2220 VarlinkServerSocket
*ss
= ASSERT_PTR(userdata
);
2221 _cleanup_close_
int cfd
= -EBADF
;
2227 varlink_server_log(ss
->server
, "New incoming connection.");
2229 cfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
2231 if (ERRNO_IS_ACCEPT_AGAIN(errno
))
2234 return varlink_server_log_errno(ss
->server
, errno
, "Failed to accept incoming socket: %m");
2237 r
= varlink_server_add_connection(ss
->server
, cfd
, &v
);
2243 if (ss
->server
->connect_callback
) {
2244 r
= ss
->server
->connect_callback(ss
->server
, v
, ss
->server
->userdata
);
2246 varlink_log_errno(v
, r
, "Connection callback returned error, disconnecting client: %m");
2255 static int varlink_server_create_listen_fd_socket(VarlinkServer
*s
, int fd
, VarlinkServerSocket
**ret_ss
) {
2256 _cleanup_(varlink_server_socket_freep
) VarlinkServerSocket
*ss
= NULL
;
2263 r
= fd_nonblock(fd
, true);
2267 ss
= new(VarlinkServerSocket
, 1);
2269 return log_oom_debug();
2271 *ss
= (VarlinkServerSocket
) {
2277 r
= sd_event_add_io(s
->event
, &ss
->event_source
, fd
, EPOLLIN
, connect_callback
, ss
);
2281 r
= sd_event_source_set_priority(ss
->event_source
, s
->event_priority
);
2286 *ret_ss
= TAKE_PTR(ss
);
2290 int varlink_server_listen_fd(VarlinkServer
*s
, int fd
) {
2291 _cleanup_(varlink_server_socket_freep
) VarlinkServerSocket
*ss
= NULL
;
2294 assert_return(s
, -EINVAL
);
2295 assert_return(fd
>= 0, -EBADF
);
2297 r
= varlink_server_create_listen_fd_socket(s
, fd
, &ss
);
2301 LIST_PREPEND(sockets
, s
->sockets
, TAKE_PTR(ss
));
2305 int varlink_server_listen_address(VarlinkServer
*s
, const char *address
, mode_t m
) {
2306 _cleanup_(varlink_server_socket_freep
) VarlinkServerSocket
*ss
= NULL
;
2307 union sockaddr_union sockaddr
;
2308 socklen_t sockaddr_len
;
2309 _cleanup_close_
int fd
= -EBADF
;
2312 assert_return(s
, -EINVAL
);
2313 assert_return(address
, -EINVAL
);
2314 assert_return((m
& ~0777) == 0, -EINVAL
);
2316 r
= sockaddr_un_set_path(&sockaddr
.un
, address
);
2321 fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
2325 fd
= fd_move_above_stdio(fd
);
2327 (void) sockaddr_un_unlink(&sockaddr
.un
);
2329 WITH_UMASK(~m
& 0777) {
2330 r
= mac_selinux_bind(fd
, &sockaddr
.sa
, sockaddr_len
);
2335 if (listen(fd
, SOMAXCONN
) < 0)
2338 r
= varlink_server_create_listen_fd_socket(s
, fd
, &ss
);
2342 r
= free_and_strdup(&ss
->address
, address
);
2346 LIST_PREPEND(sockets
, s
->sockets
, TAKE_PTR(ss
));
2351 void* varlink_server_set_userdata(VarlinkServer
*s
, void *userdata
) {
2354 assert_return(s
, NULL
);
2357 s
->userdata
= userdata
;
2362 void* varlink_server_get_userdata(VarlinkServer
*s
) {
2363 assert_return(s
, NULL
);
2368 static VarlinkServerSocket
* varlink_server_socket_destroy(VarlinkServerSocket
*ss
) {
2373 LIST_REMOVE(sockets
, ss
->server
->sockets
, ss
);
2375 sd_event_source_disable_unref(ss
->event_source
);
2383 int varlink_server_shutdown(VarlinkServer
*s
) {
2384 assert_return(s
, -EINVAL
);
2387 varlink_server_socket_destroy(s
->sockets
);
2392 static int varlink_server_add_socket_event_source(VarlinkServer
*s
, VarlinkServerSocket
*ss
, int64_t priority
) {
2393 _cleanup_(sd_event_source_unrefp
) sd_event_source
*es
= NULL
;
2400 assert(ss
->fd
>= 0);
2401 assert(!ss
->event_source
);
2403 r
= sd_event_add_io(s
->event
, &es
, ss
->fd
, EPOLLIN
, connect_callback
, ss
);
2407 r
= sd_event_source_set_priority(es
, priority
);
2411 ss
->event_source
= TAKE_PTR(es
);
2415 int varlink_server_attach_event(VarlinkServer
*s
, sd_event
*e
, int64_t priority
) {
2418 assert_return(s
, -EINVAL
);
2419 assert_return(!s
->event
, -EBUSY
);
2422 s
->event
= sd_event_ref(e
);
2424 r
= sd_event_default(&s
->event
);
2429 LIST_FOREACH(sockets
, ss
, s
->sockets
) {
2430 r
= varlink_server_add_socket_event_source(s
, ss
, priority
);
2435 s
->event_priority
= priority
;
2439 varlink_server_detach_event(s
);
2443 int varlink_server_detach_event(VarlinkServer
*s
) {
2444 assert_return(s
, -EINVAL
);
2446 LIST_FOREACH(sockets
, ss
, s
->sockets
)
2447 ss
->event_source
= sd_event_source_disable_unref(ss
->event_source
);
2449 sd_event_unref(s
->event
);
2453 sd_event
*varlink_server_get_event(VarlinkServer
*s
) {
2454 assert_return(s
, NULL
);
2459 int varlink_server_bind_method(VarlinkServer
*s
, const char *method
, VarlinkMethod callback
) {
2460 _cleanup_free_
char *m
= NULL
;
2463 assert_return(s
, -EINVAL
);
2464 assert_return(method
, -EINVAL
);
2465 assert_return(callback
, -EINVAL
);
2467 if (startswith(method
, "org.varlink.service."))
2468 return log_debug_errno(SYNTHETIC_ERRNO(EEXIST
), "Cannot bind server to '%s'.", method
);
2472 return log_oom_debug();
2474 r
= hashmap_ensure_put(&s
->methods
, &string_hash_ops
, m
, callback
);
2476 return log_oom_debug();
2478 return log_debug_errno(r
, "Failed to register callback: %m");
2485 int varlink_server_bind_method_many_internal(VarlinkServer
*s
, ...) {
2489 assert_return(s
, -EINVAL
);
2493 VarlinkMethod callback
;
2496 method
= va_arg(ap
, const char *);
2500 callback
= va_arg(ap
, VarlinkMethod
);
2502 r
= varlink_server_bind_method(s
, method
, callback
);
2511 int varlink_server_bind_connect(VarlinkServer
*s
, VarlinkConnect callback
) {
2512 assert_return(s
, -EINVAL
);
2514 if (callback
&& s
->connect_callback
&& callback
!= s
->connect_callback
)
2515 return log_debug_errno(SYNTHETIC_ERRNO(EBUSY
), "A different callback was already set.");
2517 s
->connect_callback
= callback
;
2521 int varlink_server_bind_disconnect(VarlinkServer
*s
, VarlinkDisconnect callback
) {
2522 assert_return(s
, -EINVAL
);
2524 if (callback
&& s
->disconnect_callback
&& callback
!= s
->disconnect_callback
)
2525 return log_debug_errno(SYNTHETIC_ERRNO(EBUSY
), "A different callback was already set.");
2527 s
->disconnect_callback
= callback
;
2531 unsigned varlink_server_connections_max(VarlinkServer
*s
) {
2534 /* If a server is specified, return the setting for that server, otherwise the default value */
2536 return s
->connections_max
;
2538 dts
= getdtablesize();
2541 /* Make sure we never use up more than ¾th of RLIMIT_NOFILE for IPC */
2542 if (VARLINK_DEFAULT_CONNECTIONS_MAX
> (unsigned) dts
/ 4 * 3)
2545 return VARLINK_DEFAULT_CONNECTIONS_MAX
;
2548 unsigned varlink_server_connections_per_uid_max(VarlinkServer
*s
) {
2552 return s
->connections_per_uid_max
;
2554 /* Make sure to never use up more than ¾th of available connections for a single user */
2555 m
= varlink_server_connections_max(NULL
);
2556 if (VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX
> m
)
2559 return VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX
;
2562 int varlink_server_set_connections_per_uid_max(VarlinkServer
*s
, unsigned m
) {
2563 assert_return(s
, -EINVAL
);
2564 assert_return(m
> 0, -EINVAL
);
2566 s
->connections_per_uid_max
= m
;
2570 int varlink_server_set_connections_max(VarlinkServer
*s
, unsigned m
) {
2571 assert_return(s
, -EINVAL
);
2572 assert_return(m
> 0, -EINVAL
);
2574 s
->connections_max
= m
;
2578 unsigned varlink_server_current_connections(VarlinkServer
*s
) {
2579 assert_return(s
, UINT_MAX
);
2581 return s
->n_connections
;
2584 int varlink_server_set_description(VarlinkServer
*s
, const char *description
) {
2585 assert_return(s
, -EINVAL
);
2587 return free_and_strdup(&s
->description
, description
);
2590 int varlink_server_serialize(VarlinkServer
*s
, FILE *f
, FDSet
*fds
) {
2597 LIST_FOREACH(sockets
, ss
, s
->sockets
) {
2600 assert(ss
->address
);
2601 assert(ss
->fd
>= 0);
2603 fprintf(f
, "varlink-server-socket-address=%s", ss
->address
);
2605 /* If we fail to serialize the fd, it will be considered an error during deserialization */
2606 copy
= fdset_put_dup(fds
, ss
->fd
);
2610 fprintf(f
, " varlink-server-socket-fd=%i", copy
);
2618 int varlink_server_deserialize_one(VarlinkServer
*s
, const char *value
, FDSet
*fds
) {
2619 _cleanup_(varlink_server_socket_freep
) VarlinkServerSocket
*ss
= NULL
;
2620 _cleanup_free_
char *address
= NULL
;
2621 const char *v
= ASSERT_PTR(value
);
2629 n
= strcspn(v
, " ");
2630 address
= strndup(v
, n
);
2632 return log_oom_debug();
2635 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
2636 "Failed to deserialize VarlinkServerSocket: %s: %m", value
);
2637 v
= startswith(v
+ n
+ 1, "varlink-server-socket-fd=");
2639 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
2640 "Failed to deserialize VarlinkServerSocket fd %s: %m", value
);
2642 n
= strcspn(v
, " ");
2643 buf
= strndupa_safe(v
, n
);
2645 r
= safe_atoi(buf
, &fd
);
2647 return log_debug_errno(r
, "Unable to parse VarlinkServerSocket varlink-server-socket-fd=%s: %m", buf
);
2649 if (!fdset_contains(fds
, fd
))
2650 return log_debug_errno(SYNTHETIC_ERRNO(EBADF
),
2651 "VarlinkServerSocket varlink-server-socket-fd= has unknown fd %d: %m", fd
);
2653 ss
= new(VarlinkServerSocket
, 1);
2655 return log_oom_debug();
2657 *ss
= (VarlinkServerSocket
) {
2659 .address
= TAKE_PTR(address
),
2660 .fd
= fdset_remove(fds
, fd
),
2663 r
= varlink_server_add_socket_event_source(s
, ss
, SD_EVENT_PRIORITY_NORMAL
);
2665 return log_debug_errno(r
, "Failed to add VarlinkServerSocket event source to the event loop: %m");
2667 LIST_PREPEND(sockets
, s
->sockets
, TAKE_PTR(ss
));