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