Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <endian.h>
4 : : #include <netdb.h>
5 : : #include <poll.h>
6 : : #include <pthread.h>
7 : : #include <signal.h>
8 : : #include <stdlib.h>
9 : : #include <sys/mman.h>
10 : : #include <sys/wait.h>
11 : : #include <unistd.h>
12 : :
13 : : #include "sd-bus.h"
14 : :
15 : : #include "alloc-util.h"
16 : : #include "bus-container.h"
17 : : #include "bus-control.h"
18 : : #include "bus-internal.h"
19 : : #include "bus-kernel.h"
20 : : #include "bus-label.h"
21 : : #include "bus-message.h"
22 : : #include "bus-objects.h"
23 : : #include "bus-protocol.h"
24 : : #include "bus-slot.h"
25 : : #include "bus-socket.h"
26 : : #include "bus-track.h"
27 : : #include "bus-type.h"
28 : : #include "bus-util.h"
29 : : #include "cgroup-util.h"
30 : : #include "def.h"
31 : : #include "errno-util.h"
32 : : #include "fd-util.h"
33 : : #include "hexdecoct.h"
34 : : #include "hostname-util.h"
35 : : #include "macro.h"
36 : : #include "memory-util.h"
37 : : #include "missing.h"
38 : : #include "parse-util.h"
39 : : #include "path-util.h"
40 : : #include "process-util.h"
41 : : #include "string-util.h"
42 : : #include "strv.h"
43 : :
44 : : #define log_debug_bus_message(m) \
45 : : do { \
46 : : sd_bus_message *_mm = (m); \
47 : : log_debug("Got message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s", \
48 : : bus_message_type_to_string(_mm->header->type), \
49 : : strna(sd_bus_message_get_sender(_mm)), \
50 : : strna(sd_bus_message_get_destination(_mm)), \
51 : : strna(sd_bus_message_get_path(_mm)), \
52 : : strna(sd_bus_message_get_interface(_mm)), \
53 : : strna(sd_bus_message_get_member(_mm)), \
54 : : BUS_MESSAGE_COOKIE(_mm), \
55 : : _mm->reply_cookie, \
56 : : strna(_mm->root_container.signature), \
57 : : strna(_mm->error.name), \
58 : : strna(_mm->error.message)); \
59 : : } while (false)
60 : :
61 : : static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
62 : : static void bus_detach_io_events(sd_bus *b);
63 : : static void bus_detach_inotify_event(sd_bus *b);
64 : :
65 : : static thread_local sd_bus *default_system_bus = NULL;
66 : : static thread_local sd_bus *default_user_bus = NULL;
67 : : static thread_local sd_bus *default_starter_bus = NULL;
68 : :
69 : 0 : static sd_bus **bus_choose_default(int (**bus_open)(sd_bus **)) {
70 : : const char *e;
71 : :
72 : : /* Let's try our best to reuse another cached connection. If
73 : : * the starter bus type is set, connect via our normal
74 : : * connection logic, ignoring $DBUS_STARTER_ADDRESS, so that
75 : : * we can share the connection with the user/system default
76 : : * bus. */
77 : :
78 : 0 : e = secure_getenv("DBUS_STARTER_BUS_TYPE");
79 [ # # ]: 0 : if (e) {
80 [ # # ]: 0 : if (streq(e, "system")) {
81 [ # # ]: 0 : if (bus_open)
82 : 0 : *bus_open = sd_bus_open_system;
83 : 0 : return &default_system_bus;
84 [ # # ]: 0 : } else if (STR_IN_SET(e, "user", "session")) {
85 [ # # ]: 0 : if (bus_open)
86 : 0 : *bus_open = sd_bus_open_user;
87 : 0 : return &default_user_bus;
88 : : }
89 : : }
90 : :
91 : : /* No type is specified, so we have not other option than to
92 : : * use the starter address if it is set. */
93 : 0 : e = secure_getenv("DBUS_STARTER_ADDRESS");
94 [ # # ]: 0 : if (e) {
95 [ # # ]: 0 : if (bus_open)
96 : 0 : *bus_open = sd_bus_open;
97 : 0 : return &default_starter_bus;
98 : : }
99 : :
100 : : /* Finally, if nothing is set use the cached connection for
101 : : * the right scope */
102 : :
103 [ # # ]: 0 : if (cg_pid_get_owner_uid(0, NULL) >= 0) {
104 [ # # ]: 0 : if (bus_open)
105 : 0 : *bus_open = sd_bus_open_user;
106 : 0 : return &default_user_bus;
107 : : } else {
108 [ # # ]: 0 : if (bus_open)
109 : 0 : *bus_open = sd_bus_open_system;
110 : 0 : return &default_system_bus;
111 : : }
112 : : }
113 : :
114 : 4941 : sd_bus *bus_resolve(sd_bus *bus) {
115 [ - - - + ]: 4941 : switch ((uintptr_t) bus) {
116 : 0 : case (uintptr_t) SD_BUS_DEFAULT:
117 : 0 : return *(bus_choose_default(NULL));
118 : 0 : case (uintptr_t) SD_BUS_DEFAULT_USER:
119 : 0 : return default_user_bus;
120 : 0 : case (uintptr_t) SD_BUS_DEFAULT_SYSTEM:
121 : 0 : return default_system_bus;
122 : 4941 : default:
123 : 4941 : return bus;
124 : : }
125 : : }
126 : :
127 : 700 : void bus_close_io_fds(sd_bus *b) {
128 [ - + ]: 700 : assert(b);
129 : :
130 : 700 : bus_detach_io_events(b);
131 : :
132 [ - + ]: 700 : if (b->input_fd != b->output_fd)
133 : 0 : safe_close(b->output_fd);
134 : 700 : b->output_fd = b->input_fd = safe_close(b->input_fd);
135 : 700 : }
136 : :
137 : 716 : void bus_close_inotify_fd(sd_bus *b) {
138 [ - + ]: 716 : assert(b);
139 : :
140 : 716 : bus_detach_inotify_event(b);
141 : :
142 : 716 : b->inotify_fd = safe_close(b->inotify_fd);
143 : 716 : b->inotify_watches = mfree(b->inotify_watches);
144 : 716 : b->n_inotify_watches = 0;
145 : 716 : }
146 : :
147 : 332 : static void bus_reset_queues(sd_bus *b) {
148 [ - + ]: 332 : assert(b);
149 : :
150 [ + + ]: 340 : while (b->rqueue_size > 0)
151 : 8 : bus_message_unref_queued(b->rqueue[--b->rqueue_size], b);
152 : :
153 : 332 : b->rqueue = mfree(b->rqueue);
154 : 332 : b->rqueue_allocated = 0;
155 : :
156 [ + + ]: 352 : while (b->wqueue_size > 0)
157 : 20 : bus_message_unref_queued(b->wqueue[--b->wqueue_size], b);
158 : :
159 : 332 : b->wqueue = mfree(b->wqueue);
160 : 332 : b->wqueue_allocated = 0;
161 : 332 : }
162 : :
163 : 212 : static sd_bus* bus_free(sd_bus *b) {
164 : : sd_bus_slot *s;
165 : :
166 [ - + ]: 212 : assert(b);
167 [ - + ]: 212 : assert(!b->track_queue);
168 [ - + ]: 212 : assert(!b->tracks);
169 : :
170 : 212 : b->state = BUS_CLOSED;
171 : :
172 : 212 : sd_bus_detach_event(b);
173 : :
174 [ + + ]: 445 : while ((s = b->slots)) {
175 : : /* At this point only floating slots can still be
176 : : * around, because the non-floating ones keep a
177 : : * reference to the bus, and we thus couldn't be
178 : : * destructing right now... We forcibly disconnect the
179 : : * slots here, so that they still can be referenced by
180 : : * apps, but are dead. */
181 : :
182 [ - + ]: 233 : assert(s->floating);
183 : 233 : bus_slot_disconnect(s, true);
184 : : }
185 : :
186 [ + + ]: 212 : if (b->default_bus_ptr)
187 : 4 : *b->default_bus_ptr = NULL;
188 : :
189 : 212 : bus_close_io_fds(b);
190 : 212 : bus_close_inotify_fd(b);
191 : :
192 : 212 : free(b->label);
193 : 212 : free(b->groups);
194 : 212 : free(b->rbuffer);
195 : 212 : free(b->unique_name);
196 : 212 : free(b->auth_buffer);
197 : 212 : free(b->address);
198 : 212 : free(b->machine);
199 : 212 : free(b->description);
200 : 212 : free(b->patch_sender);
201 : :
202 : 212 : free(b->exec_path);
203 : 212 : strv_free(b->exec_argv);
204 : :
205 : 212 : close_many(b->fds, b->n_fds);
206 : 212 : free(b->fds);
207 : :
208 : 212 : bus_reset_queues(b);
209 : :
210 : 212 : ordered_hashmap_free_free(b->reply_callbacks);
211 : 212 : prioq_free(b->reply_callbacks_prioq);
212 : :
213 [ - + ]: 212 : assert(b->match_callbacks.type == BUS_MATCH_ROOT);
214 : 212 : bus_match_free(&b->match_callbacks);
215 : :
216 : 212 : hashmap_free_free(b->vtable_methods);
217 : 212 : hashmap_free_free(b->vtable_properties);
218 : :
219 [ - + ]: 212 : assert(hashmap_isempty(b->nodes));
220 : 212 : hashmap_free(b->nodes);
221 : :
222 : 212 : bus_flush_memfd(b);
223 : :
224 [ - + ]: 212 : assert_se(pthread_mutex_destroy(&b->memfd_cache_mutex) == 0);
225 : :
226 : 212 : return mfree(b);
227 : : }
228 : :
229 [ - + ]: 104 : DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, bus_free);
230 : :
231 : 212 : _public_ int sd_bus_new(sd_bus **ret) {
232 : 212 : _cleanup_free_ sd_bus *b = NULL;
233 : :
234 [ - + - + ]: 212 : assert_return(ret, -EINVAL);
235 : :
236 : 212 : b = new(sd_bus, 1);
237 [ - + ]: 212 : if (!b)
238 : 0 : return -ENOMEM;
239 : :
240 : 424 : *b = (sd_bus) {
241 : : .n_ref = 1,
242 : : .input_fd = -1,
243 : : .output_fd = -1,
244 : : .inotify_fd = -1,
245 : : .message_version = 1,
246 : : .creds_mask = SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME,
247 : : .accept_fd = true,
248 : 212 : .original_pid = getpid_cached(),
249 : : .n_groups = (size_t) -1,
250 : : .close_on_exit = true,
251 : : };
252 : :
253 : : /* We guarantee that wqueue always has space for at least one entry */
254 [ - + ]: 212 : if (!GREEDY_REALLOC(b->wqueue, b->wqueue_allocated, 1))
255 : 0 : return -ENOMEM;
256 : :
257 [ - + ]: 212 : assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0);
258 : :
259 : 212 : *ret = TAKE_PTR(b);
260 : 212 : return 0;
261 : : }
262 : :
263 : 128 : _public_ int sd_bus_set_address(sd_bus *bus, const char *address) {
264 [ - + - + ]: 128 : assert_return(bus, -EINVAL);
265 [ - + - + ]: 128 : assert_return(bus = bus_resolve(bus), -ENOPKG);
266 [ - + - + ]: 128 : assert_return(bus->state == BUS_UNSET, -EPERM);
267 [ - + - + ]: 128 : assert_return(address, -EINVAL);
268 [ - + - + ]: 128 : assert_return(!bus_pid_changed(bus), -ECHILD);
269 : :
270 : 128 : return free_and_strdup(&bus->address, address);
271 : : }
272 : :
273 : 76 : _public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
274 [ - + - + ]: 76 : assert_return(bus, -EINVAL);
275 [ - + - + ]: 76 : assert_return(bus = bus_resolve(bus), -ENOPKG);
276 [ - + - + ]: 76 : assert_return(bus->state == BUS_UNSET, -EPERM);
277 [ - + - + ]: 76 : assert_return(input_fd >= 0, -EBADF);
278 [ - + - + ]: 76 : assert_return(output_fd >= 0, -EBADF);
279 [ - + - + ]: 76 : assert_return(!bus_pid_changed(bus), -ECHILD);
280 : :
281 : 76 : bus->input_fd = input_fd;
282 : 76 : bus->output_fd = output_fd;
283 : 76 : return 0;
284 : : }
285 : :
286 : 0 : _public_ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
287 : 0 : _cleanup_strv_free_ char **a = NULL;
288 : : int r;
289 : :
290 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
291 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
292 [ # # # # ]: 0 : assert_return(bus->state == BUS_UNSET, -EPERM);
293 [ # # # # ]: 0 : assert_return(path, -EINVAL);
294 [ # # # # ]: 0 : assert_return(!strv_isempty(argv), -EINVAL);
295 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
296 : :
297 : 0 : a = strv_copy(argv);
298 [ # # ]: 0 : if (!a)
299 : 0 : return -ENOMEM;
300 : :
301 : 0 : r = free_and_strdup(&bus->exec_path, path);
302 [ # # ]: 0 : if (r < 0)
303 : 0 : return r;
304 : :
305 : 0 : return strv_free_and_replace(bus->exec_argv, a);
306 : : }
307 : :
308 : 4 : _public_ int sd_bus_set_bus_client(sd_bus *bus, int b) {
309 [ - + - + ]: 4 : assert_return(bus, -EINVAL);
310 [ - + - + ]: 4 : assert_return(bus = bus_resolve(bus), -ENOPKG);
311 [ - + - + ]: 4 : assert_return(bus->state == BUS_UNSET, -EPERM);
312 [ - + - + ]: 4 : assert_return(!bus->patch_sender, -EPERM);
313 [ - + - + ]: 4 : assert_return(!bus_pid_changed(bus), -ECHILD);
314 : :
315 : 4 : bus->bus_client = !!b;
316 : 4 : return 0;
317 : : }
318 : :
319 : 0 : _public_ int sd_bus_set_monitor(sd_bus *bus, int b) {
320 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
321 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
322 [ # # # # ]: 0 : assert_return(bus->state == BUS_UNSET, -EPERM);
323 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
324 : :
325 : 0 : bus->is_monitor = !!b;
326 : 0 : return 0;
327 : : }
328 : :
329 : 56 : _public_ int sd_bus_negotiate_fds(sd_bus *bus, int b) {
330 [ - + - + ]: 56 : assert_return(bus, -EINVAL);
331 [ - + - + ]: 56 : assert_return(bus = bus_resolve(bus), -ENOPKG);
332 [ - + - + ]: 56 : assert_return(bus->state == BUS_UNSET, -EPERM);
333 [ - + - + ]: 56 : assert_return(!bus_pid_changed(bus), -ECHILD);
334 : :
335 : 56 : bus->accept_fd = !!b;
336 : 56 : return 0;
337 : : }
338 : :
339 : 0 : _public_ int sd_bus_negotiate_timestamp(sd_bus *bus, int b) {
340 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
341 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
342 [ # # # # : 0 : assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
# # ]
343 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
344 : :
345 : : /* This is not actually supported by any of our transports these days, but we do honour it for synthetic
346 : : * replies, and maybe one day classic D-Bus learns this too */
347 : 0 : bus->attach_timestamp = !!b;
348 : :
349 : 0 : return 0;
350 : : }
351 : :
352 : 4 : _public_ int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t mask) {
353 [ - + - + ]: 4 : assert_return(bus, -EINVAL);
354 [ - + - + ]: 4 : assert_return(bus = bus_resolve(bus), -ENOPKG);
355 [ - + - + ]: 4 : assert_return(mask <= _SD_BUS_CREDS_ALL, -EINVAL);
356 [ - + - + : 4 : assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
- + ]
357 [ - + - + ]: 4 : assert_return(!bus_pid_changed(bus), -ECHILD);
358 : :
359 [ + - ]: 4 : SET_FLAG(bus->creds_mask, mask, b);
360 : :
361 : : /* The well knowns we need unconditionally, so that matches can work */
362 : 4 : bus->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
363 : :
364 : 4 : return 0;
365 : : }
366 : :
367 : 44 : _public_ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
368 [ - + - + ]: 44 : assert_return(bus, -EINVAL);
369 [ - + - + ]: 44 : assert_return(bus = bus_resolve(bus), -ENOPKG);
370 [ - + # # : 44 : assert_return(b || sd_id128_equal(server_id, SD_ID128_NULL), -EINVAL);
- + ]
371 [ - + - + ]: 44 : assert_return(bus->state == BUS_UNSET, -EPERM);
372 [ - + - + ]: 44 : assert_return(!bus_pid_changed(bus), -ECHILD);
373 : :
374 : 44 : bus->is_server = !!b;
375 : 44 : bus->server_id = server_id;
376 : 44 : return 0;
377 : : }
378 : :
379 : 56 : _public_ int sd_bus_set_anonymous(sd_bus *bus, int b) {
380 [ - + - + ]: 56 : assert_return(bus, -EINVAL);
381 [ - + - + ]: 56 : assert_return(bus = bus_resolve(bus), -ENOPKG);
382 [ - + - + ]: 56 : assert_return(bus->state == BUS_UNSET, -EPERM);
383 [ - + - + ]: 56 : assert_return(!bus_pid_changed(bus), -ECHILD);
384 : :
385 : 56 : bus->anonymous_auth = !!b;
386 : 56 : return 0;
387 : : }
388 : :
389 : 4 : _public_ int sd_bus_set_trusted(sd_bus *bus, int b) {
390 [ - + - + ]: 4 : assert_return(bus, -EINVAL);
391 [ - + - + ]: 4 : assert_return(bus = bus_resolve(bus), -ENOPKG);
392 [ - + - + ]: 4 : assert_return(bus->state == BUS_UNSET, -EPERM);
393 [ - + - + ]: 4 : assert_return(!bus_pid_changed(bus), -ECHILD);
394 : :
395 : 4 : bus->trusted = !!b;
396 : 4 : return 0;
397 : : }
398 : :
399 : 84 : _public_ int sd_bus_set_description(sd_bus *bus, const char *description) {
400 [ - + - + ]: 84 : assert_return(bus, -EINVAL);
401 [ - + - + ]: 84 : assert_return(bus = bus_resolve(bus), -ENOPKG);
402 [ - + - + ]: 84 : assert_return(bus->state == BUS_UNSET, -EPERM);
403 [ - + - + ]: 84 : assert_return(!bus_pid_changed(bus), -ECHILD);
404 : :
405 : 84 : return free_and_strdup(&bus->description, description);
406 : : }
407 : :
408 : 0 : _public_ int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b) {
409 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
410 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
411 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
412 : :
413 : 0 : bus->allow_interactive_authorization = !!b;
414 : 0 : return 0;
415 : : }
416 : :
417 : 0 : _public_ int sd_bus_get_allow_interactive_authorization(sd_bus *bus) {
418 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
419 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
420 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
421 : :
422 : 0 : return bus->allow_interactive_authorization;
423 : : }
424 : :
425 : 16 : _public_ int sd_bus_set_watch_bind(sd_bus *bus, int b) {
426 [ - + - + ]: 16 : assert_return(bus, -EINVAL);
427 [ - + - + ]: 16 : assert_return(bus = bus_resolve(bus), -ENOPKG);
428 [ - + - + ]: 16 : assert_return(bus->state == BUS_UNSET, -EPERM);
429 [ - + - + ]: 16 : assert_return(!bus_pid_changed(bus), -ECHILD);
430 : :
431 : 16 : bus->watch_bind = !!b;
432 : 16 : return 0;
433 : : }
434 : :
435 : 0 : _public_ int sd_bus_get_watch_bind(sd_bus *bus) {
436 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
437 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
438 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
439 : :
440 : 0 : return bus->watch_bind;
441 : : }
442 : :
443 : 4 : _public_ int sd_bus_set_connected_signal(sd_bus *bus, int b) {
444 [ - + - + ]: 4 : assert_return(bus, -EINVAL);
445 [ - + - + ]: 4 : assert_return(bus = bus_resolve(bus), -ENOPKG);
446 [ - + - + ]: 4 : assert_return(bus->state == BUS_UNSET, -EPERM);
447 [ - + - + ]: 4 : assert_return(!bus_pid_changed(bus), -ECHILD);
448 : :
449 : 4 : bus->connected_signal = !!b;
450 : 4 : return 0;
451 : : }
452 : :
453 : 0 : _public_ int sd_bus_get_connected_signal(sd_bus *bus) {
454 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
455 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
456 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
457 : :
458 : 0 : return bus->connected_signal;
459 : : }
460 : :
461 : 176 : static int synthesize_connected_signal(sd_bus *bus) {
462 : 176 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
463 : : int r;
464 : :
465 [ - + ]: 176 : assert(bus);
466 : :
467 : : /* If enabled, synthesizes a local "Connected" signal mirroring the local "Disconnected" signal. This is called
468 : : * whenever we fully established a connection, i.e. after the authorization phase, and after receiving the
469 : : * Hello() reply. Or in other words, whenever we enter BUS_RUNNING state.
470 : : *
471 : : * This is useful so that clients can start doing stuff whenever the connection is fully established in a way
472 : : * that works independently from whether we connected to a full bus or just a direct connection. */
473 : :
474 [ + + ]: 176 : if (!bus->connected_signal)
475 : 172 : return 0;
476 : :
477 : 4 : r = sd_bus_message_new_signal(
478 : : bus,
479 : : &m,
480 : : "/org/freedesktop/DBus/Local",
481 : : "org.freedesktop.DBus.Local",
482 : : "Connected");
483 [ - + ]: 4 : if (r < 0)
484 : 0 : return r;
485 : :
486 : 4 : bus_message_set_sender_local(bus, m);
487 : 4 : m->read_counter = ++bus->read_counter;
488 : :
489 : 4 : r = bus_seal_synthetic_message(bus, m);
490 [ - + ]: 4 : if (r < 0)
491 : 0 : return r;
492 : :
493 : 4 : r = bus_rqueue_make_room(bus);
494 [ - + ]: 4 : if (r < 0)
495 : 0 : return r;
496 : :
497 : : /* Insert at the very front */
498 : 4 : memmove(bus->rqueue + 1, bus->rqueue, sizeof(sd_bus_message*) * bus->rqueue_size);
499 : 4 : bus->rqueue[0] = bus_message_ref_queued(m, bus);
500 : 4 : bus->rqueue_size++;
501 : :
502 : 4 : return 0;
503 : : }
504 : :
505 : 864 : void bus_set_state(sd_bus *bus, enum bus_state state) {
506 : :
507 : : static const char * const table[_BUS_STATE_MAX] = {
508 : : [BUS_UNSET] = "UNSET",
509 : : [BUS_WATCH_BIND] = "WATCH_BIND",
510 : : [BUS_OPENING] = "OPENING",
511 : : [BUS_AUTHENTICATING] = "AUTHENTICATING",
512 : : [BUS_HELLO] = "HELLO",
513 : : [BUS_RUNNING] = "RUNNING",
514 : : [BUS_CLOSING] = "CLOSING",
515 : : [BUS_CLOSED] = "CLOSED",
516 : : };
517 : :
518 [ - + ]: 864 : assert(bus);
519 [ - + ]: 864 : assert(state < _BUS_STATE_MAX);
520 : :
521 [ + + ]: 864 : if (state == bus->state)
522 : 48 : return;
523 : :
524 [ + + ]: 816 : log_debug("Bus %s: changing state %s → %s", strna(bus->description), table[bus->state], table[state]);
525 : 816 : bus->state = state;
526 : : }
527 : :
528 : 96 : static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
529 : : const char *s;
530 : : sd_bus *bus;
531 : : int r;
532 : :
533 [ - + ]: 96 : assert(reply);
534 : 96 : bus = reply->bus;
535 [ - + ]: 96 : assert(bus);
536 [ + - - + ]: 96 : assert(IN_SET(bus->state, BUS_HELLO, BUS_CLOSING));
537 : :
538 : 96 : r = sd_bus_message_get_errno(reply);
539 [ - + ]: 96 : if (r > 0)
540 : 0 : return -r;
541 : :
542 : 96 : r = sd_bus_message_read(reply, "s", &s);
543 [ - + ]: 96 : if (r < 0)
544 : 0 : return r;
545 : :
546 [ + - - + ]: 96 : if (!service_name_is_valid(s) || s[0] != ':')
547 : 0 : return -EBADMSG;
548 : :
549 : 96 : r = free_and_strdup(&bus->unique_name, s);
550 [ - + ]: 96 : if (r < 0)
551 : 0 : return r;
552 : :
553 [ + - ]: 96 : if (bus->state == BUS_HELLO) {
554 : 96 : bus_set_state(bus, BUS_RUNNING);
555 : :
556 : 96 : r = synthesize_connected_signal(bus);
557 [ - + ]: 96 : if (r < 0)
558 : 0 : return r;
559 : : }
560 : :
561 : 96 : return 1;
562 : : }
563 : :
564 : 204 : static int bus_send_hello(sd_bus *bus) {
565 : 204 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
566 : : int r;
567 : :
568 [ - + ]: 204 : assert(bus);
569 : :
570 [ + + ]: 204 : if (!bus->bus_client)
571 : 96 : return 0;
572 : :
573 : 108 : r = sd_bus_message_new_method_call(
574 : : bus,
575 : : &m,
576 : : "org.freedesktop.DBus",
577 : : "/org/freedesktop/DBus",
578 : : "org.freedesktop.DBus",
579 : : "Hello");
580 [ - + ]: 108 : if (r < 0)
581 : 0 : return r;
582 : :
583 : 108 : return sd_bus_call_async(bus, NULL, m, hello_callback, NULL, 0);
584 : : }
585 : :
586 : 176 : int bus_start_running(sd_bus *bus) {
587 : : struct reply_callback *c;
588 : : Iterator i;
589 : : usec_t n;
590 : : int r;
591 : :
592 [ - + ]: 176 : assert(bus);
593 [ - + ]: 176 : assert(bus->state < BUS_HELLO);
594 : :
595 : : /* We start all method call timeouts when we enter BUS_HELLO or BUS_RUNNING mode. At this point let's convert
596 : : * all relative to absolute timestamps. Note that we do not reshuffle the reply callback priority queue since
597 : : * adding a fixed value to all entries should not alter the internal order. */
598 : :
599 : 176 : n = now(CLOCK_MONOTONIC);
600 [ + + ]: 332 : ORDERED_HASHMAP_FOREACH(c, bus->reply_callbacks, i) {
601 [ - + ]: 156 : if (c->timeout_usec == 0)
602 : 0 : continue;
603 : :
604 : 156 : c->timeout_usec = usec_add(n, c->timeout_usec);
605 : : }
606 : :
607 [ + + ]: 176 : if (bus->bus_client) {
608 : 96 : bus_set_state(bus, BUS_HELLO);
609 : 96 : return 1;
610 : : }
611 : :
612 : 80 : bus_set_state(bus, BUS_RUNNING);
613 : :
614 : 80 : r = synthesize_connected_signal(bus);
615 [ - + ]: 80 : if (r < 0)
616 : 0 : return r;
617 : :
618 : 80 : return 1;
619 : : }
620 : :
621 : 256 : static int parse_address_key(const char **p, const char *key, char **value) {
622 : 256 : size_t l, n = 0, allocated = 0;
623 : 256 : _cleanup_free_ char *r = NULL;
624 : : const char *a;
625 : :
626 [ - + ]: 256 : assert(p);
627 [ - + ]: 256 : assert(*p);
628 [ - + ]: 256 : assert(value);
629 : :
630 [ + - ]: 256 : if (key) {
631 : 256 : l = strlen(key);
632 [ + + ]: 256 : if (strncmp(*p, key, l) != 0)
633 : 128 : return 0;
634 : :
635 [ - + ]: 128 : if ((*p)[l] != '=')
636 : 0 : return 0;
637 : :
638 [ - + ]: 128 : if (*value)
639 : 0 : return -EINVAL;
640 : :
641 : 128 : a = *p + l + 1;
642 : : } else
643 : 0 : a = *p;
644 : :
645 [ + + + + ]: 3476 : while (!IN_SET(*a, ';', ',', 0)) {
646 : : char c;
647 : :
648 [ - + ]: 3348 : if (*a == '%') {
649 : : int x, y;
650 : :
651 : 0 : x = unhexchar(a[1]);
652 [ # # ]: 0 : if (x < 0)
653 : 0 : return x;
654 : :
655 : 0 : y = unhexchar(a[2]);
656 [ # # ]: 0 : if (y < 0)
657 : 0 : return y;
658 : :
659 : 0 : c = (char) ((x << 4) | y);
660 : 0 : a += 3;
661 : : } else {
662 : 3348 : c = *a;
663 : 3348 : a++;
664 : : }
665 : :
666 [ - + ]: 3348 : if (!GREEDY_REALLOC(r, allocated, n + 2))
667 : 0 : return -ENOMEM;
668 : :
669 : 3348 : r[n++] = c;
670 : : }
671 : :
672 [ - + ]: 128 : if (!r) {
673 : 0 : r = strdup("");
674 [ # # ]: 0 : if (!r)
675 : 0 : return -ENOMEM;
676 : : } else
677 : 128 : r[n] = 0;
678 : :
679 [ - + ]: 128 : if (*a == ',')
680 : 0 : a++;
681 : :
682 : 128 : *p = a;
683 : :
684 : 128 : free_and_replace(*value, r);
685 : :
686 : 128 : return 1;
687 : : }
688 : :
689 : 0 : static void skip_address_key(const char **p) {
690 [ # # ]: 0 : assert(p);
691 [ # # ]: 0 : assert(*p);
692 : :
693 : 0 : *p += strcspn(*p, ",");
694 : :
695 [ # # ]: 0 : if (**p == ',')
696 : 0 : (*p)++;
697 : 0 : }
698 : :
699 : 128 : static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
700 : 128 : _cleanup_free_ char *path = NULL, *abstract = NULL;
701 : : size_t l;
702 : : int r;
703 : :
704 [ - + ]: 128 : assert(b);
705 [ - + ]: 128 : assert(p);
706 [ - + ]: 128 : assert(*p);
707 [ - + ]: 128 : assert(guid);
708 : :
709 [ + + + + ]: 256 : while (!IN_SET(**p, 0, ';')) {
710 : 128 : r = parse_address_key(p, "guid", guid);
711 [ - + ]: 128 : if (r < 0)
712 : 0 : return r;
713 [ - + ]: 128 : else if (r > 0)
714 : 0 : continue;
715 : :
716 : 128 : r = parse_address_key(p, "path", &path);
717 [ - + ]: 128 : if (r < 0)
718 : 0 : return r;
719 [ + - ]: 128 : else if (r > 0)
720 : 128 : continue;
721 : :
722 : 0 : r = parse_address_key(p, "abstract", &abstract);
723 [ # # ]: 0 : if (r < 0)
724 : 0 : return r;
725 [ # # ]: 0 : else if (r > 0)
726 : 0 : continue;
727 : :
728 : 0 : skip_address_key(p);
729 : : }
730 : :
731 [ - + # # ]: 128 : if (!path && !abstract)
732 : 0 : return -EINVAL;
733 : :
734 [ + - - + ]: 128 : if (path && abstract)
735 : 0 : return -EINVAL;
736 : :
737 [ + - ]: 128 : if (path) {
738 : 128 : l = strlen(path);
739 [ - + ]: 128 : if (l >= sizeof(b->sockaddr.un.sun_path)) /* We insist on NUL termination */
740 : 0 : return -E2BIG;
741 : :
742 : 128 : b->sockaddr.un = (struct sockaddr_un) {
743 : : .sun_family = AF_UNIX,
744 : : };
745 : :
746 : 128 : memcpy(b->sockaddr.un.sun_path, path, l);
747 : 128 : b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l + 1;
748 : :
749 : : } else {
750 [ # # ]: 0 : assert(abstract);
751 : :
752 : 0 : l = strlen(abstract);
753 [ # # ]: 0 : if (l >= sizeof(b->sockaddr.un.sun_path) - 1) /* We insist on NUL termination */
754 : 0 : return -E2BIG;
755 : :
756 : 0 : b->sockaddr.un = (struct sockaddr_un) {
757 : : .sun_family = AF_UNIX,
758 : : };
759 : :
760 : 0 : memcpy(b->sockaddr.un.sun_path+1, abstract, l);
761 : 0 : b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
762 : : }
763 : :
764 : 128 : b->is_local = true;
765 : :
766 : 128 : return 0;
767 : : }
768 : :
769 : 0 : static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
770 : 0 : _cleanup_free_ char *host = NULL, *port = NULL, *family = NULL;
771 : : int r;
772 : 0 : struct addrinfo *result, hints = {
773 : : .ai_socktype = SOCK_STREAM,
774 : : .ai_flags = AI_ADDRCONFIG,
775 : : };
776 : :
777 [ # # ]: 0 : assert(b);
778 [ # # ]: 0 : assert(p);
779 [ # # ]: 0 : assert(*p);
780 [ # # ]: 0 : assert(guid);
781 : :
782 [ # # # # ]: 0 : while (!IN_SET(**p, 0, ';')) {
783 : 0 : r = parse_address_key(p, "guid", guid);
784 [ # # ]: 0 : if (r < 0)
785 : 0 : return r;
786 [ # # ]: 0 : else if (r > 0)
787 : 0 : continue;
788 : :
789 : 0 : r = parse_address_key(p, "host", &host);
790 [ # # ]: 0 : if (r < 0)
791 : 0 : return r;
792 [ # # ]: 0 : else if (r > 0)
793 : 0 : continue;
794 : :
795 : 0 : r = parse_address_key(p, "port", &port);
796 [ # # ]: 0 : if (r < 0)
797 : 0 : return r;
798 [ # # ]: 0 : else if (r > 0)
799 : 0 : continue;
800 : :
801 : 0 : r = parse_address_key(p, "family", &family);
802 [ # # ]: 0 : if (r < 0)
803 : 0 : return r;
804 [ # # ]: 0 : else if (r > 0)
805 : 0 : continue;
806 : :
807 : 0 : skip_address_key(p);
808 : : }
809 : :
810 [ # # # # ]: 0 : if (!host || !port)
811 : 0 : return -EINVAL;
812 : :
813 [ # # ]: 0 : if (family) {
814 [ # # ]: 0 : if (streq(family, "ipv4"))
815 : 0 : hints.ai_family = AF_INET;
816 [ # # ]: 0 : else if (streq(family, "ipv6"))
817 : 0 : hints.ai_family = AF_INET6;
818 : : else
819 : 0 : return -EINVAL;
820 : : }
821 : :
822 : 0 : r = getaddrinfo(host, port, &hints, &result);
823 [ # # ]: 0 : if (r == EAI_SYSTEM)
824 : 0 : return -errno;
825 [ # # ]: 0 : else if (r != 0)
826 : 0 : return -EADDRNOTAVAIL;
827 : :
828 : 0 : memcpy(&b->sockaddr, result->ai_addr, result->ai_addrlen);
829 : 0 : b->sockaddr_size = result->ai_addrlen;
830 : :
831 : 0 : freeaddrinfo(result);
832 : :
833 : 0 : b->is_local = false;
834 : :
835 : 0 : return 0;
836 : : }
837 : :
838 : 0 : static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
839 : 0 : char *path = NULL;
840 : 0 : unsigned n_argv = 0, j;
841 : 0 : char **argv = NULL;
842 : 0 : size_t allocated = 0;
843 : : int r;
844 : :
845 [ # # ]: 0 : assert(b);
846 [ # # ]: 0 : assert(p);
847 [ # # ]: 0 : assert(*p);
848 [ # # ]: 0 : assert(guid);
849 : :
850 [ # # # # ]: 0 : while (!IN_SET(**p, 0, ';')) {
851 : 0 : r = parse_address_key(p, "guid", guid);
852 [ # # ]: 0 : if (r < 0)
853 : 0 : goto fail;
854 [ # # ]: 0 : else if (r > 0)
855 : 0 : continue;
856 : :
857 : 0 : r = parse_address_key(p, "path", &path);
858 [ # # ]: 0 : if (r < 0)
859 : 0 : goto fail;
860 [ # # ]: 0 : else if (r > 0)
861 : 0 : continue;
862 : :
863 [ # # ]: 0 : if (startswith(*p, "argv")) {
864 : : unsigned ul;
865 : :
866 : 0 : errno = 0;
867 : 0 : ul = strtoul(*p + 4, (char**) p, 10);
868 [ # # # # : 0 : if (errno > 0 || **p != '=' || ul > 256) {
# # ]
869 : 0 : r = -EINVAL;
870 : 0 : goto fail;
871 : : }
872 : :
873 : 0 : (*p)++;
874 : :
875 [ # # ]: 0 : if (ul >= n_argv) {
876 [ # # ]: 0 : if (!GREEDY_REALLOC0(argv, allocated, ul + 2)) {
877 : 0 : r = -ENOMEM;
878 : 0 : goto fail;
879 : : }
880 : :
881 : 0 : n_argv = ul + 1;
882 : : }
883 : :
884 : 0 : r = parse_address_key(p, NULL, argv + ul);
885 [ # # ]: 0 : if (r < 0)
886 : 0 : goto fail;
887 : :
888 : 0 : continue;
889 : : }
890 : :
891 : 0 : skip_address_key(p);
892 : : }
893 : :
894 [ # # ]: 0 : if (!path) {
895 : 0 : r = -EINVAL;
896 : 0 : goto fail;
897 : : }
898 : :
899 : : /* Make sure there are no holes in the array, with the
900 : : * exception of argv[0] */
901 [ # # ]: 0 : for (j = 1; j < n_argv; j++)
902 [ # # ]: 0 : if (!argv[j]) {
903 : 0 : r = -EINVAL;
904 : 0 : goto fail;
905 : : }
906 : :
907 [ # # # # ]: 0 : if (argv && argv[0] == NULL) {
908 : 0 : argv[0] = strdup(path);
909 [ # # ]: 0 : if (!argv[0]) {
910 : 0 : r = -ENOMEM;
911 : 0 : goto fail;
912 : : }
913 : : }
914 : :
915 : 0 : b->exec_path = path;
916 : 0 : b->exec_argv = argv;
917 : :
918 : 0 : b->is_local = false;
919 : :
920 : 0 : return 0;
921 : :
922 : 0 : fail:
923 [ # # ]: 0 : for (j = 0; j < n_argv; j++)
924 : 0 : free(argv[j]);
925 : :
926 : 0 : free(argv);
927 : 0 : free(path);
928 : 0 : return r;
929 : : }
930 : :
931 : 0 : static int parse_container_unix_address(sd_bus *b, const char **p, char **guid) {
932 : 0 : _cleanup_free_ char *machine = NULL, *pid = NULL;
933 : : int r;
934 : :
935 [ # # ]: 0 : assert(b);
936 [ # # ]: 0 : assert(p);
937 [ # # ]: 0 : assert(*p);
938 [ # # ]: 0 : assert(guid);
939 : :
940 [ # # # # ]: 0 : while (!IN_SET(**p, 0, ';')) {
941 : 0 : r = parse_address_key(p, "guid", guid);
942 [ # # ]: 0 : if (r < 0)
943 : 0 : return r;
944 [ # # ]: 0 : else if (r > 0)
945 : 0 : continue;
946 : :
947 : 0 : r = parse_address_key(p, "machine", &machine);
948 [ # # ]: 0 : if (r < 0)
949 : 0 : return r;
950 [ # # ]: 0 : else if (r > 0)
951 : 0 : continue;
952 : :
953 : 0 : r = parse_address_key(p, "pid", &pid);
954 [ # # ]: 0 : if (r < 0)
955 : 0 : return r;
956 [ # # ]: 0 : else if (r > 0)
957 : 0 : continue;
958 : :
959 : 0 : skip_address_key(p);
960 : : }
961 : :
962 [ # # ]: 0 : if (!machine == !pid)
963 : 0 : return -EINVAL;
964 : :
965 [ # # ]: 0 : if (machine) {
966 [ # # # # ]: 0 : if (!streq(machine, ".host") && !machine_name_is_valid(machine))
967 : 0 : return -EINVAL;
968 : :
969 : 0 : free_and_replace(b->machine, machine);
970 : : } else {
971 : 0 : b->machine = mfree(b->machine);
972 : : }
973 : :
974 [ # # ]: 0 : if (pid) {
975 : 0 : r = parse_pid(pid, &b->nspid);
976 [ # # ]: 0 : if (r < 0)
977 : 0 : return r;
978 : : } else
979 : 0 : b->nspid = 0;
980 : :
981 : 0 : b->sockaddr.un = (struct sockaddr_un) {
982 : : .sun_family = AF_UNIX,
983 : : /* Note that we use the old /var/run prefix here, to increase compatibility with really old containers */
984 : : .sun_path = "/var/run/dbus/system_bus_socket",
985 : : };
986 [ # # # # ]: 0 : b->sockaddr_size = SOCKADDR_UN_LEN(b->sockaddr.un);
987 : 0 : b->is_local = false;
988 : :
989 : 0 : return 0;
990 : : }
991 : :
992 : 128 : static void bus_reset_parsed_address(sd_bus *b) {
993 [ - + ]: 128 : assert(b);
994 : :
995 [ + - ]: 128 : zero(b->sockaddr);
996 : 128 : b->sockaddr_size = 0;
997 : 128 : b->exec_argv = strv_free(b->exec_argv);
998 : 128 : b->exec_path = mfree(b->exec_path);
999 : 128 : b->server_id = SD_ID128_NULL;
1000 : 128 : b->machine = mfree(b->machine);
1001 : 128 : b->nspid = 0;
1002 : 128 : }
1003 : :
1004 : 128 : static int bus_parse_next_address(sd_bus *b) {
1005 : 128 : _cleanup_free_ char *guid = NULL;
1006 : : const char *a;
1007 : : int r;
1008 : :
1009 [ - + ]: 128 : assert(b);
1010 : :
1011 [ - + ]: 128 : if (!b->address)
1012 : 0 : return 0;
1013 [ - + ]: 128 : if (b->address[b->address_index] == 0)
1014 : 0 : return 0;
1015 : :
1016 : 128 : bus_reset_parsed_address(b);
1017 : :
1018 : 128 : a = b->address + b->address_index;
1019 : :
1020 [ + - ]: 128 : while (*a != 0) {
1021 : :
1022 [ - + ]: 128 : if (*a == ';') {
1023 : 0 : a++;
1024 : 0 : continue;
1025 : : }
1026 : :
1027 [ + - ]: 128 : if (startswith(a, "unix:")) {
1028 : 128 : a += 5;
1029 : :
1030 : 128 : r = parse_unix_address(b, &a, &guid);
1031 [ - + ]: 128 : if (r < 0)
1032 : 0 : return r;
1033 : 128 : break;
1034 : :
1035 [ # # ]: 0 : } else if (startswith(a, "tcp:")) {
1036 : :
1037 : 0 : a += 4;
1038 : 0 : r = parse_tcp_address(b, &a, &guid);
1039 [ # # ]: 0 : if (r < 0)
1040 : 0 : return r;
1041 : :
1042 : 0 : break;
1043 : :
1044 [ # # ]: 0 : } else if (startswith(a, "unixexec:")) {
1045 : :
1046 : 0 : a += 9;
1047 : 0 : r = parse_exec_address(b, &a, &guid);
1048 [ # # ]: 0 : if (r < 0)
1049 : 0 : return r;
1050 : :
1051 : 0 : break;
1052 : :
1053 [ # # ]: 0 : } else if (startswith(a, "x-machine-unix:")) {
1054 : :
1055 : 0 : a += 15;
1056 : 0 : r = parse_container_unix_address(b, &a, &guid);
1057 [ # # ]: 0 : if (r < 0)
1058 : 0 : return r;
1059 : :
1060 : 0 : break;
1061 : : }
1062 : :
1063 : 0 : a = strchr(a, ';');
1064 [ # # ]: 0 : if (!a)
1065 : 0 : return 0;
1066 : : }
1067 : :
1068 [ - + ]: 128 : if (guid) {
1069 : 0 : r = sd_id128_from_string(guid, &b->server_id);
1070 [ # # ]: 0 : if (r < 0)
1071 : 0 : return r;
1072 : : }
1073 : :
1074 : 128 : b->address_index = a - b->address;
1075 : 128 : return 1;
1076 : : }
1077 : :
1078 : 432 : static void bus_kill_exec(sd_bus *bus) {
1079 [ - + ]: 432 : if (pid_is_valid(bus->busexec_pid) > 0) {
1080 : 0 : sigterm_wait(bus->busexec_pid);
1081 : 0 : bus->busexec_pid = 0;
1082 : : }
1083 : 432 : }
1084 : :
1085 : 128 : static int bus_start_address(sd_bus *b) {
1086 : : int r;
1087 : :
1088 [ - + ]: 128 : assert(b);
1089 : :
1090 : : for (;;) {
1091 : 256 : bus_close_io_fds(b);
1092 : 256 : bus_close_inotify_fd(b);
1093 : :
1094 : 256 : bus_kill_exec(b);
1095 : :
1096 : : /* If you provide multiple different bus-addresses, we
1097 : : * try all of them in order and use the first one that
1098 : : * succeeds. */
1099 : :
1100 [ - + ]: 256 : if (b->exec_path)
1101 : 0 : r = bus_socket_exec(b);
1102 [ + - - + : 256 : else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC)
# # ]
1103 : 0 : r = bus_container_connect_socket(b);
1104 [ + + ]: 256 : else if (b->sockaddr.sa.sa_family != AF_UNSPEC)
1105 : 128 : r = bus_socket_connect(b);
1106 : : else
1107 : 128 : goto next;
1108 : :
1109 [ + - ]: 128 : if (r >= 0) {
1110 : : int q;
1111 : :
1112 : 128 : q = bus_attach_io_events(b);
1113 [ - + ]: 128 : if (q < 0)
1114 : 0 : return q;
1115 : :
1116 : 128 : q = bus_attach_inotify_event(b);
1117 [ - + ]: 128 : if (q < 0)
1118 : 0 : return q;
1119 : :
1120 : 128 : return r;
1121 : : }
1122 : :
1123 : 0 : b->last_connect_error = -r;
1124 : :
1125 : 128 : next:
1126 : 128 : r = bus_parse_next_address(b);
1127 [ - + ]: 128 : if (r < 0)
1128 : 0 : return r;
1129 [ - + ]: 128 : if (r == 0)
1130 [ # # ]: 0 : return b->last_connect_error > 0 ? -b->last_connect_error : -ECONNREFUSED;
1131 : : }
1132 : : }
1133 : :
1134 : 0 : int bus_next_address(sd_bus *b) {
1135 [ # # ]: 0 : assert(b);
1136 : :
1137 : 0 : bus_reset_parsed_address(b);
1138 : 0 : return bus_start_address(b);
1139 : : }
1140 : :
1141 : 76 : static int bus_start_fd(sd_bus *b) {
1142 : : struct stat st;
1143 : : int r;
1144 : :
1145 [ - + ]: 76 : assert(b);
1146 [ - + ]: 76 : assert(b->input_fd >= 0);
1147 [ - + ]: 76 : assert(b->output_fd >= 0);
1148 : :
1149 : 76 : r = fd_nonblock(b->input_fd, true);
1150 [ - + ]: 76 : if (r < 0)
1151 : 0 : return r;
1152 : :
1153 : 76 : r = fd_cloexec(b->input_fd, true);
1154 [ - + ]: 76 : if (r < 0)
1155 : 0 : return r;
1156 : :
1157 [ - + ]: 76 : if (b->input_fd != b->output_fd) {
1158 : 0 : r = fd_nonblock(b->output_fd, true);
1159 [ # # ]: 0 : if (r < 0)
1160 : 0 : return r;
1161 : :
1162 : 0 : r = fd_cloexec(b->output_fd, true);
1163 [ # # ]: 0 : if (r < 0)
1164 : 0 : return r;
1165 : : }
1166 : :
1167 [ - + ]: 76 : if (fstat(b->input_fd, &st) < 0)
1168 : 0 : return -errno;
1169 : :
1170 : 76 : return bus_socket_take_fd(b);
1171 : : }
1172 : :
1173 : 204 : _public_ int sd_bus_start(sd_bus *bus) {
1174 : : int r;
1175 : :
1176 [ - + - + ]: 204 : assert_return(bus, -EINVAL);
1177 [ - + - + ]: 204 : assert_return(bus = bus_resolve(bus), -ENOPKG);
1178 [ - + - + ]: 204 : assert_return(bus->state == BUS_UNSET, -EPERM);
1179 [ - + - + ]: 204 : assert_return(!bus_pid_changed(bus), -ECHILD);
1180 : :
1181 : 204 : bus_set_state(bus, BUS_OPENING);
1182 : :
1183 [ + + - + ]: 204 : if (bus->is_server && bus->bus_client)
1184 : 0 : return -EINVAL;
1185 : :
1186 [ + + ]: 204 : if (bus->input_fd >= 0)
1187 : 76 : r = bus_start_fd(bus);
1188 [ - + # # : 128 : else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->machine)
# # # # ]
1189 : 128 : r = bus_start_address(bus);
1190 : : else
1191 : 0 : return -EINVAL;
1192 : :
1193 [ - + ]: 204 : if (r < 0) {
1194 : 0 : sd_bus_close(bus);
1195 : 0 : return r;
1196 : : }
1197 : :
1198 : 204 : return bus_send_hello(bus);
1199 : : }
1200 : :
1201 : 0 : _public_ int sd_bus_open_with_description(sd_bus **ret, const char *description) {
1202 : : const char *e;
1203 : 0 : _cleanup_(bus_freep) sd_bus *b = NULL;
1204 : : int r;
1205 : :
1206 [ # # # # ]: 0 : assert_return(ret, -EINVAL);
1207 : :
1208 : : /* Let's connect to the starter bus if it is set, and
1209 : : * otherwise to the bus that is appropriate for the scope
1210 : : * we are running in */
1211 : :
1212 : 0 : e = secure_getenv("DBUS_STARTER_BUS_TYPE");
1213 [ # # ]: 0 : if (e) {
1214 [ # # ]: 0 : if (streq(e, "system"))
1215 : 0 : return sd_bus_open_system_with_description(ret, description);
1216 [ # # ]: 0 : else if (STR_IN_SET(e, "session", "user"))
1217 : 0 : return sd_bus_open_user_with_description(ret, description);
1218 : : }
1219 : :
1220 : 0 : e = secure_getenv("DBUS_STARTER_ADDRESS");
1221 [ # # ]: 0 : if (!e) {
1222 [ # # ]: 0 : if (cg_pid_get_owner_uid(0, NULL) >= 0)
1223 : 0 : return sd_bus_open_user_with_description(ret, description);
1224 : : else
1225 : 0 : return sd_bus_open_system_with_description(ret, description);
1226 : : }
1227 : :
1228 : 0 : r = sd_bus_new(&b);
1229 [ # # ]: 0 : if (r < 0)
1230 : 0 : return r;
1231 : :
1232 : 0 : r = sd_bus_set_address(b, e);
1233 [ # # ]: 0 : if (r < 0)
1234 : 0 : return r;
1235 : :
1236 : 0 : b->bus_client = true;
1237 : :
1238 : : /* We don't know whether the bus is trusted or not, so better
1239 : : * be safe, and authenticate everything */
1240 : 0 : b->trusted = false;
1241 : 0 : b->is_local = false;
1242 : 0 : b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS;
1243 : :
1244 : 0 : r = sd_bus_start(b);
1245 [ # # ]: 0 : if (r < 0)
1246 : 0 : return r;
1247 : :
1248 : 0 : *ret = TAKE_PTR(b);
1249 : 0 : return 0;
1250 : : }
1251 : :
1252 : 0 : _public_ int sd_bus_open(sd_bus **ret) {
1253 : 0 : return sd_bus_open_with_description(ret, NULL);
1254 : : }
1255 : :
1256 : 60 : int bus_set_address_system(sd_bus *b) {
1257 : : const char *e;
1258 [ - + ]: 60 : assert(b);
1259 : :
1260 : 60 : e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
1261 [ - + ]: 60 : if (e)
1262 : 0 : return sd_bus_set_address(b, e);
1263 : :
1264 : 60 : return sd_bus_set_address(b, DEFAULT_SYSTEM_BUS_ADDRESS);
1265 : : }
1266 : :
1267 : 60 : _public_ int sd_bus_open_system_with_description(sd_bus **ret, const char *description) {
1268 : 60 : _cleanup_(bus_freep) sd_bus *b = NULL;
1269 : : int r;
1270 : :
1271 [ - + - + ]: 60 : assert_return(ret, -EINVAL);
1272 : :
1273 : 60 : r = sd_bus_new(&b);
1274 [ - + ]: 60 : if (r < 0)
1275 : 0 : return r;
1276 : :
1277 [ + + ]: 60 : if (description) {
1278 : 52 : r = sd_bus_set_description(b, description);
1279 [ - + ]: 52 : if (r < 0)
1280 : 0 : return r;
1281 : : }
1282 : :
1283 : 60 : r = bus_set_address_system(b);
1284 [ - + ]: 60 : if (r < 0)
1285 : 0 : return r;
1286 : :
1287 : 60 : b->bus_client = true;
1288 : 60 : b->is_system = true;
1289 : :
1290 : : /* Let's do per-method access control on the system bus. We
1291 : : * need the caller's UID and capability set for that. */
1292 : 60 : b->trusted = false;
1293 : 60 : b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS;
1294 : 60 : b->is_local = true;
1295 : :
1296 : 60 : r = sd_bus_start(b);
1297 [ - + ]: 60 : if (r < 0)
1298 : 0 : return r;
1299 : :
1300 : 60 : *ret = TAKE_PTR(b);
1301 : 60 : return 0;
1302 : : }
1303 : :
1304 : 8 : _public_ int sd_bus_open_system(sd_bus **ret) {
1305 : 8 : return sd_bus_open_system_with_description(ret, NULL);
1306 : : }
1307 : :
1308 : 44 : int bus_set_address_user(sd_bus *b) {
1309 : : const char *e;
1310 : 44 : _cleanup_free_ char *ee = NULL, *s = NULL;
1311 : :
1312 [ - + ]: 44 : assert(b);
1313 : :
1314 : 44 : e = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
1315 [ + - ]: 44 : if (e)
1316 : 44 : return sd_bus_set_address(b, e);
1317 : :
1318 : 0 : e = secure_getenv("XDG_RUNTIME_DIR");
1319 [ # # ]: 0 : if (!e)
1320 : 0 : return -ENOENT;
1321 : :
1322 : 0 : ee = bus_address_escape(e);
1323 [ # # ]: 0 : if (!ee)
1324 : 0 : return -ENOMEM;
1325 : :
1326 [ # # ]: 0 : if (asprintf(&s, DEFAULT_USER_BUS_ADDRESS_FMT, ee) < 0)
1327 : 0 : return -ENOMEM;
1328 : :
1329 : 0 : b->address = TAKE_PTR(s);
1330 : :
1331 : 0 : return 0;
1332 : : }
1333 : :
1334 : 44 : _public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *description) {
1335 : 44 : _cleanup_(bus_freep) sd_bus *b = NULL;
1336 : : int r;
1337 : :
1338 [ - + - + ]: 44 : assert_return(ret, -EINVAL);
1339 : :
1340 : 44 : r = sd_bus_new(&b);
1341 [ - + ]: 44 : if (r < 0)
1342 : 0 : return r;
1343 : :
1344 [ + + ]: 44 : if (description) {
1345 : 4 : r = sd_bus_set_description(b, description);
1346 [ - + ]: 4 : if (r < 0)
1347 : 0 : return r;
1348 : : }
1349 : :
1350 : 44 : r = bus_set_address_user(b);
1351 [ - + ]: 44 : if (r < 0)
1352 : 0 : return r;
1353 : :
1354 : 44 : b->bus_client = true;
1355 : 44 : b->is_user = true;
1356 : :
1357 : : /* We don't do any per-method access control on the user
1358 : : * bus. */
1359 : 44 : b->trusted = true;
1360 : 44 : b->is_local = true;
1361 : :
1362 : 44 : r = sd_bus_start(b);
1363 [ - + ]: 44 : if (r < 0)
1364 : 0 : return r;
1365 : :
1366 : 44 : *ret = TAKE_PTR(b);
1367 : 44 : return 0;
1368 : : }
1369 : :
1370 : 40 : _public_ int sd_bus_open_user(sd_bus **ret) {
1371 : 40 : return sd_bus_open_user_with_description(ret, NULL);
1372 : : }
1373 : :
1374 : 52 : int bus_set_address_system_remote(sd_bus *b, const char *host) {
1375 : 52 : _cleanup_free_ char *e = NULL;
1376 : 52 : char *m = NULL, *c = NULL, *a, *rbracket = NULL, *p = NULL;
1377 : :
1378 [ - + ]: 52 : assert(b);
1379 [ - + ]: 52 : assert(host);
1380 : :
1381 : : /* Skip ":"s in ipv6 addresses */
1382 [ + + ]: 52 : if (*host == '[') {
1383 : : char *t;
1384 : :
1385 : 4 : rbracket = strchr(host, ']');
1386 [ - + ]: 4 : if (!rbracket)
1387 : 0 : return -EINVAL;
1388 : 4 : t = strndupa(host + 1, rbracket - host - 1);
1389 : 4 : e = bus_address_escape(t);
1390 [ - + ]: 4 : if (!e)
1391 : 0 : return -ENOMEM;
1392 [ + + ]: 48 : } else if ((a = strchr(host, '@'))) {
1393 [ + + ]: 32 : if (*(a + 1) == '[') {
1394 [ + + ]: 16 : _cleanup_free_ char *t = NULL;
1395 : :
1396 : 16 : rbracket = strchr(a + 1, ']');
1397 [ + + ]: 16 : if (!rbracket)
1398 : 4 : return -EINVAL;
1399 [ + - ]: 12 : t = new0(char, strlen(host));
1400 [ - + ]: 12 : if (!t)
1401 : 0 : return -ENOMEM;
1402 : 12 : strncat(t, host, a - host + 1);
1403 : 12 : strncat(t, a + 2, rbracket - a - 2);
1404 : 12 : e = bus_address_escape(t);
1405 [ - + ]: 12 : if (!e)
1406 : 0 : return -ENOMEM;
1407 [ + + + + ]: 16 : } else if (*(a + 1) == '\0' || strchr(a + 1, '@'))
1408 : 12 : return -EINVAL;
1409 : : }
1410 : :
1411 : : /* Let's see if a port was given */
1412 [ + + ]: 36 : m = strchr(rbracket ? rbracket + 1 : host, ':');
1413 [ + + ]: 36 : if (m) {
1414 : : char *t;
1415 : 20 : bool got_forward_slash = false;
1416 : :
1417 : 20 : p = m + 1;
1418 : :
1419 : 20 : t = strchr(p, '/');
1420 [ - + ]: 20 : if (t) {
1421 : 0 : p = strndupa(p, t - p);
1422 : 0 : got_forward_slash = true;
1423 : : }
1424 : :
1425 [ + + + + ]: 20 : if (!in_charset(p, "0123456789") || *p == '\0') {
1426 [ - + # # ]: 12 : if (!machine_name_is_valid(p) || got_forward_slash)
1427 : 12 : return -EINVAL;
1428 : :
1429 : 0 : m = TAKE_PTR(p);
1430 : 0 : goto interpret_port_as_machine_old_syntax;
1431 : : }
1432 : : }
1433 : :
1434 : : /* Let's see if a machine was given */
1435 [ + + ]: 24 : m = strchr(rbracket ? rbracket + 1 : host, '/');
1436 [ - + ]: 24 : if (m) {
1437 : 0 : m++;
1438 : 0 : interpret_port_as_machine_old_syntax:
1439 : : /* Let's make sure this is not a port of some kind,
1440 : : * and is a valid machine name. */
1441 [ # # # # ]: 0 : if (!in_charset(m, "0123456789") && machine_name_is_valid(m))
1442 [ # # # # : 0 : c = strjoina(",argv", p ? "7" : "5", "=--machine=", m);
# # # # #
# # # #
# ]
1443 : : }
1444 : :
1445 [ + + ]: 24 : if (!e) {
1446 : : char *t;
1447 : :
1448 : 12 : t = strndupa(host, strcspn(host, ":/"));
1449 : :
1450 : 12 : e = bus_address_escape(t);
1451 [ - + ]: 12 : if (!e)
1452 : 0 : return -ENOMEM;
1453 : : }
1454 : :
1455 [ + + + + : 24 : a = strjoin("unixexec:path=ssh,argv1=-xT", p ? ",argv2=-p,argv3=" : "", strempty(p),
+ + + + ]
1456 : : ",argv", p ? "4" : "2", "=--,argv", p ? "5" : "3", "=", e,
1457 : : ",argv", p ? "6" : "4", "=systemd-stdio-bridge", c);
1458 [ - + ]: 24 : if (!a)
1459 : 0 : return -ENOMEM;
1460 : :
1461 : 24 : return free_and_replace(b->address, a);
1462 : : }
1463 : :
1464 : 0 : _public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) {
1465 : 0 : _cleanup_(bus_freep) sd_bus *b = NULL;
1466 : : int r;
1467 : :
1468 [ # # # # ]: 0 : assert_return(host, -EINVAL);
1469 [ # # # # ]: 0 : assert_return(ret, -EINVAL);
1470 : :
1471 : 0 : r = sd_bus_new(&b);
1472 [ # # ]: 0 : if (r < 0)
1473 : 0 : return r;
1474 : :
1475 : 0 : r = bus_set_address_system_remote(b, host);
1476 [ # # ]: 0 : if (r < 0)
1477 : 0 : return r;
1478 : :
1479 : 0 : b->bus_client = true;
1480 : 0 : b->trusted = false;
1481 : 0 : b->is_system = true;
1482 : 0 : b->is_local = false;
1483 : :
1484 : 0 : r = sd_bus_start(b);
1485 [ # # ]: 0 : if (r < 0)
1486 : 0 : return r;
1487 : :
1488 : 0 : *ret = TAKE_PTR(b);
1489 : 0 : return 0;
1490 : : }
1491 : :
1492 : 0 : int bus_set_address_system_machine(sd_bus *b, const char *machine) {
1493 : 0 : _cleanup_free_ char *e = NULL;
1494 : : char *a;
1495 : :
1496 [ # # ]: 0 : assert(b);
1497 [ # # ]: 0 : assert(machine);
1498 : :
1499 : 0 : e = bus_address_escape(machine);
1500 [ # # ]: 0 : if (!e)
1501 : 0 : return -ENOMEM;
1502 : :
1503 : 0 : a = strjoin("x-machine-unix:machine=", e);
1504 [ # # ]: 0 : if (!a)
1505 : 0 : return -ENOMEM;
1506 : :
1507 : 0 : return free_and_replace(b->address, a);
1508 : : }
1509 : :
1510 : 0 : _public_ int sd_bus_open_system_machine(sd_bus **ret, const char *machine) {
1511 : 0 : _cleanup_(bus_freep) sd_bus *b = NULL;
1512 : : int r;
1513 : :
1514 [ # # # # ]: 0 : assert_return(machine, -EINVAL);
1515 [ # # # # ]: 0 : assert_return(ret, -EINVAL);
1516 [ # # # # : 0 : assert_return(streq(machine, ".host") || machine_name_is_valid(machine), -EINVAL);
# # ]
1517 : :
1518 : 0 : r = sd_bus_new(&b);
1519 [ # # ]: 0 : if (r < 0)
1520 : 0 : return r;
1521 : :
1522 : 0 : r = bus_set_address_system_machine(b, machine);
1523 [ # # ]: 0 : if (r < 0)
1524 : 0 : return r;
1525 : :
1526 : 0 : b->bus_client = true;
1527 : 0 : b->trusted = false;
1528 : 0 : b->is_system = true;
1529 : 0 : b->is_local = false;
1530 : :
1531 : 0 : r = sd_bus_start(b);
1532 [ # # ]: 0 : if (r < 0)
1533 : 0 : return r;
1534 : :
1535 : 0 : *ret = TAKE_PTR(b);
1536 : 0 : return 0;
1537 : : }
1538 : :
1539 : 136 : _public_ void sd_bus_close(sd_bus *bus) {
1540 [ - + ]: 136 : if (!bus)
1541 : 0 : return;
1542 [ + + ]: 136 : if (bus->state == BUS_CLOSED)
1543 : 16 : return;
1544 [ - + ]: 120 : if (bus_pid_changed(bus))
1545 : 0 : return;
1546 : :
1547 : : /* Don't leave ssh hanging around */
1548 : 120 : bus_kill_exec(bus);
1549 : :
1550 : 120 : bus_set_state(bus, BUS_CLOSED);
1551 : :
1552 : 120 : sd_bus_detach_event(bus);
1553 : :
1554 : : /* Drop all queued messages so that they drop references to
1555 : : * the bus object and the bus may be freed */
1556 : 120 : bus_reset_queues(bus);
1557 : :
1558 : 120 : bus_close_io_fds(bus);
1559 : 120 : bus_close_inotify_fd(bus);
1560 : : }
1561 : :
1562 : 108 : _public_ sd_bus *sd_bus_close_unref(sd_bus *bus) {
1563 [ - + ]: 108 : if (!bus)
1564 : 0 : return NULL;
1565 : :
1566 : 108 : sd_bus_close(bus);
1567 : :
1568 : 108 : return sd_bus_unref(bus);
1569 : : }
1570 : :
1571 : 96 : _public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) {
1572 [ + + ]: 96 : if (!bus)
1573 : 40 : return NULL;
1574 : :
1575 : : /* Have to do this before flush() to prevent hang */
1576 : 56 : bus_kill_exec(bus);
1577 : 56 : sd_bus_flush(bus);
1578 : :
1579 : 56 : return sd_bus_close_unref(bus);
1580 : : }
1581 : :
1582 : 8 : void bus_enter_closing(sd_bus *bus) {
1583 [ - + ]: 8 : assert(bus);
1584 : :
1585 [ + - - + ]: 8 : if (!IN_SET(bus->state, BUS_WATCH_BIND, BUS_OPENING, BUS_AUTHENTICATING, BUS_HELLO, BUS_RUNNING))
1586 : 0 : return;
1587 : :
1588 : 8 : bus_set_state(bus, BUS_CLOSING);
1589 : : }
1590 : :
1591 [ - + - + : 7840 : DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus, sd_bus, bus_free);
+ + ]
1592 : :
1593 : 0 : _public_ int sd_bus_is_open(sd_bus *bus) {
1594 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
1595 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
1596 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
1597 : :
1598 : 0 : return BUS_IS_OPEN(bus->state);
1599 : : }
1600 : :
1601 : 0 : _public_ int sd_bus_is_ready(sd_bus *bus) {
1602 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
1603 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
1604 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
1605 : :
1606 : 0 : return bus->state == BUS_RUNNING;
1607 : : }
1608 : :
1609 : 32 : _public_ int sd_bus_can_send(sd_bus *bus, char type) {
1610 : : int r;
1611 : :
1612 [ - + - + ]: 32 : assert_return(bus, -EINVAL);
1613 [ - + - + ]: 32 : assert_return(bus = bus_resolve(bus), -ENOPKG);
1614 [ - + - + ]: 32 : assert_return(bus->state != BUS_UNSET, -ENOTCONN);
1615 [ - + - + ]: 32 : assert_return(!bus_pid_changed(bus), -ECHILD);
1616 : :
1617 [ - + ]: 32 : if (bus->is_monitor)
1618 : 0 : return 0;
1619 : :
1620 [ + - ]: 32 : if (type == SD_BUS_TYPE_UNIX_FD) {
1621 [ + + ]: 32 : if (!bus->accept_fd)
1622 : 8 : return 0;
1623 : :
1624 : 24 : r = bus_ensure_running(bus);
1625 [ - + ]: 24 : if (r < 0)
1626 : 0 : return r;
1627 : :
1628 : 24 : return bus->can_fds;
1629 : : }
1630 : :
1631 : 0 : return bus_type_is_valid(type);
1632 : : }
1633 : :
1634 : 4 : _public_ int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id) {
1635 : : int r;
1636 : :
1637 [ - + - + ]: 4 : assert_return(bus, -EINVAL);
1638 [ - + - + ]: 4 : assert_return(bus = bus_resolve(bus), -ENOPKG);
1639 [ - + - + ]: 4 : assert_return(id, -EINVAL);
1640 [ - + - + ]: 4 : assert_return(!bus_pid_changed(bus), -ECHILD);
1641 : :
1642 : 4 : r = bus_ensure_running(bus);
1643 [ - + ]: 4 : if (r < 0)
1644 : 0 : return r;
1645 : :
1646 : 4 : *id = bus->server_id;
1647 : 4 : return 0;
1648 : : }
1649 : :
1650 : : #define COOKIE_CYCLED (UINT32_C(1) << 31)
1651 : :
1652 : 560 : static uint64_t cookie_inc(uint64_t cookie) {
1653 : :
1654 : : /* Stay within the 32bit range, since classic D-Bus can't deal with more */
1655 [ - + ]: 560 : if (cookie >= UINT32_MAX)
1656 : 0 : return COOKIE_CYCLED; /* Don't go back to zero, but use the highest bit for checking
1657 : : * whether we are looping. */
1658 : :
1659 : 560 : return cookie + 1;
1660 : : }
1661 : :
1662 : 560 : static int next_cookie(sd_bus *b) {
1663 : : uint64_t new_cookie;
1664 : :
1665 [ - + ]: 560 : assert(b);
1666 : :
1667 : 560 : new_cookie = cookie_inc(b->cookie);
1668 : :
1669 : : /* Small optimization: don't bother with checking for cookie reuse until we overran cookiespace at
1670 : : * least once, but then do it thorougly. */
1671 [ - + ]: 560 : if (FLAGS_SET(new_cookie, COOKIE_CYCLED)) {
1672 : : uint32_t i;
1673 : :
1674 : : /* Check if the cookie is currently in use. If so, pick the next one */
1675 [ # # ]: 0 : for (i = 0; i < COOKIE_CYCLED; i++) {
1676 [ # # ]: 0 : if (!ordered_hashmap_contains(b->reply_callbacks, &new_cookie))
1677 : 0 : goto good;
1678 : :
1679 : 0 : new_cookie = cookie_inc(new_cookie);
1680 : : }
1681 : :
1682 : : /* Can't fulfill request */
1683 : 0 : return -EBUSY;
1684 : : }
1685 : :
1686 : 560 : good:
1687 : 560 : b->cookie = new_cookie;
1688 : 560 : return 0;
1689 : : }
1690 : :
1691 : 912 : static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
1692 : : int r;
1693 : :
1694 [ - + ]: 912 : assert(b);
1695 [ - + ]: 912 : assert(m);
1696 : :
1697 [ + + ]: 912 : if (m->sealed) {
1698 : : /* If we copy the same message to multiple
1699 : : * destinations, avoid using the same cookie
1700 : : * numbers. */
1701 : 352 : b->cookie = MAX(b->cookie, BUS_MESSAGE_COOKIE(m));
1702 : 352 : return 0;
1703 : : }
1704 : :
1705 [ + + ]: 560 : if (timeout == 0) {
1706 : 552 : r = sd_bus_get_method_call_timeout(b, &timeout);
1707 [ - + ]: 552 : if (r < 0)
1708 : 0 : return r;
1709 : : }
1710 : :
1711 [ + - - + ]: 560 : if (!m->sender && b->patch_sender) {
1712 : 0 : r = sd_bus_message_set_sender(m, b->patch_sender);
1713 [ # # ]: 0 : if (r < 0)
1714 : 0 : return r;
1715 : : }
1716 : :
1717 : 560 : r = next_cookie(b);
1718 [ - + ]: 560 : if (r < 0)
1719 : 0 : return r;
1720 : :
1721 : 560 : return sd_bus_message_seal(m, b->cookie, timeout);
1722 : : }
1723 : :
1724 : 908 : static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) {
1725 : 908 : bool remarshal = false;
1726 : :
1727 [ - + ]: 908 : assert(b);
1728 : :
1729 : : /* wrong packet version */
1730 [ + - - + ]: 908 : if (b->message_version != 0 && b->message_version != (*m)->header->version)
1731 : 0 : remarshal = true;
1732 : :
1733 : : /* wrong packet endianness */
1734 [ - + # # ]: 908 : if (b->message_endian != 0 && b->message_endian != (*m)->header->endian)
1735 : 0 : remarshal = true;
1736 : :
1737 [ - + ]: 908 : return remarshal ? bus_message_remarshal(b, m) : 0;
1738 : : }
1739 : :
1740 : 12 : int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) {
1741 [ - + ]: 12 : assert(b);
1742 [ - + ]: 12 : assert(m);
1743 : :
1744 : : /* Fake some timestamps, if they were requested, and not
1745 : : * already initialized */
1746 [ - + ]: 12 : if (b->attach_timestamp) {
1747 [ # # ]: 0 : if (m->realtime <= 0)
1748 : 0 : m->realtime = now(CLOCK_REALTIME);
1749 : :
1750 [ # # ]: 0 : if (m->monotonic <= 0)
1751 : 0 : m->monotonic = now(CLOCK_MONOTONIC);
1752 : : }
1753 : :
1754 : : /* The bus specification says the serial number cannot be 0,
1755 : : * hence let's fill something in for synthetic messages. Since
1756 : : * synthetic messages might have a fake sender and we don't
1757 : : * want to interfere with the real sender's serial numbers we
1758 : : * pick a fixed, artificial one. We use (uint32_t) -1 rather
1759 : : * than (uint64_t) -1 since dbus1 only had 32bit identifiers,
1760 : : * even though kdbus can do 64bit. */
1761 : 12 : return sd_bus_message_seal(m, 0xFFFFFFFFULL, 0);
1762 : : }
1763 : :
1764 : 536 : static int bus_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
1765 : : int r;
1766 : :
1767 [ - + ]: 536 : assert(bus);
1768 [ - + ]: 536 : assert(m);
1769 : :
1770 : 536 : r = bus_socket_write_message(bus, m, idx);
1771 [ - + ]: 536 : if (r <= 0)
1772 : 0 : return r;
1773 : :
1774 [ + - ]: 536 : if (*idx >= BUS_MESSAGE_SIZE(m))
1775 [ + + ]: 536 : log_debug("Sent message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s",
1776 : : bus_message_type_to_string(m->header->type),
1777 : : strna(sd_bus_message_get_sender(m)),
1778 : : strna(sd_bus_message_get_destination(m)),
1779 : : strna(sd_bus_message_get_path(m)),
1780 : : strna(sd_bus_message_get_interface(m)),
1781 : : strna(sd_bus_message_get_member(m)),
1782 : : BUS_MESSAGE_COOKIE(m),
1783 : : m->reply_cookie,
1784 : : strna(m->root_container.signature),
1785 : : strna(m->error.name),
1786 : : strna(m->error.message));
1787 : :
1788 : 536 : return r;
1789 : : }
1790 : :
1791 : 827 : static int dispatch_wqueue(sd_bus *bus) {
1792 : 827 : int r, ret = 0;
1793 : :
1794 [ - + ]: 827 : assert(bus);
1795 [ + - - + ]: 827 : assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
1796 : :
1797 [ + + ]: 995 : while (bus->wqueue_size > 0) {
1798 : :
1799 : 168 : r = bus_write_message(bus, bus->wqueue[0], &bus->windex);
1800 [ - + ]: 168 : if (r < 0)
1801 : 0 : return r;
1802 [ - + ]: 168 : else if (r == 0)
1803 : : /* Didn't do anything this time */
1804 : 0 : return ret;
1805 [ + - ]: 168 : else if (bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
1806 : : /* Fully written. Let's drop the entry from
1807 : : * the queue.
1808 : : *
1809 : : * This isn't particularly optimized, but
1810 : : * well, this is supposed to be our worst-case
1811 : : * buffer only, and the socket buffer is
1812 : : * supposed to be our primary buffer, and if
1813 : : * it got full, then all bets are off
1814 : : * anyway. */
1815 : :
1816 : 168 : bus->wqueue_size--;
1817 : 168 : bus_message_unref_queued(bus->wqueue[0], bus);
1818 : 168 : memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
1819 : 168 : bus->windex = 0;
1820 : :
1821 : 168 : ret = 1;
1822 : : }
1823 : : }
1824 : :
1825 : 827 : return ret;
1826 : : }
1827 : :
1828 : 1341 : static int bus_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
1829 [ - + ]: 1341 : assert(bus);
1830 : :
1831 : 1341 : return bus_socket_read_message(bus);
1832 : : }
1833 : :
1834 : 530 : int bus_rqueue_make_room(sd_bus *bus) {
1835 [ - + ]: 530 : assert(bus);
1836 : :
1837 [ - + ]: 530 : if (bus->rqueue_size >= BUS_RQUEUE_MAX)
1838 : 0 : return -ENOBUFS;
1839 : :
1840 [ - + ]: 530 : if (!GREEDY_REALLOC(bus->rqueue, bus->rqueue_allocated, bus->rqueue_size + 1))
1841 : 0 : return -ENOMEM;
1842 : :
1843 : 530 : return 0;
1844 : : }
1845 : :
1846 : 522 : static void rqueue_drop_one(sd_bus *bus, size_t i) {
1847 [ - + ]: 522 : assert(bus);
1848 [ - + ]: 522 : assert(i < bus->rqueue_size);
1849 : :
1850 : 522 : bus_message_unref_queued(bus->rqueue[i], bus);
1851 : 522 : memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
1852 : 522 : bus->rqueue_size--;
1853 : 522 : }
1854 : :
1855 : 563 : static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **m) {
1856 : 563 : int r, ret = 0;
1857 : :
1858 [ - + ]: 563 : assert(bus);
1859 [ - + ]: 563 : assert(m);
1860 [ + - - + ]: 563 : assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
1861 : :
1862 : : /* Note that the priority logic is only available on kdbus,
1863 : : * where the rqueue is unused. We check the rqueue here
1864 : : * anyway, because it's simple... */
1865 : :
1866 : : for (;;) {
1867 [ + + ]: 1179 : if (bus->rqueue_size > 0) {
1868 : : /* Dispatch a queued message */
1869 : 358 : *m = sd_bus_message_ref(bus->rqueue[0]);
1870 : 358 : rqueue_drop_one(bus, 0);
1871 : 358 : return 1;
1872 : : }
1873 : :
1874 : : /* Try to read a new message */
1875 : 821 : r = bus_read_message(bus, hint_priority, priority);
1876 [ + + ]: 821 : if (r < 0)
1877 : 4 : return r;
1878 [ + + ]: 817 : if (r == 0) {
1879 : 201 : *m = NULL;
1880 : 201 : return ret;
1881 : : }
1882 : :
1883 : 616 : ret = 1;
1884 : : }
1885 : : }
1886 : :
1887 : 560 : _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) {
1888 : 1120 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
1889 : : int r;
1890 : :
1891 [ - + - + ]: 560 : assert_return(m, -EINVAL);
1892 : :
1893 [ - + ]: 560 : if (!bus)
1894 : 0 : bus = m->bus;
1895 : :
1896 [ - + - + ]: 560 : assert_return(!bus_pid_changed(bus), -ECHILD);
1897 : :
1898 [ - + ]: 560 : if (!BUS_IS_OPEN(bus->state))
1899 : 0 : return -ENOTCONN;
1900 : :
1901 [ + + ]: 560 : if (m->n_fds > 0) {
1902 : 4 : r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
1903 [ - + ]: 4 : if (r < 0)
1904 : 0 : return r;
1905 [ - + ]: 4 : if (r == 0)
1906 : 0 : return -EOPNOTSUPP;
1907 : : }
1908 : :
1909 : : /* If the cookie number isn't kept, then we know that no reply
1910 : : * is expected */
1911 [ + + + + ]: 560 : if (!cookie && !m->sealed)
1912 : 208 : m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
1913 : :
1914 : 560 : r = bus_seal_message(bus, m, 0);
1915 [ + + ]: 560 : if (r < 0)
1916 : 4 : return r;
1917 : :
1918 : : /* Remarshall if we have to. This will possibly unref the
1919 : : * message and place a replacement in m */
1920 : 556 : r = bus_remarshal_message(bus, &m);
1921 [ - + ]: 556 : if (r < 0)
1922 : 0 : return r;
1923 : :
1924 : : /* If this is a reply and no reply was requested, then let's
1925 : : * suppress this, if we can */
1926 [ - + ]: 556 : if (m->dont_send)
1927 : 0 : goto finish;
1928 : :
1929 [ + + + + : 924 : if (IN_SET(bus->state, BUS_RUNNING, BUS_HELLO) && bus->wqueue_size <= 0) {
+ - ]
1930 : 368 : size_t idx = 0;
1931 : :
1932 : 368 : r = bus_write_message(bus, m, &idx);
1933 [ - + ]: 368 : if (r < 0) {
1934 [ # # ]: 0 : if (ERRNO_IS_DISCONNECT(r)) {
1935 : 0 : bus_enter_closing(bus);
1936 : 0 : return -ECONNRESET;
1937 : : }
1938 : :
1939 : 0 : return r;
1940 : : }
1941 : :
1942 [ - + ]: 368 : if (idx < BUS_MESSAGE_SIZE(m)) {
1943 : : /* Wasn't fully written. So let's remember how
1944 : : * much was written. Note that the first entry
1945 : : * of the wqueue array is always allocated so
1946 : : * that we always can remember how much was
1947 : : * written. */
1948 : 0 : bus->wqueue[0] = bus_message_ref_queued(m, bus);
1949 : 0 : bus->wqueue_size = 1;
1950 : 0 : bus->windex = idx;
1951 : : }
1952 : :
1953 : : } else {
1954 : : /* Just append it to the queue. */
1955 : :
1956 [ - + ]: 188 : if (bus->wqueue_size >= BUS_WQUEUE_MAX)
1957 : 0 : return -ENOBUFS;
1958 : :
1959 [ - + ]: 188 : if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1))
1960 : 0 : return -ENOMEM;
1961 : :
1962 : 188 : bus->wqueue[bus->wqueue_size++] = bus_message_ref_queued(m, bus);
1963 : : }
1964 : :
1965 : 556 : finish:
1966 [ + + ]: 556 : if (cookie)
1967 : 348 : *cookie = BUS_MESSAGE_COOKIE(m);
1968 : :
1969 : 556 : return 1;
1970 : : }
1971 : :
1972 : 0 : _public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie) {
1973 : : int r;
1974 : :
1975 [ # # # # ]: 0 : assert_return(m, -EINVAL);
1976 : :
1977 [ # # ]: 0 : if (!bus)
1978 : 0 : bus = m->bus;
1979 : :
1980 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
1981 : :
1982 [ # # ]: 0 : if (!BUS_IS_OPEN(bus->state))
1983 : 0 : return -ENOTCONN;
1984 : :
1985 [ # # ]: 0 : if (!streq_ptr(m->destination, destination)) {
1986 : :
1987 [ # # ]: 0 : if (!destination)
1988 : 0 : return -EEXIST;
1989 : :
1990 : 0 : r = sd_bus_message_set_destination(m, destination);
1991 [ # # ]: 0 : if (r < 0)
1992 : 0 : return r;
1993 : : }
1994 : :
1995 : 0 : return sd_bus_send(bus, m, cookie);
1996 : : }
1997 : :
1998 : 348 : static usec_t calc_elapse(sd_bus *bus, uint64_t usec) {
1999 [ - + ]: 348 : assert(bus);
2000 : :
2001 [ - + ]: 348 : if (usec == (uint64_t) -1)
2002 : 0 : return 0;
2003 : :
2004 : : /* We start all timeouts the instant we enter BUS_HELLO/BUS_RUNNING state, so that the don't run in parallel
2005 : : * with any connection setup states. Hence, if a method callback is started earlier than that we just store the
2006 : : * relative timestamp, and afterwards the absolute one. */
2007 : :
2008 [ + + + + ]: 348 : if (IN_SET(bus->state, BUS_WATCH_BIND, BUS_OPENING, BUS_AUTHENTICATING))
2009 : 172 : return usec;
2010 : : else
2011 : 176 : return now(CLOCK_MONOTONIC) + usec;
2012 : : }
2013 : :
2014 : 64 : static int timeout_compare(const void *a, const void *b) {
2015 : 64 : const struct reply_callback *x = a, *y = b;
2016 : :
2017 [ + - - + ]: 64 : if (x->timeout_usec != 0 && y->timeout_usec == 0)
2018 : 0 : return -1;
2019 : :
2020 [ - + # # ]: 64 : if (x->timeout_usec == 0 && y->timeout_usec != 0)
2021 : 0 : return 1;
2022 : :
2023 [ + + ]: 64 : return CMP(x->timeout_usec, y->timeout_usec);
2024 : : }
2025 : :
2026 : 184 : _public_ int sd_bus_call_async(
2027 : : sd_bus *bus,
2028 : : sd_bus_slot **slot,
2029 : : sd_bus_message *_m,
2030 : : sd_bus_message_handler_t callback,
2031 : : void *userdata,
2032 : : uint64_t usec) {
2033 : :
2034 : 368 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
2035 : 184 : _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *s = NULL;
2036 : : int r;
2037 : :
2038 [ - + - + ]: 184 : assert_return(m, -EINVAL);
2039 [ - + - + ]: 184 : assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
2040 [ - + # # : 184 : assert_return(!m->sealed || (!!callback == !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)), -EINVAL);
- + ]
2041 : :
2042 [ - + ]: 184 : if (!bus)
2043 : 0 : bus = m->bus;
2044 : :
2045 [ - + - + ]: 184 : assert_return(!bus_pid_changed(bus), -ECHILD);
2046 : :
2047 [ - + ]: 184 : if (!BUS_IS_OPEN(bus->state))
2048 : 0 : return -ENOTCONN;
2049 : :
2050 : : /* If no callback is specified and there's no interest in a slot, then there's no reason to ask for a reply */
2051 [ + + + - : 184 : if (!callback && !slot && !m->sealed)
+ - ]
2052 : 4 : m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
2053 : :
2054 : 184 : r = ordered_hashmap_ensure_allocated(&bus->reply_callbacks, &uint64_hash_ops);
2055 [ - + ]: 184 : if (r < 0)
2056 : 0 : return r;
2057 : :
2058 : 184 : r = prioq_ensure_allocated(&bus->reply_callbacks_prioq, timeout_compare);
2059 [ - + ]: 184 : if (r < 0)
2060 : 0 : return r;
2061 : :
2062 : 184 : r = bus_seal_message(bus, m, usec);
2063 [ - + ]: 184 : if (r < 0)
2064 : 0 : return r;
2065 : :
2066 : 184 : r = bus_remarshal_message(bus, &m);
2067 [ - + ]: 184 : if (r < 0)
2068 : 0 : return r;
2069 : :
2070 [ + + + + ]: 184 : if (slot || callback) {
2071 : 180 : s = bus_slot_allocate(bus, !slot, BUS_REPLY_CALLBACK, sizeof(struct reply_callback), userdata);
2072 [ - + ]: 180 : if (!s)
2073 : 0 : return -ENOMEM;
2074 : :
2075 : 180 : s->reply_callback.callback = callback;
2076 : :
2077 : 180 : s->reply_callback.cookie = BUS_MESSAGE_COOKIE(m);
2078 : 180 : r = ordered_hashmap_put(bus->reply_callbacks, &s->reply_callback.cookie, &s->reply_callback);
2079 [ - + ]: 180 : if (r < 0) {
2080 : 0 : s->reply_callback.cookie = 0;
2081 : 0 : return r;
2082 : : }
2083 : :
2084 : 180 : s->reply_callback.timeout_usec = calc_elapse(bus, m->timeout);
2085 [ + - ]: 180 : if (s->reply_callback.timeout_usec != 0) {
2086 : 180 : r = prioq_put(bus->reply_callbacks_prioq, &s->reply_callback, &s->reply_callback.prioq_idx);
2087 [ - + ]: 180 : if (r < 0) {
2088 : 0 : s->reply_callback.timeout_usec = 0;
2089 : 0 : return r;
2090 : : }
2091 : : }
2092 : : }
2093 : :
2094 [ + + ]: 184 : r = sd_bus_send(bus, m, s ? &s->reply_callback.cookie : NULL);
2095 [ - + ]: 184 : if (r < 0)
2096 : 0 : return r;
2097 : :
2098 [ + + ]: 184 : if (slot)
2099 : 64 : *slot = s;
2100 : 184 : s = NULL;
2101 : :
2102 : 184 : return r;
2103 : : }
2104 : :
2105 : 356 : int bus_ensure_running(sd_bus *bus) {
2106 : : int r;
2107 : :
2108 [ - + ]: 356 : assert(bus);
2109 : :
2110 [ - + - + ]: 356 : if (IN_SET(bus->state, BUS_UNSET, BUS_CLOSED, BUS_CLOSING))
2111 : 0 : return -ENOTCONN;
2112 [ + + ]: 356 : if (bus->state == BUS_RUNNING)
2113 : 231 : return 1;
2114 : :
2115 : : for (;;) {
2116 : 437 : r = sd_bus_process(bus, NULL);
2117 [ + + ]: 437 : if (r < 0)
2118 : 4 : return r;
2119 [ + + ]: 433 : if (bus->state == BUS_RUNNING)
2120 : 121 : return 1;
2121 [ + + ]: 312 : if (r > 0)
2122 : 172 : continue;
2123 : :
2124 : 140 : r = sd_bus_wait(bus, (uint64_t) -1);
2125 [ - + ]: 140 : if (r < 0)
2126 : 0 : return r;
2127 : : }
2128 : : }
2129 : :
2130 : 172 : _public_ int sd_bus_call(
2131 : : sd_bus *bus,
2132 : : sd_bus_message *_m,
2133 : : uint64_t usec,
2134 : : sd_bus_error *error,
2135 : : sd_bus_message **reply) {
2136 : :
2137 : 344 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
2138 : : usec_t timeout;
2139 : : uint64_t cookie;
2140 : : size_t i;
2141 : : int r;
2142 : :
2143 [ - + - + ]: 172 : bus_assert_return(m, -EINVAL, error);
2144 [ - + - + ]: 172 : bus_assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL, error);
2145 [ - + - + ]: 172 : bus_assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL, error);
2146 [ - + - + ]: 172 : bus_assert_return(!bus_error_is_dirty(error), -EINVAL, error);
2147 : :
2148 [ - + ]: 172 : if (!bus)
2149 : 0 : bus = m->bus;
2150 : :
2151 [ - + - + ]: 172 : bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
2152 : :
2153 [ - + ]: 172 : if (!BUS_IS_OPEN(bus->state)) {
2154 : 0 : r = -ENOTCONN;
2155 : 0 : goto fail;
2156 : : }
2157 : :
2158 : 172 : r = bus_ensure_running(bus);
2159 [ + + ]: 172 : if (r < 0)
2160 : 4 : goto fail;
2161 : :
2162 : 168 : i = bus->rqueue_size;
2163 : :
2164 : 168 : r = bus_seal_message(bus, m, usec);
2165 [ - + ]: 168 : if (r < 0)
2166 : 0 : goto fail;
2167 : :
2168 : 168 : r = bus_remarshal_message(bus, &m);
2169 [ - + ]: 168 : if (r < 0)
2170 : 0 : goto fail;
2171 : :
2172 : 168 : r = sd_bus_send(bus, m, &cookie);
2173 [ - + ]: 168 : if (r < 0)
2174 : 0 : goto fail;
2175 : :
2176 : 168 : timeout = calc_elapse(bus, m->timeout);
2177 : :
2178 : 516 : for (;;) {
2179 : : usec_t left;
2180 : :
2181 [ + + ]: 736 : while (i < bus->rqueue_size) {
2182 [ + + - ]: 216 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *incoming = NULL;
2183 : :
2184 : 216 : incoming = sd_bus_message_ref(bus->rqueue[i]);
2185 : :
2186 [ + + ]: 216 : if (incoming->reply_cookie == cookie) {
2187 : : /* Found a match! */
2188 : :
2189 : 164 : rqueue_drop_one(bus, i);
2190 [ + + ]: 164 : log_debug_bus_message(incoming);
2191 : :
2192 [ + + ]: 164 : if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) {
2193 : :
2194 [ - + # # ]: 148 : if (incoming->n_fds <= 0 || bus->accept_fd) {
2195 [ + + ]: 148 : if (reply)
2196 : 92 : *reply = TAKE_PTR(incoming);
2197 : :
2198 : 148 : return 1;
2199 : : }
2200 : :
2201 : 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
2202 : :
2203 [ + - ]: 16 : } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
2204 : 16 : return sd_bus_error_copy(error, &incoming->error);
2205 : : else {
2206 : 0 : r = -EIO;
2207 : 0 : goto fail;
2208 : : }
2209 : :
2210 [ + + ]: 52 : } else if (BUS_MESSAGE_COOKIE(incoming) == cookie &&
2211 [ + - ]: 16 : bus->unique_name &&
2212 [ + - ]: 16 : incoming->sender &&
2213 [ - + ]: 16 : streq(bus->unique_name, incoming->sender)) {
2214 : :
2215 : 0 : rqueue_drop_one(bus, i);
2216 : :
2217 : : /* Our own message? Somebody is trying to send its own client a message,
2218 : : * let's not dead-lock, let's fail immediately. */
2219 : :
2220 : 0 : r = -ELOOP;
2221 : 0 : goto fail;
2222 : : }
2223 : :
2224 : : /* Try to read more, right-away */
2225 : 52 : i++;
2226 : : }
2227 : :
2228 : 520 : r = bus_read_message(bus, false, 0);
2229 [ - + ]: 520 : if (r < 0) {
2230 [ # # ]: 0 : if (ERRNO_IS_DISCONNECT(r)) {
2231 : 0 : bus_enter_closing(bus);
2232 : 0 : r = -ECONNRESET;
2233 : : }
2234 : :
2235 : 0 : goto fail;
2236 : : }
2237 [ + + ]: 520 : if (r > 0)
2238 : 356 : continue;
2239 : :
2240 [ + - ]: 164 : if (timeout > 0) {
2241 : : usec_t n;
2242 : :
2243 : 164 : n = now(CLOCK_MONOTONIC);
2244 [ - + ]: 164 : if (n >= timeout) {
2245 : 0 : r = -ETIMEDOUT;
2246 : 0 : goto fail;
2247 : : }
2248 : :
2249 : 164 : left = timeout - n;
2250 : : } else
2251 : 0 : left = (uint64_t) -1;
2252 : :
2253 : 164 : r = bus_poll(bus, true, left);
2254 [ - + ]: 164 : if (r < 0)
2255 : 0 : goto fail;
2256 [ + + ]: 164 : if (r == 0) {
2257 : 4 : r = -ETIMEDOUT;
2258 : 4 : goto fail;
2259 : : }
2260 : :
2261 : 160 : r = dispatch_wqueue(bus);
2262 [ - + ]: 160 : if (r < 0) {
2263 [ # # ]: 0 : if (ERRNO_IS_DISCONNECT(r)) {
2264 : 0 : bus_enter_closing(bus);
2265 : 0 : r = -ECONNRESET;
2266 : : }
2267 : :
2268 : 0 : goto fail;
2269 : : }
2270 : : }
2271 : :
2272 : 8 : fail:
2273 : 8 : return sd_bus_error_set_errno(error, r);
2274 : : }
2275 : :
2276 : 4 : _public_ int sd_bus_get_fd(sd_bus *bus) {
2277 : :
2278 [ - + - + ]: 4 : assert_return(bus, -EINVAL);
2279 [ - + - + ]: 4 : assert_return(bus = bus_resolve(bus), -ENOPKG);
2280 [ - + - + ]: 4 : assert_return(bus->input_fd == bus->output_fd, -EPERM);
2281 [ - + - + ]: 4 : assert_return(!bus_pid_changed(bus), -ECHILD);
2282 : :
2283 [ - + ]: 4 : if (bus->state == BUS_CLOSED)
2284 : 0 : return -ENOTCONN;
2285 : :
2286 [ - + ]: 4 : if (bus->inotify_fd >= 0)
2287 : 0 : return bus->inotify_fd;
2288 : :
2289 [ + - ]: 4 : if (bus->input_fd >= 0)
2290 : 4 : return bus->input_fd;
2291 : :
2292 : 0 : return -ENOTCONN;
2293 : : }
2294 : :
2295 : 666 : _public_ int sd_bus_get_events(sd_bus *bus) {
2296 : 666 : int flags = 0;
2297 : :
2298 [ - + - + ]: 666 : assert_return(bus, -EINVAL);
2299 [ - + - + ]: 666 : assert_return(bus = bus_resolve(bus), -ENOPKG);
2300 [ - + - + ]: 666 : assert_return(!bus_pid_changed(bus), -ECHILD);
2301 : :
2302 [ - - - + : 666 : switch (bus->state) {
+ + - ]
2303 : :
2304 : 0 : case BUS_UNSET:
2305 : : case BUS_CLOSED:
2306 : 0 : return -ENOTCONN;
2307 : :
2308 : 0 : case BUS_WATCH_BIND:
2309 : 0 : flags |= POLLIN;
2310 : 0 : break;
2311 : :
2312 : 0 : case BUS_OPENING:
2313 : 0 : flags |= POLLOUT;
2314 : 0 : break;
2315 : :
2316 : 157 : case BUS_AUTHENTICATING:
2317 [ + + ]: 157 : if (bus_socket_auth_needs_write(bus))
2318 : 12 : flags |= POLLOUT;
2319 : :
2320 : 157 : flags |= POLLIN;
2321 : 157 : break;
2322 : :
2323 : 505 : case BUS_RUNNING:
2324 : : case BUS_HELLO:
2325 [ + + ]: 505 : if (bus->rqueue_size <= 0)
2326 : 459 : flags |= POLLIN;
2327 [ + + ]: 505 : if (bus->wqueue_size > 0)
2328 : 31 : flags |= POLLOUT;
2329 : 505 : break;
2330 : :
2331 : 4 : case BUS_CLOSING:
2332 : 4 : break;
2333 : :
2334 : 0 : default:
2335 : 0 : assert_not_reached("Unknown state");
2336 : : }
2337 : :
2338 : 666 : return flags;
2339 : : }
2340 : :
2341 : 502 : _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
2342 : : struct reply_callback *c;
2343 : :
2344 [ - + - + ]: 502 : assert_return(bus, -EINVAL);
2345 [ - + - + ]: 502 : assert_return(bus = bus_resolve(bus), -ENOPKG);
2346 [ - + - + ]: 502 : assert_return(timeout_usec, -EINVAL);
2347 [ - + - + ]: 502 : assert_return(!bus_pid_changed(bus), -ECHILD);
2348 : :
2349 [ + + - + ]: 502 : if (!BUS_IS_OPEN(bus->state) && bus->state != BUS_CLOSING)
2350 : 0 : return -ENOTCONN;
2351 : :
2352 [ + + ]: 502 : if (bus->track_queue) {
2353 : 4 : *timeout_usec = 0;
2354 : 4 : return 1;
2355 : : }
2356 : :
2357 [ + + + - : 498 : switch (bus->state) {
- ]
2358 : :
2359 : 157 : case BUS_AUTHENTICATING:
2360 : 157 : *timeout_usec = bus->auth_timeout;
2361 : 157 : return 1;
2362 : :
2363 : 337 : case BUS_RUNNING:
2364 : : case BUS_HELLO:
2365 [ + + ]: 337 : if (bus->rqueue_size > 0) {
2366 : 12 : *timeout_usec = 0;
2367 : 12 : return 1;
2368 : : }
2369 : :
2370 : 325 : c = prioq_peek(bus->reply_callbacks_prioq);
2371 [ + + ]: 325 : if (!c) {
2372 : 184 : *timeout_usec = (uint64_t) -1;
2373 : 184 : return 0;
2374 : : }
2375 : :
2376 [ - + ]: 141 : if (c->timeout_usec == 0) {
2377 : 0 : *timeout_usec = (uint64_t) -1;
2378 : 0 : return 0;
2379 : : }
2380 : :
2381 : 141 : *timeout_usec = c->timeout_usec;
2382 : 141 : return 1;
2383 : :
2384 : 4 : case BUS_CLOSING:
2385 : 4 : *timeout_usec = 0;
2386 : 4 : return 1;
2387 : :
2388 : 0 : case BUS_WATCH_BIND:
2389 : : case BUS_OPENING:
2390 : 0 : *timeout_usec = (uint64_t) -1;
2391 : 0 : return 0;
2392 : :
2393 : 0 : default:
2394 : 0 : assert_not_reached("Unknown or unexpected stat");
2395 : : }
2396 : : }
2397 : :
2398 : 671 : static int process_timeout(sd_bus *bus) {
2399 : 671 : _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
2400 : 671 : _cleanup_(sd_bus_message_unrefp) sd_bus_message* m = NULL;
2401 : : struct reply_callback *c;
2402 : : sd_bus_slot *slot;
2403 : : bool is_hello;
2404 : : usec_t n;
2405 : : int r;
2406 : :
2407 [ - + ]: 671 : assert(bus);
2408 [ + - - + ]: 671 : assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
2409 : :
2410 : 671 : c = prioq_peek(bus->reply_callbacks_prioq);
2411 [ + + ]: 671 : if (!c)
2412 : 371 : return 0;
2413 : :
2414 : 300 : n = now(CLOCK_MONOTONIC);
2415 [ + + ]: 300 : if (c->timeout_usec > n)
2416 : 296 : return 0;
2417 : :
2418 : 4 : r = bus_message_new_synthetic_error(
2419 : : bus,
2420 : : c->cookie,
2421 : 4 : &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out"),
2422 : : &m);
2423 [ - + ]: 4 : if (r < 0)
2424 : 0 : return r;
2425 : :
2426 : 4 : m->read_counter = ++bus->read_counter;
2427 : :
2428 : 4 : r = bus_seal_synthetic_message(bus, m);
2429 [ - + ]: 4 : if (r < 0)
2430 : 0 : return r;
2431 : :
2432 [ - + ]: 4 : assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
2433 : 4 : c->timeout_usec = 0;
2434 : :
2435 : 4 : ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
2436 : 4 : c->cookie = 0;
2437 : :
2438 : 4 : slot = container_of(c, sd_bus_slot, reply_callback);
2439 : :
2440 : 4 : bus->iteration_counter++;
2441 : :
2442 [ - + # # ]: 4 : is_hello = bus->state == BUS_HELLO && c->callback == hello_callback;
2443 : :
2444 : 4 : bus->current_message = m;
2445 : 4 : bus->current_slot = sd_bus_slot_ref(slot);
2446 : 4 : bus->current_handler = c->callback;
2447 : 4 : bus->current_userdata = slot->userdata;
2448 : 4 : r = c->callback(m, slot->userdata, &error_buffer);
2449 : 4 : bus->current_userdata = NULL;
2450 : 4 : bus->current_handler = NULL;
2451 : 4 : bus->current_slot = NULL;
2452 : 4 : bus->current_message = NULL;
2453 : :
2454 [ + - ]: 4 : if (slot->floating)
2455 : 4 : bus_slot_disconnect(slot, true);
2456 : :
2457 : 4 : sd_bus_slot_unref(slot);
2458 : :
2459 : : /* When this is the hello message and it timed out, then make sure to propagate the error up, don't just log
2460 : : * and ignore the callback handler's return value. */
2461 [ - + ]: 4 : if (is_hello)
2462 : 0 : return r;
2463 : :
2464 : 4 : return bus_maybe_reply_error(m, r, &error_buffer);
2465 : : }
2466 : :
2467 : 358 : static int process_hello(sd_bus *bus, sd_bus_message *m) {
2468 [ - + ]: 358 : assert(bus);
2469 [ - + ]: 358 : assert(m);
2470 : :
2471 [ + + ]: 358 : if (bus->state != BUS_HELLO)
2472 : 262 : return 0;
2473 : :
2474 : : /* Let's make sure the first message on the bus is the HELLO
2475 : : * reply. But note that we don't actually parse the message
2476 : : * here (we leave that to the usual handling), we just verify
2477 : : * we don't let any earlier msg through. */
2478 : :
2479 [ + - - + ]: 96 : if (!IN_SET(m->header->type, SD_BUS_MESSAGE_METHOD_RETURN, SD_BUS_MESSAGE_METHOD_ERROR))
2480 : 0 : return -EIO;
2481 : :
2482 [ - + ]: 96 : if (m->reply_cookie != 1)
2483 : 0 : return -EIO;
2484 : :
2485 : 96 : return 0;
2486 : : }
2487 : :
2488 : 358 : static int process_reply(sd_bus *bus, sd_bus_message *m) {
2489 : 358 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *synthetic_reply = NULL;
2490 : 358 : _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
2491 : : struct reply_callback *c;
2492 : : sd_bus_slot *slot;
2493 : : bool is_hello;
2494 : : int r;
2495 : :
2496 [ - + ]: 358 : assert(bus);
2497 [ - + ]: 358 : assert(m);
2498 : :
2499 [ + + + + ]: 358 : if (!IN_SET(m->header->type, SD_BUS_MESSAGE_METHOD_RETURN, SD_BUS_MESSAGE_METHOD_ERROR))
2500 : 239 : return 0;
2501 : :
2502 [ + + + + : 119 : if (m->destination && bus->unique_name && !streq_ptr(m->destination, bus->unique_name))
- + ]
2503 : 0 : return 0;
2504 : :
2505 : 119 : c = ordered_hashmap_remove(bus->reply_callbacks, &m->reply_cookie);
2506 [ - + ]: 119 : if (!c)
2507 : 0 : return 0;
2508 : :
2509 : 119 : c->cookie = 0;
2510 : :
2511 : 119 : slot = container_of(c, sd_bus_slot, reply_callback);
2512 : :
2513 [ - + # # ]: 119 : if (m->n_fds > 0 && !bus->accept_fd) {
2514 : :
2515 : : /* If the reply contained a file descriptor which we
2516 : : * didn't want we pass an error instead. */
2517 : :
2518 : 0 : r = bus_message_new_synthetic_error(
2519 : : bus,
2520 : : m->reply_cookie,
2521 : 0 : &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptor"),
2522 : : &synthetic_reply);
2523 [ # # ]: 0 : if (r < 0)
2524 : 0 : return r;
2525 : :
2526 : : /* Copy over original timestamp */
2527 : 0 : synthetic_reply->realtime = m->realtime;
2528 : 0 : synthetic_reply->monotonic = m->monotonic;
2529 : 0 : synthetic_reply->seqnum = m->seqnum;
2530 : 0 : synthetic_reply->read_counter = m->read_counter;
2531 : :
2532 : 0 : r = bus_seal_synthetic_message(bus, synthetic_reply);
2533 [ # # ]: 0 : if (r < 0)
2534 : 0 : return r;
2535 : :
2536 : 0 : m = synthetic_reply;
2537 : : } else {
2538 : 119 : r = sd_bus_message_rewind(m, true);
2539 [ - + ]: 119 : if (r < 0)
2540 : 0 : return r;
2541 : : }
2542 : :
2543 [ + - ]: 119 : if (c->timeout_usec != 0) {
2544 : 119 : prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
2545 : 119 : c->timeout_usec = 0;
2546 : : }
2547 : :
2548 [ + + + - ]: 119 : is_hello = bus->state == BUS_HELLO && c->callback == hello_callback;
2549 : :
2550 : 119 : bus->current_slot = sd_bus_slot_ref(slot);
2551 : 119 : bus->current_handler = c->callback;
2552 : 119 : bus->current_userdata = slot->userdata;
2553 : 119 : r = c->callback(m, slot->userdata, &error_buffer);
2554 : 119 : bus->current_userdata = NULL;
2555 : 119 : bus->current_handler = NULL;
2556 : 119 : bus->current_slot = NULL;
2557 : :
2558 [ + - ]: 119 : if (slot->floating)
2559 : 119 : bus_slot_disconnect(slot, true);
2560 : :
2561 : 119 : sd_bus_slot_unref(slot);
2562 : :
2563 : : /* When this is the hello message and it failed, then make sure to propagate the error up, don't just log and
2564 : : * ignore the callback handler's return value. */
2565 [ + + ]: 119 : if (is_hello)
2566 : 96 : return r;
2567 : :
2568 : 23 : return bus_maybe_reply_error(m, r, &error_buffer);
2569 : : }
2570 : :
2571 : 247 : static int process_filter(sd_bus *bus, sd_bus_message *m) {
2572 : 247 : _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
2573 : : struct filter_callback *l;
2574 : : int r;
2575 : :
2576 [ - + ]: 247 : assert(bus);
2577 [ - + ]: 247 : assert(m);
2578 : :
2579 : : do {
2580 : 247 : bus->filter_callbacks_modified = false;
2581 : :
2582 [ - + ]: 247 : LIST_FOREACH(callbacks, l, bus->filter_callbacks) {
2583 : : sd_bus_slot *slot;
2584 : :
2585 [ # # ]: 0 : if (bus->filter_callbacks_modified)
2586 : 0 : break;
2587 : :
2588 : : /* Don't run this more than once per iteration */
2589 [ # # ]: 0 : if (l->last_iteration == bus->iteration_counter)
2590 : 0 : continue;
2591 : :
2592 : 0 : l->last_iteration = bus->iteration_counter;
2593 : :
2594 : 0 : r = sd_bus_message_rewind(m, true);
2595 [ # # ]: 0 : if (r < 0)
2596 : 0 : return r;
2597 : :
2598 : 0 : slot = container_of(l, sd_bus_slot, filter_callback);
2599 : :
2600 : 0 : bus->current_slot = sd_bus_slot_ref(slot);
2601 : 0 : bus->current_handler = l->callback;
2602 : 0 : bus->current_userdata = slot->userdata;
2603 : 0 : r = l->callback(m, slot->userdata, &error_buffer);
2604 : 0 : bus->current_userdata = NULL;
2605 : 0 : bus->current_handler = NULL;
2606 : 0 : bus->current_slot = sd_bus_slot_unref(slot);
2607 : :
2608 : 0 : r = bus_maybe_reply_error(m, r, &error_buffer);
2609 [ # # ]: 0 : if (r != 0)
2610 : 0 : return r;
2611 : :
2612 : : }
2613 : :
2614 [ - + ]: 247 : } while (bus->filter_callbacks_modified);
2615 : :
2616 : 247 : return 0;
2617 : : }
2618 : :
2619 : 247 : static int process_match(sd_bus *bus, sd_bus_message *m) {
2620 : : int r;
2621 : :
2622 [ - + ]: 247 : assert(bus);
2623 [ - + ]: 247 : assert(m);
2624 : :
2625 : : do {
2626 : 251 : bus->match_callbacks_modified = false;
2627 : :
2628 : 251 : r = bus_match_run(bus, &bus->match_callbacks, m);
2629 [ - + ]: 251 : if (r != 0)
2630 : 0 : return r;
2631 : :
2632 [ + + ]: 251 : } while (bus->match_callbacks_modified);
2633 : :
2634 : 247 : return 0;
2635 : : }
2636 : :
2637 : 243 : static int process_builtin(sd_bus *bus, sd_bus_message *m) {
2638 : 243 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2639 : : int r;
2640 : :
2641 [ - + ]: 243 : assert(bus);
2642 [ - + ]: 243 : assert(m);
2643 : :
2644 [ - + ]: 243 : if (bus->is_monitor)
2645 : 0 : return 0;
2646 : :
2647 [ - + ]: 243 : if (bus->manual_peer_interface)
2648 : 0 : return 0;
2649 : :
2650 [ + + ]: 243 : if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
2651 : 75 : return 0;
2652 : :
2653 [ + + ]: 168 : if (!streq_ptr(m->interface, "org.freedesktop.DBus.Peer"))
2654 : 164 : return 0;
2655 : :
2656 [ - + ]: 4 : if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
2657 : 0 : return 1;
2658 : :
2659 [ - + ]: 4 : if (streq_ptr(m->member, "Ping"))
2660 : 0 : r = sd_bus_message_new_method_return(m, &reply);
2661 [ + - ]: 4 : else if (streq_ptr(m->member, "GetMachineId")) {
2662 : : sd_id128_t id;
2663 : : char sid[33];
2664 : :
2665 : 4 : r = sd_id128_get_machine(&id);
2666 [ - + ]: 4 : if (r < 0)
2667 : 0 : return r;
2668 : :
2669 : 4 : r = sd_bus_message_new_method_return(m, &reply);
2670 [ - + ]: 4 : if (r < 0)
2671 : 0 : return r;
2672 : :
2673 : 4 : r = sd_bus_message_append(reply, "s", sd_id128_to_string(id, sid));
2674 : : } else {
2675 : 0 : r = sd_bus_message_new_method_errorf(
2676 : : m, &reply,
2677 : : SD_BUS_ERROR_UNKNOWN_METHOD,
2678 : : "Unknown method '%s' on interface '%s'.", m->member, m->interface);
2679 : : }
2680 [ - + ]: 4 : if (r < 0)
2681 : 0 : return r;
2682 : :
2683 : 4 : r = sd_bus_send(bus, reply, NULL);
2684 [ - + ]: 4 : if (r < 0)
2685 : 0 : return r;
2686 : :
2687 : 4 : return 1;
2688 : : }
2689 : :
2690 : 243 : static int process_fd_check(sd_bus *bus, sd_bus_message *m) {
2691 [ - + ]: 243 : assert(bus);
2692 [ - + ]: 243 : assert(m);
2693 : :
2694 : : /* If we got a message with a file descriptor which we didn't
2695 : : * want to accept, then let's drop it. How can this even
2696 : : * happen? For example, when the kernel queues a message into
2697 : : * an activatable names's queue which allows fds, and then is
2698 : : * delivered to us later even though we ourselves did not
2699 : : * negotiate it. */
2700 : :
2701 [ - + ]: 243 : if (bus->is_monitor)
2702 : 0 : return 0;
2703 : :
2704 [ + + ]: 243 : if (m->n_fds <= 0)
2705 : 239 : return 0;
2706 : :
2707 [ + - ]: 4 : if (bus->accept_fd)
2708 : 4 : return 0;
2709 : :
2710 [ # # ]: 0 : if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
2711 : 0 : return 1; /* just eat it up */
2712 : :
2713 : 0 : return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Message contains file descriptors, which I cannot accept. Sorry.");
2714 : : }
2715 : :
2716 : 358 : static int process_message(sd_bus *bus, sd_bus_message *m) {
2717 : : int r;
2718 : :
2719 [ - + ]: 358 : assert(bus);
2720 [ - + ]: 358 : assert(m);
2721 : :
2722 : 358 : bus->current_message = m;
2723 : 358 : bus->iteration_counter++;
2724 : :
2725 [ + + ]: 358 : log_debug_bus_message(m);
2726 : :
2727 : 358 : r = process_hello(bus, m);
2728 [ - + ]: 358 : if (r != 0)
2729 : 0 : goto finish;
2730 : :
2731 : 358 : r = process_reply(bus, m);
2732 [ + + ]: 358 : if (r != 0)
2733 : 115 : goto finish;
2734 : :
2735 : 243 : r = process_fd_check(bus, m);
2736 [ - + ]: 243 : if (r != 0)
2737 : 0 : goto finish;
2738 : :
2739 : 243 : r = process_filter(bus, m);
2740 [ - + ]: 243 : if (r != 0)
2741 : 0 : goto finish;
2742 : :
2743 : 243 : r = process_match(bus, m);
2744 [ - + ]: 243 : if (r != 0)
2745 : 0 : goto finish;
2746 : :
2747 : 243 : r = process_builtin(bus, m);
2748 [ + + ]: 243 : if (r != 0)
2749 : 4 : goto finish;
2750 : :
2751 : 239 : r = bus_process_object(bus, m);
2752 : :
2753 : 358 : finish:
2754 : 358 : bus->current_message = NULL;
2755 : 358 : return r;
2756 : : }
2757 : :
2758 : 567 : static int dispatch_track(sd_bus *bus) {
2759 [ - + ]: 567 : assert(bus);
2760 : :
2761 [ + + ]: 567 : if (!bus->track_queue)
2762 : 563 : return 0;
2763 : :
2764 : 4 : bus_track_dispatch(bus->track_queue);
2765 : 4 : return 1;
2766 : : }
2767 : :
2768 : 671 : static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) {
2769 : 671 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
2770 : : int r;
2771 : :
2772 [ - + ]: 671 : assert(bus);
2773 [ + - - + ]: 671 : assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
2774 : :
2775 : 671 : r = process_timeout(bus);
2776 [ + + ]: 671 : if (r != 0)
2777 : 4 : goto null_message;
2778 : :
2779 : 667 : r = dispatch_wqueue(bus);
2780 [ + + ]: 667 : if (r != 0)
2781 : 100 : goto null_message;
2782 : :
2783 : 567 : r = dispatch_track(bus);
2784 [ + + ]: 567 : if (r != 0)
2785 : 4 : goto null_message;
2786 : :
2787 : 563 : r = dispatch_rqueue(bus, hint_priority, priority, &m);
2788 [ + + ]: 563 : if (r < 0)
2789 : 4 : return r;
2790 [ + + ]: 559 : if (!m)
2791 : 201 : goto null_message;
2792 : :
2793 : 358 : r = process_message(bus, m);
2794 [ + + ]: 358 : if (r != 0)
2795 : 235 : goto null_message;
2796 : :
2797 [ + + ]: 123 : if (ret) {
2798 : 96 : r = sd_bus_message_rewind(m, true);
2799 [ - + ]: 96 : if (r < 0)
2800 : 0 : return r;
2801 : :
2802 : 96 : *ret = TAKE_PTR(m);
2803 : 96 : return 1;
2804 : : }
2805 : :
2806 [ - + ]: 27 : if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) {
2807 : :
2808 [ # # ]: 0 : log_debug("Unprocessed message call sender=%s object=%s interface=%s member=%s",
2809 : : strna(sd_bus_message_get_sender(m)),
2810 : : strna(sd_bus_message_get_path(m)),
2811 : : strna(sd_bus_message_get_interface(m)),
2812 : : strna(sd_bus_message_get_member(m)));
2813 : :
2814 : 0 : r = sd_bus_reply_method_errorf(
2815 : : m,
2816 : : SD_BUS_ERROR_UNKNOWN_OBJECT,
2817 : 0 : "Unknown object '%s'.", m->path);
2818 [ # # ]: 0 : if (r < 0)
2819 : 0 : return r;
2820 : : }
2821 : :
2822 : 27 : return 1;
2823 : :
2824 : 544 : null_message:
2825 [ + - + + ]: 544 : if (r >= 0 && ret)
2826 : 51 : *ret = NULL;
2827 : :
2828 : 544 : return r;
2829 : : }
2830 : :
2831 : 4 : static int bus_exit_now(sd_bus *bus) {
2832 [ - + ]: 4 : assert(bus);
2833 : :
2834 : : /* Exit due to close, if this is requested. If this is bus object is attached to an event source, invokes
2835 : : * sd_event_exit(), otherwise invokes libc exit(). */
2836 : :
2837 [ - + ]: 4 : if (bus->exited) /* did we already exit? */
2838 : 0 : return 0;
2839 [ - + ]: 4 : if (!bus->exit_triggered) /* was the exit condition triggered? */
2840 : 0 : return 0;
2841 [ + - ]: 4 : if (!bus->exit_on_disconnect) /* Shall we actually exit on disconnection? */
2842 : 4 : return 0;
2843 : :
2844 : 0 : bus->exited = true; /* never exit more than once */
2845 : :
2846 [ # # ]: 0 : log_debug("Bus connection disconnected, exiting.");
2847 : :
2848 [ # # ]: 0 : if (bus->event)
2849 : 0 : return sd_event_exit(bus->event, EXIT_FAILURE);
2850 : : else
2851 : 0 : exit(EXIT_FAILURE);
2852 : :
2853 : : assert_not_reached("exit() didn't exit?");
2854 : : }
2855 : :
2856 : 0 : static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c) {
2857 : 0 : _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
2858 : 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
2859 : : sd_bus_slot *slot;
2860 : : int r;
2861 : :
2862 [ # # ]: 0 : assert(bus);
2863 [ # # ]: 0 : assert(c);
2864 : :
2865 : 0 : r = bus_message_new_synthetic_error(
2866 : : bus,
2867 : : c->cookie,
2868 : 0 : &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
2869 : : &m);
2870 [ # # ]: 0 : if (r < 0)
2871 : 0 : return r;
2872 : :
2873 : 0 : m->read_counter = ++bus->read_counter;
2874 : :
2875 : 0 : r = bus_seal_synthetic_message(bus, m);
2876 [ # # ]: 0 : if (r < 0)
2877 : 0 : return r;
2878 : :
2879 [ # # ]: 0 : if (c->timeout_usec != 0) {
2880 : 0 : prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
2881 : 0 : c->timeout_usec = 0;
2882 : : }
2883 : :
2884 : 0 : ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
2885 : 0 : c->cookie = 0;
2886 : :
2887 : 0 : slot = container_of(c, sd_bus_slot, reply_callback);
2888 : :
2889 : 0 : bus->iteration_counter++;
2890 : :
2891 : 0 : bus->current_message = m;
2892 : 0 : bus->current_slot = sd_bus_slot_ref(slot);
2893 : 0 : bus->current_handler = c->callback;
2894 : 0 : bus->current_userdata = slot->userdata;
2895 : 0 : r = c->callback(m, slot->userdata, &error_buffer);
2896 : 0 : bus->current_userdata = NULL;
2897 : 0 : bus->current_handler = NULL;
2898 : 0 : bus->current_slot = NULL;
2899 : 0 : bus->current_message = NULL;
2900 : :
2901 [ # # ]: 0 : if (slot->floating)
2902 : 0 : bus_slot_disconnect(slot, true);
2903 : :
2904 : 0 : sd_bus_slot_unref(slot);
2905 : :
2906 : 0 : return bus_maybe_reply_error(m, r, &error_buffer);
2907 : : }
2908 : :
2909 : 8 : static int process_closing(sd_bus *bus, sd_bus_message **ret) {
2910 : 8 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
2911 : : struct reply_callback *c;
2912 : : int r;
2913 : :
2914 [ - + ]: 8 : assert(bus);
2915 [ - + ]: 8 : assert(bus->state == BUS_CLOSING);
2916 : :
2917 : : /* First, fail all outstanding method calls */
2918 : 8 : c = ordered_hashmap_first(bus->reply_callbacks);
2919 [ - + ]: 8 : if (c)
2920 : 0 : return process_closing_reply_callback(bus, c);
2921 : :
2922 : : /* Then, fake-drop all remaining bus tracking references */
2923 [ + + ]: 8 : if (bus->tracks) {
2924 : 4 : bus_track_close(bus->tracks);
2925 : 4 : return 1;
2926 : : }
2927 : :
2928 : : /* Then, synthesize a Disconnected message */
2929 : 4 : r = sd_bus_message_new_signal(
2930 : : bus,
2931 : : &m,
2932 : : "/org/freedesktop/DBus/Local",
2933 : : "org.freedesktop.DBus.Local",
2934 : : "Disconnected");
2935 [ - + ]: 4 : if (r < 0)
2936 : 0 : return r;
2937 : :
2938 : 4 : bus_message_set_sender_local(bus, m);
2939 : 4 : m->read_counter = ++bus->read_counter;
2940 : :
2941 : 4 : r = bus_seal_synthetic_message(bus, m);
2942 [ - + ]: 4 : if (r < 0)
2943 : 0 : return r;
2944 : :
2945 : 4 : sd_bus_close(bus);
2946 : :
2947 : 4 : bus->current_message = m;
2948 : 4 : bus->iteration_counter++;
2949 : :
2950 : 4 : r = process_filter(bus, m);
2951 [ - + ]: 4 : if (r != 0)
2952 : 0 : goto finish;
2953 : :
2954 : 4 : r = process_match(bus, m);
2955 [ - + ]: 4 : if (r != 0)
2956 : 0 : goto finish;
2957 : :
2958 : : /* Nothing else to do, exit now, if the condition holds */
2959 : 4 : bus->exit_triggered = true;
2960 : 4 : (void) bus_exit_now(bus);
2961 : :
2962 [ + - ]: 4 : if (ret)
2963 : 4 : *ret = TAKE_PTR(m);
2964 : :
2965 : 4 : r = 1;
2966 : :
2967 : 4 : finish:
2968 : 4 : bus->current_message = NULL;
2969 : :
2970 : 4 : return r;
2971 : : }
2972 : :
2973 : 1070 : static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) {
2974 : : int r;
2975 : :
2976 : : /* Returns 0 when we didn't do anything. This should cause the
2977 : : * caller to invoke sd_bus_wait() before returning the next
2978 : : * time. Returns > 0 when we did something, which possibly
2979 : : * means *ret is filled in with an unprocessed message. */
2980 : :
2981 [ - + - + ]: 1070 : assert_return(bus, -EINVAL);
2982 [ - + - + ]: 1070 : assert_return(bus = bus_resolve(bus), -ENOPKG);
2983 [ - + - + ]: 1070 : assert_return(!bus_pid_changed(bus), -ECHILD);
2984 : :
2985 : : /* We don't allow recursively invoking sd_bus_process(). */
2986 [ - + - + ]: 1070 : assert_return(!bus->current_message, -EBUSY);
2987 [ - + ]: 1070 : assert(!bus->current_slot); /* This should be NULL whenever bus->current_message is */
2988 : :
2989 : 2140 : BUS_DONT_DESTROY(bus);
2990 : :
2991 [ - + + - : 1070 : switch (bus->state) {
+ + + - ]
2992 : :
2993 : 0 : case BUS_UNSET:
2994 : 0 : return -ENOTCONN;
2995 : :
2996 : 4 : case BUS_CLOSED:
2997 : 4 : return -ECONNRESET;
2998 : :
2999 : 84 : case BUS_WATCH_BIND:
3000 : 84 : r = bus_socket_process_watch_bind(bus);
3001 : 84 : break;
3002 : :
3003 : 0 : case BUS_OPENING:
3004 : 0 : r = bus_socket_process_opening(bus);
3005 : 0 : break;
3006 : :
3007 : 303 : case BUS_AUTHENTICATING:
3008 : 303 : r = bus_socket_process_authenticating(bus);
3009 : 303 : break;
3010 : :
3011 : 671 : case BUS_RUNNING:
3012 : : case BUS_HELLO:
3013 : 671 : r = process_running(bus, hint_priority, priority, ret);
3014 [ + + ]: 671 : if (r >= 0)
3015 : 667 : return r;
3016 : :
3017 : : /* This branch initializes *ret, hence we don't use the generic error checking below */
3018 : 4 : break;
3019 : :
3020 : 8 : case BUS_CLOSING:
3021 : 8 : return process_closing(bus, ret);
3022 : :
3023 : 0 : default:
3024 : 0 : assert_not_reached("Unknown state");
3025 : : }
3026 : :
3027 [ + + ]: 391 : if (ERRNO_IS_DISCONNECT(r)) {
3028 : 8 : bus_enter_closing(bus);
3029 : 8 : r = 1;
3030 [ + + ]: 383 : } else if (r < 0)
3031 : 4 : return r;
3032 : :
3033 [ + + ]: 387 : if (ret)
3034 : 69 : *ret = NULL;
3035 : :
3036 : 387 : return r;
3037 : : }
3038 : :
3039 : 1070 : _public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
3040 : 1070 : return bus_process_internal(bus, false, 0, ret);
3041 : : }
3042 : :
3043 : 0 : _public_ int sd_bus_process_priority(sd_bus *bus, int64_t priority, sd_bus_message **ret) {
3044 : 0 : return bus_process_internal(bus, true, priority, ret);
3045 : : }
3046 : :
3047 : 459 : static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
3048 : 459 : struct pollfd p[2] = {};
3049 : : int r, n;
3050 : : struct timespec ts;
3051 : 459 : usec_t m = USEC_INFINITY;
3052 : :
3053 [ - + ]: 459 : assert(bus);
3054 : :
3055 [ - + ]: 459 : if (bus->state == BUS_CLOSING)
3056 : 0 : return 1;
3057 : :
3058 [ - + ]: 459 : if (!BUS_IS_OPEN(bus->state))
3059 : 0 : return -ENOTCONN;
3060 : :
3061 [ + + ]: 459 : if (bus->state == BUS_WATCH_BIND) {
3062 [ - + ]: 24 : assert(bus->inotify_fd >= 0);
3063 : :
3064 : 24 : p[0].events = POLLIN;
3065 : 24 : p[0].fd = bus->inotify_fd;
3066 : 24 : n = 1;
3067 : : } else {
3068 : : int e;
3069 : :
3070 : 435 : e = sd_bus_get_events(bus);
3071 [ - + ]: 435 : if (e < 0)
3072 : 0 : return e;
3073 : :
3074 [ + + ]: 435 : if (need_more)
3075 : : /* The caller really needs some more data, he doesn't
3076 : : * care about what's already read, or any timeouts
3077 : : * except its own. */
3078 : 164 : e |= POLLIN;
3079 : : else {
3080 : : usec_t until;
3081 : : /* The caller wants to process if there's something to
3082 : : * process, but doesn't care otherwise */
3083 : :
3084 : 271 : r = sd_bus_get_timeout(bus, &until);
3085 [ - + ]: 271 : if (r < 0)
3086 : 0 : return r;
3087 [ + + ]: 271 : if (r > 0)
3088 : 128 : m = usec_sub_unsigned(until, now(CLOCK_MONOTONIC));
3089 : : }
3090 : :
3091 : 435 : p[0].fd = bus->input_fd;
3092 [ + - ]: 435 : if (bus->output_fd == bus->input_fd) {
3093 : 435 : p[0].events = e;
3094 : 435 : n = 1;
3095 : : } else {
3096 : 0 : p[0].events = e & POLLIN;
3097 : 0 : p[1].fd = bus->output_fd;
3098 : 0 : p[1].events = e & POLLOUT;
3099 : 0 : n = 2;
3100 : : }
3101 : : }
3102 : :
3103 [ + + - + : 459 : if (timeout_usec != (uint64_t) -1 && (m == USEC_INFINITY || timeout_usec < m))
# # ]
3104 : 164 : m = timeout_usec;
3105 : :
3106 [ + + ]: 459 : r = ppoll(p, n, m == USEC_INFINITY ? NULL : timespec_store(&ts, m), NULL);
3107 [ - + ]: 459 : if (r < 0)
3108 : 0 : return -errno;
3109 : :
3110 : 459 : return r > 0 ? 1 : 0;
3111 : : }
3112 : :
3113 : 295 : _public_ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
3114 : :
3115 [ - + - + ]: 295 : assert_return(bus, -EINVAL);
3116 [ - + - + ]: 295 : assert_return(bus = bus_resolve(bus), -ENOPKG);
3117 [ - + - + ]: 295 : assert_return(!bus_pid_changed(bus), -ECHILD);
3118 : :
3119 [ - + ]: 295 : if (bus->state == BUS_CLOSING)
3120 : 0 : return 0;
3121 : :
3122 [ - + ]: 295 : if (!BUS_IS_OPEN(bus->state))
3123 : 0 : return -ENOTCONN;
3124 : :
3125 [ - + ]: 295 : if (bus->rqueue_size > 0)
3126 : 0 : return 0;
3127 : :
3128 : 295 : return bus_poll(bus, false, timeout_usec);
3129 : : }
3130 : :
3131 : 168 : _public_ int sd_bus_flush(sd_bus *bus) {
3132 : : int r;
3133 : :
3134 [ - + - + ]: 168 : assert_return(bus, -EINVAL);
3135 [ - + - + ]: 168 : assert_return(bus = bus_resolve(bus), -ENOPKG);
3136 [ - + - + ]: 168 : assert_return(!bus_pid_changed(bus), -ECHILD);
3137 : :
3138 [ + + ]: 168 : if (bus->state == BUS_CLOSING)
3139 : 4 : return 0;
3140 : :
3141 [ + + ]: 164 : if (!BUS_IS_OPEN(bus->state))
3142 : 20 : return -ENOTCONN;
3143 : :
3144 : : /* We never were connected? Don't hang in inotify for good, as there's no timeout set for it */
3145 [ - + ]: 144 : if (bus->state == BUS_WATCH_BIND)
3146 : 0 : return -EUNATCH;
3147 : :
3148 : 144 : r = bus_ensure_running(bus);
3149 [ - + ]: 144 : if (r < 0)
3150 : 0 : return r;
3151 : :
3152 [ + - ]: 144 : if (bus->wqueue_size <= 0)
3153 : 144 : return 0;
3154 : :
3155 : : for (;;) {
3156 : 0 : r = dispatch_wqueue(bus);
3157 [ # # ]: 0 : if (r < 0) {
3158 [ # # ]: 0 : if (ERRNO_IS_DISCONNECT(r)) {
3159 : 0 : bus_enter_closing(bus);
3160 : 0 : return -ECONNRESET;
3161 : : }
3162 : :
3163 : 0 : return r;
3164 : : }
3165 : :
3166 [ # # ]: 0 : if (bus->wqueue_size <= 0)
3167 : 0 : return 0;
3168 : :
3169 : 0 : r = bus_poll(bus, false, (uint64_t) -1);
3170 [ # # ]: 0 : if (r < 0)
3171 : 0 : return r;
3172 : : }
3173 : : }
3174 : :
3175 : 0 : _public_ int sd_bus_add_filter(
3176 : : sd_bus *bus,
3177 : : sd_bus_slot **slot,
3178 : : sd_bus_message_handler_t callback,
3179 : : void *userdata) {
3180 : :
3181 : : sd_bus_slot *s;
3182 : :
3183 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
3184 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
3185 [ # # # # ]: 0 : assert_return(callback, -EINVAL);
3186 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
3187 : :
3188 : 0 : s = bus_slot_allocate(bus, !slot, BUS_FILTER_CALLBACK, sizeof(struct filter_callback), userdata);
3189 [ # # ]: 0 : if (!s)
3190 : 0 : return -ENOMEM;
3191 : :
3192 : 0 : s->filter_callback.callback = callback;
3193 : :
3194 : 0 : bus->filter_callbacks_modified = true;
3195 [ # # # # ]: 0 : LIST_PREPEND(callbacks, bus->filter_callbacks, &s->filter_callback);
3196 : :
3197 [ # # ]: 0 : if (slot)
3198 : 0 : *slot = s;
3199 : :
3200 : 0 : return 0;
3201 : : }
3202 : :
3203 : 19 : static int add_match_callback(
3204 : : sd_bus_message *m,
3205 : : void *userdata,
3206 : : sd_bus_error *ret_error) {
3207 : :
3208 : 19 : sd_bus_slot *match_slot = userdata;
3209 : 19 : bool failed = false;
3210 : : int r;
3211 : :
3212 [ - + ]: 19 : assert(m);
3213 [ - + ]: 19 : assert(match_slot);
3214 : :
3215 : 19 : sd_bus_slot_ref(match_slot);
3216 : :
3217 [ - + ]: 19 : if (sd_bus_message_is_method_error(m, NULL)) {
3218 [ # # ]: 0 : log_debug_errno(sd_bus_message_get_errno(m),
3219 : : "Unable to add match %s, failing connection: %s",
3220 : : match_slot->match_callback.match_string,
3221 : : sd_bus_message_get_error(m)->message);
3222 : :
3223 : 0 : failed = true;
3224 : : } else
3225 [ - + ]: 19 : log_debug("Match %s successfully installed.", match_slot->match_callback.match_string);
3226 : :
3227 [ - + ]: 19 : if (match_slot->match_callback.install_callback) {
3228 : : sd_bus *bus;
3229 : :
3230 : 0 : bus = sd_bus_message_get_bus(m);
3231 : :
3232 : : /* This function has been called as slot handler, and we want to call another slot handler. Let's
3233 : : * update the slot callback metadata temporarily with our own data, and then revert back to the old
3234 : : * values. */
3235 : :
3236 [ # # ]: 0 : assert(bus->current_slot == match_slot->match_callback.install_slot);
3237 [ # # ]: 0 : assert(bus->current_handler == add_match_callback);
3238 [ # # ]: 0 : assert(bus->current_userdata == userdata);
3239 : :
3240 : 0 : bus->current_slot = match_slot;
3241 : 0 : bus->current_handler = match_slot->match_callback.install_callback;
3242 : 0 : bus->current_userdata = match_slot->userdata;
3243 : :
3244 : 0 : r = match_slot->match_callback.install_callback(m, match_slot->userdata, ret_error);
3245 : :
3246 : 0 : bus->current_slot = match_slot->match_callback.install_slot;
3247 : 0 : bus->current_handler = add_match_callback;
3248 : 0 : bus->current_userdata = userdata;
3249 : : } else {
3250 [ - + ]: 19 : if (failed) /* Generic failure handling: destroy the connection */
3251 : 0 : bus_enter_closing(sd_bus_message_get_bus(m));
3252 : :
3253 : 19 : r = 1;
3254 : : }
3255 : :
3256 : : /* We don't need the install method reply slot anymore, let's free it */
3257 : 19 : match_slot->match_callback.install_slot = sd_bus_slot_unref(match_slot->match_callback.install_slot);
3258 : :
3259 [ - + # # ]: 19 : if (failed && match_slot->floating)
3260 : 0 : bus_slot_disconnect(match_slot, true);
3261 : :
3262 : 19 : sd_bus_slot_unref(match_slot);
3263 : :
3264 : 19 : return r;
3265 : : }
3266 : :
3267 : 120 : static int bus_add_match_full(
3268 : : sd_bus *bus,
3269 : : sd_bus_slot **slot,
3270 : : bool asynchronous,
3271 : : const char *match,
3272 : : sd_bus_message_handler_t callback,
3273 : : sd_bus_message_handler_t install_callback,
3274 : : void *userdata) {
3275 : :
3276 : 120 : struct bus_match_component *components = NULL;
3277 : 120 : unsigned n_components = 0;
3278 : 120 : sd_bus_slot *s = NULL;
3279 : 120 : int r = 0;
3280 : :
3281 [ - + - + ]: 120 : assert_return(bus, -EINVAL);
3282 [ - + - + ]: 120 : assert_return(bus = bus_resolve(bus), -ENOPKG);
3283 [ - + - + ]: 120 : assert_return(match, -EINVAL);
3284 [ - + - + ]: 120 : assert_return(!bus_pid_changed(bus), -ECHILD);
3285 : :
3286 : 120 : r = bus_match_parse(match, &components, &n_components);
3287 [ - + ]: 120 : if (r < 0)
3288 : 0 : goto finish;
3289 : :
3290 : 120 : s = bus_slot_allocate(bus, !slot, BUS_MATCH_CALLBACK, sizeof(struct match_callback), userdata);
3291 [ - + ]: 120 : if (!s) {
3292 : 0 : r = -ENOMEM;
3293 : 0 : goto finish;
3294 : : }
3295 : :
3296 : 120 : s->match_callback.callback = callback;
3297 : 120 : s->match_callback.install_callback = install_callback;
3298 : :
3299 [ + - ]: 120 : if (bus->bus_client) {
3300 : : enum bus_match_scope scope;
3301 : :
3302 : 120 : scope = bus_match_get_scope(components, n_components);
3303 : :
3304 : : /* Do not install server-side matches for matches against the local service, interface or bus path. */
3305 [ + + ]: 120 : if (scope != BUS_MATCH_LOCAL) {
3306 : :
3307 : : /* We store the original match string, so that we can use it to remove the match again. */
3308 : :
3309 : 68 : s->match_callback.match_string = strdup(match);
3310 [ - + ]: 68 : if (!s->match_callback.match_string) {
3311 : 0 : r = -ENOMEM;
3312 : 0 : goto finish;
3313 : : }
3314 : :
3315 [ + + ]: 68 : if (asynchronous) {
3316 : 60 : r = bus_add_match_internal_async(bus,
3317 : : &s->match_callback.install_slot,
3318 : 60 : s->match_callback.match_string,
3319 : : add_match_callback,
3320 : : s);
3321 : :
3322 [ - + ]: 60 : if (r < 0)
3323 : 0 : return r;
3324 : :
3325 : : /* Make the slot of the match call floating now. We need the reference, but we don't
3326 : : * want that this match pins the bus object, hence we first create it non-floating, but
3327 : : * then make it floating. */
3328 : 60 : r = sd_bus_slot_set_floating(s->match_callback.install_slot, true);
3329 : : } else
3330 : 8 : r = bus_add_match_internal(bus, s->match_callback.match_string, &s->match_callback.after);
3331 [ - + ]: 68 : if (r < 0)
3332 : 0 : goto finish;
3333 : :
3334 : 68 : s->match_added = true;
3335 : : }
3336 : : }
3337 : :
3338 : 120 : bus->match_callbacks_modified = true;
3339 : 120 : r = bus_match_add(&bus->match_callbacks, components, n_components, &s->match_callback);
3340 [ - + ]: 120 : if (r < 0)
3341 : 0 : goto finish;
3342 : :
3343 [ + + ]: 120 : if (slot)
3344 : 8 : *slot = s;
3345 : 120 : s = NULL;
3346 : :
3347 : 120 : finish:
3348 : 120 : bus_match_parse_free(components, n_components);
3349 : 120 : sd_bus_slot_unref(s);
3350 : :
3351 : 120 : return r;
3352 : : }
3353 : :
3354 : 8 : _public_ int sd_bus_add_match(
3355 : : sd_bus *bus,
3356 : : sd_bus_slot **slot,
3357 : : const char *match,
3358 : : sd_bus_message_handler_t callback,
3359 : : void *userdata) {
3360 : :
3361 : 8 : return bus_add_match_full(bus, slot, false, match, callback, NULL, userdata);
3362 : : }
3363 : :
3364 : 112 : _public_ int sd_bus_add_match_async(
3365 : : sd_bus *bus,
3366 : : sd_bus_slot **slot,
3367 : : const char *match,
3368 : : sd_bus_message_handler_t callback,
3369 : : sd_bus_message_handler_t install_callback,
3370 : : void *userdata) {
3371 : :
3372 : 112 : return bus_add_match_full(bus, slot, true, match, callback, install_callback, userdata);
3373 : : }
3374 : :
3375 : 5373 : bool bus_pid_changed(sd_bus *bus) {
3376 [ - + ]: 5373 : assert(bus);
3377 : :
3378 : : /* We don't support people creating a bus connection and
3379 : : * keeping it around over a fork(). Let's complain. */
3380 : :
3381 : 5373 : return bus->original_pid != getpid_cached();
3382 : : }
3383 : :
3384 : 169 : static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
3385 : 169 : sd_bus *bus = userdata;
3386 : : int r;
3387 : :
3388 [ - + ]: 169 : assert(bus);
3389 : :
3390 : : /* Note that this is called both on input_fd, output_fd as well as inotify_fd events */
3391 : :
3392 : 169 : r = sd_bus_process(bus, NULL);
3393 [ - + ]: 169 : if (r < 0) {
3394 [ # # ]: 0 : log_debug_errno(r, "Processing of bus failed, closing down: %m");
3395 : 0 : bus_enter_closing(bus);
3396 : : }
3397 : :
3398 : 169 : return 1;
3399 : : }
3400 : :
3401 : 20 : static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) {
3402 : 20 : sd_bus *bus = userdata;
3403 : : int r;
3404 : :
3405 [ - + ]: 20 : assert(bus);
3406 : :
3407 : 20 : r = sd_bus_process(bus, NULL);
3408 [ - + ]: 20 : if (r < 0) {
3409 [ # # ]: 0 : log_debug_errno(r, "Processing of bus failed, closing down: %m");
3410 : 0 : bus_enter_closing(bus);
3411 : : }
3412 : :
3413 : 20 : return 1;
3414 : : }
3415 : :
3416 : 231 : static int prepare_callback(sd_event_source *s, void *userdata) {
3417 : 231 : sd_bus *bus = userdata;
3418 : : int r, e;
3419 : : usec_t until;
3420 : :
3421 [ - + ]: 231 : assert(s);
3422 [ - + ]: 231 : assert(bus);
3423 : :
3424 : 231 : e = sd_bus_get_events(bus);
3425 [ - + ]: 231 : if (e < 0) {
3426 : 0 : r = e;
3427 : 0 : goto fail;
3428 : : }
3429 : :
3430 [ - + ]: 231 : if (bus->output_fd != bus->input_fd) {
3431 : :
3432 : 0 : r = sd_event_source_set_io_events(bus->input_io_event_source, e & POLLIN);
3433 [ # # ]: 0 : if (r < 0)
3434 : 0 : goto fail;
3435 : :
3436 : 0 : r = sd_event_source_set_io_events(bus->output_io_event_source, e & POLLOUT);
3437 : : } else
3438 : 231 : r = sd_event_source_set_io_events(bus->input_io_event_source, e);
3439 [ - + ]: 231 : if (r < 0)
3440 : 0 : goto fail;
3441 : :
3442 : 231 : r = sd_bus_get_timeout(bus, &until);
3443 [ - + ]: 231 : if (r < 0)
3444 : 0 : goto fail;
3445 [ + + ]: 231 : if (r > 0) {
3446 : : int j;
3447 : :
3448 : 190 : j = sd_event_source_set_time(bus->time_event_source, until);
3449 [ - + ]: 190 : if (j < 0) {
3450 : 0 : r = j;
3451 : 0 : goto fail;
3452 : : }
3453 : : }
3454 : :
3455 : 231 : r = sd_event_source_set_enabled(bus->time_event_source, r > 0);
3456 [ - + ]: 231 : if (r < 0)
3457 : 0 : goto fail;
3458 : :
3459 : 231 : return 1;
3460 : :
3461 : 0 : fail:
3462 [ # # ]: 0 : log_debug_errno(r, "Preparing of bus events failed, closing down: %m");
3463 : 0 : bus_enter_closing(bus);
3464 : :
3465 : 0 : return 1;
3466 : : }
3467 : :
3468 : 20 : static int quit_callback(sd_event_source *event, void *userdata) {
3469 : 20 : sd_bus *bus = userdata;
3470 : :
3471 [ - + ]: 20 : assert(event);
3472 : :
3473 [ + - ]: 20 : if (bus->close_on_exit) {
3474 : 20 : sd_bus_flush(bus);
3475 : 20 : sd_bus_close(bus);
3476 : : }
3477 : :
3478 : 20 : return 1;
3479 : : }
3480 : :
3481 : 260 : int bus_attach_io_events(sd_bus *bus) {
3482 : : int r;
3483 : :
3484 [ - + ]: 260 : assert(bus);
3485 : :
3486 [ + + ]: 260 : if (bus->input_fd < 0)
3487 : 60 : return 0;
3488 : :
3489 [ + + ]: 200 : if (!bus->event)
3490 : 124 : return 0;
3491 : :
3492 [ + - ]: 76 : if (!bus->input_io_event_source) {
3493 : 76 : r = sd_event_add_io(bus->event, &bus->input_io_event_source, bus->input_fd, 0, io_callback, bus);
3494 [ - + ]: 76 : if (r < 0)
3495 : 0 : return r;
3496 : :
3497 : 76 : r = sd_event_source_set_prepare(bus->input_io_event_source, prepare_callback);
3498 [ - + ]: 76 : if (r < 0)
3499 : 0 : return r;
3500 : :
3501 : 76 : r = sd_event_source_set_priority(bus->input_io_event_source, bus->event_priority);
3502 [ - + ]: 76 : if (r < 0)
3503 : 0 : return r;
3504 : :
3505 : 76 : r = sd_event_source_set_description(bus->input_io_event_source, "bus-input");
3506 : : } else
3507 : 0 : r = sd_event_source_set_io_fd(bus->input_io_event_source, bus->input_fd);
3508 : :
3509 [ - + ]: 76 : if (r < 0)
3510 : 0 : return r;
3511 : :
3512 [ - + ]: 76 : if (bus->output_fd != bus->input_fd) {
3513 [ # # ]: 0 : assert(bus->output_fd >= 0);
3514 : :
3515 [ # # ]: 0 : if (!bus->output_io_event_source) {
3516 : 0 : r = sd_event_add_io(bus->event, &bus->output_io_event_source, bus->output_fd, 0, io_callback, bus);
3517 [ # # ]: 0 : if (r < 0)
3518 : 0 : return r;
3519 : :
3520 : 0 : r = sd_event_source_set_priority(bus->output_io_event_source, bus->event_priority);
3521 [ # # ]: 0 : if (r < 0)
3522 : 0 : return r;
3523 : :
3524 : 0 : r = sd_event_source_set_description(bus->input_io_event_source, "bus-output");
3525 : : } else
3526 : 0 : r = sd_event_source_set_io_fd(bus->output_io_event_source, bus->output_fd);
3527 : :
3528 [ # # ]: 0 : if (r < 0)
3529 : 0 : return r;
3530 : : }
3531 : :
3532 : 76 : return 0;
3533 : : }
3534 : :
3535 : 776 : static void bus_detach_io_events(sd_bus *bus) {
3536 [ - + ]: 776 : assert(bus);
3537 : :
3538 [ + + ]: 776 : if (bus->input_io_event_source) {
3539 : 76 : sd_event_source_set_enabled(bus->input_io_event_source, SD_EVENT_OFF);
3540 : 76 : bus->input_io_event_source = sd_event_source_unref(bus->input_io_event_source);
3541 : : }
3542 : :
3543 [ - + ]: 776 : if (bus->output_io_event_source) {
3544 : 0 : sd_event_source_set_enabled(bus->output_io_event_source, SD_EVENT_OFF);
3545 : 0 : bus->output_io_event_source = sd_event_source_unref(bus->output_io_event_source);
3546 : : }
3547 : 776 : }
3548 : :
3549 : 260 : int bus_attach_inotify_event(sd_bus *bus) {
3550 : : int r;
3551 : :
3552 [ - + ]: 260 : assert(bus);
3553 : :
3554 [ + + ]: 260 : if (bus->inotify_fd < 0)
3555 : 204 : return 0;
3556 : :
3557 [ + + ]: 56 : if (!bus->event)
3558 : 28 : return 0;
3559 : :
3560 [ + + ]: 28 : if (!bus->inotify_event_source) {
3561 : 4 : r = sd_event_add_io(bus->event, &bus->inotify_event_source, bus->inotify_fd, EPOLLIN, io_callback, bus);
3562 [ - + ]: 4 : if (r < 0)
3563 : 0 : return r;
3564 : :
3565 : 4 : r = sd_event_source_set_priority(bus->inotify_event_source, bus->event_priority);
3566 [ - + ]: 4 : if (r < 0)
3567 : 0 : return r;
3568 : :
3569 : 4 : r = sd_event_source_set_description(bus->inotify_event_source, "bus-inotify");
3570 : : } else
3571 : 24 : r = sd_event_source_set_io_fd(bus->inotify_event_source, bus->inotify_fd);
3572 [ - + ]: 28 : if (r < 0)
3573 : 0 : return r;
3574 : :
3575 : 28 : return 0;
3576 : : }
3577 : :
3578 : 792 : static void bus_detach_inotify_event(sd_bus *bus) {
3579 [ - + ]: 792 : assert(bus);
3580 : :
3581 [ + + ]: 792 : if (bus->inotify_event_source) {
3582 : 4 : sd_event_source_set_enabled(bus->inotify_event_source, SD_EVENT_OFF);
3583 : 4 : bus->inotify_event_source = sd_event_source_unref(bus->inotify_event_source);
3584 : : }
3585 : 792 : }
3586 : :
3587 : 76 : _public_ int sd_bus_attach_event(sd_bus *bus, sd_event *event, int priority) {
3588 : : int r;
3589 : :
3590 [ - + - + ]: 76 : assert_return(bus, -EINVAL);
3591 [ - + - + ]: 76 : assert_return(bus = bus_resolve(bus), -ENOPKG);
3592 [ - + - + ]: 76 : assert_return(!bus->event, -EBUSY);
3593 : :
3594 [ - + ]: 76 : assert(!bus->input_io_event_source);
3595 [ - + ]: 76 : assert(!bus->output_io_event_source);
3596 [ - + ]: 76 : assert(!bus->time_event_source);
3597 : :
3598 [ + - ]: 76 : if (event)
3599 : 76 : bus->event = sd_event_ref(event);
3600 : : else {
3601 : 0 : r = sd_event_default(&bus->event);
3602 [ # # ]: 0 : if (r < 0)
3603 : 0 : return r;
3604 : : }
3605 : :
3606 : 76 : bus->event_priority = priority;
3607 : :
3608 : 76 : r = sd_event_add_time(bus->event, &bus->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, bus);
3609 [ - + ]: 76 : if (r < 0)
3610 : 0 : goto fail;
3611 : :
3612 : 76 : r = sd_event_source_set_priority(bus->time_event_source, priority);
3613 [ - + ]: 76 : if (r < 0)
3614 : 0 : goto fail;
3615 : :
3616 : 76 : r = sd_event_source_set_description(bus->time_event_source, "bus-time");
3617 [ - + ]: 76 : if (r < 0)
3618 : 0 : goto fail;
3619 : :
3620 : 76 : r = sd_event_add_exit(bus->event, &bus->quit_event_source, quit_callback, bus);
3621 [ - + ]: 76 : if (r < 0)
3622 : 0 : goto fail;
3623 : :
3624 : 76 : r = sd_event_source_set_description(bus->quit_event_source, "bus-exit");
3625 [ - + ]: 76 : if (r < 0)
3626 : 0 : goto fail;
3627 : :
3628 : 76 : r = bus_attach_io_events(bus);
3629 [ - + ]: 76 : if (r < 0)
3630 : 0 : goto fail;
3631 : :
3632 : 76 : r = bus_attach_inotify_event(bus);
3633 [ - + ]: 76 : if (r < 0)
3634 : 0 : goto fail;
3635 : :
3636 : 76 : return 0;
3637 : :
3638 : 0 : fail:
3639 : 0 : sd_bus_detach_event(bus);
3640 : 0 : return r;
3641 : : }
3642 : :
3643 : 332 : _public_ int sd_bus_detach_event(sd_bus *bus) {
3644 [ - + - + ]: 332 : assert_return(bus, -EINVAL);
3645 [ - + - + ]: 332 : assert_return(bus = bus_resolve(bus), -ENOPKG);
3646 : :
3647 [ + + ]: 332 : if (!bus->event)
3648 : 256 : return 0;
3649 : :
3650 : 76 : bus_detach_io_events(bus);
3651 : 76 : bus_detach_inotify_event(bus);
3652 : :
3653 [ + - ]: 76 : if (bus->time_event_source) {
3654 : 76 : sd_event_source_set_enabled(bus->time_event_source, SD_EVENT_OFF);
3655 : 76 : bus->time_event_source = sd_event_source_unref(bus->time_event_source);
3656 : : }
3657 : :
3658 [ + - ]: 76 : if (bus->quit_event_source) {
3659 : 76 : sd_event_source_set_enabled(bus->quit_event_source, SD_EVENT_OFF);
3660 : 76 : bus->quit_event_source = sd_event_source_unref(bus->quit_event_source);
3661 : : }
3662 : :
3663 : 76 : bus->event = sd_event_unref(bus->event);
3664 : 76 : return 1;
3665 : : }
3666 : :
3667 : 20 : _public_ sd_event* sd_bus_get_event(sd_bus *bus) {
3668 [ - + - + ]: 20 : assert_return(bus, NULL);
3669 : :
3670 : 20 : return bus->event;
3671 : : }
3672 : :
3673 : 0 : _public_ sd_bus_message* sd_bus_get_current_message(sd_bus *bus) {
3674 [ # # # # ]: 0 : assert_return(bus, NULL);
3675 : :
3676 : 0 : return bus->current_message;
3677 : : }
3678 : :
3679 : 0 : _public_ sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus) {
3680 [ # # # # ]: 0 : assert_return(bus, NULL);
3681 : :
3682 : 0 : return bus->current_slot;
3683 : : }
3684 : :
3685 : 0 : _public_ sd_bus_message_handler_t sd_bus_get_current_handler(sd_bus *bus) {
3686 [ # # # # ]: 0 : assert_return(bus, NULL);
3687 : :
3688 : 0 : return bus->current_handler;
3689 : : }
3690 : :
3691 : 0 : _public_ void* sd_bus_get_current_userdata(sd_bus *bus) {
3692 [ # # # # ]: 0 : assert_return(bus, NULL);
3693 : :
3694 : 0 : return bus->current_userdata;
3695 : : }
3696 : :
3697 : 4 : static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus **ret) {
3698 : 4 : sd_bus *b = NULL;
3699 : : int r;
3700 : :
3701 [ - + ]: 4 : assert(bus_open);
3702 [ - + ]: 4 : assert(default_bus);
3703 : :
3704 [ - + ]: 4 : if (!ret)
3705 : 0 : return !!*default_bus;
3706 : :
3707 [ - + ]: 4 : if (*default_bus) {
3708 : 0 : *ret = sd_bus_ref(*default_bus);
3709 : 0 : return 0;
3710 : : }
3711 : :
3712 : 4 : r = bus_open(&b);
3713 [ - + ]: 4 : if (r < 0)
3714 : 0 : return r;
3715 : :
3716 : 4 : b->default_bus_ptr = default_bus;
3717 : 4 : b->tid = gettid();
3718 : 4 : *default_bus = b;
3719 : :
3720 : 4 : *ret = b;
3721 : 4 : return 1;
3722 : : }
3723 : :
3724 : 0 : _public_ int sd_bus_default_system(sd_bus **ret) {
3725 : 0 : return bus_default(sd_bus_open_system, &default_system_bus, ret);
3726 : : }
3727 : :
3728 : 4 : _public_ int sd_bus_default_user(sd_bus **ret) {
3729 : 4 : return bus_default(sd_bus_open_user, &default_user_bus, ret);
3730 : : }
3731 : :
3732 : 0 : _public_ int sd_bus_default(sd_bus **ret) {
3733 : 0 : int (*bus_open)(sd_bus **) = NULL;
3734 : : sd_bus **busp;
3735 : :
3736 : 0 : busp = bus_choose_default(&bus_open);
3737 : 0 : return bus_default(bus_open, busp, ret);
3738 : : }
3739 : :
3740 : 0 : _public_ int sd_bus_get_tid(sd_bus *b, pid_t *tid) {
3741 [ # # # # ]: 0 : assert_return(b, -EINVAL);
3742 [ # # # # ]: 0 : assert_return(tid, -EINVAL);
3743 [ # # # # ]: 0 : assert_return(!bus_pid_changed(b), -ECHILD);
3744 : :
3745 [ # # ]: 0 : if (b->tid != 0) {
3746 : 0 : *tid = b->tid;
3747 : 0 : return 0;
3748 : : }
3749 : :
3750 [ # # ]: 0 : if (b->event)
3751 : 0 : return sd_event_get_tid(b->event, tid);
3752 : :
3753 : 0 : return -ENXIO;
3754 : : }
3755 : :
3756 : 20 : _public_ int sd_bus_path_encode(const char *prefix, const char *external_id, char **ret_path) {
3757 : 20 : _cleanup_free_ char *e = NULL;
3758 : : char *ret;
3759 : :
3760 [ + + + + ]: 20 : assert_return(object_path_is_valid(prefix), -EINVAL);
3761 [ - + - + ]: 12 : assert_return(external_id, -EINVAL);
3762 [ - + - + ]: 12 : assert_return(ret_path, -EINVAL);
3763 : :
3764 : 12 : e = bus_label_escape(external_id);
3765 [ - + ]: 12 : if (!e)
3766 : 0 : return -ENOMEM;
3767 : :
3768 : 12 : ret = path_join(prefix, e);
3769 [ - + ]: 12 : if (!ret)
3770 : 0 : return -ENOMEM;
3771 : :
3772 : 12 : *ret_path = ret;
3773 : 12 : return 0;
3774 : : }
3775 : :
3776 : 16 : _public_ int sd_bus_path_decode(const char *path, const char *prefix, char **external_id) {
3777 : : const char *e;
3778 : : char *ret;
3779 : :
3780 [ - + - + ]: 16 : assert_return(object_path_is_valid(path), -EINVAL);
3781 [ - + - + ]: 16 : assert_return(object_path_is_valid(prefix), -EINVAL);
3782 [ - + - + ]: 16 : assert_return(external_id, -EINVAL);
3783 : :
3784 : 16 : e = object_path_startswith(path, prefix);
3785 [ + + ]: 16 : if (!e) {
3786 : 4 : *external_id = NULL;
3787 : 4 : return 0;
3788 : : }
3789 : :
3790 : 12 : ret = bus_label_unescape(e);
3791 [ - + ]: 12 : if (!ret)
3792 : 0 : return -ENOMEM;
3793 : :
3794 : 12 : *external_id = ret;
3795 : 12 : return 1;
3796 : : }
3797 : :
3798 : 4 : _public_ int sd_bus_path_encode_many(char **out, const char *path_template, ...) {
3799 : 4 : _cleanup_strv_free_ char **labels = NULL;
3800 : : char *path, *path_pos, **label_pos;
3801 : : const char *sep, *template_pos;
3802 : : size_t path_length;
3803 : : va_list list;
3804 : : int r;
3805 : :
3806 [ - + - + ]: 4 : assert_return(out, -EINVAL);
3807 [ - + - + ]: 4 : assert_return(path_template, -EINVAL);
3808 : :
3809 : 4 : path_length = strlen(path_template);
3810 : :
3811 : 4 : va_start(list, path_template);
3812 [ + + ]: 12 : for (sep = strchr(path_template, '%'); sep; sep = strchr(sep + 1, '%')) {
3813 : : const char *arg;
3814 : : char *label;
3815 : :
3816 : 8 : arg = va_arg(list, const char *);
3817 [ - + ]: 8 : if (!arg) {
3818 : 0 : va_end(list);
3819 : 0 : return -EINVAL;
3820 : : }
3821 : :
3822 : 8 : label = bus_label_escape(arg);
3823 [ - + ]: 8 : if (!label) {
3824 : 0 : va_end(list);
3825 : 0 : return -ENOMEM;
3826 : : }
3827 : :
3828 : 8 : r = strv_consume(&labels, label);
3829 [ - + ]: 8 : if (r < 0) {
3830 : 0 : va_end(list);
3831 : 0 : return r;
3832 : : }
3833 : :
3834 : : /* add label length, but account for the format character */
3835 : 8 : path_length += strlen(label) - 1;
3836 : : }
3837 : 4 : va_end(list);
3838 : :
3839 : 4 : path = malloc(path_length + 1);
3840 [ - + ]: 4 : if (!path)
3841 : 0 : return -ENOMEM;
3842 : :
3843 : 4 : path_pos = path;
3844 : 4 : label_pos = labels;
3845 : :
3846 [ + - ]: 12 : for (template_pos = path_template; *template_pos; ) {
3847 : 12 : sep = strchrnul(template_pos, '%');
3848 : 12 : path_pos = mempcpy(path_pos, template_pos, sep - template_pos);
3849 [ + + ]: 12 : if (!*sep)
3850 : 4 : break;
3851 : :
3852 : 8 : path_pos = stpcpy(path_pos, *label_pos++);
3853 : 8 : template_pos = sep + 1;
3854 : : }
3855 : :
3856 : 4 : *path_pos = 0;
3857 : 4 : *out = path;
3858 : 4 : return 0;
3859 : : }
3860 : :
3861 : 88 : _public_ int sd_bus_path_decode_many(const char *path, const char *path_template, ...) {
3862 : 88 : _cleanup_strv_free_ char **labels = NULL;
3863 : : const char *template_pos, *path_pos;
3864 : : char **label_pos;
3865 : : va_list list;
3866 : : int r;
3867 : :
3868 : : /*
3869 : : * This decodes an object-path based on a template argument. The
3870 : : * template consists of a verbatim path, optionally including special
3871 : : * directives:
3872 : : *
3873 : : * - Each occurrence of '%' in the template matches an arbitrary
3874 : : * substring of a label in the given path. At most one such
3875 : : * directive is allowed per label. For each such directive, the
3876 : : * caller must provide an output parameter (char **) via va_arg. If
3877 : : * NULL is passed, the given label is verified, but not returned.
3878 : : * For each matched label, the *decoded* label is stored in the
3879 : : * passed output argument, and the caller is responsible to free
3880 : : * it. Note that the output arguments are only modified if the
3881 : : * actually path matched the template. Otherwise, they're left
3882 : : * untouched.
3883 : : *
3884 : : * This function returns <0 on error, 0 if the path does not match the
3885 : : * template, 1 if it matched.
3886 : : */
3887 : :
3888 [ - + - + ]: 88 : assert_return(path, -EINVAL);
3889 [ - + - + ]: 88 : assert_return(path_template, -EINVAL);
3890 : :
3891 : 88 : path_pos = path;
3892 : :
3893 [ + + ]: 192 : for (template_pos = path_template; *template_pos; ) {
3894 : : const char *sep;
3895 : : size_t length;
3896 : : char *label;
3897 : :
3898 : : /* verify everything until the next '%' matches verbatim */
3899 : 156 : sep = strchrnul(template_pos, '%');
3900 : 156 : length = sep - template_pos;
3901 [ + + ]: 156 : if (strncmp(path_pos, template_pos, length))
3902 : 16 : return 0;
3903 : :
3904 : 140 : path_pos += length;
3905 : 140 : template_pos += length;
3906 : :
3907 [ + + ]: 140 : if (!*template_pos)
3908 : 32 : break;
3909 : :
3910 : : /* We found the next '%' character. Everything up until here
3911 : : * matched. We now skip ahead to the end of this label and make
3912 : : * sure it matches the tail of the label in the path. Then we
3913 : : * decode the string in-between and save it for later use. */
3914 : :
3915 : 108 : ++template_pos; /* skip over '%' */
3916 : :
3917 : 108 : sep = strchrnul(template_pos, '/');
3918 : 108 : length = sep - template_pos; /* length of suffix to match verbatim */
3919 : :
3920 : : /* verify the suffixes match */
3921 : 108 : sep = strchrnul(path_pos, '/');
3922 [ + - ]: 108 : if (sep - path_pos < (ssize_t)length ||
3923 [ + + ]: 108 : strncmp(sep - length, template_pos, length))
3924 : 4 : return 0;
3925 : :
3926 : 104 : template_pos += length; /* skip over matched label */
3927 : 104 : length = sep - path_pos - length; /* length of sub-label to decode */
3928 : :
3929 : : /* store unescaped label for later use */
3930 : 104 : label = bus_label_unescape_n(path_pos, length);
3931 [ - + ]: 104 : if (!label)
3932 : 0 : return -ENOMEM;
3933 : :
3934 : 104 : r = strv_consume(&labels, label);
3935 [ - + ]: 104 : if (r < 0)
3936 : 0 : return r;
3937 : :
3938 : 104 : path_pos = sep; /* skip decoded label and suffix */
3939 : : }
3940 : :
3941 : : /* end of template must match end of path */
3942 [ + + ]: 68 : if (*path_pos)
3943 : 36 : return 0;
3944 : :
3945 : : /* copy the labels over to the caller */
3946 : 32 : va_start(list, path_template);
3947 [ + + + + ]: 80 : for (label_pos = labels; label_pos && *label_pos; ++label_pos) {
3948 : : char **arg;
3949 : :
3950 : 48 : arg = va_arg(list, char **);
3951 [ + + ]: 48 : if (arg)
3952 : 20 : *arg = *label_pos;
3953 : : else
3954 : 28 : free(*label_pos);
3955 : : }
3956 : 32 : va_end(list);
3957 : :
3958 : 32 : labels = mfree(labels);
3959 : 32 : return 1;
3960 : : }
3961 : :
3962 : 0 : _public_ int sd_bus_try_close(sd_bus *bus) {
3963 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
3964 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
3965 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
3966 : :
3967 : 0 : return -EOPNOTSUPP;
3968 : : }
3969 : :
3970 : 4 : _public_ int sd_bus_get_description(sd_bus *bus, const char **description) {
3971 [ - + - + ]: 4 : assert_return(bus, -EINVAL);
3972 [ - + - + ]: 4 : assert_return(bus = bus_resolve(bus), -ENOPKG);
3973 [ - + - + ]: 4 : assert_return(description, -EINVAL);
3974 [ - + - + ]: 4 : assert_return(bus->description, -ENXIO);
3975 [ - + - + ]: 4 : assert_return(!bus_pid_changed(bus), -ECHILD);
3976 : :
3977 [ + - ]: 4 : if (bus->description)
3978 : 4 : *description = bus->description;
3979 [ # # ]: 0 : else if (bus->is_system)
3980 : 0 : *description = "system";
3981 [ # # ]: 0 : else if (bus->is_user)
3982 : 0 : *description = "user";
3983 : : else
3984 : 0 : *description = NULL;
3985 : :
3986 : 4 : return 0;
3987 : : }
3988 : :
3989 : 0 : _public_ int sd_bus_get_scope(sd_bus *bus, const char **scope) {
3990 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
3991 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
3992 [ # # # # ]: 0 : assert_return(scope, -EINVAL);
3993 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
3994 : :
3995 [ # # ]: 0 : if (bus->is_user) {
3996 : 0 : *scope = "user";
3997 : 0 : return 0;
3998 : : }
3999 : :
4000 [ # # ]: 0 : if (bus->is_system) {
4001 : 0 : *scope = "system";
4002 : 0 : return 0;
4003 : : }
4004 : :
4005 : 0 : return -ENODATA;
4006 : : }
4007 : :
4008 : 0 : _public_ int sd_bus_get_address(sd_bus *bus, const char **address) {
4009 : :
4010 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4011 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4012 [ # # # # ]: 0 : assert_return(address, -EINVAL);
4013 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
4014 : :
4015 [ # # ]: 0 : if (bus->address) {
4016 : 0 : *address = bus->address;
4017 : 0 : return 0;
4018 : : }
4019 : :
4020 : 0 : return -ENODATA;
4021 : : }
4022 : :
4023 : 0 : _public_ int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *mask) {
4024 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4025 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4026 [ # # # # ]: 0 : assert_return(mask, -EINVAL);
4027 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
4028 : :
4029 : 0 : *mask = bus->creds_mask;
4030 : 0 : return 0;
4031 : : }
4032 : :
4033 : 0 : _public_ int sd_bus_is_bus_client(sd_bus *bus) {
4034 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4035 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4036 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
4037 : :
4038 : 0 : return bus->bus_client;
4039 : : }
4040 : :
4041 : 0 : _public_ int sd_bus_is_server(sd_bus *bus) {
4042 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4043 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4044 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
4045 : :
4046 : 0 : return bus->is_server;
4047 : : }
4048 : :
4049 : 0 : _public_ int sd_bus_is_anonymous(sd_bus *bus) {
4050 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4051 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4052 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
4053 : :
4054 : 0 : return bus->anonymous_auth;
4055 : : }
4056 : :
4057 : 0 : _public_ int sd_bus_is_trusted(sd_bus *bus) {
4058 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4059 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4060 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
4061 : :
4062 : 0 : return bus->trusted;
4063 : : }
4064 : :
4065 : 0 : _public_ int sd_bus_is_monitor(sd_bus *bus) {
4066 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4067 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4068 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
4069 : :
4070 : 0 : return bus->is_monitor;
4071 : : }
4072 : :
4073 : 0 : static void flush_close(sd_bus *bus) {
4074 [ # # ]: 0 : if (!bus)
4075 : 0 : return;
4076 : :
4077 : : /* Flushes and closes the specified bus. We take a ref before,
4078 : : * to ensure the flushing does not cause the bus to be
4079 : : * unreferenced. */
4080 : :
4081 : 0 : sd_bus_flush_close_unref(sd_bus_ref(bus));
4082 : : }
4083 : :
4084 : 0 : _public_ void sd_bus_default_flush_close(void) {
4085 : 0 : flush_close(default_starter_bus);
4086 : 0 : flush_close(default_user_bus);
4087 : 0 : flush_close(default_system_bus);
4088 : 0 : }
4089 : :
4090 : 0 : _public_ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b) {
4091 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4092 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4093 : :
4094 : : /* Turns on exit-on-disconnect, and triggers it immediately if the bus connection was already
4095 : : * disconnected. Note that this is triggered exclusively on disconnections triggered by the server side, never
4096 : : * from the client side. */
4097 : 0 : bus->exit_on_disconnect = b;
4098 : :
4099 : : /* If the exit condition was triggered already, exit immediately. */
4100 : 0 : return bus_exit_now(bus);
4101 : : }
4102 : :
4103 : 0 : _public_ int sd_bus_get_exit_on_disconnect(sd_bus *bus) {
4104 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4105 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4106 : :
4107 : 0 : return bus->exit_on_disconnect;
4108 : : }
4109 : :
4110 : 0 : _public_ int sd_bus_set_sender(sd_bus *bus, const char *sender) {
4111 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4112 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4113 [ # # # # ]: 0 : assert_return(!bus->bus_client, -EPERM);
4114 [ # # # # : 0 : assert_return(!sender || service_name_is_valid(sender), -EINVAL);
# # ]
4115 : :
4116 : 0 : return free_and_strdup(&bus->patch_sender, sender);
4117 : : }
4118 : :
4119 : 0 : _public_ int sd_bus_get_sender(sd_bus *bus, const char **ret) {
4120 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4121 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4122 [ # # # # ]: 0 : assert_return(ret, -EINVAL);
4123 : :
4124 [ # # ]: 0 : if (!bus->patch_sender)
4125 : 0 : return -ENODATA;
4126 : :
4127 : 0 : *ret = bus->patch_sender;
4128 : 0 : return 0;
4129 : : }
4130 : :
4131 : 0 : _public_ int sd_bus_get_n_queued_read(sd_bus *bus, uint64_t *ret) {
4132 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4133 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4134 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
4135 [ # # # # ]: 0 : assert_return(ret, -EINVAL);
4136 : :
4137 : 0 : *ret = bus->rqueue_size;
4138 : 0 : return 0;
4139 : : }
4140 : :
4141 : 0 : _public_ int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret) {
4142 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4143 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4144 [ # # # # ]: 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
4145 [ # # # # ]: 0 : assert_return(ret, -EINVAL);
4146 : :
4147 : 0 : *ret = bus->wqueue_size;
4148 : 0 : return 0;
4149 : : }
4150 : :
4151 : 0 : _public_ int sd_bus_set_method_call_timeout(sd_bus *bus, uint64_t usec) {
4152 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4153 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4154 : :
4155 : 0 : bus->method_call_timeout = usec;
4156 : 0 : return 0;
4157 : : }
4158 : :
4159 : 552 : _public_ int sd_bus_get_method_call_timeout(sd_bus *bus, uint64_t *ret) {
4160 : : const char *e;
4161 : : usec_t usec;
4162 : :
4163 [ - + - + ]: 552 : assert_return(bus, -EINVAL);
4164 [ - + - + ]: 552 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4165 [ - + - + ]: 552 : assert_return(ret, -EINVAL);
4166 : :
4167 [ + + ]: 552 : if (bus->method_call_timeout != 0) {
4168 : 364 : *ret = bus->method_call_timeout;
4169 : 364 : return 0;
4170 : : }
4171 : :
4172 : 188 : e = secure_getenv("SYSTEMD_BUS_TIMEOUT");
4173 [ - + # # : 188 : if (e && parse_sec(e, &usec) >= 0 && usec != 0) {
# # ]
4174 : : /* Save the parsed value to avoid multiple parsing. To change the timeout value,
4175 : : * use sd_bus_set_method_call_timeout() instead of setenv(). */
4176 : 0 : *ret = bus->method_call_timeout = usec;
4177 : 0 : return 0;
4178 : : }
4179 : :
4180 : 188 : *ret = bus->method_call_timeout = BUS_DEFAULT_TIMEOUT;
4181 : 188 : return 0;
4182 : : }
4183 : :
4184 : 0 : _public_ int sd_bus_set_close_on_exit(sd_bus *bus, int b) {
4185 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4186 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4187 : :
4188 : 0 : bus->close_on_exit = b;
4189 : 0 : return 0;
4190 : : }
4191 : :
4192 : 0 : _public_ int sd_bus_get_close_on_exit(sd_bus *bus) {
4193 [ # # # # ]: 0 : assert_return(bus, -EINVAL);
4194 [ # # # # ]: 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
4195 : :
4196 : 0 : return bus->close_on_exit;
4197 : : }
|