]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/bus-util.c
Merge pull request #1668 from ssahani/net1
[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 r = sd_bus_message_append(m, "v", "s", eq);
1514
1515 else if (streq(field, "SyslogLevel")) {
1516 int level;
1517
1518 level = log_level_from_string(eq);
1519 if (level < 0) {
1520 log_error("Failed to parse %s value %s.", field, eq);
1521 return -EINVAL;
1522 }
1523
1524 r = sd_bus_message_append(m, "v", "i", level);
1525
1526 } else if (streq(field, "SyslogFacility")) {
1527 int facility;
1528
1529 facility = log_facility_unshifted_from_string(eq);
1530 if (facility < 0) {
1531 log_error("Failed to parse %s value %s.", field, eq);
1532 return -EINVAL;
1533 }
1534
1535 r = sd_bus_message_append(m, "v", "i", facility);
1536
1537 } else if (streq(field, "DeviceAllow")) {
1538
1539 if (isempty(eq))
1540 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1541 else {
1542 const char *path, *rwm, *e;
1543
1544 e = strchr(eq, ' ');
1545 if (e) {
1546 path = strndupa(eq, e - eq);
1547 rwm = e+1;
1548 } else {
1549 path = eq;
1550 rwm = "";
1551 }
1552
1553 if (!path_startswith(path, "/dev")) {
1554 log_error("%s is not a device file in /dev.", path);
1555 return -EINVAL;
1556 }
1557
1558 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1559 }
1560
1561 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1562
1563 if (isempty(eq))
1564 r = sd_bus_message_append(m, "v", "a(st)", 0);
1565 else {
1566 const char *path, *bandwidth, *e;
1567 uint64_t bytes;
1568
1569 e = strchr(eq, ' ');
1570 if (e) {
1571 path = strndupa(eq, e - eq);
1572 bandwidth = e+1;
1573 } else {
1574 log_error("Failed to parse %s value %s.", field, eq);
1575 return -EINVAL;
1576 }
1577
1578 if (!path_startswith(path, "/dev")) {
1579 log_error("%s is not a device file in /dev.", path);
1580 return -EINVAL;
1581 }
1582
1583 r = parse_size(bandwidth, 1000, &bytes);
1584 if (r < 0) {
1585 log_error("Failed to parse byte value %s.", bandwidth);
1586 return -EINVAL;
1587 }
1588
1589 r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes);
1590 }
1591
1592 } else if (streq(field, "BlockIODeviceWeight")) {
1593
1594 if (isempty(eq))
1595 r = sd_bus_message_append(m, "v", "a(st)", 0);
1596 else {
1597 const char *path, *weight, *e;
1598 uint64_t u;
1599
1600 e = strchr(eq, ' ');
1601 if (e) {
1602 path = strndupa(eq, e - eq);
1603 weight = e+1;
1604 } else {
1605 log_error("Failed to parse %s value %s.", field, eq);
1606 return -EINVAL;
1607 }
1608
1609 if (!path_startswith(path, "/dev")) {
1610 log_error("%s is not a device file in /dev.", path);
1611 return -EINVAL;
1612 }
1613
1614 r = safe_atou64(weight, &u);
1615 if (r < 0) {
1616 log_error("Failed to parse %s value %s.", field, weight);
1617 return -EINVAL;
1618 }
1619 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1620 }
1621
1622 } else if (rlimit_from_string(field) >= 0) {
1623 uint64_t rl;
1624
1625 if (streq(eq, "infinity"))
1626 rl = (uint64_t) -1;
1627 else {
1628 r = safe_atou64(eq, &rl);
1629 if (r < 0) {
1630 log_error("Invalid resource limit: %s", eq);
1631 return -EINVAL;
1632 }
1633 }
1634
1635 r = sd_bus_message_append(m, "v", "t", rl);
1636
1637 } else if (streq(field, "Nice")) {
1638 int32_t i;
1639
1640 r = safe_atoi32(eq, &i);
1641 if (r < 0) {
1642 log_error("Failed to parse %s value %s.", field, eq);
1643 return -EINVAL;
1644 }
1645
1646 r = sd_bus_message_append(m, "v", "i", i);
1647
1648 } else if (streq(field, "Environment")) {
1649 const char *p;
1650
1651 r = sd_bus_message_open_container(m, 'v', "as");
1652 if (r < 0)
1653 return bus_log_create_error(r);
1654
1655 r = sd_bus_message_open_container(m, 'a', "s");
1656 if (r < 0)
1657 return bus_log_create_error(r);
1658
1659 p = eq;
1660
1661 for (;;) {
1662 _cleanup_free_ char *word = NULL;
1663
1664 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE);
1665 if (r < 0) {
1666 log_error("Failed to parse Environment value %s", eq);
1667 return -EINVAL;
1668 }
1669 if (r == 0)
1670 break;
1671
1672 if (!env_assignment_is_valid(word)) {
1673 log_error("Invalid environment assignment: %s", eq);
1674 return -EINVAL;
1675 }
1676
1677 r = sd_bus_message_append_basic(m, 's', word);
1678 if (r < 0)
1679 return bus_log_create_error(r);
1680 }
1681
1682 r = sd_bus_message_close_container(m);
1683 if (r < 0)
1684 return bus_log_create_error(r);
1685
1686 r = sd_bus_message_close_container(m);
1687
1688 } else if (streq(field, "KillSignal")) {
1689 int sig;
1690
1691 sig = signal_from_string_try_harder(eq);
1692 if (sig < 0) {
1693 log_error("Failed to parse %s value %s.", field, eq);
1694 return -EINVAL;
1695 }
1696
1697 r = sd_bus_message_append(m, "v", "i", sig);
1698
1699 } else if (streq(field, "AccuracySec")) {
1700 usec_t u;
1701
1702 r = parse_sec(eq, &u);
1703 if (r < 0) {
1704 log_error("Failed to parse %s value %s", field, eq);
1705 return -EINVAL;
1706 }
1707
1708 r = sd_bus_message_append(m, "v", "t", u);
1709 } else if (streq(field, "TimerSlackNSec")) {
1710 nsec_t n;
1711
1712 r = parse_nsec(eq, &n);
1713 if (r < 0) {
1714 log_error("Failed to parse %s value %s", field, eq);
1715 return -EINVAL;
1716 }
1717
1718 r = sd_bus_message_append(m, "v", "t", n);
1719 } else if (streq(field, "OOMScoreAdjust")) {
1720 int oa;
1721
1722 r = safe_atoi(eq, &oa);
1723 if (r < 0) {
1724 log_error("Failed to parse %s value %s", field, eq);
1725 return -EINVAL;
1726 }
1727
1728 if (!oom_score_adjust_is_valid(oa)) {
1729 log_error("OOM score adjust value out of range");
1730 return -EINVAL;
1731 }
1732
1733 r = sd_bus_message_append(m, "v", "i", oa);
1734 } else if (STR_IN_SET(field, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1735 const char *p;
1736
1737 r = sd_bus_message_open_container(m, 'v', "as");
1738 if (r < 0)
1739 return bus_log_create_error(r);
1740
1741 r = sd_bus_message_open_container(m, 'a', "s");
1742 if (r < 0)
1743 return bus_log_create_error(r);
1744
1745 p = eq;
1746
1747 for (;;) {
1748 _cleanup_free_ char *word = NULL;
1749 int offset;
1750
1751 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
1752 if (r < 0) {
1753 log_error("Failed to parse %s value %s", field, eq);
1754 return -EINVAL;
1755 }
1756 if (r == 0)
1757 break;
1758
1759 if (!utf8_is_valid(word)) {
1760 log_error("Failed to parse %s value %s", field, eq);
1761 return -EINVAL;
1762 }
1763
1764 offset = word[0] == '-';
1765 if (!path_is_absolute(word + offset)) {
1766 log_error("Failed to parse %s value %s", field, eq);
1767 return -EINVAL;
1768 }
1769
1770 path_kill_slashes(word + offset);
1771
1772 r = sd_bus_message_append_basic(m, 's', word);
1773 if (r < 0)
1774 return bus_log_create_error(r);
1775 }
1776
1777 r = sd_bus_message_close_container(m);
1778 if (r < 0)
1779 return bus_log_create_error(r);
1780
1781 r = sd_bus_message_close_container(m);
1782
1783 } else {
1784 log_error("Unknown assignment %s.", assignment);
1785 return -EINVAL;
1786 }
1787
1788 if (r < 0)
1789 return bus_log_create_error(r);
1790
1791 return 0;
1792 }
1793
1794 typedef struct BusWaitForJobs {
1795 sd_bus *bus;
1796 Set *jobs;
1797
1798 char *name;
1799 char *result;
1800
1801 sd_bus_slot *slot_job_removed;
1802 sd_bus_slot *slot_disconnected;
1803 } BusWaitForJobs;
1804
1805 static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1806 assert(m);
1807
1808 log_error("Warning! D-Bus connection terminated.");
1809 sd_bus_close(sd_bus_message_get_bus(m));
1810
1811 return 0;
1812 }
1813
1814 static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1815 const char *path, *unit, *result;
1816 BusWaitForJobs *d = userdata;
1817 uint32_t id;
1818 char *found;
1819 int r;
1820
1821 assert(m);
1822 assert(d);
1823
1824 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1825 if (r < 0) {
1826 bus_log_parse_error(r);
1827 return 0;
1828 }
1829
1830 found = set_remove(d->jobs, (char*) path);
1831 if (!found)
1832 return 0;
1833
1834 free(found);
1835
1836 if (!isempty(result))
1837 d->result = strdup(result);
1838
1839 if (!isempty(unit))
1840 d->name = strdup(unit);
1841
1842 return 0;
1843 }
1844
1845 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1846 if (!d)
1847 return;
1848
1849 set_free_free(d->jobs);
1850
1851 sd_bus_slot_unref(d->slot_disconnected);
1852 sd_bus_slot_unref(d->slot_job_removed);
1853
1854 sd_bus_unref(d->bus);
1855
1856 free(d->name);
1857 free(d->result);
1858
1859 free(d);
1860 }
1861
1862 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1863 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1864 int r;
1865
1866 assert(bus);
1867 assert(ret);
1868
1869 d = new0(BusWaitForJobs, 1);
1870 if (!d)
1871 return -ENOMEM;
1872
1873 d->bus = sd_bus_ref(bus);
1874
1875 /* When we are a bus client we match by sender. Direct
1876 * connections OTOH have no initialized sender field, and
1877 * hence we ignore the sender then */
1878 r = sd_bus_add_match(
1879 bus,
1880 &d->slot_job_removed,
1881 bus->bus_client ?
1882 "type='signal',"
1883 "sender='org.freedesktop.systemd1',"
1884 "interface='org.freedesktop.systemd1.Manager',"
1885 "member='JobRemoved',"
1886 "path='/org/freedesktop/systemd1'" :
1887 "type='signal',"
1888 "interface='org.freedesktop.systemd1.Manager',"
1889 "member='JobRemoved',"
1890 "path='/org/freedesktop/systemd1'",
1891 match_job_removed, d);
1892 if (r < 0)
1893 return r;
1894
1895 r = sd_bus_add_match(
1896 bus,
1897 &d->slot_disconnected,
1898 "type='signal',"
1899 "sender='org.freedesktop.DBus.Local',"
1900 "interface='org.freedesktop.DBus.Local',"
1901 "member='Disconnected'",
1902 match_disconnected, d);
1903 if (r < 0)
1904 return r;
1905
1906 *ret = d;
1907 d = NULL;
1908
1909 return 0;
1910 }
1911
1912 static int bus_process_wait(sd_bus *bus) {
1913 int r;
1914
1915 for (;;) {
1916 r = sd_bus_process(bus, NULL);
1917 if (r < 0)
1918 return r;
1919 if (r > 0)
1920 return 0;
1921
1922 r = sd_bus_wait(bus, (uint64_t) -1);
1923 if (r < 0)
1924 return r;
1925 }
1926 }
1927
1928 static int bus_job_get_service_result(BusWaitForJobs *d, char **result) {
1929 _cleanup_free_ char *dbus_path = NULL;
1930
1931 assert(d);
1932 assert(d->name);
1933 assert(result);
1934
1935 dbus_path = unit_dbus_path_from_name(d->name);
1936 if (!dbus_path)
1937 return -ENOMEM;
1938
1939 return sd_bus_get_property_string(d->bus,
1940 "org.freedesktop.systemd1",
1941 dbus_path,
1942 "org.freedesktop.systemd1.Service",
1943 "Result",
1944 NULL,
1945 result);
1946 }
1947
1948 static const struct {
1949 const char *result, *explanation;
1950 } explanations [] = {
1951 { "resources", "a configured resource limit was exceeded" },
1952 { "timeout", "a timeout was exceeded" },
1953 { "exit-code", "the control process exited with error code" },
1954 { "signal", "a fatal signal was delivered to the control process" },
1955 { "core-dump", "a fatal signal was delivered causing the control process to dump core" },
1956 { "watchdog", "the service failed to send watchdog ping" },
1957 { "start-limit", "start of the service was attempted too often" }
1958 };
1959
1960 static void log_job_error_with_service_result(const char* service, const char *result) {
1961 _cleanup_free_ char *service_shell_quoted = NULL;
1962
1963 assert(service);
1964
1965 service_shell_quoted = shell_maybe_quote(service);
1966
1967 if (!isempty(result)) {
1968 unsigned i;
1969
1970 for (i = 0; i < ELEMENTSOF(explanations); ++i)
1971 if (streq(result, explanations[i].result))
1972 break;
1973
1974 if (i < ELEMENTSOF(explanations)) {
1975 log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1976 service,
1977 explanations[i].explanation,
1978 strna(service_shell_quoted));
1979
1980 goto finish;
1981 }
1982 }
1983
1984 log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1985 service,
1986 strna(service_shell_quoted));
1987
1988 finish:
1989 /* For some results maybe additional explanation is required */
1990 if (streq_ptr(result, "start-limit"))
1991 log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.",
1992 strna(service_shell_quoted));
1993 }
1994
1995 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
1996 int r = 0;
1997
1998 assert(d->result);
1999
2000 if (!quiet) {
2001 if (streq(d->result, "canceled"))
2002 log_error("Job for %s canceled.", strna(d->name));
2003 else if (streq(d->result, "timeout"))
2004 log_error("Job for %s timed out.", strna(d->name));
2005 else if (streq(d->result, "dependency"))
2006 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2007 else if (streq(d->result, "invalid"))
2008 log_error("Job for %s invalid.", strna(d->name));
2009 else if (streq(d->result, "assert"))
2010 log_error("Assertion failed on job for %s.", strna(d->name));
2011 else if (streq(d->result, "unsupported"))
2012 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
2013 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2014 if (d->name) {
2015 int q;
2016 _cleanup_free_ char *result = NULL;
2017
2018 q = bus_job_get_service_result(d, &result);
2019 if (q < 0)
2020 log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
2021
2022 log_job_error_with_service_result(d->name, result);
2023 } else
2024 log_error("Job failed. See \"journalctl -xe\" for details.");
2025 }
2026 }
2027
2028 if (streq(d->result, "canceled"))
2029 r = -ECANCELED;
2030 else if (streq(d->result, "timeout"))
2031 r = -ETIME;
2032 else if (streq(d->result, "dependency"))
2033 r = -EIO;
2034 else if (streq(d->result, "invalid"))
2035 r = -ENOEXEC;
2036 else if (streq(d->result, "assert"))
2037 r = -EPROTO;
2038 else if (streq(d->result, "unsupported"))
2039 r = -EOPNOTSUPP;
2040 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2041 r = -EIO;
2042
2043 return r;
2044 }
2045
2046 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
2047 int r = 0;
2048
2049 assert(d);
2050
2051 while (!set_isempty(d->jobs)) {
2052 int q;
2053
2054 q = bus_process_wait(d->bus);
2055 if (q < 0)
2056 return log_error_errno(q, "Failed to wait for response: %m");
2057
2058 if (d->result) {
2059 q = check_wait_response(d, quiet);
2060 /* Return the first error as it is most likely to be
2061 * meaningful. */
2062 if (q < 0 && r == 0)
2063 r = q;
2064
2065 log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
2066 }
2067
2068 d->name = mfree(d->name);
2069 d->result = mfree(d->result);
2070 }
2071
2072 return r;
2073 }
2074
2075 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
2076 int r;
2077
2078 assert(d);
2079
2080 r = set_ensure_allocated(&d->jobs, &string_hash_ops);
2081 if (r < 0)
2082 return r;
2083
2084 return set_put_strdup(d->jobs, path);
2085 }
2086
2087 int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) {
2088 int r;
2089
2090 r = bus_wait_for_jobs_add(d, path);
2091 if (r < 0)
2092 return log_oom();
2093
2094 return bus_wait_for_jobs(d, quiet);
2095 }
2096
2097 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
2098 const char *type, *path, *source;
2099 int r;
2100
2101 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
2102 if (r < 0)
2103 return bus_log_parse_error(r);
2104
2105 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
2106 if (!quiet) {
2107 if (streq(type, "symlink"))
2108 log_info("Created symlink from %s to %s.", path, source);
2109 else
2110 log_info("Removed symlink %s.", path);
2111 }
2112
2113 r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source);
2114 if (r < 0)
2115 return r;
2116 }
2117 if (r < 0)
2118 return bus_log_parse_error(r);
2119
2120 r = sd_bus_message_exit_container(m);
2121 if (r < 0)
2122 return bus_log_parse_error(r);
2123
2124 return 0;
2125 }
2126
2127 /**
2128 * bus_path_encode_unique() - encode unique object path
2129 * @b: bus connection or NULL
2130 * @prefix: object path prefix
2131 * @sender_id: unique-name of client, or NULL
2132 * @external_id: external ID to be chosen by client, or NULL
2133 * @ret_path: storage for encoded object path pointer
2134 *
2135 * Whenever we provide a bus API that allows clients to create and manage
2136 * server-side objects, we need to provide a unique name for these objects. If
2137 * we let the server choose the name, we suffer from a race condition: If a
2138 * client creates an object asynchronously, it cannot destroy that object until
2139 * it received the method reply. It cannot know the name of the new object,
2140 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
2141 *
2142 * Therefore, many APIs allow the client to choose the unique name for newly
2143 * created objects. There're two problems to solve, though:
2144 * 1) Object names are usually defined via dbus object paths, which are
2145 * usually globally namespaced. Therefore, multiple clients must be able
2146 * to choose unique object names without interference.
2147 * 2) If multiple libraries share the same bus connection, they must be
2148 * able to choose unique object names without interference.
2149 * The first problem is solved easily by prefixing a name with the
2150 * unique-bus-name of a connection. The server side must enforce this and
2151 * reject any other name. The second problem is solved by providing unique
2152 * suffixes from within sd-bus.
2153 *
2154 * This helper allows clients to create unique object-paths. It uses the
2155 * template '/prefix/sender_id/external_id' and returns the new path in
2156 * @ret_path (must be freed by the caller).
2157 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
2158 * NULL, this function allocates a unique suffix via @b (by requesting a new
2159 * cookie). If both @sender_id and @external_id are given, @b can be passed as
2160 * NULL.
2161 *
2162 * Returns: 0 on success, negative error code on failure.
2163 */
2164 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
2165 _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
2166 char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
2167 int r;
2168
2169 assert_return(b || (sender_id && external_id), -EINVAL);
2170 assert_return(object_path_is_valid(prefix), -EINVAL);
2171 assert_return(ret_path, -EINVAL);
2172
2173 if (!sender_id) {
2174 r = sd_bus_get_unique_name(b, &sender_id);
2175 if (r < 0)
2176 return r;
2177 }
2178
2179 if (!external_id) {
2180 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
2181 external_id = external_buf;
2182 }
2183
2184 sender_label = bus_label_escape(sender_id);
2185 if (!sender_label)
2186 return -ENOMEM;
2187
2188 external_label = bus_label_escape(external_id);
2189 if (!external_label)
2190 return -ENOMEM;
2191
2192 p = strjoin(prefix, "/", sender_label, "/", external_label, NULL);
2193 if (!p)
2194 return -ENOMEM;
2195
2196 *ret_path = p;
2197 return 0;
2198 }
2199
2200 /**
2201 * bus_path_decode_unique() - decode unique object path
2202 * @path: object path to decode
2203 * @prefix: object path prefix
2204 * @ret_sender: output parameter for sender-id label
2205 * @ret_external: output parameter for external-id label
2206 *
2207 * This does the reverse of bus_path_encode_unique() (see its description for
2208 * details). Both trailing labels, sender-id and external-id, are unescaped and
2209 * returned in the given output parameters (the caller must free them).
2210 *
2211 * Note that this function returns 0 if the path does not match the template
2212 * (see bus_path_encode_unique()), 1 if it matched.
2213 *
2214 * Returns: Negative error code on failure, 0 if the given object path does not
2215 * match the template (return parameters are set to NULL), 1 if it was
2216 * parsed successfully (return parameters contain allocated labels).
2217 */
2218 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
2219 const char *p, *q;
2220 char *sender, *external;
2221
2222 assert(object_path_is_valid(path));
2223 assert(object_path_is_valid(prefix));
2224 assert(ret_sender);
2225 assert(ret_external);
2226
2227 p = object_path_startswith(path, prefix);
2228 if (!p) {
2229 *ret_sender = NULL;
2230 *ret_external = NULL;
2231 return 0;
2232 }
2233
2234 q = strchr(p, '/');
2235 if (!q) {
2236 *ret_sender = NULL;
2237 *ret_external = NULL;
2238 return 0;
2239 }
2240
2241 sender = bus_label_unescape_n(p, q - p);
2242 external = bus_label_unescape(q + 1);
2243 if (!sender || !external) {
2244 free(sender);
2245 free(external);
2246 return -ENOMEM;
2247 }
2248
2249 *ret_sender = sender;
2250 *ret_external = external;
2251 return 1;
2252 }
2253
2254 bool is_kdbus_wanted(void) {
2255 _cleanup_free_ char *value = NULL;
2256 #ifdef ENABLE_KDBUS
2257 const bool configured = true;
2258 #else
2259 const bool configured = false;
2260 #endif
2261
2262 int r;
2263
2264 if (get_proc_cmdline_key("kdbus", NULL) > 0)
2265 return true;
2266
2267 r = get_proc_cmdline_key("kdbus=", &value);
2268 if (r <= 0)
2269 return configured;
2270
2271 return parse_boolean(value) == 1;
2272 }
2273
2274 bool is_kdbus_available(void) {
2275 _cleanup_close_ int fd = -1;
2276 struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE };
2277
2278 if (!is_kdbus_wanted())
2279 return false;
2280
2281 fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
2282 if (fd < 0)
2283 return false;
2284
2285 return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;
2286 }
2287
2288 int bus_property_get_rlimit(
2289 sd_bus *bus,
2290 const char *path,
2291 const char *interface,
2292 const char *property,
2293 sd_bus_message *reply,
2294 void *userdata,
2295 sd_bus_error *error) {
2296
2297 struct rlimit *rl;
2298 uint64_t u;
2299 rlim_t x;
2300
2301 assert(bus);
2302 assert(reply);
2303 assert(userdata);
2304
2305 rl = *(struct rlimit**) userdata;
2306 if (rl)
2307 x = rl->rlim_max;
2308 else {
2309 struct rlimit buf = {};
2310 int z;
2311
2312 z = rlimit_from_string(strstr(property, "Limit"));
2313 assert(z >= 0);
2314
2315 getrlimit(z, &buf);
2316 x = buf.rlim_max;
2317 }
2318
2319 /* rlim_t might have different sizes, let's map
2320 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
2321 * all archs */
2322 u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
2323
2324 return sd_bus_message_append(reply, "t", u);
2325 }