]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/bus-util.c
fdf41cec194a63c566401b2b5296161d12a19ce5
[thirdparty/systemd.git] / src / shared / bus-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/socket.h>
23
24 #include "sd-daemon.h"
25 #include "sd-event.h"
26 #include "sd-bus.h"
27
28 #include "bus-error.h"
29 #include "bus-internal.h"
30 #include "bus-label.h"
31 #include "bus-message.h"
32 #include "cgroup-util.h"
33 #include "def.h"
34 #include "macro.h"
35 #include "missing.h"
36 #include "path-util.h"
37 #include "set.h"
38 #include "signal-util.h"
39 #include "strv.h"
40 #include "unit-name.h"
41 #include "util.h"
42
43 #include "bus-util.h"
44
45 static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
46 sd_event *e = userdata;
47
48 assert(m);
49 assert(e);
50
51 sd_bus_close(sd_bus_message_get_bus(m));
52 sd_event_exit(e, 0);
53
54 return 1;
55 }
56
57 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
58 _cleanup_free_ char *match = NULL;
59 const char *unique;
60 int r;
61
62 assert(e);
63 assert(bus);
64 assert(name);
65
66 /* We unregister the name here and then wait for the
67 * NameOwnerChanged signal for this event to arrive before we
68 * quit. We do this in order to make sure that any queued
69 * requests are still processed before we really exit. */
70
71 r = sd_bus_get_unique_name(bus, &unique);
72 if (r < 0)
73 return r;
74
75 r = asprintf(&match,
76 "sender='org.freedesktop.DBus',"
77 "type='signal',"
78 "interface='org.freedesktop.DBus',"
79 "member='NameOwnerChanged',"
80 "path='/org/freedesktop/DBus',"
81 "arg0='%s',"
82 "arg1='%s',"
83 "arg2=''", name, unique);
84 if (r < 0)
85 return -ENOMEM;
86
87 r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
88 if (r < 0)
89 return r;
90
91 r = sd_bus_release_name(bus, name);
92 if (r < 0)
93 return r;
94
95 return 0;
96 }
97
98 int bus_event_loop_with_idle(
99 sd_event *e,
100 sd_bus *bus,
101 const char *name,
102 usec_t timeout,
103 check_idle_t check_idle,
104 void *userdata) {
105 bool exiting = false;
106 int r, code;
107
108 assert(e);
109 assert(bus);
110 assert(name);
111
112 for (;;) {
113 bool idle;
114
115 r = sd_event_get_state(e);
116 if (r < 0)
117 return r;
118 if (r == SD_EVENT_FINISHED)
119 break;
120
121 if (check_idle)
122 idle = check_idle(userdata);
123 else
124 idle = true;
125
126 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
127 if (r < 0)
128 return r;
129
130 if (r == 0 && !exiting && idle) {
131
132 r = sd_bus_try_close(bus);
133 if (r == -EBUSY)
134 continue;
135
136 /* Fallback for dbus1 connections: we
137 * unregister the name and wait for the
138 * response to come through for it */
139 if (r == -EOPNOTSUPP) {
140
141 /* Inform the service manager that we
142 * are going down, so that it will
143 * queue all further start requests,
144 * instead of assuming we are already
145 * running. */
146 sd_notify(false, "STOPPING=1");
147
148 r = bus_async_unregister_and_exit(e, bus, name);
149 if (r < 0)
150 return r;
151
152 exiting = true;
153 continue;
154 }
155
156 if (r < 0)
157 return r;
158
159 sd_event_exit(e, 0);
160 break;
161 }
162 }
163
164 r = sd_event_get_exit_code(e, &code);
165 if (r < 0)
166 return r;
167
168 return code;
169 }
170
171 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
172 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
173 int r, has_owner = 0;
174
175 assert(c);
176 assert(name);
177
178 r = sd_bus_call_method(c,
179 "org.freedesktop.DBus",
180 "/org/freedesktop/dbus",
181 "org.freedesktop.DBus",
182 "NameHasOwner",
183 error,
184 &rep,
185 "s",
186 name);
187 if (r < 0)
188 return r;
189
190 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
191 if (r < 0)
192 return sd_bus_error_set_errno(error, r);
193
194 return has_owner;
195 }
196
197 static int check_good_user(sd_bus_message *m, uid_t good_user) {
198 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
199 uid_t sender_uid;
200 int r;
201
202 assert(m);
203
204 if (good_user == UID_INVALID)
205 return 0;
206
207 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
208 if (r < 0)
209 return r;
210
211 /* Don't trust augmented credentials for authorization */
212 assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
213
214 r = sd_bus_creds_get_euid(creds, &sender_uid);
215 if (r < 0)
216 return r;
217
218 return sender_uid == good_user;
219 }
220
221 int bus_test_polkit(
222 sd_bus_message *call,
223 int capability,
224 const char *action,
225 const char **details,
226 uid_t good_user,
227 bool *_challenge,
228 sd_bus_error *e) {
229
230 int r;
231
232 assert(call);
233 assert(action);
234
235 /* Tests non-interactively! */
236
237 r = check_good_user(call, good_user);
238 if (r != 0)
239 return r;
240
241 r = sd_bus_query_sender_privilege(call, capability);
242 if (r < 0)
243 return r;
244 else if (r > 0)
245 return 1;
246 #ifdef ENABLE_POLKIT
247 else {
248 _cleanup_bus_message_unref_ sd_bus_message *request = NULL;
249 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
250 int authorized = false, challenge = false;
251 const char *sender, **k, **v;
252
253 sender = sd_bus_message_get_sender(call);
254 if (!sender)
255 return -EBADMSG;
256
257 r = sd_bus_message_new_method_call(
258 call->bus,
259 &request,
260 "org.freedesktop.PolicyKit1",
261 "/org/freedesktop/PolicyKit1/Authority",
262 "org.freedesktop.PolicyKit1.Authority",
263 "CheckAuthorization");
264 if (r < 0)
265 return r;
266
267 r = sd_bus_message_append(
268 request,
269 "(sa{sv})s",
270 "system-bus-name", 1, "name", "s", sender,
271 action);
272 if (r < 0)
273 return r;
274
275 r = sd_bus_message_open_container(request, 'a', "{ss}");
276 if (r < 0)
277 return r;
278
279 STRV_FOREACH_PAIR(k, v, details) {
280 r = sd_bus_message_append(request, "{ss}", *k, *v);
281 if (r < 0)
282 return r;
283 }
284
285 r = sd_bus_message_close_container(request);
286 if (r < 0)
287 return r;
288
289 r = sd_bus_message_append(request, "us", 0, NULL);
290 if (r < 0)
291 return r;
292
293 r = sd_bus_call(call->bus, request, 0, e, &reply);
294 if (r < 0) {
295 /* Treat no PK available as access denied */
296 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
297 sd_bus_error_free(e);
298 return -EACCES;
299 }
300
301 return r;
302 }
303
304 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
305 if (r < 0)
306 return r;
307
308 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
309 if (r < 0)
310 return r;
311
312 if (authorized)
313 return 1;
314
315 if (_challenge) {
316 *_challenge = challenge;
317 return 0;
318 }
319 }
320 #endif
321
322 return -EACCES;
323 }
324
325 #ifdef ENABLE_POLKIT
326
327 typedef struct AsyncPolkitQuery {
328 sd_bus_message *request, *reply;
329 sd_bus_message_handler_t callback;
330 void *userdata;
331 sd_bus_slot *slot;
332 Hashmap *registry;
333 } AsyncPolkitQuery;
334
335 static void async_polkit_query_free(AsyncPolkitQuery *q) {
336
337 if (!q)
338 return;
339
340 sd_bus_slot_unref(q->slot);
341
342 if (q->registry && q->request)
343 hashmap_remove(q->registry, q->request);
344
345 sd_bus_message_unref(q->request);
346 sd_bus_message_unref(q->reply);
347
348 free(q);
349 }
350
351 static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
352 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
353 AsyncPolkitQuery *q = userdata;
354 int r;
355
356 assert(reply);
357 assert(q);
358
359 q->slot = sd_bus_slot_unref(q->slot);
360 q->reply = sd_bus_message_ref(reply);
361
362 r = sd_bus_message_rewind(q->request, true);
363 if (r < 0) {
364 r = sd_bus_reply_method_errno(q->request, r, NULL);
365 goto finish;
366 }
367
368 r = q->callback(q->request, q->userdata, &error_buffer);
369 r = bus_maybe_reply_error(q->request, r, &error_buffer);
370
371 finish:
372 async_polkit_query_free(q);
373
374 return r;
375 }
376
377 #endif
378
379 int bus_verify_polkit_async(
380 sd_bus_message *call,
381 int capability,
382 const char *action,
383 const char **details,
384 bool interactive,
385 uid_t good_user,
386 Hashmap **registry,
387 sd_bus_error *error) {
388
389 #ifdef ENABLE_POLKIT
390 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
391 AsyncPolkitQuery *q;
392 const char *sender, **k, **v;
393 sd_bus_message_handler_t callback;
394 void *userdata;
395 int c;
396 #endif
397 int r;
398
399 assert(call);
400 assert(action);
401 assert(registry);
402
403 r = check_good_user(call, good_user);
404 if (r != 0)
405 return r;
406
407 #ifdef ENABLE_POLKIT
408 q = hashmap_get(*registry, call);
409 if (q) {
410 int authorized, challenge;
411
412 /* This is the second invocation of this function, and
413 * there's already a response from polkit, let's
414 * process it */
415 assert(q->reply);
416
417 if (sd_bus_message_is_method_error(q->reply, NULL)) {
418 const sd_bus_error *e;
419
420 /* Copy error from polkit reply */
421 e = sd_bus_message_get_error(q->reply);
422 sd_bus_error_copy(error, e);
423
424 /* Treat no PK available as access denied */
425 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
426 return -EACCES;
427
428 return -sd_bus_error_get_errno(e);
429 }
430
431 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
432 if (r >= 0)
433 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
434
435 if (r < 0)
436 return r;
437
438 if (authorized)
439 return 1;
440
441 if (challenge)
442 return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
443
444 return -EACCES;
445 }
446 #endif
447
448 r = sd_bus_query_sender_privilege(call, capability);
449 if (r < 0)
450 return r;
451 else if (r > 0)
452 return 1;
453
454 #ifdef ENABLE_POLKIT
455 if (sd_bus_get_current_message(call->bus) != call)
456 return -EINVAL;
457
458 callback = sd_bus_get_current_handler(call->bus);
459 if (!callback)
460 return -EINVAL;
461
462 userdata = sd_bus_get_current_userdata(call->bus);
463
464 sender = sd_bus_message_get_sender(call);
465 if (!sender)
466 return -EBADMSG;
467
468 c = sd_bus_message_get_allow_interactive_authorization(call);
469 if (c < 0)
470 return c;
471 if (c > 0)
472 interactive = true;
473
474 r = hashmap_ensure_allocated(registry, NULL);
475 if (r < 0)
476 return r;
477
478 r = sd_bus_message_new_method_call(
479 call->bus,
480 &pk,
481 "org.freedesktop.PolicyKit1",
482 "/org/freedesktop/PolicyKit1/Authority",
483 "org.freedesktop.PolicyKit1.Authority",
484 "CheckAuthorization");
485 if (r < 0)
486 return r;
487
488 r = sd_bus_message_append(
489 pk,
490 "(sa{sv})s",
491 "system-bus-name", 1, "name", "s", sender,
492 action);
493 if (r < 0)
494 return r;
495
496 r = sd_bus_message_open_container(pk, 'a', "{ss}");
497 if (r < 0)
498 return r;
499
500 STRV_FOREACH_PAIR(k, v, details) {
501 r = sd_bus_message_append(pk, "{ss}", *k, *v);
502 if (r < 0)
503 return r;
504 }
505
506 r = sd_bus_message_close_container(pk);
507 if (r < 0)
508 return r;
509
510 r = sd_bus_message_append(pk, "us", !!interactive, NULL);
511 if (r < 0)
512 return r;
513
514 q = new0(AsyncPolkitQuery, 1);
515 if (!q)
516 return -ENOMEM;
517
518 q->request = sd_bus_message_ref(call);
519 q->callback = callback;
520 q->userdata = userdata;
521
522 r = hashmap_put(*registry, call, q);
523 if (r < 0) {
524 async_polkit_query_free(q);
525 return r;
526 }
527
528 q->registry = *registry;
529
530 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
531 if (r < 0) {
532 async_polkit_query_free(q);
533 return r;
534 }
535
536 return 0;
537 #endif
538
539 return -EACCES;
540 }
541
542 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
543 #ifdef ENABLE_POLKIT
544 AsyncPolkitQuery *q;
545
546 while ((q = hashmap_steal_first(registry)))
547 async_polkit_query_free(q);
548
549 hashmap_free(registry);
550 #endif
551 }
552
553 int bus_check_peercred(sd_bus *c) {
554 struct ucred ucred;
555 socklen_t l;
556 int fd;
557
558 assert(c);
559
560 fd = sd_bus_get_fd(c);
561 if (fd < 0)
562 return fd;
563
564 l = sizeof(struct ucred);
565 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
566 return -errno;
567
568 if (l != sizeof(struct ucred))
569 return -E2BIG;
570
571 if (ucred.uid != 0 && ucred.uid != geteuid())
572 return -EPERM;
573
574 return 1;
575 }
576
577 int bus_open_system_systemd(sd_bus **_bus) {
578 _cleanup_bus_unref_ sd_bus *bus = NULL;
579 int r;
580
581 assert(_bus);
582
583 if (geteuid() != 0)
584 return sd_bus_open_system(_bus);
585
586 /* If we are root and kdbus is not available, then let's talk
587 * directly to the system instance, instead of going via the
588 * bus */
589
590 r = sd_bus_new(&bus);
591 if (r < 0)
592 return r;
593
594 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
595 if (r < 0)
596 return r;
597
598 bus->bus_client = true;
599
600 r = sd_bus_start(bus);
601 if (r >= 0) {
602 *_bus = bus;
603 bus = NULL;
604 return 0;
605 }
606
607 bus = sd_bus_unref(bus);
608
609 r = sd_bus_new(&bus);
610 if (r < 0)
611 return r;
612
613 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
614 if (r < 0)
615 return r;
616
617 r = sd_bus_start(bus);
618 if (r < 0)
619 return sd_bus_open_system(_bus);
620
621 r = bus_check_peercred(bus);
622 if (r < 0)
623 return r;
624
625 *_bus = bus;
626 bus = NULL;
627
628 return 0;
629 }
630
631 int bus_open_user_systemd(sd_bus **_bus) {
632 _cleanup_bus_unref_ sd_bus *bus = NULL;
633 _cleanup_free_ char *ee = NULL;
634 const char *e;
635 int r;
636
637 /* Try via kdbus first, and then directly */
638
639 assert(_bus);
640
641 r = sd_bus_new(&bus);
642 if (r < 0)
643 return r;
644
645 if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
646 return -ENOMEM;
647
648 bus->bus_client = true;
649
650 r = sd_bus_start(bus);
651 if (r >= 0) {
652 *_bus = bus;
653 bus = NULL;
654 return 0;
655 }
656
657 bus = sd_bus_unref(bus);
658
659 e = secure_getenv("XDG_RUNTIME_DIR");
660 if (!e)
661 return sd_bus_open_user(_bus);
662
663 ee = bus_address_escape(e);
664 if (!ee)
665 return -ENOMEM;
666
667 r = sd_bus_new(&bus);
668 if (r < 0)
669 return r;
670
671 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
672 if (!bus->address)
673 return -ENOMEM;
674
675 r = sd_bus_start(bus);
676 if (r < 0)
677 return sd_bus_open_user(_bus);
678
679 r = bus_check_peercred(bus);
680 if (r < 0)
681 return r;
682
683 *_bus = bus;
684 bus = NULL;
685
686 return 0;
687 }
688
689 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
690 char type;
691 const char *contents;
692 int r;
693
694 assert(name);
695 assert(property);
696
697 r = sd_bus_message_peek_type(property, &type, &contents);
698 if (r < 0)
699 return r;
700
701 switch (type) {
702
703 case SD_BUS_TYPE_STRING: {
704 const char *s;
705
706 r = sd_bus_message_read_basic(property, type, &s);
707 if (r < 0)
708 return r;
709
710 if (all || !isempty(s)) {
711 _cleanup_free_ char *escaped = NULL;
712
713 escaped = xescape(s, "\n");
714 if (!escaped)
715 return -ENOMEM;
716
717 printf("%s=%s\n", name, escaped);
718 }
719
720 return 1;
721 }
722
723 case SD_BUS_TYPE_BOOLEAN: {
724 int b;
725
726 r = sd_bus_message_read_basic(property, type, &b);
727 if (r < 0)
728 return r;
729
730 printf("%s=%s\n", name, yes_no(b));
731
732 return 1;
733 }
734
735 case SD_BUS_TYPE_UINT64: {
736 uint64_t u;
737
738 r = sd_bus_message_read_basic(property, type, &u);
739 if (r < 0)
740 return r;
741
742 /* Yes, heuristics! But we can change this check
743 * should it turn out to not be sufficient */
744
745 if (endswith(name, "Timestamp")) {
746 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
747
748 t = format_timestamp(timestamp, sizeof(timestamp), u);
749 if (t || all)
750 printf("%s=%s\n", name, strempty(t));
751
752 } else if (strstr(name, "USec")) {
753 char timespan[FORMAT_TIMESPAN_MAX];
754
755 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
756 } else
757 printf("%s=%llu\n", name, (unsigned long long) u);
758
759 return 1;
760 }
761
762 case SD_BUS_TYPE_INT64: {
763 int64_t i;
764
765 r = sd_bus_message_read_basic(property, type, &i);
766 if (r < 0)
767 return r;
768
769 printf("%s=%lld\n", name, (long long) i);
770
771 return 1;
772 }
773
774 case SD_BUS_TYPE_UINT32: {
775 uint32_t u;
776
777 r = sd_bus_message_read_basic(property, type, &u);
778 if (r < 0)
779 return r;
780
781 if (strstr(name, "UMask") || strstr(name, "Mode"))
782 printf("%s=%04o\n", name, u);
783 else
784 printf("%s=%u\n", name, (unsigned) u);
785
786 return 1;
787 }
788
789 case SD_BUS_TYPE_INT32: {
790 int32_t i;
791
792 r = sd_bus_message_read_basic(property, type, &i);
793 if (r < 0)
794 return r;
795
796 printf("%s=%i\n", name, (int) i);
797 return 1;
798 }
799
800 case SD_BUS_TYPE_DOUBLE: {
801 double d;
802
803 r = sd_bus_message_read_basic(property, type, &d);
804 if (r < 0)
805 return r;
806
807 printf("%s=%g\n", name, d);
808 return 1;
809 }
810
811 case SD_BUS_TYPE_ARRAY:
812 if (streq(contents, "s")) {
813 bool first = true;
814 const char *str;
815
816 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
817 if (r < 0)
818 return r;
819
820 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
821 _cleanup_free_ char *escaped = NULL;
822
823 if (first)
824 printf("%s=", name);
825
826 escaped = xescape(str, "\n ");
827 if (!escaped)
828 return -ENOMEM;
829
830 printf("%s%s", first ? "" : " ", escaped);
831
832 first = false;
833 }
834 if (r < 0)
835 return r;
836
837 if (first && all)
838 printf("%s=", name);
839 if (!first || all)
840 puts("");
841
842 r = sd_bus_message_exit_container(property);
843 if (r < 0)
844 return r;
845
846 return 1;
847
848 } else if (streq(contents, "y")) {
849 const uint8_t *u;
850 size_t n;
851
852 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
853 if (r < 0)
854 return r;
855
856 if (all || n > 0) {
857 unsigned int i;
858
859 printf("%s=", name);
860
861 for (i = 0; i < n; i++)
862 printf("%02x", u[i]);
863
864 puts("");
865 }
866
867 return 1;
868
869 } else if (streq(contents, "u")) {
870 uint32_t *u;
871 size_t n;
872
873 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
874 if (r < 0)
875 return r;
876
877 if (all || n > 0) {
878 unsigned int i;
879
880 printf("%s=", name);
881
882 for (i = 0; i < n; i++)
883 printf("%08x", u[i]);
884
885 puts("");
886 }
887
888 return 1;
889 }
890
891 break;
892 }
893
894 return 0;
895 }
896
897 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
898 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
899 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
900 int r;
901
902 assert(bus);
903 assert(path);
904
905 r = sd_bus_call_method(bus,
906 dest,
907 path,
908 "org.freedesktop.DBus.Properties",
909 "GetAll",
910 &error,
911 &reply,
912 "s", "");
913 if (r < 0)
914 return r;
915
916 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
917 if (r < 0)
918 return r;
919
920 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
921 const char *name;
922 const char *contents;
923
924 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
925 if (r < 0)
926 return r;
927
928 if (!filter || strv_find(filter, name)) {
929 r = sd_bus_message_peek_type(reply, NULL, &contents);
930 if (r < 0)
931 return r;
932
933 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
934 if (r < 0)
935 return r;
936
937 r = bus_print_property(name, reply, all);
938 if (r < 0)
939 return r;
940 if (r == 0) {
941 if (all)
942 printf("%s=[unprintable]\n", name);
943 /* skip what we didn't read */
944 r = sd_bus_message_skip(reply, contents);
945 if (r < 0)
946 return r;
947 }
948
949 r = sd_bus_message_exit_container(reply);
950 if (r < 0)
951 return r;
952 } else {
953 r = sd_bus_message_skip(reply, "v");
954 if (r < 0)
955 return r;
956 }
957
958 r = sd_bus_message_exit_container(reply);
959 if (r < 0)
960 return r;
961 }
962 if (r < 0)
963 return r;
964
965 r = sd_bus_message_exit_container(reply);
966 if (r < 0)
967 return r;
968
969 return 0;
970 }
971
972 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
973 sd_id128_t *p = userdata;
974 const void *v;
975 size_t n;
976 int r;
977
978 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
979 if (r < 0)
980 return r;
981
982 if (n == 0)
983 *p = SD_ID128_NULL;
984 else if (n == 16)
985 memcpy((*p).bytes, v, n);
986 else
987 return -EINVAL;
988
989 return 0;
990 }
991
992 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
993 char type;
994 int r;
995
996 r = sd_bus_message_peek_type(m, &type, NULL);
997 if (r < 0)
998 return r;
999
1000 switch (type) {
1001 case SD_BUS_TYPE_STRING: {
1002 const char *s;
1003 char **p = userdata;
1004
1005 r = sd_bus_message_read_basic(m, type, &s);
1006 if (r < 0)
1007 break;
1008
1009 if (isempty(s))
1010 break;
1011
1012 r = free_and_strdup(p, s);
1013 break;
1014 }
1015
1016 case SD_BUS_TYPE_ARRAY: {
1017 _cleanup_strv_free_ char **l = NULL;
1018 char ***p = userdata;
1019
1020 r = bus_message_read_strv_extend(m, &l);
1021 if (r < 0)
1022 break;
1023
1024 strv_free(*p);
1025 *p = l;
1026 l = NULL;
1027
1028 break;
1029 }
1030
1031 case SD_BUS_TYPE_BOOLEAN: {
1032 unsigned b;
1033 bool *p = userdata;
1034
1035 r = sd_bus_message_read_basic(m, type, &b);
1036 if (r < 0)
1037 break;
1038
1039 *p = b;
1040
1041 break;
1042 }
1043
1044 case SD_BUS_TYPE_UINT32: {
1045 uint64_t u;
1046 uint32_t *p = userdata;
1047
1048 r = sd_bus_message_read_basic(m, type, &u);
1049 if (r < 0)
1050 break;
1051
1052 *p = u;
1053
1054 break;
1055 }
1056
1057 case SD_BUS_TYPE_UINT64: {
1058 uint64_t t;
1059 uint64_t *p = userdata;
1060
1061 r = sd_bus_message_read_basic(m, type, &t);
1062 if (r < 0)
1063 break;
1064
1065 *p = t;
1066
1067 break;
1068 }
1069
1070 default:
1071 break;
1072 }
1073
1074 return r;
1075 }
1076
1077 int bus_message_map_all_properties(
1078 sd_bus_message *m,
1079 const struct bus_properties_map *map,
1080 void *userdata) {
1081
1082 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1083 int r;
1084
1085 assert(m);
1086 assert(map);
1087
1088 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1089 if (r < 0)
1090 return r;
1091
1092 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1093 const struct bus_properties_map *prop;
1094 const char *member;
1095 const char *contents;
1096 void *v;
1097 unsigned i;
1098
1099 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1100 if (r < 0)
1101 return r;
1102
1103 for (i = 0, prop = NULL; map[i].member; i++)
1104 if (streq(map[i].member, member)) {
1105 prop = &map[i];
1106 break;
1107 }
1108
1109 if (prop) {
1110 r = sd_bus_message_peek_type(m, NULL, &contents);
1111 if (r < 0)
1112 return r;
1113
1114 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1115 if (r < 0)
1116 return r;
1117
1118 v = (uint8_t *)userdata + prop->offset;
1119 if (map[i].set)
1120 r = prop->set(sd_bus_message_get_bus(m), member, m, &error, v);
1121 else
1122 r = map_basic(sd_bus_message_get_bus(m), member, m, &error, v);
1123 if (r < 0)
1124 return r;
1125
1126 r = sd_bus_message_exit_container(m);
1127 if (r < 0)
1128 return r;
1129 } else {
1130 r = sd_bus_message_skip(m, "v");
1131 if (r < 0)
1132 return r;
1133 }
1134
1135 r = sd_bus_message_exit_container(m);
1136 if (r < 0)
1137 return r;
1138 }
1139 if (r < 0)
1140 return r;
1141
1142 return sd_bus_message_exit_container(m);
1143 }
1144
1145 int bus_message_map_properties_changed(
1146 sd_bus_message *m,
1147 const struct bus_properties_map *map,
1148 void *userdata) {
1149
1150 const char *member;
1151 int r, invalidated, i;
1152
1153 assert(m);
1154 assert(map);
1155
1156 r = bus_message_map_all_properties(m, map, userdata);
1157 if (r < 0)
1158 return r;
1159
1160 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1161 if (r < 0)
1162 return r;
1163
1164 invalidated = 0;
1165 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1166 for (i = 0; map[i].member; i++)
1167 if (streq(map[i].member, member)) {
1168 ++invalidated;
1169 break;
1170 }
1171 if (r < 0)
1172 return r;
1173
1174 r = sd_bus_message_exit_container(m);
1175 if (r < 0)
1176 return r;
1177
1178 return invalidated;
1179 }
1180
1181 int bus_map_all_properties(
1182 sd_bus *bus,
1183 const char *destination,
1184 const char *path,
1185 const struct bus_properties_map *map,
1186 void *userdata) {
1187
1188 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1189 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1190 int r;
1191
1192 assert(bus);
1193 assert(destination);
1194 assert(path);
1195 assert(map);
1196
1197 r = sd_bus_call_method(
1198 bus,
1199 destination,
1200 path,
1201 "org.freedesktop.DBus.Properties",
1202 "GetAll",
1203 &error,
1204 &m,
1205 "s", "");
1206 if (r < 0)
1207 return r;
1208
1209 return bus_message_map_all_properties(m, map, userdata);
1210 }
1211
1212 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1213 int r;
1214
1215 assert(transport >= 0);
1216 assert(transport < _BUS_TRANSPORT_MAX);
1217 assert(bus);
1218
1219 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1220 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1221
1222 switch (transport) {
1223
1224 case BUS_TRANSPORT_LOCAL:
1225 if (user)
1226 r = sd_bus_default_user(bus);
1227 else
1228 r = sd_bus_default_system(bus);
1229
1230 break;
1231
1232 case BUS_TRANSPORT_REMOTE:
1233 r = sd_bus_open_system_remote(bus, host);
1234 break;
1235
1236 case BUS_TRANSPORT_MACHINE:
1237 r = sd_bus_open_system_machine(bus, host);
1238 break;
1239
1240 default:
1241 assert_not_reached("Hmm, unknown transport type.");
1242 }
1243
1244 return r;
1245 }
1246
1247 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1248 int r;
1249
1250 assert(transport >= 0);
1251 assert(transport < _BUS_TRANSPORT_MAX);
1252 assert(bus);
1253
1254 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1255 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1256
1257 switch (transport) {
1258
1259 case BUS_TRANSPORT_LOCAL:
1260 if (user)
1261 r = bus_open_user_systemd(bus);
1262 else
1263 r = bus_open_system_systemd(bus);
1264
1265 break;
1266
1267 case BUS_TRANSPORT_REMOTE:
1268 r = sd_bus_open_system_remote(bus, host);
1269 break;
1270
1271 case BUS_TRANSPORT_MACHINE:
1272 r = sd_bus_open_system_machine(bus, host);
1273 break;
1274
1275 default:
1276 assert_not_reached("Hmm, unknown transport type.");
1277 }
1278
1279 return r;
1280 }
1281
1282 int bus_property_get_bool(
1283 sd_bus *bus,
1284 const char *path,
1285 const char *interface,
1286 const char *property,
1287 sd_bus_message *reply,
1288 void *userdata,
1289 sd_bus_error *error) {
1290
1291 int b = *(bool*) userdata;
1292
1293 return sd_bus_message_append_basic(reply, 'b', &b);
1294 }
1295
1296 #if __SIZEOF_SIZE_T__ != 8
1297 int bus_property_get_size(
1298 sd_bus *bus,
1299 const char *path,
1300 const char *interface,
1301 const char *property,
1302 sd_bus_message *reply,
1303 void *userdata,
1304 sd_bus_error *error) {
1305
1306 uint64_t sz = *(size_t*) userdata;
1307
1308 return sd_bus_message_append_basic(reply, 't', &sz);
1309 }
1310 #endif
1311
1312 #if __SIZEOF_LONG__ != 8
1313 int bus_property_get_long(
1314 sd_bus *bus,
1315 const char *path,
1316 const char *interface,
1317 const char *property,
1318 sd_bus_message *reply,
1319 void *userdata,
1320 sd_bus_error *error) {
1321
1322 int64_t l = *(long*) userdata;
1323
1324 return sd_bus_message_append_basic(reply, 'x', &l);
1325 }
1326
1327 int bus_property_get_ulong(
1328 sd_bus *bus,
1329 const char *path,
1330 const char *interface,
1331 const char *property,
1332 sd_bus_message *reply,
1333 void *userdata,
1334 sd_bus_error *error) {
1335
1336 uint64_t ul = *(unsigned long*) userdata;
1337
1338 return sd_bus_message_append_basic(reply, 't', &ul);
1339 }
1340 #endif
1341
1342 int bus_log_parse_error(int r) {
1343 return log_error_errno(r, "Failed to parse bus message: %m");
1344 }
1345
1346 int bus_log_create_error(int r) {
1347 return log_error_errno(r, "Failed to create bus message: %m");
1348 }
1349
1350 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1351 assert(message);
1352 assert(u);
1353
1354 u->machine = NULL;
1355
1356 return sd_bus_message_read(
1357 message,
1358 "(ssssssouso)",
1359 &u->id,
1360 &u->description,
1361 &u->load_state,
1362 &u->active_state,
1363 &u->sub_state,
1364 &u->following,
1365 &u->unit_path,
1366 &u->job_id,
1367 &u->job_type,
1368 &u->job_path);
1369 }
1370
1371 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1372 const char *eq, *field;
1373 int r;
1374
1375 assert(m);
1376 assert(assignment);
1377
1378 eq = strchr(assignment, '=');
1379 if (!eq) {
1380 log_error("Not an assignment: %s", assignment);
1381 return -EINVAL;
1382 }
1383
1384 field = strndupa(assignment, eq - assignment);
1385 eq ++;
1386
1387 if (streq(field, "CPUQuota")) {
1388
1389 if (isempty(eq)) {
1390
1391 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1392 if (r < 0)
1393 return bus_log_create_error(r);
1394
1395 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1396
1397 } else if (endswith(eq, "%")) {
1398 double percent;
1399
1400 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1401 log_error("CPU quota '%s' invalid.", eq);
1402 return -EINVAL;
1403 }
1404
1405 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1406 if (r < 0)
1407 return bus_log_create_error(r);
1408
1409 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1410 } else {
1411 log_error("CPU quota needs to be in percent.");
1412 return -EINVAL;
1413 }
1414
1415 if (r < 0)
1416 return bus_log_create_error(r);
1417
1418 return 0;
1419 }
1420
1421 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1422 if (r < 0)
1423 return bus_log_create_error(r);
1424
1425 if (STR_IN_SET(field,
1426 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
1427 "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
1428 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
1429 "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges")) {
1430
1431 r = parse_boolean(eq);
1432 if (r < 0) {
1433 log_error("Failed to parse boolean assignment %s.", assignment);
1434 return -EINVAL;
1435 }
1436
1437 r = sd_bus_message_append(m, "v", "b", r);
1438
1439 } else if (streq(field, "MemoryLimit")) {
1440 uint64_t bytes;
1441
1442 if (isempty(eq) || streq(eq, "infinity"))
1443 bytes = (uint64_t) -1;
1444 else {
1445 r = parse_size(eq, 1024, &bytes);
1446 if (r < 0) {
1447 log_error("Failed to parse bytes specification %s", assignment);
1448 return -EINVAL;
1449 }
1450 }
1451
1452 r = sd_bus_message_append(m, "v", "t", bytes);
1453
1454 } else if (streq(field, "TasksMax")) {
1455 uint64_t n;
1456
1457 if (isempty(eq) || streq(eq, "infinity"))
1458 n = (uint64_t) -1;
1459 else {
1460 r = safe_atou64(eq, &n);
1461 if (r < 0) {
1462 log_error("Failed to parse maximum tasks specification %s", assignment);
1463 return -EINVAL;
1464 }
1465 }
1466
1467 r = sd_bus_message_append(m, "v", "t", n);
1468
1469 } else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) {
1470 uint64_t u;
1471
1472 r = cg_cpu_shares_parse(eq, &u);
1473 if (r < 0) {
1474 log_error("Failed to parse %s value %s.", field, eq);
1475 return -EINVAL;
1476 }
1477
1478 r = sd_bus_message_append(m, "v", "t", u);
1479
1480 } else if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight")) {
1481 uint64_t u;
1482
1483 r = cg_cpu_shares_parse(eq, &u);
1484 if (r < 0) {
1485 log_error("Failed to parse %s value %s.", field, eq);
1486 return -EINVAL;
1487 }
1488
1489 r = sd_bus_message_append(m, "v", "t", u);
1490
1491 } else if (STR_IN_SET(field,
1492 "User", "Group", "DevicePolicy", "KillMode",
1493 "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath",
1494 "StandardInput", "StandardOutput", "StandardError",
1495 "Description", "Slice", "Type"))
1496 r = sd_bus_message_append(m, "v", "s", eq);
1497
1498 else if (streq(field, "DeviceAllow")) {
1499
1500 if (isempty(eq))
1501 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1502 else {
1503 const char *path, *rwm, *e;
1504
1505 e = strchr(eq, ' ');
1506 if (e) {
1507 path = strndupa(eq, e - eq);
1508 rwm = e+1;
1509 } else {
1510 path = eq;
1511 rwm = "";
1512 }
1513
1514 if (!path_startswith(path, "/dev")) {
1515 log_error("%s is not a device file in /dev.", path);
1516 return -EINVAL;
1517 }
1518
1519 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1520 }
1521
1522 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1523
1524 if (isempty(eq))
1525 r = sd_bus_message_append(m, "v", "a(st)", 0);
1526 else {
1527 const char *path, *bandwidth, *e;
1528 uint64_t bytes;
1529
1530 e = strchr(eq, ' ');
1531 if (e) {
1532 path = strndupa(eq, e - eq);
1533 bandwidth = e+1;
1534 } else {
1535 log_error("Failed to parse %s value %s.", field, eq);
1536 return -EINVAL;
1537 }
1538
1539 if (!path_startswith(path, "/dev")) {
1540 log_error("%s is not a device file in /dev.", path);
1541 return -EINVAL;
1542 }
1543
1544 r = parse_size(bandwidth, 1000, &bytes);
1545 if (r < 0) {
1546 log_error("Failed to parse byte value %s.", bandwidth);
1547 return -EINVAL;
1548 }
1549
1550 r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes);
1551 }
1552
1553 } else if (streq(field, "BlockIODeviceWeight")) {
1554
1555 if (isempty(eq))
1556 r = sd_bus_message_append(m, "v", "a(st)", 0);
1557 else {
1558 const char *path, *weight, *e;
1559 uint64_t u;
1560
1561 e = strchr(eq, ' ');
1562 if (e) {
1563 path = strndupa(eq, e - eq);
1564 weight = e+1;
1565 } else {
1566 log_error("Failed to parse %s value %s.", field, eq);
1567 return -EINVAL;
1568 }
1569
1570 if (!path_startswith(path, "/dev")) {
1571 log_error("%s is not a device file in /dev.", path);
1572 return -EINVAL;
1573 }
1574
1575 r = safe_atou64(weight, &u);
1576 if (r < 0) {
1577 log_error("Failed to parse %s value %s.", field, weight);
1578 return -EINVAL;
1579 }
1580 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1581 }
1582
1583 } else if (rlimit_from_string(field) >= 0) {
1584 uint64_t rl;
1585
1586 if (streq(eq, "infinity"))
1587 rl = (uint64_t) -1;
1588 else {
1589 r = safe_atou64(eq, &rl);
1590 if (r < 0) {
1591 log_error("Invalid resource limit: %s", eq);
1592 return -EINVAL;
1593 }
1594 }
1595
1596 r = sd_bus_message_append(m, "v", "t", rl);
1597
1598 } else if (streq(field, "Nice")) {
1599 int32_t i;
1600
1601 r = safe_atoi32(eq, &i);
1602 if (r < 0) {
1603 log_error("Failed to parse %s value %s.", field, eq);
1604 return -EINVAL;
1605 }
1606
1607 r = sd_bus_message_append(m, "v", "i", i);
1608
1609 } else if (streq(field, "Environment")) {
1610
1611 r = sd_bus_message_append(m, "v", "as", 1, eq);
1612
1613 } else if (streq(field, "KillSignal")) {
1614 int sig;
1615
1616 sig = signal_from_string_try_harder(eq);
1617 if (sig < 0) {
1618 log_error("Failed to parse %s value %s.", field, eq);
1619 return -EINVAL;
1620 }
1621
1622 r = sd_bus_message_append(m, "v", "i", sig);
1623
1624 } else if (streq(field, "AccuracySec")) {
1625 usec_t u;
1626
1627 r = parse_sec(eq, &u);
1628 if (r < 0) {
1629 log_error("Failed to parse %s value %s", field, eq);
1630 return -EINVAL;
1631 }
1632
1633 r = sd_bus_message_append(m, "v", "t", u);
1634
1635 } else {
1636 log_error("Unknown assignment %s.", assignment);
1637 return -EINVAL;
1638 }
1639
1640 if (r < 0)
1641 return bus_log_create_error(r);
1642
1643 return 0;
1644 }
1645
1646 typedef struct BusWaitForJobs {
1647 sd_bus *bus;
1648 Set *jobs;
1649
1650 char *name;
1651 char *result;
1652
1653 sd_bus_slot *slot_job_removed;
1654 sd_bus_slot *slot_disconnected;
1655 } BusWaitForJobs;
1656
1657 static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1658 assert(m);
1659
1660 log_error("Warning! D-Bus connection terminated.");
1661 sd_bus_close(sd_bus_message_get_bus(m));
1662
1663 return 0;
1664 }
1665
1666 static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1667 const char *path, *unit, *result;
1668 BusWaitForJobs *d = userdata;
1669 uint32_t id;
1670 char *found;
1671 int r;
1672
1673 assert(m);
1674 assert(d);
1675
1676 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1677 if (r < 0) {
1678 bus_log_parse_error(r);
1679 return 0;
1680 }
1681
1682 found = set_remove(d->jobs, (char*) path);
1683 if (!found)
1684 return 0;
1685
1686 free(found);
1687
1688 if (!isempty(result))
1689 d->result = strdup(result);
1690
1691 if (!isempty(unit))
1692 d->name = strdup(unit);
1693
1694 return 0;
1695 }
1696
1697 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1698 if (!d)
1699 return;
1700
1701 set_free_free(d->jobs);
1702
1703 sd_bus_slot_unref(d->slot_disconnected);
1704 sd_bus_slot_unref(d->slot_job_removed);
1705
1706 sd_bus_unref(d->bus);
1707
1708 free(d->name);
1709 free(d->result);
1710
1711 free(d);
1712 }
1713
1714 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1715 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1716 int r;
1717
1718 assert(bus);
1719 assert(ret);
1720
1721 d = new0(BusWaitForJobs, 1);
1722 if (!d)
1723 return -ENOMEM;
1724
1725 d->bus = sd_bus_ref(bus);
1726
1727 /* When we are a bus client we match by sender. Direct
1728 * connections OTOH have no initialized sender field, and
1729 * hence we ignore the sender then */
1730 r = sd_bus_add_match(
1731 bus,
1732 &d->slot_job_removed,
1733 bus->bus_client ?
1734 "type='signal',"
1735 "sender='org.freedesktop.systemd1',"
1736 "interface='org.freedesktop.systemd1.Manager',"
1737 "member='JobRemoved',"
1738 "path='/org/freedesktop/systemd1'" :
1739 "type='signal',"
1740 "interface='org.freedesktop.systemd1.Manager',"
1741 "member='JobRemoved',"
1742 "path='/org/freedesktop/systemd1'",
1743 match_job_removed, d);
1744 if (r < 0)
1745 return r;
1746
1747 r = sd_bus_add_match(
1748 bus,
1749 &d->slot_disconnected,
1750 "type='signal',"
1751 "sender='org.freedesktop.DBus.Local',"
1752 "interface='org.freedesktop.DBus.Local',"
1753 "member='Disconnected'",
1754 match_disconnected, d);
1755 if (r < 0)
1756 return r;
1757
1758 *ret = d;
1759 d = NULL;
1760
1761 return 0;
1762 }
1763
1764 static int bus_process_wait(sd_bus *bus) {
1765 int r;
1766
1767 for (;;) {
1768 r = sd_bus_process(bus, NULL);
1769 if (r < 0)
1770 return r;
1771 if (r > 0)
1772 return 0;
1773
1774 r = sd_bus_wait(bus, (uint64_t) -1);
1775 if (r < 0)
1776 return r;
1777 }
1778 }
1779
1780 static int bus_job_get_service_result(BusWaitForJobs *d, char **result) {
1781 _cleanup_free_ char *dbus_path = NULL;
1782
1783 assert(d);
1784 assert(d->name);
1785 assert(result);
1786
1787 dbus_path = unit_dbus_path_from_name(d->name);
1788 if (!dbus_path)
1789 return -ENOMEM;
1790
1791 return sd_bus_get_property_string(d->bus,
1792 "org.freedesktop.systemd1",
1793 dbus_path,
1794 "org.freedesktop.systemd1.Service",
1795 "Result",
1796 NULL,
1797 result);
1798 }
1799
1800 static const struct {
1801 const char *result, *explanation;
1802 } explanations [] = {
1803 { "resources", "a configured resource limit was exceeded" },
1804 { "timeout", "a timeout was exceeded" },
1805 { "exit-code", "the control process exited with error code" },
1806 { "signal", "a fatal signal was delivered to the control process" },
1807 { "core-dump", "a fatal signal was delivered causing the control process to dump core" },
1808 { "watchdog", "the service failed to send watchdog ping" },
1809 { "start-limit", "start of the service was attempted too often" }
1810 };
1811
1812 static void log_job_error_with_service_result(const char* service, const char *result) {
1813 _cleanup_free_ char *service_shell_quoted = NULL;
1814
1815 assert(service);
1816
1817 service_shell_quoted = shell_maybe_quote(service);
1818
1819 if (!isempty(result)) {
1820 unsigned i;
1821
1822 for (i = 0; i < ELEMENTSOF(explanations); ++i)
1823 if (streq(result, explanations[i].result))
1824 break;
1825
1826 if (i < ELEMENTSOF(explanations)) {
1827 log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1828 service,
1829 explanations[i].explanation,
1830 strna(service_shell_quoted));
1831
1832 goto finish;
1833 }
1834 }
1835
1836 log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1837 service,
1838 strna(service_shell_quoted));
1839
1840 finish:
1841 /* For some results maybe additional explanation is required */
1842 if (streq_ptr(result, "start-limit"))
1843 log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.",
1844 strna(service_shell_quoted));
1845 }
1846
1847 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
1848 int r = 0;
1849
1850 assert(d->result);
1851
1852 if (!quiet) {
1853 if (streq(d->result, "canceled"))
1854 log_error("Job for %s canceled.", strna(d->name));
1855 else if (streq(d->result, "timeout"))
1856 log_error("Job for %s timed out.", strna(d->name));
1857 else if (streq(d->result, "dependency"))
1858 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
1859 else if (streq(d->result, "invalid"))
1860 log_error("Job for %s invalid.", strna(d->name));
1861 else if (streq(d->result, "assert"))
1862 log_error("Assertion failed on job for %s.", strna(d->name));
1863 else if (streq(d->result, "unsupported"))
1864 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
1865 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
1866 if (d->name) {
1867 int q;
1868 _cleanup_free_ char *result = NULL;
1869
1870 q = bus_job_get_service_result(d, &result);
1871 if (q < 0)
1872 log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
1873
1874 log_job_error_with_service_result(d->name, result);
1875 } else
1876 log_error("Job failed. See \"journalctl -xe\" for details.");
1877 }
1878 }
1879
1880 if (streq(d->result, "canceled"))
1881 r = -ECANCELED;
1882 else if (streq(d->result, "timeout"))
1883 r = -ETIME;
1884 else if (streq(d->result, "dependency"))
1885 r = -EIO;
1886 else if (streq(d->result, "invalid"))
1887 r = -ENOEXEC;
1888 else if (streq(d->result, "assert"))
1889 r = -EPROTO;
1890 else if (streq(d->result, "unsupported"))
1891 r = -EOPNOTSUPP;
1892 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
1893 r = -EIO;
1894
1895 return r;
1896 }
1897
1898 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
1899 int r = 0;
1900
1901 assert(d);
1902
1903 while (!set_isempty(d->jobs)) {
1904 int q;
1905
1906 q = bus_process_wait(d->bus);
1907 if (q < 0)
1908 return log_error_errno(q, "Failed to wait for response: %m");
1909
1910 if (d->result) {
1911 q = check_wait_response(d, quiet);
1912 /* Return the first error as it is most likely to be
1913 * meaningful. */
1914 if (q < 0 && r == 0)
1915 r = q;
1916
1917 log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
1918 }
1919
1920 d->name = mfree(d->name);
1921 d->result = mfree(d->result);
1922 }
1923
1924 return r;
1925 }
1926
1927 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
1928 int r;
1929
1930 assert(d);
1931
1932 r = set_ensure_allocated(&d->jobs, &string_hash_ops);
1933 if (r < 0)
1934 return r;
1935
1936 return set_put_strdup(d->jobs, path);
1937 }
1938
1939 int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) {
1940 int r;
1941
1942 r = bus_wait_for_jobs_add(d, path);
1943 if (r < 0)
1944 return log_oom();
1945
1946 return bus_wait_for_jobs(d, quiet);
1947 }
1948
1949 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
1950 const char *type, *path, *source;
1951 int r;
1952
1953 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1954 if (r < 0)
1955 return bus_log_parse_error(r);
1956
1957 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1958 if (!quiet) {
1959 if (streq(type, "symlink"))
1960 log_info("Created symlink from %s to %s.", path, source);
1961 else
1962 log_info("Removed symlink %s.", path);
1963 }
1964
1965 r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source);
1966 if (r < 0)
1967 return r;
1968 }
1969 if (r < 0)
1970 return bus_log_parse_error(r);
1971
1972 r = sd_bus_message_exit_container(m);
1973 if (r < 0)
1974 return bus_log_parse_error(r);
1975
1976 return 0;
1977 }
1978
1979 /**
1980 * bus_path_encode_unique() - encode unique object path
1981 * @b: bus connection or NULL
1982 * @prefix: object path prefix
1983 * @sender_id: unique-name of client, or NULL
1984 * @external_id: external ID to be chosen by client, or NULL
1985 * @ret_path: storage for encoded object path pointer
1986 *
1987 * Whenever we provide a bus API that allows clients to create and manage
1988 * server-side objects, we need to provide a unique name for these objects. If
1989 * we let the server choose the name, we suffer from a race condition: If a
1990 * client creates an object asynchronously, it cannot destroy that object until
1991 * it received the method reply. It cannot know the name of the new object,
1992 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1993 *
1994 * Therefore, many APIs allow the client to choose the unique name for newly
1995 * created objects. There're two problems to solve, though:
1996 * 1) Object names are usually defined via dbus object paths, which are
1997 * usually globally namespaced. Therefore, multiple clients must be able
1998 * to choose unique object names without interference.
1999 * 2) If multiple libraries share the same bus connection, they must be
2000 * able to choose unique object names without interference.
2001 * The first problem is solved easily by prefixing a name with the
2002 * unique-bus-name of a connection. The server side must enforce this and
2003 * reject any other name. The second problem is solved by providing unique
2004 * suffixes from within sd-bus.
2005 *
2006 * This helper allows clients to create unique object-paths. It uses the
2007 * template '/prefix/sender_id/external_id' and returns the new path in
2008 * @ret_path (must be freed by the caller).
2009 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
2010 * NULL, this function allocates a unique suffix via @b (by requesting a new
2011 * cookie). If both @sender_id and @external_id are given, @b can be passed as
2012 * NULL.
2013 *
2014 * Returns: 0 on success, negative error code on failure.
2015 */
2016 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
2017 _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
2018 char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
2019 int r;
2020
2021 assert_return(b || (sender_id && external_id), -EINVAL);
2022 assert_return(object_path_is_valid(prefix), -EINVAL);
2023 assert_return(ret_path, -EINVAL);
2024
2025 if (!sender_id) {
2026 r = sd_bus_get_unique_name(b, &sender_id);
2027 if (r < 0)
2028 return r;
2029 }
2030
2031 if (!external_id) {
2032 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
2033 external_id = external_buf;
2034 }
2035
2036 sender_label = bus_label_escape(sender_id);
2037 if (!sender_label)
2038 return -ENOMEM;
2039
2040 external_label = bus_label_escape(external_id);
2041 if (!external_label)
2042 return -ENOMEM;
2043
2044 p = strjoin(prefix, "/", sender_label, "/", external_label, NULL);
2045 if (!p)
2046 return -ENOMEM;
2047
2048 *ret_path = p;
2049 return 0;
2050 }
2051
2052 /**
2053 * bus_path_decode_unique() - decode unique object path
2054 * @path: object path to decode
2055 * @prefix: object path prefix
2056 * @ret_sender: output parameter for sender-id label
2057 * @ret_external: output parameter for external-id label
2058 *
2059 * This does the reverse of bus_path_encode_unique() (see its description for
2060 * details). Both trailing labels, sender-id and external-id, are unescaped and
2061 * returned in the given output parameters (the caller must free them).
2062 *
2063 * Note that this function returns 0 if the path does not match the template
2064 * (see bus_path_encode_unique()), 1 if it matched.
2065 *
2066 * Returns: Negative error code on failure, 0 if the given object path does not
2067 * match the template (return parameters are set to NULL), 1 if it was
2068 * parsed successfully (return parameters contain allocated labels).
2069 */
2070 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
2071 const char *p, *q;
2072 char *sender, *external;
2073
2074 assert(object_path_is_valid(path));
2075 assert(object_path_is_valid(prefix));
2076 assert(ret_sender);
2077 assert(ret_external);
2078
2079 p = object_path_startswith(path, prefix);
2080 if (!p) {
2081 *ret_sender = NULL;
2082 *ret_external = NULL;
2083 return 0;
2084 }
2085
2086 q = strchr(p, '/');
2087 if (!q) {
2088 *ret_sender = NULL;
2089 *ret_external = NULL;
2090 return 0;
2091 }
2092
2093 sender = bus_label_unescape_n(p, q - p);
2094 external = bus_label_unescape(q + 1);
2095 if (!sender || !external) {
2096 free(sender);
2097 free(external);
2098 return -ENOMEM;
2099 }
2100
2101 *ret_sender = sender;
2102 *ret_external = external;
2103 return 1;
2104 }
2105
2106 bool is_kdbus_wanted(void) {
2107 _cleanup_free_ char *value = NULL;
2108 #ifdef ENABLE_KDBUS
2109 const bool configured = true;
2110 #else
2111 const bool configured = false;
2112 #endif
2113
2114 int r;
2115
2116 if (get_proc_cmdline_key("kdbus", NULL) > 0)
2117 return true;
2118
2119 r = get_proc_cmdline_key("kdbus=", &value);
2120 if (r <= 0)
2121 return configured;
2122
2123 return parse_boolean(value) == 1;
2124 }
2125
2126 bool is_kdbus_available(void) {
2127 _cleanup_close_ int fd = -1;
2128 struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE };
2129
2130 if (!is_kdbus_wanted())
2131 return false;
2132
2133 fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
2134 if (fd < 0)
2135 return false;
2136
2137 return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;
2138 }