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