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