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