]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-unit.c
bootspec: fix debug message about default entry
[thirdparty/systemd.git] / src / core / dbus-unit.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include "sd-bus.h"
22
23 #include "alloc-util.h"
24 #include "bpf-firewall.h"
25 #include "bus-common-errors.h"
26 #include "cgroup-util.h"
27 #include "dbus-job.h"
28 #include "dbus-unit.h"
29 #include "dbus.h"
30 #include "fd-util.h"
31 #include "locale-util.h"
32 #include "log.h"
33 #include "process-util.h"
34 #include "selinux-access.h"
35 #include "signal-util.h"
36 #include "special.h"
37 #include "string-util.h"
38 #include "strv.h"
39 #include "user-util.h"
40
41 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode);
42 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
43 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
44 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
45
46 static int property_get_names(
47 sd_bus *bus,
48 const char *path,
49 const char *interface,
50 const char *property,
51 sd_bus_message *reply,
52 void *userdata,
53 sd_bus_error *error) {
54
55 Unit *u = userdata;
56 Iterator i;
57 const char *t;
58 int r;
59
60 assert(bus);
61 assert(reply);
62 assert(u);
63
64 r = sd_bus_message_open_container(reply, 'a', "s");
65 if (r < 0)
66 return r;
67
68 SET_FOREACH(t, u->names, i) {
69 r = sd_bus_message_append(reply, "s", t);
70 if (r < 0)
71 return r;
72 }
73
74 return sd_bus_message_close_container(reply);
75 }
76
77 static int property_get_following(
78 sd_bus *bus,
79 const char *path,
80 const char *interface,
81 const char *property,
82 sd_bus_message *reply,
83 void *userdata,
84 sd_bus_error *error) {
85
86 Unit *u = userdata, *f;
87
88 assert(bus);
89 assert(reply);
90 assert(u);
91
92 f = unit_following(u);
93 return sd_bus_message_append(reply, "s", f ? f->id : "");
94 }
95
96 static int property_get_dependencies(
97 sd_bus *bus,
98 const char *path,
99 const char *interface,
100 const char *property,
101 sd_bus_message *reply,
102 void *userdata,
103 sd_bus_error *error) {
104
105 Hashmap *h = *(Hashmap**) userdata;
106 Iterator j;
107 Unit *u;
108 void *v;
109 int r;
110
111 assert(bus);
112 assert(reply);
113
114 r = sd_bus_message_open_container(reply, 'a', "s");
115 if (r < 0)
116 return r;
117
118 HASHMAP_FOREACH_KEY(v, u, h, j) {
119 r = sd_bus_message_append(reply, "s", u->id);
120 if (r < 0)
121 return r;
122 }
123
124 return sd_bus_message_close_container(reply);
125 }
126
127 static int property_get_obsolete_dependencies(
128 sd_bus *bus,
129 const char *path,
130 const char *interface,
131 const char *property,
132 sd_bus_message *reply,
133 void *userdata,
134 sd_bus_error *error) {
135
136 assert(bus);
137 assert(reply);
138
139 /* For dependency types we don't support anymore always return an empty array */
140 return sd_bus_message_append(reply, "as", 0);
141 }
142
143 static int property_get_requires_mounts_for(
144 sd_bus *bus,
145 const char *path,
146 const char *interface,
147 const char *property,
148 sd_bus_message *reply,
149 void *userdata,
150 sd_bus_error *error) {
151
152 Hashmap *h = *(Hashmap**) userdata;
153 const char *p;
154 Iterator j;
155 void *v;
156 int r;
157
158 assert(bus);
159 assert(reply);
160
161 r = sd_bus_message_open_container(reply, 'a', "s");
162 if (r < 0)
163 return r;
164
165 HASHMAP_FOREACH_KEY(v, p, h, j) {
166 r = sd_bus_message_append(reply, "s", p);
167 if (r < 0)
168 return r;
169 }
170
171 return sd_bus_message_close_container(reply);
172 }
173
174 static int property_get_description(
175 sd_bus *bus,
176 const char *path,
177 const char *interface,
178 const char *property,
179 sd_bus_message *reply,
180 void *userdata,
181 sd_bus_error *error) {
182
183 Unit *u = userdata;
184
185 assert(bus);
186 assert(reply);
187 assert(u);
188
189 return sd_bus_message_append(reply, "s", unit_description(u));
190 }
191
192 static int property_get_active_state(
193 sd_bus *bus,
194 const char *path,
195 const char *interface,
196 const char *property,
197 sd_bus_message *reply,
198 void *userdata,
199 sd_bus_error *error) {
200
201 Unit *u = userdata;
202
203 assert(bus);
204 assert(reply);
205 assert(u);
206
207 return sd_bus_message_append(reply, "s", unit_active_state_to_string(unit_active_state(u)));
208 }
209
210 static int property_get_sub_state(
211 sd_bus *bus,
212 const char *path,
213 const char *interface,
214 const char *property,
215 sd_bus_message *reply,
216 void *userdata,
217 sd_bus_error *error) {
218
219 Unit *u = userdata;
220
221 assert(bus);
222 assert(reply);
223 assert(u);
224
225 return sd_bus_message_append(reply, "s", unit_sub_state_to_string(u));
226 }
227
228 static int property_get_unit_file_preset(
229 sd_bus *bus,
230 const char *path,
231 const char *interface,
232 const char *property,
233 sd_bus_message *reply,
234 void *userdata,
235 sd_bus_error *error) {
236
237 Unit *u = userdata;
238 int r;
239
240 assert(bus);
241 assert(reply);
242 assert(u);
243
244 r = unit_get_unit_file_preset(u);
245
246 return sd_bus_message_append(reply, "s",
247 r < 0 ? "":
248 r > 0 ? "enabled" : "disabled");
249 }
250
251 static int property_get_unit_file_state(
252 sd_bus *bus,
253 const char *path,
254 const char *interface,
255 const char *property,
256 sd_bus_message *reply,
257 void *userdata,
258 sd_bus_error *error) {
259
260 Unit *u = userdata;
261
262 assert(bus);
263 assert(reply);
264 assert(u);
265
266 return sd_bus_message_append(reply, "s", unit_file_state_to_string(unit_get_unit_file_state(u)));
267 }
268
269 static int property_get_can_start(
270 sd_bus *bus,
271 const char *path,
272 const char *interface,
273 const char *property,
274 sd_bus_message *reply,
275 void *userdata,
276 sd_bus_error *error) {
277
278 Unit *u = userdata;
279
280 assert(bus);
281 assert(reply);
282 assert(u);
283
284 return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_start);
285 }
286
287 static int property_get_can_stop(
288 sd_bus *bus,
289 const char *path,
290 const char *interface,
291 const char *property,
292 sd_bus_message *reply,
293 void *userdata,
294 sd_bus_error *error) {
295
296 Unit *u = userdata;
297
298 assert(bus);
299 assert(reply);
300 assert(u);
301
302 return sd_bus_message_append(reply, "b", unit_can_stop(u) && !u->refuse_manual_stop);
303 }
304
305 static int property_get_can_reload(
306 sd_bus *bus,
307 const char *path,
308 const char *interface,
309 const char *property,
310 sd_bus_message *reply,
311 void *userdata,
312 sd_bus_error *error) {
313
314 Unit *u = userdata;
315
316 assert(bus);
317 assert(reply);
318 assert(u);
319
320 return sd_bus_message_append(reply, "b", unit_can_reload(u));
321 }
322
323 static int property_get_can_isolate(
324 sd_bus *bus,
325 const char *path,
326 const char *interface,
327 const char *property,
328 sd_bus_message *reply,
329 void *userdata,
330 sd_bus_error *error) {
331
332 Unit *u = userdata;
333
334 assert(bus);
335 assert(reply);
336 assert(u);
337
338 return sd_bus_message_append(reply, "b", unit_can_isolate(u) && !u->refuse_manual_start);
339 }
340
341 static int property_get_job(
342 sd_bus *bus,
343 const char *path,
344 const char *interface,
345 const char *property,
346 sd_bus_message *reply,
347 void *userdata,
348 sd_bus_error *error) {
349
350 _cleanup_free_ char *p = NULL;
351 Unit *u = userdata;
352
353 assert(bus);
354 assert(reply);
355 assert(u);
356
357 if (!u->job)
358 return sd_bus_message_append(reply, "(uo)", 0, "/");
359
360 p = job_dbus_path(u->job);
361 if (!p)
362 return -ENOMEM;
363
364 return sd_bus_message_append(reply, "(uo)", u->job->id, p);
365 }
366
367 static int property_get_need_daemon_reload(
368 sd_bus *bus,
369 const char *path,
370 const char *interface,
371 const char *property,
372 sd_bus_message *reply,
373 void *userdata,
374 sd_bus_error *error) {
375
376 Unit *u = userdata;
377
378 assert(bus);
379 assert(reply);
380 assert(u);
381
382 return sd_bus_message_append(reply, "b", unit_need_daemon_reload(u));
383 }
384
385 static int property_get_conditions(
386 sd_bus *bus,
387 const char *path,
388 const char *interface,
389 const char *property,
390 sd_bus_message *reply,
391 void *userdata,
392 sd_bus_error *error) {
393
394 const char *(*to_string)(ConditionType type) = NULL;
395 Condition **list = userdata, *c;
396 int r;
397
398 assert(bus);
399 assert(reply);
400 assert(list);
401
402 to_string = streq(property, "Asserts") ? assert_type_to_string : condition_type_to_string;
403
404 r = sd_bus_message_open_container(reply, 'a', "(sbbsi)");
405 if (r < 0)
406 return r;
407
408 LIST_FOREACH(conditions, c, *list) {
409 int tristate;
410
411 tristate =
412 c->result == CONDITION_UNTESTED ? 0 :
413 c->result == CONDITION_SUCCEEDED ? 1 : -1;
414
415 r = sd_bus_message_append(reply, "(sbbsi)",
416 to_string(c->type),
417 c->trigger, c->negate,
418 c->parameter, tristate);
419 if (r < 0)
420 return r;
421
422 }
423
424 return sd_bus_message_close_container(reply);
425 }
426
427 static int property_get_load_error(
428 sd_bus *bus,
429 const char *path,
430 const char *interface,
431 const char *property,
432 sd_bus_message *reply,
433 void *userdata,
434 sd_bus_error *error) {
435
436 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
437 Unit *u = userdata;
438
439 assert(bus);
440 assert(reply);
441 assert(u);
442
443 if (u->load_error != 0)
444 sd_bus_error_set_errno(&e, u->load_error);
445
446 return sd_bus_message_append(reply, "(ss)", e.name, e.message);
447 }
448
449 static int bus_verify_manage_units_async_full(
450 Unit *u,
451 const char *verb,
452 int capability,
453 const char *polkit_message,
454 bool interactive,
455 sd_bus_message *call,
456 sd_bus_error *error) {
457
458 const char *details[9] = {
459 "unit", u->id,
460 "verb", verb,
461 };
462
463 if (polkit_message) {
464 details[4] = "polkit.message";
465 details[5] = polkit_message;
466 details[6] = "polkit.gettext_domain";
467 details[7] = GETTEXT_PACKAGE;
468 }
469
470 return bus_verify_polkit_async(
471 call,
472 capability,
473 "org.freedesktop.systemd1.manage-units",
474 details,
475 interactive,
476 UID_INVALID,
477 &u->manager->polkit_registry,
478 error);
479 }
480
481 int bus_unit_method_start_generic(
482 sd_bus_message *message,
483 Unit *u,
484 JobType job_type,
485 bool reload_if_possible,
486 sd_bus_error *error) {
487
488 const char *smode;
489 JobMode mode;
490 _cleanup_free_ char *verb = NULL;
491 static const char *const polkit_message_for_job[_JOB_TYPE_MAX] = {
492 [JOB_START] = N_("Authentication is required to start '$(unit)'."),
493 [JOB_STOP] = N_("Authentication is required to stop '$(unit)'."),
494 [JOB_RELOAD] = N_("Authentication is required to reload '$(unit)'."),
495 [JOB_RESTART] = N_("Authentication is required to restart '$(unit)'."),
496 [JOB_TRY_RESTART] = N_("Authentication is required to restart '$(unit)'."),
497 };
498 int r;
499
500 assert(message);
501 assert(u);
502 assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
503
504 r = mac_selinux_unit_access_check(
505 u, message,
506 job_type_to_access_method(job_type),
507 error);
508 if (r < 0)
509 return r;
510
511 r = sd_bus_message_read(message, "s", &smode);
512 if (r < 0)
513 return r;
514
515 mode = job_mode_from_string(smode);
516 if (mode < 0)
517 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
518
519 if (reload_if_possible)
520 verb = strjoin("reload-or-", job_type_to_string(job_type));
521 else
522 verb = strdup(job_type_to_string(job_type));
523 if (!verb)
524 return -ENOMEM;
525
526 r = bus_verify_manage_units_async_full(
527 u,
528 verb,
529 CAP_SYS_ADMIN,
530 job_type < _JOB_TYPE_MAX ? polkit_message_for_job[job_type] : NULL,
531 true,
532 message,
533 error);
534 if (r < 0)
535 return r;
536 if (r == 0)
537 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
538
539 return bus_unit_queue_job(message, u, job_type, mode, reload_if_possible, error);
540 }
541
542 static int method_start(sd_bus_message *message, void *userdata, sd_bus_error *error) {
543 return bus_unit_method_start_generic(message, userdata, JOB_START, false, error);
544 }
545
546 static int method_stop(sd_bus_message *message, void *userdata, sd_bus_error *error) {
547 return bus_unit_method_start_generic(message, userdata, JOB_STOP, false, error);
548 }
549
550 static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
551 return bus_unit_method_start_generic(message, userdata, JOB_RELOAD, false, error);
552 }
553
554 static int method_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
555 return bus_unit_method_start_generic(message, userdata, JOB_RESTART, false, error);
556 }
557
558 static int method_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
559 return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, false, error);
560 }
561
562 static int method_reload_or_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
563 return bus_unit_method_start_generic(message, userdata, JOB_RESTART, true, error);
564 }
565
566 static int method_reload_or_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
567 return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, true, error);
568 }
569
570 int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
571 Unit *u = userdata;
572 const char *swho;
573 int32_t signo;
574 KillWho who;
575 int r;
576
577 assert(message);
578 assert(u);
579
580 r = mac_selinux_unit_access_check(u, message, "stop", error);
581 if (r < 0)
582 return r;
583
584 r = sd_bus_message_read(message, "si", &swho, &signo);
585 if (r < 0)
586 return r;
587
588 if (isempty(swho))
589 who = KILL_ALL;
590 else {
591 who = kill_who_from_string(swho);
592 if (who < 0)
593 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho);
594 }
595
596 if (!SIGNAL_VALID(signo))
597 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
598
599 r = bus_verify_manage_units_async_full(
600 u,
601 "kill",
602 CAP_KILL,
603 N_("Authentication is required to kill '$(unit)'."),
604 true,
605 message,
606 error);
607 if (r < 0)
608 return r;
609 if (r == 0)
610 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
611
612 r = unit_kill(u, who, signo, error);
613 if (r < 0)
614 return r;
615
616 return sd_bus_reply_method_return(message, NULL);
617 }
618
619 int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
620 Unit *u = userdata;
621 int r;
622
623 assert(message);
624 assert(u);
625
626 r = mac_selinux_unit_access_check(u, message, "reload", error);
627 if (r < 0)
628 return r;
629
630 r = bus_verify_manage_units_async_full(
631 u,
632 "reset-failed",
633 CAP_SYS_ADMIN,
634 N_("Authentication is required to reset the \"failed\" state of '$(unit)'."),
635 true,
636 message,
637 error);
638 if (r < 0)
639 return r;
640 if (r == 0)
641 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
642
643 unit_reset_failed(u);
644
645 return sd_bus_reply_method_return(message, NULL);
646 }
647
648 int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) {
649 Unit *u = userdata;
650 int runtime, r;
651
652 assert(message);
653 assert(u);
654
655 r = mac_selinux_unit_access_check(u, message, "start", error);
656 if (r < 0)
657 return r;
658
659 r = sd_bus_message_read(message, "b", &runtime);
660 if (r < 0)
661 return r;
662
663 r = bus_verify_manage_units_async_full(
664 u,
665 "set-property",
666 CAP_SYS_ADMIN,
667 N_("Authentication is required to set properties on '$(unit)'."),
668 true,
669 message,
670 error);
671 if (r < 0)
672 return r;
673 if (r == 0)
674 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
675
676 r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, error);
677 if (r < 0)
678 return r;
679
680 return sd_bus_reply_method_return(message, NULL);
681 }
682
683 int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error) {
684 Unit *u = userdata;
685 int r;
686
687 assert(message);
688 assert(u);
689
690 r = mac_selinux_unit_access_check(u, message, "start", error);
691 if (r < 0)
692 return r;
693
694 r = bus_verify_manage_units_async_full(
695 u,
696 "ref",
697 CAP_SYS_ADMIN,
698 NULL,
699 false,
700 message,
701 error);
702 if (r < 0)
703 return r;
704 if (r == 0)
705 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
706
707 r = bus_unit_track_add_sender(u, message);
708 if (r < 0)
709 return r;
710
711 return sd_bus_reply_method_return(message, NULL);
712 }
713
714 int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error) {
715 Unit *u = userdata;
716 int r;
717
718 assert(message);
719 assert(u);
720
721 r = bus_unit_track_remove_sender(u, message);
722 if (r == -EUNATCH)
723 return sd_bus_error_setf(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet.");
724 if (r < 0)
725 return r;
726
727 return sd_bus_reply_method_return(message, NULL);
728 }
729
730 const sd_bus_vtable bus_unit_vtable[] = {
731 SD_BUS_VTABLE_START(0),
732
733 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), SD_BUS_VTABLE_PROPERTY_CONST),
734 SD_BUS_PROPERTY("Names", "as", property_get_names, 0, SD_BUS_VTABLE_PROPERTY_CONST),
735 SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
736 SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST),
737 SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST),
738 SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), SD_BUS_VTABLE_PROPERTY_CONST),
739 SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
740 SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
741 SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
742 SD_BUS_PROPERTY("RequisiteOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
743 SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
744 SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
745 SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
746 SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), SD_BUS_VTABLE_PROPERTY_CONST),
747 SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
748 SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), SD_BUS_VTABLE_PROPERTY_CONST),
749 SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), SD_BUS_VTABLE_PROPERTY_CONST),
750 SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), SD_BUS_VTABLE_PROPERTY_CONST),
751 SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), SD_BUS_VTABLE_PROPERTY_CONST),
752 SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
753 SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
754 SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), SD_BUS_VTABLE_PROPERTY_CONST),
755 SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_JOINS_NAMESPACE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
756 SD_BUS_PROPERTY("RequiresMountsFor", "as", property_get_requires_mounts_for, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST),
757 SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST),
758 SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST),
759 SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), SD_BUS_VTABLE_PROPERTY_CONST),
760 SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
761 SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
762 SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), SD_BUS_VTABLE_PROPERTY_CONST),
763 SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), SD_BUS_VTABLE_PROPERTY_CONST),
764 SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), SD_BUS_VTABLE_PROPERTY_CONST),
765 SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
766 SD_BUS_PROPERTY("UnitFilePreset", "s", property_get_unit_file_preset, 0, 0),
767 BUS_PROPERTY_DUAL_TIMESTAMP("StateChangeTimestamp", offsetof(Unit, state_change_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
768 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
769 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
770 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
771 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
772 SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, SD_BUS_VTABLE_PROPERTY_CONST),
773 SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, SD_BUS_VTABLE_PROPERTY_CONST),
774 SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
775 SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, SD_BUS_VTABLE_PROPERTY_CONST),
776 SD_BUS_PROPERTY("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
777 SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), SD_BUS_VTABLE_PROPERTY_CONST),
778 SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), SD_BUS_VTABLE_PROPERTY_CONST),
779 SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST),
780 SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
781 SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST),
782 SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
783 SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
784 SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
785 SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
786 SD_BUS_PROPERTY("JobRunningTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_running_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
787 SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
788 SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
789 SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
790 SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
791 BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
792 BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
793 SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), 0),
794 SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
795 SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
796 SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
797 SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST),
798 SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
799 SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
800 SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
801 SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
802 SD_BUS_PROPERTY("SuccessAction", "s", property_get_emergency_action, offsetof(Unit, success_action), SD_BUS_VTABLE_PROPERTY_CONST),
803 SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
804 SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), 0),
805 SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0),
806
807 SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED),
808 SD_BUS_METHOD("Stop", "s", "o", method_stop, SD_BUS_VTABLE_UNPRIVILEGED),
809 SD_BUS_METHOD("Reload", "s", "o", method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
810 SD_BUS_METHOD("Restart", "s", "o", method_restart, SD_BUS_VTABLE_UNPRIVILEGED),
811 SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, SD_BUS_VTABLE_UNPRIVILEGED),
812 SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, SD_BUS_VTABLE_UNPRIVILEGED),
813 SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, SD_BUS_VTABLE_UNPRIVILEGED),
814 SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
815 SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED),
816 SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED),
817 SD_BUS_METHOD("Ref", NULL, NULL, bus_unit_method_ref, SD_BUS_VTABLE_UNPRIVILEGED),
818 SD_BUS_METHOD("Unref", NULL, NULL, bus_unit_method_unref, SD_BUS_VTABLE_UNPRIVILEGED),
819
820 /* Obsolete properties or obsolete alias names */
821 SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
822 SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
823 SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
824 SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
825 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
826 SD_BUS_VTABLE_END
827 };
828
829 static int property_get_slice(
830 sd_bus *bus,
831 const char *path,
832 const char *interface,
833 const char *property,
834 sd_bus_message *reply,
835 void *userdata,
836 sd_bus_error *error) {
837
838 Unit *u = userdata;
839
840 assert(bus);
841 assert(reply);
842 assert(u);
843
844 return sd_bus_message_append(reply, "s", unit_slice_name(u));
845 }
846
847 static int property_get_current_memory(
848 sd_bus *bus,
849 const char *path,
850 const char *interface,
851 const char *property,
852 sd_bus_message *reply,
853 void *userdata,
854 sd_bus_error *error) {
855
856 uint64_t sz = (uint64_t) -1;
857 Unit *u = userdata;
858 int r;
859
860 assert(bus);
861 assert(reply);
862 assert(u);
863
864 r = unit_get_memory_current(u, &sz);
865 if (r < 0 && r != -ENODATA)
866 log_unit_warning_errno(u, r, "Failed to get memory.usage_in_bytes attribute: %m");
867
868 return sd_bus_message_append(reply, "t", sz);
869 }
870
871 static int property_get_current_tasks(
872 sd_bus *bus,
873 const char *path,
874 const char *interface,
875 const char *property,
876 sd_bus_message *reply,
877 void *userdata,
878 sd_bus_error *error) {
879
880 uint64_t cn = (uint64_t) -1;
881 Unit *u = userdata;
882 int r;
883
884 assert(bus);
885 assert(reply);
886 assert(u);
887
888 r = unit_get_tasks_current(u, &cn);
889 if (r < 0 && r != -ENODATA)
890 log_unit_warning_errno(u, r, "Failed to get pids.current attribute: %m");
891
892 return sd_bus_message_append(reply, "t", cn);
893 }
894
895 static int property_get_cpu_usage(
896 sd_bus *bus,
897 const char *path,
898 const char *interface,
899 const char *property,
900 sd_bus_message *reply,
901 void *userdata,
902 sd_bus_error *error) {
903
904 nsec_t ns = (nsec_t) -1;
905 Unit *u = userdata;
906 int r;
907
908 assert(bus);
909 assert(reply);
910 assert(u);
911
912 r = unit_get_cpu_usage(u, &ns);
913 if (r < 0 && r != -ENODATA)
914 log_unit_warning_errno(u, r, "Failed to get cpuacct.usage attribute: %m");
915
916 return sd_bus_message_append(reply, "t", ns);
917 }
918
919 static int property_get_cgroup(
920 sd_bus *bus,
921 const char *path,
922 const char *interface,
923 const char *property,
924 sd_bus_message *reply,
925 void *userdata,
926 sd_bus_error *error) {
927
928 Unit *u = userdata;
929 const char *t;
930
931 assert(bus);
932 assert(reply);
933 assert(u);
934
935 /* Three cases: a) u->cgroup_path is NULL, in which case the
936 * unit has no control group, which we report as the empty
937 * string. b) u->cgroup_path is the empty string, which
938 * indicates the root cgroup, which we report as "/". c) all
939 * other cases we report as-is. */
940
941 if (u->cgroup_path)
942 t = isempty(u->cgroup_path) ? "/" : u->cgroup_path;
943 else
944 t = "";
945
946 return sd_bus_message_append(reply, "s", t);
947 }
948
949 static int append_process(sd_bus_message *reply, const char *p, pid_t pid, Set *pids) {
950 _cleanup_free_ char *buf = NULL, *cmdline = NULL;
951 int r;
952
953 assert(reply);
954 assert(pid > 0);
955
956 r = set_put(pids, PID_TO_PTR(pid));
957 if (IN_SET(r, 0, -EEXIST))
958 return 0;
959 if (r < 0)
960 return r;
961
962 if (!p) {
963 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &buf);
964 if (r == -ESRCH)
965 return 0;
966 if (r < 0)
967 return r;
968
969 p = buf;
970 }
971
972 (void) get_process_cmdline(pid, 0, true, &cmdline);
973
974 return sd_bus_message_append(reply,
975 "(sus)",
976 p,
977 (uint32_t) pid,
978 cmdline);
979 }
980
981 static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) {
982 _cleanup_closedir_ DIR *d = NULL;
983 _cleanup_fclose_ FILE *f = NULL;
984 int r;
985
986 assert(reply);
987 assert(p);
988
989 r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, p, &f);
990 if (r == ENOENT)
991 return 0;
992 if (r < 0)
993 return r;
994
995 for (;;) {
996 pid_t pid;
997
998 r = cg_read_pid(f, &pid);
999 if (r < 0)
1000 return r;
1001 if (r == 0)
1002 break;
1003
1004 if (is_kernel_thread(pid) > 0)
1005 continue;
1006
1007 r = append_process(reply, p, pid, pids);
1008 if (r < 0)
1009 return r;
1010 }
1011
1012 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, p, &d);
1013 if (r == -ENOENT)
1014 return 0;
1015 if (r < 0)
1016 return r;
1017
1018 for (;;) {
1019 _cleanup_free_ char *g = NULL, *j = NULL;
1020
1021 r = cg_read_subgroup(d, &g);
1022 if (r < 0)
1023 return r;
1024 if (r == 0)
1025 break;
1026
1027 j = strjoin(p, "/", g);
1028 if (!j)
1029 return -ENOMEM;
1030
1031 r = append_cgroup(reply, j, pids);
1032 if (r < 0)
1033 return r;
1034 }
1035
1036 return 0;
1037 }
1038
1039 int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1040 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1041 _cleanup_(set_freep) Set *pids = NULL;
1042 Unit *u = userdata;
1043 pid_t pid;
1044 int r;
1045
1046 assert(message);
1047
1048 r = mac_selinux_unit_access_check(u, message, "status", error);
1049 if (r < 0)
1050 return r;
1051
1052 pids = set_new(NULL);
1053 if (!pids)
1054 return -ENOMEM;
1055
1056 r = sd_bus_message_new_method_return(message, &reply);
1057 if (r < 0)
1058 return r;
1059
1060 r = sd_bus_message_open_container(reply, 'a', "(sus)");
1061 if (r < 0)
1062 return r;
1063
1064 if (u->cgroup_path) {
1065 r = append_cgroup(reply, u->cgroup_path, pids);
1066 if (r < 0)
1067 return r;
1068 }
1069
1070 /* The main and control pids might live outside of the cgroup, hence fetch them separately */
1071 pid = unit_main_pid(u);
1072 if (pid > 0) {
1073 r = append_process(reply, NULL, pid, pids);
1074 if (r < 0)
1075 return r;
1076 }
1077
1078 pid = unit_control_pid(u);
1079 if (pid > 0) {
1080 r = append_process(reply, NULL, pid, pids);
1081 if (r < 0)
1082 return r;
1083 }
1084
1085 r = sd_bus_message_close_container(reply);
1086 if (r < 0)
1087 return r;
1088
1089 return sd_bus_send(NULL, reply, NULL);
1090 }
1091
1092 static int property_get_ip_counter(
1093 sd_bus *bus,
1094 const char *path,
1095 const char *interface,
1096 const char *property,
1097 sd_bus_message *reply,
1098 void *userdata,
1099 sd_bus_error *error) {
1100
1101 CGroupIPAccountingMetric metric;
1102 uint64_t value = (uint64_t) -1;
1103 Unit *u = userdata;
1104
1105 assert(bus);
1106 assert(reply);
1107 assert(property);
1108 assert(u);
1109
1110 if (streq(property, "IPIngressBytes"))
1111 metric = CGROUP_IP_INGRESS_BYTES;
1112 else if (streq(property, "IPIngressPackets"))
1113 metric = CGROUP_IP_INGRESS_PACKETS;
1114 else if (streq(property, "IPEgressBytes"))
1115 metric = CGROUP_IP_EGRESS_BYTES;
1116 else {
1117 assert(streq(property, "IPEgressPackets"));
1118 metric = CGROUP_IP_EGRESS_PACKETS;
1119 }
1120
1121 (void) unit_get_ip_accounting(u, metric, &value);
1122 return sd_bus_message_append(reply, "t", value);
1123 }
1124
1125 const sd_bus_vtable bus_unit_cgroup_vtable[] = {
1126 SD_BUS_VTABLE_START(0),
1127 SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
1128 SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0),
1129 SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0),
1130 SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0),
1131 SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0),
1132 SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter, 0, 0),
1133 SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter, 0, 0),
1134 SD_BUS_PROPERTY("IPEgressBytes", "t", property_get_ip_counter, 0, 0),
1135 SD_BUS_PROPERTY("IPEgressPackets", "t", property_get_ip_counter, 0, 0),
1136 SD_BUS_METHOD("GetProcesses", NULL, "a(sus)", bus_unit_method_get_processes, SD_BUS_VTABLE_UNPRIVILEGED),
1137 SD_BUS_VTABLE_END
1138 };
1139
1140 static int send_new_signal(sd_bus *bus, void *userdata) {
1141 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1142 _cleanup_free_ char *p = NULL;
1143 Unit *u = userdata;
1144 int r;
1145
1146 assert(bus);
1147 assert(u);
1148
1149 p = unit_dbus_path(u);
1150 if (!p)
1151 return -ENOMEM;
1152
1153 r = sd_bus_message_new_signal(
1154 bus,
1155 &m,
1156 "/org/freedesktop/systemd1",
1157 "org.freedesktop.systemd1.Manager",
1158 "UnitNew");
1159 if (r < 0)
1160 return r;
1161
1162 r = sd_bus_message_append(m, "so", u->id, p);
1163 if (r < 0)
1164 return r;
1165
1166 return sd_bus_send(bus, m, NULL);
1167 }
1168
1169 static int send_changed_signal(sd_bus *bus, void *userdata) {
1170 _cleanup_free_ char *p = NULL;
1171 Unit *u = userdata;
1172 int r;
1173
1174 assert(bus);
1175 assert(u);
1176
1177 p = unit_dbus_path(u);
1178 if (!p)
1179 return -ENOMEM;
1180
1181 /* Send a properties changed signal. First for the specific
1182 * type, then for the generic unit. The clients may rely on
1183 * this order to get atomic behavior if needed. */
1184
1185 r = sd_bus_emit_properties_changed_strv(
1186 bus, p,
1187 unit_dbus_interface_from_type(u->type),
1188 NULL);
1189 if (r < 0)
1190 return r;
1191
1192 return sd_bus_emit_properties_changed_strv(
1193 bus, p,
1194 "org.freedesktop.systemd1.Unit",
1195 NULL);
1196 }
1197
1198 void bus_unit_send_change_signal(Unit *u) {
1199 int r;
1200 assert(u);
1201
1202 if (u->in_dbus_queue) {
1203 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
1204 u->in_dbus_queue = false;
1205 }
1206
1207 if (!u->id)
1208 return;
1209
1210 r = bus_foreach_bus(u->manager, u->bus_track, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
1211 if (r < 0)
1212 log_unit_debug_errno(u, r, "Failed to send unit change signal for %s: %m", u->id);
1213
1214 u->sent_dbus_new_signal = true;
1215 }
1216
1217 static int send_removed_signal(sd_bus *bus, void *userdata) {
1218 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1219 _cleanup_free_ char *p = NULL;
1220 Unit *u = userdata;
1221 int r;
1222
1223 assert(bus);
1224 assert(u);
1225
1226 p = unit_dbus_path(u);
1227 if (!p)
1228 return -ENOMEM;
1229
1230 r = sd_bus_message_new_signal(
1231 bus,
1232 &m,
1233 "/org/freedesktop/systemd1",
1234 "org.freedesktop.systemd1.Manager",
1235 "UnitRemoved");
1236 if (r < 0)
1237 return r;
1238
1239 r = sd_bus_message_append(m, "so", u->id, p);
1240 if (r < 0)
1241 return r;
1242
1243 return sd_bus_send(bus, m, NULL);
1244 }
1245
1246 void bus_unit_send_removed_signal(Unit *u) {
1247 int r;
1248 assert(u);
1249
1250 if (!u->sent_dbus_new_signal || u->in_dbus_queue)
1251 bus_unit_send_change_signal(u);
1252
1253 if (!u->id)
1254 return;
1255
1256 r = bus_foreach_bus(u->manager, u->bus_track, send_removed_signal, u);
1257 if (r < 0)
1258 log_unit_debug_errno(u, r, "Failed to send unit remove signal for %s: %m", u->id);
1259 }
1260
1261 int bus_unit_queue_job(
1262 sd_bus_message *message,
1263 Unit *u,
1264 JobType type,
1265 JobMode mode,
1266 bool reload_if_possible,
1267 sd_bus_error *error) {
1268
1269 _cleanup_free_ char *path = NULL;
1270 Job *j;
1271 int r;
1272
1273 assert(message);
1274 assert(u);
1275 assert(type >= 0 && type < _JOB_TYPE_MAX);
1276 assert(mode >= 0 && mode < _JOB_MODE_MAX);
1277
1278 r = mac_selinux_unit_access_check(
1279 u, message,
1280 job_type_to_access_method(type),
1281 error);
1282 if (r < 0)
1283 return r;
1284
1285 if (reload_if_possible && unit_can_reload(u)) {
1286 if (type == JOB_RESTART)
1287 type = JOB_RELOAD_OR_START;
1288 else if (type == JOB_TRY_RESTART)
1289 type = JOB_TRY_RELOAD;
1290 }
1291
1292 if (type == JOB_STOP &&
1293 (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR)) &&
1294 unit_active_state(u) == UNIT_INACTIVE)
1295 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
1296
1297 if ((type == JOB_START && u->refuse_manual_start) ||
1298 (type == JOB_STOP && u->refuse_manual_stop) ||
1299 (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) ||
1300 (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start))
1301 return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id);
1302
1303 r = manager_add_job(u->manager, type, u, mode, error, &j);
1304 if (r < 0)
1305 return r;
1306
1307 r = bus_job_track_sender(j, message);
1308 if (r < 0)
1309 return r;
1310
1311 path = job_dbus_path(j);
1312 if (!path)
1313 return -ENOMEM;
1314
1315 return sd_bus_reply_method_return(message, "o", path);
1316 }
1317
1318 static int bus_unit_set_live_property(
1319 Unit *u,
1320 const char *name,
1321 sd_bus_message *message,
1322 UnitWriteFlags flags,
1323 sd_bus_error *error) {
1324
1325 int r;
1326
1327 assert(u);
1328 assert(name);
1329 assert(message);
1330
1331 /* Handles setting properties both "live" (i.e. at any time during runtime), and during creation (for transient
1332 * units that are being created). */
1333
1334 if (streq(name, "Description")) {
1335 const char *d;
1336
1337 r = sd_bus_message_read(message, "s", &d);
1338 if (r < 0)
1339 return r;
1340
1341 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1342 r = unit_set_description(u, d);
1343 if (r < 0)
1344 return r;
1345
1346 unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "Description=%s", d);
1347 }
1348
1349 return 1;
1350 }
1351
1352 return 0;
1353 }
1354
1355 static int bus_unit_set_transient_property(
1356 Unit *u,
1357 const char *name,
1358 sd_bus_message *message,
1359 UnitWriteFlags flags,
1360 sd_bus_error *error) {
1361
1362 int r;
1363
1364 assert(u);
1365 assert(name);
1366 assert(message);
1367
1368 /* Handles settings when transient units are created. This settings cannot be altered anymore after the unit
1369 * has been created. */
1370
1371 if (streq(name, "DefaultDependencies")) {
1372 int b;
1373
1374 r = sd_bus_message_read(message, "b", &b);
1375 if (r < 0)
1376 return r;
1377
1378 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1379 u->default_dependencies = b;
1380 unit_write_settingf(u, flags, name, "DefaultDependencies=%s", yes_no(b));
1381 }
1382
1383 return 1;
1384
1385 } else if (streq(name, "CollectMode")) {
1386 const char *s;
1387 CollectMode m;
1388
1389 r = sd_bus_message_read(message, "s", &s);
1390 if (r < 0)
1391 return r;
1392
1393 m = collect_mode_from_string(s);
1394 if (m < 0)
1395 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown garbage collection mode: %s", s);
1396
1397 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1398 u->collect_mode = m;
1399 unit_write_settingf(u, flags, name, "CollectMode=%s", collect_mode_to_string(m));
1400 }
1401
1402 return 1;
1403
1404 } else if (streq(name, "Slice")) {
1405 Unit *slice;
1406 const char *s;
1407
1408 if (!UNIT_HAS_CGROUP_CONTEXT(u))
1409 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "The slice property is only available for units with control groups.");
1410 if (u->type == UNIT_SLICE)
1411 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Slice may not be set for slice units.");
1412 if (unit_has_name(u, SPECIAL_INIT_SCOPE))
1413 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set slice for init.scope");
1414
1415 r = sd_bus_message_read(message, "s", &s);
1416 if (r < 0)
1417 return r;
1418
1419 if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
1420 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name '%s'", s);
1421
1422 /* Note that we do not dispatch the load queue here yet, as we don't want our own transient unit to be
1423 * loaded while we are still setting it up. Or in other words, we use manager_load_unit_prepare()
1424 * instead of manager_load_unit() on purpose, here. */
1425 r = manager_load_unit_prepare(u->manager, s, NULL, error, &slice);
1426 if (r < 0)
1427 return r;
1428
1429 if (slice->type != UNIT_SLICE)
1430 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit name '%s' is not a slice", s);
1431
1432 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1433 r = unit_set_slice(u, slice);
1434 if (r < 0)
1435 return r;
1436
1437 unit_write_settingf(u, flags|UNIT_PRIVATE, name, "Slice=%s", s);
1438 }
1439
1440 return 1;
1441
1442 } else if (STR_IN_SET(name,
1443 "Requires", "RequiresOverridable",
1444 "Requisite", "RequisiteOverridable",
1445 "Wants",
1446 "BindsTo",
1447 "Conflicts",
1448 "Before", "After",
1449 "OnFailure",
1450 "PropagatesReloadTo", "ReloadPropagatedFrom",
1451 "PartOf")) {
1452
1453 UnitDependency d;
1454 const char *other;
1455
1456 if (streq(name, "RequiresOverridable"))
1457 d = UNIT_REQUIRES; /* redirect for obsolete unit dependency type */
1458 else if (streq(name, "RequisiteOverridable"))
1459 d = UNIT_REQUISITE; /* same here */
1460 else {
1461 d = unit_dependency_from_string(name);
1462 if (d < 0)
1463 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit dependency: %s", name);
1464 }
1465
1466 r = sd_bus_message_enter_container(message, 'a', "s");
1467 if (r < 0)
1468 return r;
1469
1470 while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
1471 if (!unit_name_is_valid(other, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
1472 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
1473
1474 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1475 _cleanup_free_ char *label = NULL;
1476
1477 r = unit_add_dependency_by_name(u, d, other, NULL, true, UNIT_DEPENDENCY_FILE);
1478 if (r < 0)
1479 return r;
1480
1481 label = strjoin(name, "-", other);
1482 if (!label)
1483 return -ENOMEM;
1484
1485 unit_write_settingf(u, flags, label, "%s=%s", name, other);
1486 }
1487
1488 }
1489 if (r < 0)
1490 return r;
1491
1492 r = sd_bus_message_exit_container(message);
1493 if (r < 0)
1494 return r;
1495
1496 return 1;
1497
1498 } else if (STR_IN_SET(name, "FailureAction", "SuccessAction")) {
1499 EmergencyAction action;
1500 const char *s;
1501
1502 r = sd_bus_message_read(message, "s", &s);
1503 if (r < 0)
1504 return r;
1505
1506 action = emergency_action_from_string(s);
1507 if (action < 0)
1508 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid emergency action: %s", s);
1509
1510 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1511
1512 if (streq(name, "FailureAction"))
1513 u->failure_action = action;
1514 else
1515 u->success_action = action;
1516
1517 unit_write_settingf(u, flags, name, "%s=%s", name, emergency_action_to_string(action));
1518 }
1519
1520 return 1;
1521
1522 } else if (streq(name, "AddRef")) {
1523
1524 int b;
1525
1526 /* Why is this called "AddRef" rather than just "Ref", or "Reference"? There's already a "Ref()" method
1527 * on the Unit interface, and it's probably not a good idea to expose a property and a method on the
1528 * same interface (well, strictly speaking AddRef isn't exposed as full property, we just read it for
1529 * transient units, but still). And "References" and "ReferencedBy" is already used as unit reference
1530 * dependency type, hence let's not confuse things with that.
1531 *
1532 * Note that we don't acually add the reference to the bus track. We do that only after the setup of
1533 * the transient unit is complete, so that setting this property multiple times in the same transient
1534 * unit creation call doesn't count as individual references. */
1535
1536 r = sd_bus_message_read(message, "b", &b);
1537 if (r < 0)
1538 return r;
1539
1540 if (!UNIT_WRITE_FLAGS_NOOP(flags))
1541 u->bus_track_add = b;
1542
1543 return 1;
1544 }
1545
1546 return 0;
1547 }
1548
1549 int bus_unit_set_properties(
1550 Unit *u,
1551 sd_bus_message *message,
1552 UnitWriteFlags flags,
1553 bool commit,
1554 sd_bus_error *error) {
1555
1556 bool for_real = false;
1557 unsigned n = 0;
1558 int r;
1559
1560 assert(u);
1561 assert(message);
1562
1563 /* We iterate through the array twice. First run we just check
1564 * if all passed data is valid, second run actually applies
1565 * it. This is to implement transaction-like behaviour without
1566 * actually providing full transactions. */
1567
1568 r = sd_bus_message_enter_container(message, 'a', "(sv)");
1569 if (r < 0)
1570 return r;
1571
1572 for (;;) {
1573 const char *name;
1574 UnitWriteFlags f;
1575
1576 r = sd_bus_message_enter_container(message, 'r', "sv");
1577 if (r < 0)
1578 return r;
1579 if (r == 0) {
1580 if (for_real || UNIT_WRITE_FLAGS_NOOP(flags))
1581 break;
1582
1583 /* Reached EOF. Let's try again, and this time for realz... */
1584 r = sd_bus_message_rewind(message, false);
1585 if (r < 0)
1586 return r;
1587
1588 for_real = true;
1589 continue;
1590 }
1591
1592 r = sd_bus_message_read(message, "s", &name);
1593 if (r < 0)
1594 return r;
1595
1596 if (!UNIT_VTABLE(u)->bus_set_property)
1597 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
1598
1599 r = sd_bus_message_enter_container(message, 'v', NULL);
1600 if (r < 0)
1601 return r;
1602
1603 /* If not for real, then mask out the two target flags */
1604 f = for_real ? flags : (flags & ~(UNIT_RUNTIME|UNIT_PERSISTENT));
1605
1606 r = UNIT_VTABLE(u)->bus_set_property(u, name, message, f, error);
1607 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
1608 r = bus_unit_set_transient_property(u, name, message, f, error);
1609 if (r == 0)
1610 r = bus_unit_set_live_property(u, name, message, f, error);
1611 if (r < 0)
1612 return r;
1613
1614 if (r == 0)
1615 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
1616
1617 r = sd_bus_message_exit_container(message);
1618 if (r < 0)
1619 return r;
1620
1621 r = sd_bus_message_exit_container(message);
1622 if (r < 0)
1623 return r;
1624
1625 n += for_real;
1626 }
1627
1628 r = sd_bus_message_exit_container(message);
1629 if (r < 0)
1630 return r;
1631
1632 if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
1633 UNIT_VTABLE(u)->bus_commit_properties(u);
1634
1635 return n;
1636 }
1637
1638 int bus_unit_check_load_state(Unit *u, sd_bus_error *error) {
1639 assert(u);
1640
1641 if (u->load_state == UNIT_LOADED)
1642 return 0;
1643
1644 /* Give a better description of the unit error when
1645 * possible. Note that in the case of UNIT_MASKED, load_error
1646 * is not set. */
1647 if (u->load_state == UNIT_MASKED)
1648 return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id);
1649
1650 if (u->load_state == UNIT_NOT_FOUND)
1651 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not found.", u->id);
1652
1653 return sd_bus_error_set_errnof(error, u->load_error, "Unit %s is not loaded properly: %m.", u->id);
1654 }
1655
1656 static int bus_unit_track_handler(sd_bus_track *t, void *userdata) {
1657 Unit *u = userdata;
1658
1659 assert(t);
1660 assert(u);
1661
1662 u->bus_track = sd_bus_track_unref(u->bus_track); /* make sure we aren't called again */
1663
1664 unit_add_to_gc_queue(u);
1665 return 0;
1666 }
1667
1668 static int bus_unit_allocate_bus_track(Unit *u) {
1669 int r;
1670
1671 assert(u);
1672
1673 if (u->bus_track)
1674 return 0;
1675
1676 r = sd_bus_track_new(u->manager->api_bus, &u->bus_track, bus_unit_track_handler, u);
1677 if (r < 0)
1678 return r;
1679
1680 r = sd_bus_track_set_recursive(u->bus_track, true);
1681 if (r < 0) {
1682 u->bus_track = sd_bus_track_unref(u->bus_track);
1683 return r;
1684 }
1685
1686 return 0;
1687 }
1688
1689 int bus_unit_track_add_name(Unit *u, const char *name) {
1690 int r;
1691
1692 assert(u);
1693
1694 r = bus_unit_allocate_bus_track(u);
1695 if (r < 0)
1696 return r;
1697
1698 return sd_bus_track_add_name(u->bus_track, name);
1699 }
1700
1701 int bus_unit_track_add_sender(Unit *u, sd_bus_message *m) {
1702 int r;
1703
1704 assert(u);
1705
1706 r = bus_unit_allocate_bus_track(u);
1707 if (r < 0)
1708 return r;
1709
1710 return sd_bus_track_add_sender(u->bus_track, m);
1711 }
1712
1713 int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m) {
1714 assert(u);
1715
1716 /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet, return an
1717 * error */
1718 if (!u->bus_track)
1719 return -EUNATCH;
1720
1721 return sd_bus_track_remove_sender(u->bus_track, m);
1722 }