]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-manager.c
bus: introduce "trusted" bus concept and encode access control in object vtables
[thirdparty/systemd.git] / src / core / dbus-manager.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 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 <errno.h>
23 #include <unistd.h>
24
25 #include "log.h"
26 #include "strv.h"
27 #include "build.h"
28 #include "install.h"
29 #include "selinux-access.h"
30 #include "watchdog.h"
31 #include "hwclock.h"
32 #include "path-util.h"
33 #include "virt.h"
34 #include "env-util.h"
35 #include "dbus.h"
36 #include "dbus-manager.h"
37 #include "dbus-unit.h"
38 #include "dbus-snapshot.h"
39 #include "dbus-client-track.h"
40 #include "dbus-execute.h"
41 #include "bus-errors.h"
42
43 static int property_get_version(
44 sd_bus *bus,
45 const char *path,
46 const char *interface,
47 const char *property,
48 sd_bus_message *reply,
49 void *userdata,
50 sd_bus_error *error) {
51
52 assert(bus);
53 assert(reply);
54
55 return sd_bus_message_append(reply, "s", PACKAGE_VERSION);
56 }
57
58 static int property_get_features(
59 sd_bus *bus,
60 const char *path,
61 const char *interface,
62 const char *property,
63 sd_bus_message *reply,
64 void *userdata,
65 sd_bus_error *error) {
66
67 assert(bus);
68 assert(reply);
69
70 return sd_bus_message_append(reply, "s", SYSTEMD_FEATURES);
71 }
72
73 static int property_get_virtualization(
74 sd_bus *bus,
75 const char *path,
76 const char *interface,
77 const char *property,
78 sd_bus_message *reply,
79 void *userdata,
80 sd_bus_error *error) {
81
82 const char *id = NULL;
83
84 assert(bus);
85 assert(reply);
86
87 detect_virtualization(&id);
88
89 return sd_bus_message_append(reply, "s", id);
90 }
91
92 static int property_get_tainted(
93 sd_bus *bus,
94 const char *path,
95 const char *interface,
96 const char *property,
97 sd_bus_message *reply,
98 void *userdata,
99 sd_bus_error *error) {
100
101 char buf[sizeof("split-usr:mtab-not-symlink:cgroups-missing:local-hwclock:")] = "", *e = buf;
102 _cleanup_free_ char *p = NULL;
103 Manager *m = userdata;
104
105 assert(bus);
106 assert(reply);
107 assert(m);
108
109 if (m->taint_usr)
110 e = stpcpy(e, "split-usr:");
111
112 if (readlink_malloc("/etc/mtab", &p) < 0)
113 e = stpcpy(e, "mtab-not-symlink:");
114
115 if (access("/proc/cgroups", F_OK) < 0)
116 e = stpcpy(e, "cgroups-missing:");
117
118 if (hwclock_is_localtime() > 0)
119 e = stpcpy(e, "local-hwclock:");
120
121 /* remove the last ':' */
122 if (e != buf)
123 e[-1] = 0;
124
125 return sd_bus_message_append(reply, "s", buf);
126 }
127
128 static int property_get_log_target(
129 sd_bus *bus,
130 const char *path,
131 const char *interface,
132 const char *property,
133 sd_bus_message *reply,
134 void *userdata,
135 sd_bus_error *error) {
136
137 assert(bus);
138 assert(reply);
139
140 return sd_bus_message_append(reply, "s", log_target_to_string(log_get_target()));
141 }
142
143 static int property_set_log_target(
144 sd_bus *bus,
145 const char *path,
146 const char *interface,
147 const char *property,
148 sd_bus_message *value,
149 void *userdata,
150 sd_bus_error *error) {
151
152 const char *t;
153 int r;
154
155 assert(bus);
156 assert(value);
157
158 r = sd_bus_message_read(value, "s", &t);
159 if (r < 0)
160 return r;
161
162 return log_set_target_from_string(t);
163 }
164
165 static int property_get_log_level(
166 sd_bus *bus,
167 const char *path,
168 const char *interface,
169 const char *property,
170 sd_bus_message *reply,
171 void *userdata,
172 sd_bus_error *error) {
173
174 _cleanup_free_ char *t = NULL;
175 int r;
176
177 assert(bus);
178 assert(reply);
179
180 r = log_level_to_string_alloc(log_get_max_level(), &t);
181 if (r < 0)
182 return r;
183
184 return sd_bus_message_append(reply, "s", t);
185 }
186
187 static int property_set_log_level(
188 sd_bus *bus,
189 const char *path,
190 const char *interface,
191 const char *property,
192 sd_bus_message *value,
193 void *userdata,
194 sd_bus_error *error) {
195
196 const char *t;
197 int r;
198
199 assert(bus);
200 assert(value);
201
202 r = sd_bus_message_read(value, "s", &t);
203 if (r < 0)
204 return r;
205
206 return log_set_max_level_from_string(t);
207 }
208
209 static int property_get_n_names(
210 sd_bus *bus,
211 const char *path,
212 const char *interface,
213 const char *property,
214 sd_bus_message *reply,
215 void *userdata,
216 sd_bus_error *error) {
217
218 Manager *m = userdata;
219
220 assert(bus);
221 assert(reply);
222 assert(m);
223
224 return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->units));
225 }
226
227 static int property_get_n_jobs(
228 sd_bus *bus,
229 const char *path,
230 const char *interface,
231 const char *property,
232 sd_bus_message *reply,
233 void *userdata,
234 sd_bus_error *error) {
235
236 Manager *m = userdata;
237
238 assert(bus);
239 assert(reply);
240 assert(m);
241
242 return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->jobs));
243 }
244
245 static int property_get_progress(
246 sd_bus *bus,
247 const char *path,
248 const char *interface,
249 const char *property,
250 sd_bus_message *reply,
251 void *userdata,
252 sd_bus_error *error) {
253
254 Manager *m = userdata;
255 double d;
256
257 assert(bus);
258 assert(reply);
259 assert(m);
260
261 if (dual_timestamp_is_set(&m->finish_timestamp))
262 d = 1.0;
263 else
264 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
265
266 return sd_bus_message_append(reply, "d", d);
267 }
268
269 static int property_set_runtime_watchdog(
270 sd_bus *bus,
271 const char *path,
272 const char *interface,
273 const char *property,
274 sd_bus_message *value,
275 void *userdata,
276 sd_bus_error *error) {
277
278 usec_t *t = userdata;
279 int r;
280
281 assert(bus);
282 assert(value);
283
284 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
285
286 r = sd_bus_message_read(value, "t", t);
287 if (r < 0)
288 return r;
289
290 return watchdog_set_timeout(t);
291 }
292
293 static int method_get_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
294 _cleanup_free_ char *path = NULL;
295 Manager *m = userdata;
296 const char *name;
297 Unit *u;
298 int r;
299
300 assert(bus);
301 assert(message);
302 assert(m);
303
304 r = sd_bus_message_read(message, "s", &name);
305 if (r < 0)
306 return r;
307
308 u = manager_get_unit(m, name);
309 if (!u)
310 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
311
312 r = selinux_unit_access_check(u, bus, message, "status", error);
313 if (r < 0)
314 return r;
315
316 path = unit_dbus_path(u);
317 if (!path)
318 return -ENOMEM;
319
320 return sd_bus_reply_method_return(message, "o", path);
321 }
322
323 static int method_get_unit_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
324 _cleanup_free_ char *path = NULL;
325 Manager *m = userdata;
326 pid_t pid;
327 Unit *u;
328 int r;
329
330 assert(bus);
331 assert(message);
332 assert(m);
333
334 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
335
336 r = sd_bus_message_read(message, "u", &pid);
337 if (r < 0)
338 return r;
339
340 if (pid == 0) {
341 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
342
343 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
344 if (r < 0)
345 return r;
346
347 r = sd_bus_creds_get_pid(creds, &pid);
348 if (r < 0)
349 return r;
350 }
351
352 u = manager_get_unit_by_pid(m, pid);
353 if (!u)
354 return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID %u does not belong to any loaded unit.", pid);
355
356 r = selinux_unit_access_check(u, bus, message, "status", error);
357 if (r < 0)
358 return r;
359
360 path = unit_dbus_path(u);
361 if (!path)
362 return -ENOMEM;
363
364 return sd_bus_reply_method_return(message, "o", path);
365 }
366
367 static int method_load_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
368 _cleanup_free_ char *path = NULL;
369 Manager *m = userdata;
370 const char *name;
371 Unit *u;
372 int r;
373
374 assert(bus);
375 assert(message);
376 assert(m);
377
378 r = sd_bus_message_read(message, "s", &name);
379 if (r < 0)
380 return r;
381
382 r = manager_load_unit(m, name, NULL, error, &u);
383 if (r < 0)
384 return r;
385
386 r = selinux_unit_access_check(u, bus, message, "status", error);
387 if (r < 0)
388 return r;
389
390 path = unit_dbus_path(u);
391 if (!path)
392 return -ENOMEM;
393
394 return sd_bus_reply_method_return(message, "o", path);
395 }
396
397 static int method_start_unit_generic(sd_bus *bus, sd_bus_message *message, Manager *m, JobType job_type, bool reload_if_possible, sd_bus_error *error) {
398 const char *name;
399 Unit *u;
400 int r;
401
402 assert(bus);
403 assert(message);
404 assert(m);
405
406 r = sd_bus_message_read(message, "s", &name);
407 if (r < 0)
408 return r;
409
410 r = manager_load_unit(m, name, NULL, error, &u);
411 if (r < 0)
412 return r;
413
414 return bus_unit_method_start_generic(bus, message, u, job_type, reload_if_possible, error);
415 }
416
417 static int method_start_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
418 return method_start_unit_generic(bus, message, userdata, JOB_START, false, error);
419 }
420
421 static int method_stop_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
422 return method_start_unit_generic(bus, message, userdata, JOB_STOP, false, error);
423 }
424
425 static int method_reload_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
426 return method_start_unit_generic(bus, message, userdata, JOB_RELOAD, false, error);
427 }
428
429 static int method_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
430 return method_start_unit_generic(bus, message, userdata, JOB_RESTART, false, error);
431 }
432
433 static int method_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
434 return method_start_unit_generic(bus, message, userdata, JOB_TRY_RESTART, false, error);
435 }
436
437 static int method_reload_or_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
438 return method_start_unit_generic(bus, message, userdata, JOB_RESTART, true, error);
439 }
440
441 static int method_reload_or_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
442 return method_start_unit_generic(bus, message, userdata, JOB_TRY_RESTART, true, error);
443 }
444
445 static int method_start_unit_replace(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
446 Manager *m = userdata;
447 const char *old_name;
448 Unit *u;
449 int r;
450
451 assert(bus);
452 assert(message);
453 assert(m);
454
455 r = sd_bus_message_read(message, "s", &old_name);
456 if (r < 0)
457 return r;
458
459 u = manager_get_unit(m, old_name);
460 if (!u || !u->job || u->job->type != JOB_START)
461 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
462
463 return method_start_unit_generic(bus, message, m, JOB_START, false, error);
464 }
465
466 static int method_kill_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
467 Manager *m = userdata;
468 const char *name;
469 Unit *u;
470 int r;
471
472 assert(bus);
473 assert(message);
474 assert(m);
475
476 r = sd_bus_message_read(message, "s", &name);
477 if (r < 0)
478 return r;
479
480 u = manager_get_unit(m, name);
481 if (!u)
482 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
483
484 return bus_unit_method_kill(bus, message, u, error);
485 }
486
487 static int method_reset_failed_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
488 Manager *m = userdata;
489 const char *name;
490 Unit *u;
491 int r;
492
493 assert(bus);
494 assert(message);
495 assert(m);
496
497 r = sd_bus_message_read(message, "s", &name);
498 if (r < 0)
499 return r;
500
501 u = manager_get_unit(m, name);
502 if (!u)
503 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
504
505 return bus_unit_method_reset_failed(bus, message, u, error);
506 }
507
508 static int method_set_unit_properties(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
509 Manager *m = userdata;
510 const char *name;
511 Unit *u;
512 int r;
513
514 assert(bus);
515 assert(message);
516 assert(m);
517
518 r = sd_bus_message_read(message, "s", &name);
519 if (r < 0)
520 return r;
521
522 u = manager_get_unit(m, name);
523 if (!u)
524 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
525
526 return bus_unit_method_set_properties(bus, message, u, error);
527 }
528
529 static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
530 const char *name, *smode;
531 Manager *m = userdata;
532 JobMode mode;
533 UnitType t;
534 Unit *u;
535 int r;
536
537 assert(bus);
538 assert(message);
539 assert(m);
540
541 r = sd_bus_message_read(message, "ss", &name, &smode);
542 if (r < 0)
543 return r;
544
545 t = unit_name_to_type(name);
546 if (t < 0)
547 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit type.");
548
549 if (!unit_vtable[t]->can_transient)
550 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.");
551
552 mode = job_mode_from_string(smode);
553 if (mode < 0)
554 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode);
555
556 r = selinux_access_check(bus, message, "start", error);
557 if (r < 0)
558 return r;
559
560 r = manager_load_unit(m, name, NULL, error, &u);
561 if (r < 0)
562 return r;
563
564 if (u->load_state != UNIT_NOT_FOUND || set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
565 return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
566
567 /* OK, the unit failed to load and is unreferenced, now let's
568 * fill in the transient data instead */
569 r = unit_make_transient(u);
570 if (r < 0)
571 return r;
572
573 /* Set our properties */
574 r = bus_unit_set_properties(u, message, UNIT_RUNTIME, false, error);
575 if (r < 0)
576 return r;
577
578 /* And load this stub fully */
579 r = unit_load(u);
580 if (r < 0)
581 return r;
582
583 manager_dispatch_load_queue(m);
584
585 /* Finally, start it */
586 return bus_unit_queue_job(bus, message, u, JOB_START, mode, false, error);
587 }
588
589 static int method_get_job(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
590 _cleanup_free_ char *path = NULL;
591 Manager *m = userdata;
592 uint32_t id;
593 Job *j;
594 int r;
595
596 assert(bus);
597 assert(message);
598 assert(m);
599
600 r = sd_bus_message_read(message, "u", &id);
601 if (r < 0)
602 return r;
603
604 j = manager_get_job(m, id);
605 if (!j)
606 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
607
608 r = selinux_unit_access_check(j->unit, bus, message, "status", error);
609 if (r < 0)
610 return r;
611
612 path = job_dbus_path(j);
613 if (!path)
614 return -ENOMEM;
615
616 return sd_bus_reply_method_return(message, "o", path);
617 }
618
619 static int method_cancel_job(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
620 Manager *m = userdata;
621 uint32_t id;
622 Job *j;
623 int r;
624
625 assert(bus);
626 assert(message);
627 assert(m);
628
629 r = sd_bus_message_read(message, "u", &id);
630 if (r < 0)
631 return r;
632
633 j = manager_get_job(m, id);
634 if (!j)
635 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
636
637 r = selinux_unit_access_check(j->unit, bus, message, "stop", error);
638 if (r < 0)
639 return r;
640
641 job_finish_and_invalidate(j, JOB_CANCELED, true);
642
643 return sd_bus_reply_method_return(message, NULL);
644 }
645
646 static int method_clear_jobs(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
647 Manager *m = userdata;
648 int r;
649
650 assert(bus);
651 assert(message);
652 assert(m);
653
654 r = selinux_access_check(bus, message, "reboot", error);
655 if (r < 0)
656 return r;
657
658 manager_clear_jobs(m);
659
660 return sd_bus_reply_method_return(message, NULL);
661 }
662
663 static int method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
664 Manager *m = userdata;
665 int r;
666
667 assert(bus);
668 assert(message);
669 assert(m);
670
671 r = selinux_access_check(bus, message, "reload", error);
672 if (r < 0)
673 return r;
674
675 manager_reset_failed(m);
676
677 return sd_bus_reply_method_return(message, NULL);
678 }
679
680 static int method_list_units(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
681 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
682 Manager *m = userdata;
683 const char *k;
684 Iterator i;
685 Unit *u;
686 int r;
687
688 assert(bus);
689 assert(message);
690 assert(m);
691
692 r = selinux_access_check(bus, message, "status", error);
693 if (r < 0)
694 return r;
695
696 r = sd_bus_message_new_method_return(message, &reply);
697 if (r < 0)
698 return r;
699
700 r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)");
701 if (r < 0)
702 return r;
703
704 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
705 _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
706 Unit *following;
707
708 if (k != u->id)
709 continue;
710
711 following = unit_following(u);
712
713 unit_path = unit_dbus_path(u);
714 if (!unit_path)
715 return -ENOMEM;
716
717 if (u->job) {
718 job_path = job_dbus_path(u->job);
719 if (!job_path)
720 return -ENOMEM;
721 }
722
723 r = sd_bus_message_append(
724 reply, "(ssssssouso)",
725 u->id,
726 unit_description(u),
727 unit_load_state_to_string(u->load_state),
728 unit_active_state_to_string(unit_active_state(u)),
729 unit_sub_state_to_string(u),
730 following ? following->id : "",
731 unit_path,
732 u->job ? u->job->id : 0,
733 u->job ? job_type_to_string(u->job->type) : "",
734 job_path ? job_path : "/");
735 if (r < 0)
736 return r;
737 }
738
739 r = sd_bus_message_close_container(reply);
740 if (r < 0)
741 return r;
742
743 return sd_bus_send(bus, reply, NULL);
744 }
745
746 static int method_list_jobs(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
747 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
748 Manager *m = userdata;
749 Iterator i;
750 Job *j;
751 int r;
752
753 assert(bus);
754 assert(message);
755 assert(m);
756
757 r = selinux_access_check(bus, message, "status", error);
758 if (r < 0)
759 return r;
760
761 r = sd_bus_message_new_method_return(message, &reply);
762 if (r < 0)
763 return r;
764
765 r = sd_bus_message_open_container(reply, 'a', "(usssoo)");
766 if (r < 0)
767 return r;
768
769 HASHMAP_FOREACH(j, m->jobs, i) {
770 _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
771
772 job_path = job_dbus_path(j);
773 if (!job_path)
774 return -ENOMEM;
775
776 unit_path = unit_dbus_path(j->unit);
777 if (!unit_path)
778 return -ENOMEM;
779
780 r = sd_bus_message_append(
781 reply, "(usssoo)",
782 j->id,
783 j->unit->id,
784 job_type_to_string(j->type),
785 job_state_to_string(j->state),
786 job_path,
787 unit_path);
788 if (r < 0)
789 return r;
790 }
791
792 r = sd_bus_message_close_container(reply);
793 if (r < 0)
794 return r;
795
796 return sd_bus_send(bus, reply, NULL);
797 }
798
799 static int method_subscribe(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
800 Manager *m = userdata;
801 int r;
802
803 assert(bus);
804 assert(message);
805 assert(m);
806
807 r = selinux_access_check(bus, message, "status", error);
808 if (r < 0)
809 return r;
810
811 r = bus_client_track(&m->subscribed, bus, sd_bus_message_get_sender(message));
812 if (r < 0)
813 return r;
814 if (r == 0)
815 return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
816
817 return sd_bus_reply_method_return(message, NULL);
818 }
819
820 static int method_unsubscribe(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
821 Manager *m = userdata;
822 int r;
823
824 assert(bus);
825 assert(message);
826 assert(m);
827
828 r = selinux_access_check(bus, message, "status", error);
829 if (r < 0)
830 return r;
831
832 r = bus_client_untrack(m->subscribed, bus, sd_bus_message_get_sender(message));
833 if (r < 0)
834 return r;
835 if (r == 0)
836 return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
837
838 return sd_bus_reply_method_return(message, NULL);
839 }
840
841 static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
842 _cleanup_free_ char *dump = NULL;
843 _cleanup_fclose_ FILE *f = NULL;
844 Manager *m = userdata;
845 size_t size;
846 int r;
847
848 assert(bus);
849 assert(message);
850 assert(m);
851
852 r = selinux_access_check(bus, message, "status", error);
853 if (r < 0)
854 return r;
855
856 f = open_memstream(&dump, &size);
857 if (!f)
858 return -ENOMEM;
859
860 manager_dump_units(m, f, NULL);
861 manager_dump_jobs(m, f, NULL);
862
863 fflush(f);
864
865 if (ferror(f))
866 return -ENOMEM;
867
868 return sd_bus_reply_method_return(message, "s", dump);
869 }
870
871 static int method_create_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
872 _cleanup_free_ char *path = NULL;
873 Manager *m = userdata;
874 const char *name;
875 int cleanup;
876 Snapshot *s;
877 int r;
878
879 assert(bus);
880 assert(message);
881 assert(m);
882
883 r = selinux_access_check(bus, message, "start", error);
884 if (r < 0)
885 return r;
886
887 r = sd_bus_message_read(message, "sb", &name, &cleanup);
888 if (r < 0)
889 return r;
890
891 if (isempty(name))
892 name = NULL;
893
894 r = snapshot_create(m, name, cleanup, error, &s);
895 if (r < 0)
896 return r;
897
898 path = unit_dbus_path(UNIT(s));
899 if (!path)
900 return -ENOMEM;
901
902 return sd_bus_reply_method_return(message, "o", path);
903 }
904
905 static int method_remove_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
906 Manager *m = userdata;
907 const char *name;
908 Unit *u;
909 int r;
910
911 assert(bus);
912 assert(message);
913 assert(m);
914
915 r = selinux_access_check(bus, message, "stop", error);
916 if (r < 0)
917 return r;
918
919 r = sd_bus_message_read(message, "s", &name);
920 if (r < 0)
921 return r;
922
923 u = manager_get_unit(m, name);
924 if (!u)
925 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
926
927 if (u->type != UNIT_SNAPSHOT)
928 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot", name);
929
930 return bus_snapshot_method_remove(bus, message, u, error);
931 }
932
933 static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
934 Manager *m = userdata;
935 int r;
936
937 assert(bus);
938 assert(message);
939 assert(m);
940
941 r = selinux_access_check(bus, message, "reload", error);
942 if (r < 0)
943 return r;
944
945 /* Instead of sending the reply back right away, we just
946 * remember that we need to and then send it after the reload
947 * is finished. That way the caller knows when the reload
948 * finished. */
949
950 assert(!m->queued_message);
951 r = sd_bus_message_new_method_return(message, &m->queued_message);
952 if (r < 0)
953 return r;
954
955 m->queued_message_bus = sd_bus_ref(bus);
956 m->exit_code = MANAGER_RELOAD;
957
958 return 1;
959 }
960
961 static int method_reexecute(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
962 Manager *m = userdata;
963 int r;
964
965 assert(bus);
966 assert(message);
967 assert(m);
968
969 r = selinux_access_check(bus, message, "reload", error);
970 if (r < 0)
971 return r;
972
973 /* We don't send a reply back here, the client should
974 * just wait for us disconnecting. */
975
976 m->exit_code = MANAGER_REEXECUTE;
977 return 1;
978 }
979
980 static int method_exit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
981 Manager *m = userdata;
982 int r;
983
984 assert(bus);
985 assert(message);
986 assert(m);
987
988 r = selinux_access_check(bus, message, "halt", error);
989 if (r < 0)
990 return r;
991
992 if (m->running_as == SYSTEMD_SYSTEM)
993 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
994
995 m->exit_code = MANAGER_EXIT;
996
997 return sd_bus_reply_method_return(message, NULL);
998 }
999
1000 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1001 Manager *m = userdata;
1002 int r;
1003
1004 assert(bus);
1005 assert(message);
1006 assert(m);
1007
1008 r = selinux_access_check(bus, message, "reboot", error);
1009 if (r < 0)
1010 return r;
1011
1012 if (m->running_as != SYSTEMD_SYSTEM)
1013 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
1014
1015 m->exit_code = MANAGER_REBOOT;
1016
1017 return sd_bus_reply_method_return(message, NULL);
1018 }
1019
1020
1021 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1022 Manager *m = userdata;
1023 int r;
1024
1025 assert(bus);
1026 assert(message);
1027 assert(m);
1028
1029 r = selinux_access_check(bus, message, "halt", error);
1030 if (r < 0)
1031 return r;
1032
1033 if (m->running_as != SYSTEMD_SYSTEM)
1034 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1035
1036 m->exit_code = MANAGER_POWEROFF;
1037
1038 return sd_bus_reply_method_return(message, NULL);
1039 }
1040
1041 static int method_halt(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1042 Manager *m = userdata;
1043 int r;
1044
1045 assert(bus);
1046 assert(message);
1047 assert(m);
1048
1049 r = selinux_access_check(bus, message, "halt", error);
1050 if (r < 0)
1051 return r;
1052
1053 if (m->running_as != SYSTEMD_SYSTEM)
1054 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
1055
1056 m->exit_code = MANAGER_HALT;
1057
1058 return sd_bus_reply_method_return(message, NULL);
1059 }
1060
1061 static int method_kexec(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1062 Manager *m = userdata;
1063 int r;
1064
1065 assert(bus);
1066 assert(message);
1067 assert(m);
1068
1069 r = selinux_access_check(bus, message, "reboot", error);
1070 if (r < 0)
1071 return r;
1072
1073 if (m->running_as != SYSTEMD_SYSTEM)
1074 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
1075
1076 m->exit_code = MANAGER_KEXEC;
1077
1078 return sd_bus_reply_method_return(message, NULL);
1079 }
1080
1081 static int method_switch_root(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1082 char *ri = NULL, *rt = NULL;
1083 const char *root, *init;
1084 Manager *m = userdata;
1085 int r;
1086
1087 assert(bus);
1088 assert(message);
1089 assert(m);
1090
1091 r = selinux_access_check(bus, message, "reboot", error);
1092 if (r < 0)
1093 return r;
1094
1095 if (m->running_as != SYSTEMD_SYSTEM)
1096 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
1097
1098 r = sd_bus_message_read(message, "ss", &root, &init);
1099 if (r < 0)
1100 return r;
1101
1102 if (path_equal(root, "/") || !path_is_absolute(root))
1103 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root);
1104
1105 /* Safety check */
1106 if (isempty(init)) {
1107 if (! path_is_os_tree(root))
1108 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. /etc/os-release is missing.", root);
1109 } else {
1110 _cleanup_free_ char *p = NULL;
1111
1112 if (!path_is_absolute(init))
1113 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
1114
1115 p = strappend(root, init);
1116 if (!p)
1117 return -ENOMEM;
1118
1119 if (access(p, X_OK) < 0)
1120 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
1121 }
1122
1123 rt = strdup(root);
1124 if (!rt)
1125 return -ENOMEM;
1126
1127 if (!isempty(init)) {
1128 ri = strdup(init);
1129 if (!ri) {
1130 free(rt);
1131 return -ENOMEM;
1132 }
1133 }
1134
1135 free(m->switch_root);
1136 m->switch_root = rt;
1137
1138 free(m->switch_root_init);
1139 m->switch_root_init = ri;
1140
1141 m->exit_code = MANAGER_SWITCH_ROOT;
1142
1143 return sd_bus_reply_method_return(message, NULL);
1144 }
1145
1146 static int method_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1147 _cleanup_strv_free_ char **plus = NULL;
1148 Manager *m = userdata;
1149 int r;
1150
1151 assert(bus);
1152 assert(message);
1153 assert(m);
1154
1155 r = selinux_access_check(bus, message, "reload", error);
1156 if (r < 0)
1157 return r;
1158
1159 r = sd_bus_message_read_strv(message, &plus);
1160 if (r < 0)
1161 return r;
1162 if (!strv_env_is_valid(plus))
1163 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1164
1165 r = manager_environment_add(m, NULL, plus);
1166 if (r < 0)
1167 return r;
1168
1169 return sd_bus_reply_method_return(message, NULL);
1170 }
1171
1172 static int method_unset_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1173 _cleanup_strv_free_ char **minus = NULL;
1174 Manager *m = userdata;
1175 int r;
1176
1177 assert(bus);
1178 assert(message);
1179 assert(m);
1180
1181 r = selinux_access_check(bus, message, "reload", error);
1182 if (r < 0)
1183 return r;
1184
1185 r = sd_bus_message_read_strv(message, &minus);
1186 if (r < 0)
1187 return r;
1188
1189 if (!strv_env_name_or_assignment_is_valid(minus))
1190 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
1191
1192 r = manager_environment_add(m, minus, NULL);
1193 if (r < 0)
1194 return r;
1195
1196 return sd_bus_reply_method_return(message, NULL);
1197 }
1198
1199 static int method_unset_and_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1200 _cleanup_strv_free_ char **minus = NULL, **plus = NULL;
1201 Manager *m = userdata;
1202 int r;
1203
1204 assert(bus);
1205 assert(message);
1206 assert(m);
1207
1208 r = selinux_access_check(bus, message, "reload", error);
1209 if (r < 0)
1210 return r;
1211
1212 r = sd_bus_message_read_strv(message, &plus);
1213 if (r < 0)
1214 return r;
1215
1216 r = sd_bus_message_read_strv(message, &minus);
1217 if (r < 0)
1218 return r;
1219
1220 if (!strv_env_is_valid(plus))
1221 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
1222 if (!strv_env_name_or_assignment_is_valid(minus))
1223 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
1224
1225 r = manager_environment_add(m, minus, plus);
1226 if (r < 0)
1227 return r;
1228
1229 return sd_bus_reply_method_return(message, NULL);
1230 }
1231
1232 static int method_list_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1233 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1234 Manager *m = userdata;
1235 UnitFileList *item;
1236 Hashmap *h;
1237 Iterator i;
1238 int r;
1239
1240 assert(bus);
1241 assert(message);
1242 assert(m);
1243
1244 r = selinux_access_check(bus, message, "status", error);
1245 if (r < 0)
1246 return r;
1247
1248 r = sd_bus_message_new_method_return(message, &reply);
1249 if (r < 0)
1250 return r;
1251
1252 h = hashmap_new(string_hash_func, string_compare_func);
1253 if (!h)
1254 return -ENOMEM;
1255
1256 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
1257 if (r < 0)
1258 goto fail;
1259
1260 r = sd_bus_message_open_container(reply, 'a', "(ss)");
1261 if (r < 0)
1262 goto fail;
1263
1264 HASHMAP_FOREACH(item, h, i) {
1265
1266 r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
1267 if (r < 0)
1268 goto fail;
1269 }
1270
1271 unit_file_list_free(h);
1272
1273 r = sd_bus_message_close_container(reply);
1274 if (r < 0)
1275 return r;
1276
1277 return sd_bus_send(bus, reply, NULL);
1278
1279 fail:
1280 unit_file_list_free(h);
1281 return r;
1282 }
1283
1284 static int method_get_unit_file_state(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1285 Manager *m = userdata;
1286 const char *name;
1287 UnitFileState state;
1288 UnitFileScope scope;
1289 int r;
1290
1291 assert(bus);
1292 assert(message);
1293 assert(m);
1294
1295 r = selinux_access_check(bus, message, "status", error);
1296 if (r < 0)
1297 return r;
1298
1299 r = sd_bus_message_read(message, "s", &name);
1300 if (r < 0)
1301 return r;
1302
1303 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1304
1305 state = unit_file_get_state(scope, NULL, name);
1306 if (state < 0)
1307 return state;
1308
1309 return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
1310 }
1311
1312 static int method_get_default_target(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1313 _cleanup_free_ char *default_target = NULL;
1314 Manager *m = userdata;
1315 UnitFileScope scope;
1316 int r;
1317
1318 assert(bus);
1319 assert(message);
1320 assert(m);
1321
1322 r = selinux_access_check(bus, message, "status", error);
1323 if (r < 0)
1324 return r;
1325
1326 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1327
1328 r = unit_file_get_default(scope, NULL, &default_target);
1329 if (r < 0)
1330 return r;
1331
1332 return sd_bus_reply_method_return(message, "s", default_target);
1333 }
1334
1335 static int send_unit_files_changed(sd_bus *bus, const char *destination, void *userdata) {
1336 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1337 int r;
1338
1339 assert(bus);
1340
1341 r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged", &message);
1342 if (r < 0)
1343 return r;
1344
1345 return sd_bus_send_to(bus, message, destination, NULL);
1346 }
1347
1348 static int reply_unit_file_changes_and_free(
1349 Manager *m,
1350 sd_bus *bus,
1351 sd_bus_message *message,
1352 int carries_install_info,
1353 UnitFileChange *changes,
1354 unsigned n_changes) {
1355
1356 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1357 unsigned i;
1358 int r;
1359
1360 if (n_changes > 0)
1361 bus_manager_foreach_client(m, send_unit_files_changed, NULL);
1362
1363 r = sd_bus_message_new_method_return(message, &reply);
1364 if (r < 0)
1365 goto fail;
1366
1367 if (carries_install_info >= 0) {
1368 r = sd_bus_message_append(reply, "b", carries_install_info);
1369 if (r < 0)
1370 goto fail;
1371 }
1372
1373 r = sd_bus_message_open_container(reply, 'a', "(sss)");
1374 if (r < 0)
1375 goto fail;
1376
1377 for (i = 0; i < n_changes; i++) {
1378 r = sd_bus_message_append(
1379 reply, "(sss)",
1380 unit_file_change_type_to_string(changes[i].type),
1381 changes[i].path,
1382 changes[i].source);
1383 if (r < 0)
1384 goto fail;
1385 }
1386
1387 r = sd_bus_message_close_container(reply);
1388 if (r < 0)
1389 goto fail;
1390
1391 return sd_bus_send(bus, reply, NULL);
1392
1393 fail:
1394 unit_file_changes_free(changes, n_changes);
1395 return r;
1396 }
1397
1398 static int method_enable_unit_files_generic(
1399 sd_bus *bus,
1400 sd_bus_message *message,
1401 Manager *m, const
1402 char *verb,
1403 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes),
1404 bool carries_install_info,
1405 sd_bus_error *error) {
1406
1407 _cleanup_strv_free_ char **l = NULL;
1408 UnitFileChange *changes = NULL;
1409 unsigned n_changes = 0;
1410 UnitFileScope scope;
1411 int runtime, force, r;
1412
1413 assert(bus);
1414 assert(message);
1415 assert(m);
1416
1417 r = selinux_access_check(bus, message, verb, error);
1418 if (r < 0)
1419 return r;
1420
1421 r = sd_bus_message_read_strv(message, &l);
1422 if (r < 0)
1423 return r;
1424
1425 r = sd_bus_message_read(message, "bb", &runtime, &force);
1426 if (r < 0)
1427 return r;
1428
1429 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1430
1431 r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
1432 if (r < 0)
1433 return r;
1434
1435 return reply_unit_file_changes_and_free(m, bus, message, carries_install_info ? r : -1, changes, n_changes);
1436 }
1437
1438 static int method_enable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1439 return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_enable, true, error);
1440 }
1441
1442 static int method_reenable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1443 return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_reenable, true, error);
1444 }
1445
1446 static int method_link_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1447 return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_link, false, error);
1448 }
1449
1450 static int method_preset_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1451 return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_preset, true, error);
1452 }
1453
1454 static int method_mask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1455 return method_enable_unit_files_generic(bus, message, userdata, "disable", unit_file_mask, false, error);
1456 }
1457
1458 static int method_disable_unit_files_generic(
1459 sd_bus *bus,
1460 sd_bus_message *message,
1461 Manager *m, const
1462 char *verb,
1463 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes),
1464 sd_bus_error *error) {
1465
1466 _cleanup_strv_free_ char **l = NULL;
1467 UnitFileChange *changes = NULL;
1468 unsigned n_changes = 0;
1469 UnitFileScope scope;
1470 int r, runtime;
1471
1472 assert(bus);
1473 assert(message);
1474 assert(m);
1475
1476 r = selinux_access_check(bus, message, verb, error);
1477 if (r < 0)
1478 return r;
1479
1480 r = sd_bus_message_read_strv(message, &l);
1481 if (r < 0)
1482 return r;
1483
1484 r = sd_bus_message_read(message, "b", &runtime);
1485 if (r < 0)
1486 return r;
1487
1488 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1489
1490 r = call(scope, runtime, NULL, l, &changes, &n_changes);
1491 if (r < 0)
1492 return r;
1493
1494 return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
1495 }
1496
1497 static int method_disable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1498 return method_disable_unit_files_generic(bus, message, userdata, "disable", unit_file_disable, error);
1499 }
1500
1501 static int method_unmask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1502 return method_disable_unit_files_generic(bus, message, userdata, "enable", unit_file_unmask, error);
1503 }
1504
1505 static int method_set_default_target(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1506 UnitFileChange *changes = NULL;
1507 unsigned n_changes = 0;
1508 Manager *m = userdata;
1509 UnitFileScope scope;
1510 const char *name;
1511 int force, r;
1512
1513 assert(bus);
1514 assert(message);
1515 assert(m);
1516
1517 r = selinux_access_check(bus, message, "enable", error);
1518 if (r < 0)
1519 return r;
1520
1521 r = sd_bus_message_read(message, "sb", &name, &force);
1522 if (r < 0)
1523 return r;
1524
1525 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1526
1527 r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes);
1528 if (r < 0)
1529 return r;
1530
1531 return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
1532 }
1533
1534 const sd_bus_vtable bus_manager_vtable[] = {
1535 SD_BUS_VTABLE_START(0),
1536
1537 SD_BUS_PROPERTY("Version", "s", property_get_version, 0, 0),
1538 SD_BUS_PROPERTY("Features", "s", property_get_features, 0, 0),
1539 SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, 0),
1540 SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, 0),
1541 BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, firmware_timestamp), 0),
1542 BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, loader_timestamp), 0),
1543 BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, kernel_timestamp), 0),
1544 BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, initrd_timestamp), 0),
1545 BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, userspace_timestamp), 0),
1546 BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, finish_timestamp), 0),
1547 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, security_start_timestamp), 0),
1548 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, security_finish_timestamp), 0),
1549 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, generators_start_timestamp), 0),
1550 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, generators_finish_timestamp), 0),
1551 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, units_load_start_timestamp), 0),
1552 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, units_load_finish_timestamp), 0),
1553 SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
1554 SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
1555 SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
1556 SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
1557 SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
1558 SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
1559 SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
1560 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
1561 SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), 0),
1562 SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), 0),
1563 SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), 0),
1564 SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), 0),
1565 SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), 0),
1566 SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
1567 SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
1568
1569 SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1570 SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1571 SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1572 SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, 0),
1573 SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, 0),
1574 SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, 0),
1575 SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, 0),
1576 SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, 0),
1577 SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, 0),
1578 SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, 0),
1579 SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, 0),
1580 SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
1581 SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, 0),
1582 SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, 0),
1583 SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, 0),
1584 SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED),
1585 SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, 0),
1586 SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, 0),
1587 SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, 0),
1588 SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, SD_BUS_VTABLE_UNPRIVILEGED),
1589 SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
1590 SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED),
1591 SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED),
1592 SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED),
1593 SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, 0),
1594 SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, 0),
1595 SD_BUS_METHOD("Reload", NULL, NULL, method_reload, 0),
1596 SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, 0),
1597 SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
1598 SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1599 SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1600 SD_BUS_METHOD("Halt", NULL, NULL, method_halt, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1601 SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1602 SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1603 SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, 0),
1604 SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, 0),
1605 SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, 0),
1606 SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
1607 SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, SD_BUS_VTABLE_UNPRIVILEGED),
1608 SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, 0),
1609 SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, 0),
1610 SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, 0),
1611 SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, 0),
1612 SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, 0),
1613 SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, 0),
1614 SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, 0),
1615 SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, 0),
1616 SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
1617
1618 SD_BUS_SIGNAL("UnitNew", "so", 0),
1619 SD_BUS_SIGNAL("UnitRemoved", "so", 0),
1620 SD_BUS_SIGNAL("JobNew", "uos", 0),
1621 SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
1622 SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
1623 SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0),
1624 SD_BUS_SIGNAL("Reloading", "b", 0),
1625
1626 SD_BUS_VTABLE_END
1627 };
1628
1629 int bus_manager_foreach_client(Manager *m, int (*send_message)(sd_bus *bus, const char *destination, void *userdata), void *userdata) {
1630 Iterator i;
1631 sd_bus *b;
1632 unsigned n;
1633 int r, ret;
1634
1635 n = set_size(m->subscribed);
1636 if (n <= 0)
1637 return 0;
1638 if (n == 1) {
1639 BusTrackedClient *d;
1640
1641 assert_se(d = set_first(m->subscribed));
1642 return send_message(d->bus, isempty(d->name) ? NULL : d->name, userdata);
1643 }
1644
1645 ret = 0;
1646
1647 /* Send to everybody */
1648 SET_FOREACH(b, m->private_buses, i) {
1649 r = send_message(b, NULL, userdata);
1650 if (r < 0)
1651 ret = r;
1652 }
1653
1654 if (m->api_bus) {
1655 r = send_message(m->api_bus, NULL, userdata);
1656 if (r < 0)
1657 ret = r;
1658 }
1659
1660 return ret;
1661 }
1662
1663 static int send_finished(sd_bus *bus, const char *destination, void *userdata) {
1664 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1665 usec_t *times = userdata;
1666 int r;
1667
1668 assert(bus);
1669 assert(times);
1670
1671 r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished", &message);
1672 if (r < 0)
1673 return r;
1674
1675 r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
1676 if (r < 0)
1677 return r;
1678
1679 return sd_bus_send_to(bus, message, destination, NULL);
1680 }
1681
1682 void bus_manager_send_finished(
1683 Manager *m,
1684 usec_t firmware_usec,
1685 usec_t loader_usec,
1686 usec_t kernel_usec,
1687 usec_t initrd_usec,
1688 usec_t userspace_usec,
1689 usec_t total_usec) {
1690
1691 int r;
1692
1693 assert(m);
1694
1695 r = bus_manager_foreach_client(m, send_finished,
1696 (usec_t[6]) { firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec });
1697 if (r < 0)
1698 log_debug("Failed to send finished signal: %s", strerror(-r));
1699 }
1700
1701 static int send_reloading(sd_bus *bus, const char *destination, void *userdata) {
1702 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1703 int r;
1704
1705 assert(bus);
1706
1707 r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading", &message);
1708 if (r < 0)
1709 return r;
1710
1711 r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
1712 if (r < 0)
1713 return r;
1714
1715 return sd_bus_send_to(bus, message, destination, NULL);
1716 }
1717
1718 void bus_manager_send_reloading(Manager *m, bool active) {
1719 int r;
1720
1721 assert(m);
1722
1723 r = bus_manager_foreach_client(m, send_reloading, INT_TO_PTR(active));
1724 if (r < 0)
1725 log_debug("Failed to send reloading signal: %s", strerror(-r));
1726
1727 }